什么是rce漏洞
rce漏洞又稱遠程代碼執行漏洞,它允許攻擊者在目標服務器上遠程執行任意代碼或操作系統命令。rce漏洞通常出現在 應用程序提供給用戶執行命令的接口,例如網頁的ping功能也就是網頁的url欄,如果不對上傳的數據進行嚴格的管控就可能出現rce漏洞。
許多程序、網站都對用戶提供交互功能,利用前端用戶提供的代碼或命令讓后端系統執行一些操作,如果對這些管控不嚴格就很容易產生rce漏洞。
PHP中執行系統命令的函數
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
執行代碼的函數
eval()
assert()
preg_replace()
creat_function()
call_user_func_arry()
call_user_func()
Windows系統命令拼接符
|:將前一個命令的輸出作為后一個命令的輸入,例如“echo a|b”,將第一個命令輸出的結果作為第二個命令輸入的結果。
||:運行前一個命令,若失敗則運行后一個命令,例如“a||b”,先運行a,如果a運行失敗了,則運行b,若成功了則不運行b
&:先運行前一個命令,后運行后一個命令,例如“a&b”,先運行a,然后運行b
&&:先運行前一個命令,如果成功則運行后一個命令,例如“a&&b”,先運行a命令如果成功則運行b,如果失敗則不運行b。
;:和&類似
rce繞過類型
這邊使用rce-labs靶場來了解
level1(一句話木馬,層級關系繞過)
上面有一個包含,下面post傳參a參數,看到這里其實第一印象是一句話木馬,網頁打開的這個php文件一個一句話木馬我們用蟻劍鏈接看看
連接成功可以得到flag,但是我又嘗試去傳參一些查詢函數,例如看一下ls
可以看到回顯,里面有一個類似flag的文件,但是通過上面我們知道flag文件的名字就是flag,所以就查一下上層目錄,但是不知道為什么查不出來
但是直接抓取上層目錄的flag可以抓出來
level2(代碼審計)
這關給了三個函數,逐一進行代碼審計
function?hello_ctf($function,?$content){global?$flag;$code?=?$function?.?"("?.?$content?.?");";echo?"Your?Code:?$code?<br>";eval($code);}
定義一個全局變量flag,將function參數和content參數拼接起來賦值給code參數,回顯拼接之后的code參數并執行它,其中.是字符串連接符
整體來看這個函數就是傳參兩個參數,將這兩個參數拼接之后輸出出來并執行它
function get_fun(){$func_list = ['eval','assert','call_user_func','create_function','array_map','call_user_func_array','usort','array_filter','array_reduce','preg_replace'];if (!isset($_SESSION['random_func'])) {$_SESSION['random_func'] = $func_list[array_rand($func_list)];}$random_func = $_SESSION['random_func'];$url_fucn = preg_replace('/_/', '-', $_SESSION['random_func']);echo "獲得新的函數: $random_func ,去 https://www.php.net/manual/zh/function.".$url_fucn.".php 查看函數詳情。<br>";return $_SESSION['random_func'];
}
定義了一個數組里面都是執行函數,定義一個會話變量,檢查這個會話變量是否被定義,如果沒定義就從上面定義的數組里面抽取一個賦值給它,對抽到的函數進行處理將_變成-這里是為了符合url的解析規則,后面就是將隨機抽取到的函數輸出到屏幕而已,這里起到一個提示作用
function start($act){$random_func = get_fun();if($act == "r"){ /* 通過發送GET ?action=r 的方式可以重置當前選中的函數 —— 或者你可以自己想辦法可控它x */session_unset();session_destroy(); }if ($act == "submit"){$user_content = $_POST['content']; hello_ctf($random_func, $user_content);}
}
這里有一個判斷,如果get傳參action=r就重置前面隨機選取到的執行函數,如果action=submit,就從post傳參中獲取名為content的參數值
整體看就是要分get傳參和post傳參
我們先個體傳參一下看看
可以看到上面抽取到的函數是assert這個函數,這個函數被賦值給了function變量我們后面用post傳參的參數是content,會將這兩個函數拼接并執行,那么我們結合assert函數的用法去post傳參一個能得到flag的數據即可