这是在 code-breaking 中遇到的一道题目,名为:easy - function。题目地址:http://51.158.75.42:8087

1

??PHP7 中新增的运算符,用于替代需要 isset 的场合,是一种语法糖。接着正则对 $action 变量进行了正则匹配,该变量如果符合正常函数名命名规则,则显示该题目源码,否则就作为函数名进行可变变量动态调用函数。

正常函数名都是以字母数字或者下划线开头的,那么有没有什么变量名不是按照这个规则命名的呢?这让我想到之前看到的一种过狗一句话:

1
<?php namespace ccc;\eval($_REQUEST['a']);

该木马在 eval 函数前面添加了一个反斜杠,竟然也能正常运行。我们查阅PHP手册,会发现官方有这么一段说明:

2

也就是说 所有PHP内置函数 均在 \命名空间下 ,这样就可以绕过上面的正则了。那么我们使用 \create_function 来作为 $action 的值,此时 create_function 函数的第二个参数可控。我们先来看看 create_function 函数的定义。

3

可以看到手册上说, create_function 函数内部实现与 eval 函数一样,我们再来看看 create_function 函数对应的内核源码。( php-src/Zend/zend_builtin_functions.c:1901

4

5

上述代码用PHP语言来表达的话,实际上就是下图 第3行 代码(下图第2、3行代码是等价的):

6

在这道题目中,用户可控的是第二个参数,也就是 code 部分,所以我们只要闭合 { 后,注入代码并注释后面的 } ,即可达到代码执行的效果。最终使用如下 payload8 即可解题:

1
http://51.158.75.42:8087/?action=\create_function&arg=return 111;}print_r(scandir('../'));highlight_file('../flag_h0w2execute_arb1trary_c0de');{

7

如果是第一个参数用户可控,那么记得闭合 ( 号即可。