前言:PHP中有很多危险函数,如phpinfo() ,这次就来详细总结一下PHP中的危险函数,并借助大师傅们的例子来进行代码审计的练习。
一、PHP代码执行函数
eval()函数
定义和用法:
eval() 函数把字符串按照 PHP 代码来计算.
该字符串必须是合法的 PHP 代码,且必须以分号结尾。
这个用法就会产生漏洞,通过一个例子来看一下:
<?php
$var = "var";
if (isset($_GET["arg"]))
{
$arg = $_GET["arg"];
eval("\$var = $arg;");
echo "\$var =".$var;
}
?>
输入:http://127.0.0.1/1.php?arg=phpinfo()
就会发现已经执行了eval函数
再输入一串字符串,让eval()函数作为命令执行
http://127.0.0.1/1.php?arg=var_dump(scandir('./'))
#scandir()函数列出./(当前)目录中的文件和目录:
除此之外,还可以结合system()
函数来获取当前运行的服务的信息
http://127.0.0.1/1.php?a=system("net start");
这就是为什么这个函数是危险函数的原因了,将只要是合法并且符号PHP语法的字符串都可以进行解析,当然这里举的例子都是没有任何防护的,一般eval
函数都是被加了黑名单的,但是如果存在这样的漏洞,真的会造成很严重的后果。
assert()函数
定义和用法:
assert ( mixed $assertion [, Throwable $exception ] ) : bool
assert() 会检查指定的 assertion 并在结果为 FALSE 时采取适当的行动。
判断一个表达式是否成立。返回true or false。
如果 assertion 是字符串,它将会被 assert() 当做 PHP 代码来执行。
一般情况下,黑名单都会禁用eval()
函数,所以用assert来代替eval来执行具体操作。
例如:
assert("phpinfo()") <=> <?phpinfo()?>
与eval函数的区别:
assert()把整个字符串参数当php代码执行,eval()把合法的php代码执行。
preg_replace()函数
定义和用法:
preg_replace 函数执行一个正则表达式的搜索和替换。
preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int KaTeX parse error: Expected 'EOF', got '&' at position 19: …it = -1 [, int &̲count ]] ) : mixed
正常来说preg_replace
()函数是用于正则表达式的,但preg_replace
函数也可能会导致命令执行。
如果subject
中有 pattern
的匹配则preg_replace
的 /e
修正符会将 replacement
参数当作 php 代码,并且以 eval 函数的方式执行。
通过一个简单的例子来看一下该函数的用法:
输入payload:
?pat=/test/e&rep=phpinfo()&sub=jutst test
也可以为
?pat=/test/e&rep=var_dump(`net user`)&sub=jutst test
create_function()函数
定义和用法:
string create_function ( string $args , string $code )
函数作用:从创建一个匿名函数传递的参数,并返回一个唯一的名称
下面通过一个例子来了解一下这个函数
<?php
error_reporting(0);
$sort_by = $_GET['sort_by'];
$sorter = 'strnatcasecmp';
$databases=array('1234','4321');
$sort_function = ' return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);';
usort($databases, create_function('$a, $b', $sort_function));
?>
#usort() 使用用户自定义的比较函数对数组进行排序
首先构造出匿名函数的原型:
function test($a,$b)
{
return 1 * ' . $sorter . '($a["' . $sort_by . '"], $b["' . $sort_by . '"]);
}
构造payload:
http://localhost/test/1.php?sort_by='"]);}phpinfo();/*
传入后便可以得到:
return 1 * strnatcasecmp($a[""]);}phpinfo();/*"], $b[""]);}phpinfo();/*"]);
可以看到构造的语句中注释符/*
将后面"], $b[""]);}phpinfo();/*"]);
这一段给注释掉了
此时匿名函数就变成了
function test($a,$b)
{
return 1 * strnatcasecmp($a[""]);
}
phpinfo();
因此可以注入成功
call_user_func函数
定义和用法:
mixed call_user_func ( callable $callback [, mixed $parameter [, mixed $… ]] )
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。
通过一个例子来了解一下这个函数:
<?php
$filter= 'assert';
$value = 'phpinfo()';
call_user_func($filter, $value);
?>
这里$filter
作为回调函数进行调用,phpinfo()
则是是回调函数的参数,所以可以执行命令
二、命令执行函数
exec()函数
定义和用法:
exec — 执行一个外部程序
shell_exec()函数
定义和用法:
通过 Shell 执行命令,并将执行结果作为字符串返回。
passthru()函数
定义和用法:
允许执行一个外部程序并回显输出,类似于 exec()。
escapeshellcmd()函数
定义和用法:
escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。
escapeshellcmd ( string $command ) : string
在DVWA中练习命令注入就会了解以上函数,这里就不再举例。
DVWA_命令注入
三、包含函数
require()
include()
require_once()
include_once()
这些包含函数在之前的博客中也有过介绍,这里就不阐述了
DVWA——文件包含
四、文件操作函数
copy()------------------------拷贝文件
file_get_contents()---------将整个文件读入一个字符串
file_put_contents()---------将一个字符串写入文件
file()----------------------------把整个文件读入一个数组中
fopen()------------------------打开文件或者url
move_uploaded_file()----将上传的文件移动到新位置
readfile()----------------------输出文件
rename()---------------------重命名一个文件或目录
rmdir()------------------------删除目录
unlink & delete()-----------删除文件
读取:可以读取配置等文件
写入:可以写入shell代码相关的内容
总结:这次了解了PHP常用的一些危险函数,下次就通过做题将这些函数用于实践。
参考博客:
常见危险函数及特殊函数
PHP代码命令注入小结