mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-07-09 20:58:38 +02:00
v3.5.0: automated login — execute the login flow and capture the live session
- harness/creds::login(): performs the real HTTP login (POST/GET form), captures a session Cookie from Set-Cookie or a Bearer token from the JSON body, with a soft success check (no hard fail on 302). Redirects not followed so Set-Cookie is visible. - apply_creds is now async: direct material (jwt/header/cookie) used as-is; a `login:` flow is EXECUTED to obtain a live session; on failure, falls back to instructing the agents to log in themselves. - --creds + --focus added to `run` (authenticated black-box) too. - Verified live against a local mock: POST /login → 302 + Set-Cookie captured as the auth header used on subsequent requests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -116,6 +116,61 @@ impl Creds {
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform the login flow now (real HTTP POST) and return an auth header to
|
||||
/// reuse on every subsequent request: a `Cookie:` from Set-Cookie, or an
|
||||
/// `Authorization: Bearer` from a token in the JSON response. Returns
|
||||
/// (auth_header, note). Redirects are not followed so the login response's
|
||||
/// Set-Cookie is visible.
|
||||
pub async fn login(l: &Login) -> anyhow::Result<(String, String)> {
|
||||
use reqwest::header::SET_COOKIE;
|
||||
let client = reqwest::Client::builder()
|
||||
.redirect(reqwest::redirect::Policy::none())
|
||||
.timeout(std::time::Duration::from_secs(30))
|
||||
.build()?;
|
||||
let form: Vec<(String, String)> = vec![
|
||||
(l.username_field.clone(), l.username.clone()),
|
||||
(l.password_field.clone(), l.password.clone()),
|
||||
];
|
||||
let req = if l.method == "GET" {
|
||||
client.get(&l.url).query(&form)
|
||||
} else {
|
||||
client.post(&l.url).form(&form)
|
||||
};
|
||||
let resp = req.send().await?;
|
||||
let status = resp.status();
|
||||
|
||||
// 1) session cookies from Set-Cookie on the login response
|
||||
let mut cookie_pairs = Vec::new();
|
||||
for hv in resp.headers().get_all(SET_COOKIE) {
|
||||
if let Ok(s) = hv.to_str() {
|
||||
if let Some(pair) = s.split(';').next() {
|
||||
let p = pair.trim();
|
||||
if !p.is_empty() {
|
||||
cookie_pairs.push(p.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let body = resp.text().await.unwrap_or_default();
|
||||
|
||||
// 2) bearer token from a JSON response body
|
||||
if let Ok(v) = serde_json::from_str::<serde_json::Value>(&body) {
|
||||
for k in ["access_token", "token", "jwt", "id_token", "accessToken"] {
|
||||
if let Some(t) = v.get(k).and_then(|x| x.as_str()).filter(|t| !t.is_empty()) {
|
||||
return Ok((format!("Authorization: Bearer {t}"), format!("bearer token from JSON `{k}` (HTTP {status})")));
|
||||
}
|
||||
}
|
||||
}
|
||||
if !cookie_pairs.is_empty() {
|
||||
let cookie = cookie_pairs.join("; ");
|
||||
// Soft success check (don't fail hard — many apps 302 on success).
|
||||
let ok = l.success.is_empty() || body.contains(&l.success) || status.is_redirection() || status.is_success();
|
||||
let note = format!("session cookie captured (HTTP {status}{})", if ok { "" } else { ", success marker not seen" });
|
||||
return Ok((format!("Cookie: {cookie}"), note));
|
||||
}
|
||||
anyhow::bail!("login returned no Set-Cookie or token (HTTP {status})")
|
||||
}
|
||||
|
||||
fn unquote(s: &str) -> String {
|
||||
let s = s.trim();
|
||||
if (s.starts_with('"') && s.ends_with('"') && s.len() >= 2)
|
||||
|
||||
Reference in New Issue
Block a user