Last active
June 9, 2021 00:41
-
-
Save dustyfresh/c6d81e6c77e0d4e30e844edc25cbee40 to your computer and use it in GitHub Desktop.
Simple http sensor written in Rust with Rocket. Always responds 200 to every request, logs POST data, and each request has a random content-length
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "http-sensor" | |
version = "0.1.0" | |
authors = [""] | |
edition = "2018" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
rocket = "0.4.10" | |
chrono = "0.4.19" | |
rand = "0.8.3" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This is a snippet of example logs from Nikto and sqlmap | |
[2021-06-08 23:10:12.888856713 UTC] -- 127.0.0.1 Mozilla/5.00 (Nikto/2.1.5) (Evasions:None) (Test:006481) POST /private.php | |
[2021-06-08 23:10:12.888927262 UTC] -- COLLECTED PAYLOAD => "my_post_key=&keywords='+or+'a'+'a&quick_search=Search+PMs&allbox=Check+All&fromfid=0&fid=4&jumpto=4&action=do_stuff" | |
[2021-06-08 23:10:12.888969288 UTC] -- Completed POST request for 127.0.0.1 | |
[2021-06-09 00:40:33.976259891 UTC] -- 127.0.0.1 sqlmap/1.4.4#stable (http://sqlmap.org) GET /test.php?id=1%29%20WAITFOR%20DELAY%20%270%3A0%3A5%27%20AND%20%286362%3D6362 | |
[2021-06-09 00:40:33.977417364 UTC] -- Completed GET request for 127.0.0.1 | |
[2021-06-09 00:40:33.980714617 UTC] -- 127.0.0.1 sqlmap/1.4.4#stable (http://sqlmap.org) GET /test.php?id=1%20WAITFOR%20DELAY%20%270%3A0%3A5%27 | |
[2021-06-09 00:40:33.981199446 UTC] -- Completed GET request for 127.0.0.1 | |
[2021-06-09 00:40:33.984192726 UTC] -- 127.0.0.1 sqlmap/1.4.4#stable (http://sqlmap.org) GET /test.php?id=1%20WAITFOR%20DELAY%20%270%3A0%3A5%27--%20ruVs | |
[2021-06-09 00:40:33.985204211 UTC] -- Completed GET request for 127.0.0.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(proc_macro_hygiene, decl_macro)] | |
#[macro_use] extern crate rocket; | |
mod web { | |
// Rocket dependencies & types | |
use rocket::data; | |
use rocket::Data; | |
use rocket::{Request}; | |
use rocket::http::Status; | |
use std::fs::OpenOptions; | |
use rocket::fairing::AdHoc; | |
use rocket::data::FromDataSimple; | |
// Non-rocket dependencies & types | |
use rand::{distributions::Alphanumeric, Rng}; | |
use std::io::{Read, Write, BufWriter}; | |
use chrono::{DateTime, Utc}; | |
use std::path::PathBuf; | |
// function for logging events | |
fn logger(data: &String){ | |
let timestamp: DateTime<Utc> = Utc::now(); | |
let mut outfile = BufWriter::new(OpenOptions::new() | |
.write(true) | |
.append(true) | |
.create(true) | |
.open("http-sensor.log") | |
.unwrap()); | |
writeln!(outfile, "[{}] -- {}", timestamp.to_string(), &data).expect("Error!"); | |
} | |
// Generate random data to include in responses for showing varying content-length | |
fn random_data() -> String { | |
let mut rng = rand::thread_rng(); | |
let random_num: u16 = rng.gen_range(100..=3000); | |
let random_str: String = rng.sample_iter(&Alphanumeric) | |
.take(random_num.into()) | |
.map(char::from) | |
.collect(); | |
random_str | |
} | |
// We create a struct to sign the post payload | |
#[derive(Debug)] | |
struct SignedPayload { | |
contents: String, | |
} | |
impl FromDataSimple for SignedPayload { | |
type Error = String; | |
fn from_data(_req: &Request, data: Data) -> data::Outcome<Self, String> { | |
let mut contents = String::new(); | |
if let Err(e) = data.open().take(10000).read_to_string(&mut contents) { | |
return rocket::Outcome::Failure((Status::InternalServerError, format!("{:?}", e))); | |
} | |
rocket::Outcome::Success(SignedPayload { contents }) | |
} | |
} | |
#[post("/", data = "<_payload>")] | |
fn honey_post(_payload: SignedPayload) -> String { | |
let log_line = format!("COLLECTED PAYLOAD => {:?}", _payload.contents); | |
logger(&log_line); | |
format!("{}", random_data()) | |
} | |
#[post("/<_path..>", data = "<_payload>")] | |
fn honey_post_dynamic(_path: PathBuf, _payload: SignedPayload) -> String { | |
let log_line = format!("COLLECTED PAYLOAD => {:?}", _payload.contents); | |
logger(&log_line); | |
format!("{}", random_data()) | |
} | |
#[get("/")] | |
fn honey_get() -> String { | |
format!("{}", random_data()) | |
} | |
#[get("/<_path..>")] | |
fn honey_get_dynamic(_path: PathBuf) -> String { | |
format!("{}", random_data()) | |
} | |
// Starts the server, mounts the routes and attaches adhoc request logic | |
pub fn server(){ | |
rocket::ignite().mount("/", routes![ | |
honey_get, | |
honey_get_dynamic, | |
honey_post, | |
honey_post_dynamic | |
]).attach(AdHoc::on_request("new request handler", |request, _| { | |
let headers = request.headers(); | |
let user_agent = headers.get_one("User-Agent").unwrap_or("No-User-Agent"); | |
let method = request.method().to_string(); | |
let uri = request.uri().to_string(); | |
let client_ip = request.client_ip().unwrap(); | |
let log_line = format!("{} {} {} {}", client_ip, user_agent, method, uri); | |
logger(&log_line); | |
})).attach(AdHoc::on_response("set custom headers on all responses", |_request, response| { | |
// Overrides the default Server header with a vuln nginx version | |
response.set_raw_header("Server", "nginx/1.20.0"); | |
})).attach(AdHoc::on_response("logger", |request, _response| { | |
let log_line = format!("Completed {} request for {}\n", | |
request.method(), | |
request.client_ip().unwrap() | |
); | |
logger(&log_line); | |
})).launch(); | |
} | |
} | |
fn main() { | |
// Start the webserver | |
web::server(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[production] | |
address = "0.0.0.0" | |
port = 80 | |
workers = 16 | |
log = "off" | |
[development] | |
address = "127.0.0.1" | |
port = 80 | |
workers = 16 | |
log = "normal" | |
[staging] | |
address = "127.0.0.1" | |
port = 80 | |
workers = 16 | |
log = "normal" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment