Code-Breaking Puzzles做題記錄
24號被XNUCA虐了,25號起床才知道P總之前說過的 ofollow,noindex" target="_blank">Code-Breaking Puzzles 已經開始了,趕緊學習一波。這裡給P總的 程式碼審計知識星球 打個廣告,滿滿乾貨,個個都是人才,我超喜歡裡面的
easy – function
程式碼:
<?php $action = $_GET['action'] ?? ''; $arg = $_GET['arg'] ?? ''; if(preg_match('/^[a-z0-9_]*$/isD', $action)) { show_source(__FILE__); } else { $action('', $arg); }
雖然是第一題,但上來還是把我難住了….一開始想不明白如何在數字字母下劃線都被禁用的情況下呼叫函式,苦思無果於是決定寄出fuzz大法:因為正則裡用了 ^$
,那麼有沒有可能在開頭或結尾加入某個字元來繞過正則且函式依然能呼叫呢?
寄出bp一跑,還真有,好神奇:
這個字元是 %5C
,不知道為什麼把它加在函式名之前依然不影響正常呼叫函式。
於是繞過了正則,可以任意函式呼叫了。我們可以控制函式的第二個引數,有哪個函式第二個引數比較危險呢?經過漫長的查詢最終發現:
PHP create_function()程式碼注入
於是最終payload:
easy – pcrewaf
程式碼:
<?php function is_php($data){ return preg_match('/<\?.*[(`;?>].*/is', $data); } if(empty($_FILES)) { die(show_source(__FILE__)); } $user_dir = 'data/' . md5($_SERVER['REMOTE_ADDR']); $data = file_get_contents($_FILES['file']['tmp_name']); if (is_php($data)) { echo "bad request"; } else { @mkdir($user_dir, 0755); $path = $user_dir . '/' . random_int(0, 10) . '.php'; move_uploaded_file($_FILES['file']['tmp_name'], $path); header("Location: $path", true, 303); }
這題讓我們上傳php,但是用正則限制了php的格式,嘗試了許久繞過都無果。
後來看見P總提示說
pcrewaf PHP正則特性
於是在手冊裡翻來覆去看了好久,無果….
過了一會兒猛然想起@pupiles 師傅在LCTF 2017也出過一個繞過 preg_match
的題目,就是利用PHP正則的特性,於是特地翻出了當時的 官方WP
WP裡如是說:
其實正解是通過pre_match函式的資源消耗來繞過,因為pre_match在匹配的時候會消耗較大的資源,並且預設存在貪婪匹配,所以通過喂一個超長的字串去給pre_match吃,導致pre_match消耗大量資源從而導致php超時,後面的php語句就不會執行。
說是 preg_match
匹配很長的資源就會超時,後面的語句就不會執行了,乍看起來好像不適合這題的環境…但是決定死馬當活馬醫一下,結果:
居然寫進去了…於是愉快的getshell:
easy – phplimit
程式碼:
<?php if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { eval($_GET['code']); } else { show_source(__FILE__); }
一眼就認出了這就是RCTF 2018的 r-cursive ,於是找來了WP一把梭:
好吧,果然不可能這麼簡單。仔細一看題目環境是 nginx
,而 getallheaders
函式是apache模組的函式,所以這裡不適用。
但是思路應該還是差不多的,只要找一個能代替 getallheaders
的函式即可。
翻了一番手冊找了個差不多的函式:
這個已定義的變數裡就包括了 $_GET
、 $_POST
等我們可以控制的變數,所以把要執行的程式碼寫在其他的get引數裡即可: