Code-Breaking Puzzles挑战
序
来自P师傅小密圈二周年的Code-Breaking Puzzles挑战的题目
easy - function
题目代码如下:
|
|
题目环境为PHP/7.2.12加上Apache/2.4.25 (Debian)
首先通过$action('', $arg);
可以想到PHP的动态代码执行,通过这里面的参数可以看出这里应该使用create_function
这个函数去进行代码执行,关于这个函数的执行流程如下:
1.获取参数, 函数体;
2.拼凑一个”function __lambda_func (参数) { 函数体;} “的字符串;
3.eval;
4.通过__lambda_func在函数表中找到eval后得到的函数体, 找不到就出错;
5.定义一个函数名:”\000_lambda_” . count(anonymous_functions)++;
6.用新的函数名替换__lambda_func;
7.返回新的函数。
以上流程可以简单理解为在使用该函数时会生成一个匿名函数,该函数的第一个参数会作为匿名函数的参数传入,该函数的第二个参数为匿名函数要执行的代码段,看下面的代码实例:
|
|
这段代码的执行过程等价于
|
|
于是有了一个思路,这里可以传入action=create_function&arg=}phpinfo();/*
去执行phpinfo,这样构造的原因是因为这里通过create_function
生成的匿名函数并没有赋值给任何变量,所以无法调用该匿名函数,但是由于此处的环境是php的eval
环境,所以可以通过}
去闭合该匿名函数,之后就执行任意代码了,而这里的/*
用来注释后面多出的代码,这里执行的代码如下
|
|
实际执行过程变为了如下代码
于是便可以成功执行phpinfo,但是这道题里只是这样构造是不可以的,这里还需要绕过对传入的$action
的正则检查,通过正则可以看出$action
的内容不能只包含数字字母和_
,在这里面卡了好久,于是看了P牛师傅的讲解,这里可以通过在函数名前加上\
去绕过,构造action=\create_function&arg=}phpinfo();/*
就可以成功执行phpinfo
至于函数前面为什么可以加\
,P牛师傅也给出了详细的解释,这里用到了php当中的命名空间,在php当中有一个默认的命名空间为\
,PHP当中的所有原生函数和类都在这个命名空间下,平常我们在使用函数的时候直接写函数名去调用函数实际上用的是相对路径,而在函数名前面加上\
用的是绝对路径去调用函数
接下来尝试使用命令执行函数执行命令,但是发现命令执行函数都被禁用掉了
只能通过执行代码的方式寻找flag文件了
寻找flag文件的位置
action=\create_function&arg=}print_r(scandir("/var/www/"));/*
找到flag文件的位置在/var/www
目录下
读取flag
action=\create_function&arg=}echo file_get_contents("/var/www/flag_h0w2execute_arb1trary_c0de");/*