parent
01c1c8a436
commit
5090a845fd
@ -0,0 +1,183 @@ |
|||||||
|
use std::{fmt::format, io::Read}; |
||||||
|
|
||||||
|
use hyper::{body::HttpBody, Body, Client, Method, Request, Uri}; |
||||||
|
use json::JsonValue; |
||||||
|
use rand::Fill; |
||||||
|
use sha2::Sha512; |
||||||
|
use srp::{ |
||||||
|
client::{srp_private_key, SrpClient}, |
||||||
|
groups::G_2048, |
||||||
|
}; |
||||||
|
|
||||||
|
const AUTH_URI: &'static str = "http://192.168.1.1/authenticate"; |
||||||
|
|
||||||
|
fn get_username<'a>() -> &'a str { |
||||||
|
"admin" |
||||||
|
} |
||||||
|
|
||||||
|
fn get_password<'a>() -> &'a str { |
||||||
|
"admin" |
||||||
|
} |
||||||
|
|
||||||
|
pub async fn try_login(cookie: &str, csrf_token: &str) -> Result<(), ()> { |
||||||
|
let mut a = [0u8; 64]; |
||||||
|
a.try_fill(&mut rand::thread_rng()).unwrap(); |
||||||
|
let srp_client = SrpClient::<Sha512>::new(&a, &G_2048); |
||||||
|
|
||||||
|
let a_pub = srp_client.get_a_pub(); |
||||||
|
let a_pub = base16::encode_lower(&a_pub); |
||||||
|
|
||||||
|
let client = Client::new(); |
||||||
|
|
||||||
|
let uri: Uri = AUTH_URI.parse().unwrap(); |
||||||
|
|
||||||
|
let req_body = format!("CSRFtoken={}&I={}&A={}", csrf_token, get_username(), a_pub); |
||||||
|
|
||||||
|
println!("{}", &req_body); |
||||||
|
|
||||||
|
let request = Request::builder() |
||||||
|
.method(Method::POST) |
||||||
|
.uri(uri.clone()) |
||||||
|
.header("Accept", "application/json, text/javascript, */*; q=0.01") |
||||||
|
.header( |
||||||
|
"Content-Type", |
||||||
|
"application/x-www-form-urlencoded; charset=UTF-8", |
||||||
|
) |
||||||
|
.header("Cookie", format!("sessionID={}", cookie).as_str()) |
||||||
|
.header("Host", "192.168.1.1") |
||||||
|
.header("Origin", "http://192.168.1.1") |
||||||
|
.header("Pragma", "no-cache") |
||||||
|
.header("Referer", "http://192.168.1.1/") |
||||||
|
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 Edg/93.0.961.52") |
||||||
|
.header("X-Requested-With", "XMLHttpRequest") |
||||||
|
.body(Body::from(req_body)) |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
match client.request(request).await { |
||||||
|
Ok(mut resp) => { |
||||||
|
let mut buffer: Vec<u8> = Vec::new(); |
||||||
|
|
||||||
|
while let Some(chunk) = resp.body_mut().data().await { |
||||||
|
match chunk { |
||||||
|
Ok(bytes) => buffer.append(&mut bytes.to_vec()), |
||||||
|
Err(e) => panic!("{}", e.to_string()), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// TODO: handle errors
|
||||||
|
let buffer = String::from_utf8(buffer).unwrap(); |
||||||
|
println!("{:?}", buffer); |
||||||
|
//let resp = json::parse(&buffer).unwrap();
|
||||||
|
|
||||||
|
if let Some((s, b_pub)) = get_salt_and_b_pub(&buffer) { |
||||||
|
let s = base16::decode(s.as_bytes()).unwrap(); |
||||||
|
|
||||||
|
let b_pub = base16::decode(b_pub.as_bytes()).unwrap(); |
||||||
|
|
||||||
|
let private_key = srp_private_key::<Sha512>( |
||||||
|
get_username().as_bytes(), |
||||||
|
get_password().as_bytes(), |
||||||
|
&s, |
||||||
|
); |
||||||
|
|
||||||
|
let verifier = srp_client.process_reply(&private_key, &b_pub).unwrap(); |
||||||
|
|
||||||
|
let user_proof = verifier.get_proof(); |
||||||
|
|
||||||
|
let m = base16::encode_lower(&user_proof); |
||||||
|
|
||||||
|
let req_body = format!("CSRFtoken={}&M={}", csrf_token, m); |
||||||
|
let request = Request::builder() |
||||||
|
.method(Method::POST) |
||||||
|
.uri(uri) |
||||||
|
.header("Accept", "application/json, text/javascript, */*; q=0.01") |
||||||
|
.header( |
||||||
|
"Content-Type", |
||||||
|
"application/x-www-form-urlencoded; charset=UTF-8", |
||||||
|
) |
||||||
|
.header("Cookie", format!("sessionID={}", cookie).as_str()) |
||||||
|
.header("Host", "192.168.1.1") |
||||||
|
.header("Origin", "http://192.168.1.1") |
||||||
|
.header("Pragma", "no-cache") |
||||||
|
.header("Referer", "http://192.168.1.1/") |
||||||
|
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36 Edg/93.0.961.52") |
||||||
|
.header("X-Requested-With", "XMLHttpRequest") |
||||||
|
.body(Body::from(req_body)) |
||||||
|
.unwrap(); |
||||||
|
|
||||||
|
match client.request(request).await { |
||||||
|
Ok(mut resp) => { |
||||||
|
let mut buffer: Vec<u8> = Vec::new(); |
||||||
|
|
||||||
|
while let Some(chunk) = resp.body_mut().data().await { |
||||||
|
match chunk { |
||||||
|
Ok(bytes) => buffer.append(&mut bytes.to_vec()), |
||||||
|
Err(e) => panic!("{}", e.to_string()), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// TODO: handle errors
|
||||||
|
let buffer = String::from_utf8(buffer).unwrap(); |
||||||
|
println!("final resp: {:?}", buffer); |
||||||
|
} |
||||||
|
Err(e) => panic!("{}", e.to_string()), |
||||||
|
} |
||||||
|
//let server_proof = conn.send_proof(user_proof);
|
||||||
|
//let key = verifier.verify_server(server_proof).unwrap();
|
||||||
|
} else { |
||||||
|
println!("{:?}", resp); |
||||||
|
} |
||||||
|
} |
||||||
|
Err(e) => panic!("{}", e.to_string()), |
||||||
|
} |
||||||
|
|
||||||
|
todo!() |
||||||
|
} |
||||||
|
|
||||||
|
fn get_salt_and_b_pub(msg: &str) -> Option<(String, String)> { |
||||||
|
let msg = json::parse(&msg).unwrap(); |
||||||
|
|
||||||
|
//_get_salt_and_b_pub(&msg, None, None)
|
||||||
|
if let JsonValue::Object(obj) = msg { |
||||||
|
println!("{:?}", obj); |
||||||
|
|
||||||
|
let mut s = String::new(); |
||||||
|
let mut b = String::new(); |
||||||
|
|
||||||
|
for (name, val) in obj.iter() { |
||||||
|
if name == "s" { |
||||||
|
s = get_json_string(val).unwrap(); |
||||||
|
} else if name == "B" { |
||||||
|
b = get_json_string(val).unwrap(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Some((s, b)) |
||||||
|
} else { |
||||||
|
None |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn get_json_string(val: &JsonValue) -> Option<String> { |
||||||
|
match val { |
||||||
|
JsonValue::Short(val) => Some(val.to_string()), |
||||||
|
JsonValue::String(val) => Some(val.to_string()), |
||||||
|
_ => None, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use crate::login::get_salt_and_b_pub; |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn parse_json_resp() { |
||||||
|
let msg = "{ \"s\":\"0DEC99D3\", \"B\":\"2FCDB529BB3F7F02BAD0ED15C62995CB9E76AC0352D91F64AD02A1EF06C533565F64A0B25D7235682E5D732CA8FD1C675231CA205D83FF317E8D7BFBC48D863822A7E9A8ADC7BBD54B54A7D59502479872E4926C6169BDDED2E7FD7BFD1714ECA3FE22511C4F48F8FA33240DB8DD289933FC19A1B7DC0EEB4A56337ADB67FFC08684822D05D2A5EC95A3B21E84B4CB0F2C6195454D1D3B59548987485555E200B5E23B7E89E87C60AF3C2AA5834B284DD182C9A508FE479357BA341750385837241ACA56AAC5E380AB3876F80761E4BE33FAA8BBE60863AFC96FEBDB2AC64636AF3035777624EF2ECC581CA7266D3F11BB30CDEF21E9802973CCC7899E375F3E\" }"; |
||||||
|
println!("{:?}", json::parse(&msg)); |
||||||
|
|
||||||
|
assert_eq!( |
||||||
|
get_salt_and_b_pub(msg), |
||||||
|
Some((String::from("0DEC99D3"), String::from("2FCDB529BB3F7F02BAD0ED15C62995CB9E76AC0352D91F64AD02A1EF06C533565F64A0B25D7235682E5D732CA8FD1C675231CA205D83FF317E8D7BFBC48D863822A7E9A8ADC7BBD54B54A7D59502479872E4926C6169BDDED2E7FD7BFD1714ECA3FE22511C4F48F8FA33240DB8DD289933FC19A1B7DC0EEB4A56337ADB67FFC08684822D05D2A5EC95A3B21E84B4CB0F2C6195454D1D3B59548987485555E200B5E23B7E89E87C60AF3C2AA5834B284DD182C9A508FE479357BA341750385837241ACA56AAC5E380AB3876F80761E4BE33FAA8BBE60863AFC96FEBDB2AC64636AF3035777624EF2ECC581CA7266D3F11BB30CDEF21E9802973CCC7899E375F3E"))) |
||||||
|
) |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue