HTB - Command Injections
什麼是 Command Injection
當網站把使用者輸入直接放進系統指令中執行,攻擊者可能插入額外指令,進而在後端伺服器執行任意系統命令,嚴重時甚至控制整台主機或進一步入侵內部網路。
Injection 漏洞的核心概念
系統把「使用者輸入」誤認為程式碼、查詢語法或系統指令的一部分。
只要輸入沒有經過適當的驗證、過濾或跳脫,攻擊者就可能跳出原本輸入範圍,改變原始指令的用途。
常見的 Injection 類型
Web 應用程式中存在許多不同類型的注入漏洞,實際類型通常取決於後端所執行的查詢、命令或程式語言。
| 注入類型 | 說明 |
|---|---|
| OS Command Injection | 使用者輸入被直接放入作業系統命令中執行 |
| Code Injection | 使用者輸入被放入可執行或解析程式碼的函式中 |
| SQL Injection | 使用者輸入被直接拼接至 SQL 查詢語句 |
| Cross-Site Scripting | 未經處理的使用者輸入被顯示在網頁中,使瀏覽器執行惡意腳本 |
| HTML Injection | 使用者輸入被當成 HTML 內容呈現在網頁中 |
Command Injection 成立條件
要產生 OS Command Injection,通常需要同時符合:
- 應用程式接收使用者可控制的輸入。
- 輸入直接或間接影響系統命令。
- 程式使用 Shell 或系統命令執行函式。
- 輸入未經適當驗證、清理或跳脫。
可以簡化成:
1 | |
Command Injection 偵測重點
偵測方式與利用方式幾乎相同
基本的 OS Command Injection,偵測方法就是嘗試在原本輸入後面附加另一條命令。
判斷依據:
- 網頁輸出是否與正常結果不同
- 是否出現額外命令的執行結果
- 原本功能是否仍有執行
若輸出被改變,通常代表注入成功。較進階的情況則可能需要 Fuzzing 或程式碼審查。
先推測後端實際執行的命令
舉例有一個 Host Checker,輸入 IP 後會回傳 Ping 結果。
輸入:
1 | |
根據輸出可以推測後端可能執行:
1 | |
基本注入格式
1 | |
如果輸入沒有被適當清理,Shell 可能將其解析成兩條命令。
常見 Command Injection 運算
| 運算子 | URL 編碼 | 執行效果 |
|---|---|---|
| ; | %3b | 結束前一個命令,再執行下一個 |
| \n | %0a | 前後兩條命令皆執行 |
| & | %26 | 把前一個命令放到背景執行,或分隔命令 |
| ` | ` | %7c |
| && | %26%26 | 第一條成功,才執行第二條 |
command |
%60%60 | 子 Shell,Linux 系統 |
| $(command) | %24%28%29 | 子 Shell,Linux 系統 |
特殊字元經過 HTTP 傳送時,可能需要 URL Encode,例如:
; → %3b
& → %26
| → %7c (把左邊輸出交給右邊)
\n → %0a (換行)
測試時,若直接輸入特殊字元被瀏覽器、前端或代理工具改寫,可以嘗試 URL 編碼形式。
繞過role黑名單
當我們使用Path時,他會顯示這樣:
1 | |
會有好幾個字元
如果我們只要第一個字元,可以使用:
1 | |
他就會只顯示/
在命令注入情境中,重點是即使輸入不能直接包含 ;,也能利用環境變數中的既有字元,把分號「切」出來。例如:
1 | |
Shell 展開後就會變成:
1 | |
因此兩個命令都會被執行。
繞過字元黑名單
基本的過黑名單過濾長這樣:
1 | |
若我們直接輸入whoami指令的話會回復Invalid input
我們要做混淆繞過的話最簡單的方法是加入引號:
- 使用單引號
1 | |
使用雙引號
1
2
3test[/test]$ w"h"o"am"i
test僅適用於Linux
1
2who$@ami
w\ho\am\i僅適用於Windows
1
2
3C:\test> who^ami
21y4d
範例:
1 | |
進階混淆
第一個技巧是大小寫混合,例如使用WhOAmI
這在windows中的poserchell跟CMD都能直接運行
不過在Linux的話就會區分大小寫,所以進行轉換:
1 | |
第二個技巧是反向命令,我們可以使用rev將輸出字串翻轉。
1 | |
第三個技巧是使用編碼
我們可以使用各種編碼工具,例如 base64或 十六進位編碼
1 | |
然後我們可以再進行解碼:
1 | |
|被原本測試網站阻擋了,所以這邊使用<<<代替|
範例:
試著找到find/usr/share/ | grep root | grep mysql | tail -n 1的輸出方法
1 | |
混淆用工具
Bashfuscator
Linux可用的一個工具Bashfuscator
1. 安裝 Bashfuscator
在 Kali / Ubuntu 上安裝:
1 | |
新版 Ubuntu 如果碰到:
1 | |
建議用 venv:
1 | |
2. 最基本用法
例如原本有:
1 | |
可以這樣混淆:
1 | |
它會產生一長串看起來非常亂的 Bash,例如大量:
1 | |
3. 簡單指令練習
例如:
1 | |
但使用這種方式工具會隨機選擇一種混淆技術,因此我們可以指定更短的混淆。
1 | |
DOSfuscation
Windows可用的一個工具DOSfuscation
DOSfuscation 是 Daniel Bohannon 的 PowerShell 工具,通常在 PowerShell 中載入,再產生 CMD 混淆內容。
1 | |
然後載入模組:
1 | |
如果 Windows 阻止腳本執行,可以只針對目前這個 PowerShell process:
1 | |
再:
1 | |
接著啟動:
1 | |
這個工具本身是互動式操作為主。專案的設計就是讓載入 command/script,再逐層選擇 obfuscation technique
最簡單的手工 DOSfuscation
例如:
1 | |
我們先設:
1 | |
然後:
1 | |
CMD 展開成:
1 | |
所以實際執行:
1 | |
這就是最初階的 CMD obfuscation。
利用 substring
例如:
1 | |
可以:
1 | |
→
1 | |
以及:
1 | |
→
1 | |
因此攻防裡常看到非常醜的:
1 | |
判別混淆
例如 Sysmon Event ID 1 可能看到:
1 | |
但是:
1 | |
這時候你不能搜尋:
1 | |
因為 command line 裡可能根本不存在 whoami。
反而可以找一些特徵,例如:
1 | |
搭配大量:
1 | |
以及異常長的 command line。
防禦
最重要:不要把使用者輸入丟進 shell
例如這種 PHP:
1 | |
問題不是 ping,而是你其實把:
1 | |
所以 shell 不只會把輸入當成 IP,還可能把某些特殊字元當成「語法」。
核心原則就是:
能用語言 API 完成,就不要啟動 shell。
這是防 Command Injection 最有效的一層。
Validation 跟 Sanitization 不一樣
Validation 不應該只放前端,後端一定也要做。
攻擊者根本不需要用你的網頁,可以直接自己送 HTTP request。
1 | |
Sanitization 是「只留下允許的東西」
1 | |
這段 regex:
1 | |
意思是:
1 | |
全部找出來。
然後:
1 | |
把它刪掉。
因此如果用途真的只需要:
1 | |
其他字元就不會保留下來。
這其實是在做:
1 | |
安全上通常:
Allowlist 比 Blacklist 好。
因為 blacklist 很容易變成:
1 | |
這正是前面 Command Injection 各種 filter bypass 為什麼存在。
為什麼只 escape 還是不夠?
escaping special characters 並不應被視為足夠安全的主要防禦,因為有些情況仍可能被繞過。
真正安全架構應該是:
1 | |
總結:
1 | |