我最近遇到在我們的代碼庫以下跌跌撞撞:不確定利用
$func = $_GET['func'] . '_xyz123';
if(function_exists($func)){
$result = $func($_GET);
echo(json_encode($result));
}
這讓我想,如果有可能的PHP內置函數+一些垃圾傳遞給$_GET['func']
,所以它會取消掉_xyz123
導致RCE利用。
這是可能的,還是我只是偏執?
我最近遇到在我們的代碼庫以下跌跌撞撞:不確定利用
$func = $_GET['func'] . '_xyz123';
if(function_exists($func)){
$result = $func($_GET);
echo(json_encode($result));
}
這讓我想,如果有可能的PHP內置函數+一些垃圾傳遞給$_GET['func']
,所以它會取消掉_xyz123
導致RCE利用。
這是可能的,還是我只是偏執?
離開代碼確實是有風險的。
I tried找到可能過早剪切字符串的字符。但是,儘管我沒有辦法做到這一點,但這不是確定性的,並且可能有其他方法來篡改函數名稱。由於PHP提供名稱空間語法(使用\
),因此也可以被創意用戶利用。
但沒有理由承擔風險並允許用戶輸入包含不應出現在函數名稱中的字符。函數名稱必須遵循rules:
函數名稱遵循與PHP中其他標籤相同的規則。有效的函數名稱以字母或下劃線開頭,後跟任意數量的字母,數字或下劃線。作爲一個正則表達式,它將被表述爲:
[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*
所以,你可以確保有違反字符任何參數被拒絕(包括命名空間語法反斜線)。使用引用正則表達式,你能做到這一點,如下所示:
function isValidName($name) {
return preg_match("/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/", $name);
}
$func = $_GET['func'] . '_xyz123';
if(isValidName($func) && function_exists($func)){
$result = $func($_GET);
echo(json_encode($result));
}
的另一種方法,以確保應用程序,是一種定義可以被稱爲這樣一類的靜態方法的所有功能。讓我們假定類被稱爲_xyz123,你的功能就沒有這個後綴,那麼代碼看起來是這樣的,使用method_exists:
$func = $_GET['func'];
if(isValidName($func) && method_exists('_xyz123', $func)){
或者你可以在一個特定的命名空間,例如定義所有的這些功能_xyz123,並做到這一點:
if(isValidName($func) && function_exists('\\_xyz123\\$func')){
感謝您的調查!相當有幫助。 – jjb
空字符可能做到這一點,但是這讓我不知道爲什麼他們會打擾。它似乎是一個非常奇怪的方式來構建一個漏洞,但是「奇怪」的是很多漏洞未被發現的方式。 – samlev
A \ 0字符不會:https://3v4l.org/6vsmJ – VolkerK
unicode範圍內的任何其他字符都不在0x0 ... 0xFFFF:https://3v4l.org/3MlSg – trincot