Web 500 是一題 PHP source code review 找 vuln 的題目
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| <?php
$cookie_key = "◢▆▅▄▃崩╰(〒皿〒)╯潰▃▄▅▇◣"; $iv = "00000000";
function safe( $s ) { if ( is_string( $s ) && strpos( $s, "\0" ) === false ) { if ( strpos( $s, 'O:' ) === false ) { return true; } else if ( ! preg_match('/(^|;|})s:[+\-0-9]+:"/', $s ) ) { return true; } } return false; }
class qoo{ var $key_var = "FakeKey"; function __construct(){}
function __destruct(){ $keyfile = $this->key_var . ".php"; $keyfile = basename( $keyfile );
include( $keyfile );
print $key; }
}
$checksum = $_COOKIE['checksum']; if ( @md5($checksum) == '' ) {
$auth_str = $_COOKIE['auth_str']; $auth_str = base64_decode( $auth_str ); $auth_str = mcrypt_decrypt( MCRYPT_BLOWFISH, $cookie_key, $auth_str, MCRYPT_MODE_ECB, $iv ); $auth_str = trim( $auth_str );
if ( safe($auth_str) ) unserialize( $auth_str ); else die( 'Auth string is not safe' ); } else { new qoo(); }
?>
|
其實考的滿簡單的,如果對 PHP Sec 有概念的話直覺會想到 unserialize 的 object inj
- 利用 object inj 覆蓋 magic method(
__destruct
) 的 key_var
變量
- 繞過
md5() == ''
可以用 checksum[]=bla
- 繞過 safe 函數的話我不小心少寫一個 byte 所以可以用 s 大小寫置換來繞過,
不過我既然題目都已經出來了就算了XD 給你們簡單解吧!
原本繞過的方式是利用 PHP 對於 unserialize 實作的不一致來繞過
O:3:”qoo”:1:{s:7:”key_var”ts:3:”Key”;}
注意的 ts:3
這樣的形式 PHP unserialize 是可以接受的,有多少人是這樣解的給我說說看XDDD
這個問題有在 2012 年 12 月底的時候 ipb 漏洞出來被人探討過。
Invision Power Board 是一款滿流行的 PHP 討論版,由於在程式碼實作上會用到 unserialize,所以 ipb 寫了一個 check function 去檢查 unserialize 是否為惡意的,但由於 PHP 對 unserialize 上的實作缺陷,讓 check function 可被繞過(這點 PHP 後來有做 bug fix掉了(待確認中))
詳細細節可參考 80vul 寫的文章
http://www.80vul.com/pch/pch-010.txt