PHP代码注入
PHP代码注入是指应用程序过滤不严,用户可以通过请求将代码注入到应用中执行.代码注入类似于SQL注入漏洞,SQLi是将SQL语句注入到数据库中执行,而代码执行则是可以把代码注入到应用中最终由服务器运行它.这样的漏洞如果没有特殊的过滤,相当于直接有一个Web后门的存在
- 程序中含有可以执行PHP代码的函数或者语言结构
- 传入第一点中的参数,客户端可控,直接修改或者影响.
漏洞危害
Web应用如果存在代码执行漏洞是一件非常可怕的事情,可以通过代码执行漏洞继承Web用户权限,执行任意代码.如果具有服务器没有正确配置,Web用户权限比较高的话,我们可以读写目标服务器任意文件内容,甚至控制整个网站以及服务器.PHP中有很多函数和语句都会造成PHP代码执行漏洞
相关函数和语句
eval()
- eval()会将字符串当作PHP代码执行
<?php
if(isset($_GET['code'])){
$code=$_GET['code'];
eval($code);
}else{
echo "Please submit code!<br />?code=phpinfo();";
}
?>
assert()
- assert()会将字符串当作PHP代码执行
<?php
if(isset($_GET['code'])){
$code=$_GET['code'];
assert($code);
}else{
echo "Please submit code!<br />?code=phpinfo()";
}
?>
- 在php7中运行没有回显,已经与php5有所差异
preg_replace()
- preg_replace()作用是对字符串进行正则处理
- preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) : mixed
- 这段代码的含义是搜索
$subject
中匹配$pattern
的部分,以$replacement
进行替换,而当$pattern
处,即第一个参数存在e
修饰符时,$replacement
的值会被当成PHP代码来执行.典型的代码如下
<?php
if(isset($_GET['code'])){
$code=$_GET['code'];
preg_replace("/\[(.*)\]/e",'\\1', $code);
}else{
echo"?code=[phpinfo()]";
}
?>
- 更高版本的php已经不支持
\e
修饰符
call_user_func()
- call_user_func()等函数都有调用其他函数的功能,其中的一个参数作为要调用的函数名,那如果这个传入的函数名可控,那就可以调用意外的函数来执行我们想要的代码,也就是存在任意代码执行漏洞
<?php
if(isset($_GET['fun'])){
$fun=$_GET['fun'];
$para=$_GET['para'];
call_user_func($fun,$para);
}else{
echo"?fun=assert&para=phpinfo()";
}
?>
- 该函数不会被允许执行eval(),所以使用低版本的php进行测试
动态函数
由于PHP的特性原因,PHP的函数支持直接由拼接的方式调用
<?php
if(isset($_GET['a'])){
$a=$_GET['a'];
$b=$_GET['b'];
$a($b);
}else{
echo "
?a=assert&b=phpinfo()
";
}
?>
- 在php7中使用eval会直接返回500
命令注入
使用脚本语言(比如PHP)开发应用程序过程中,脚本语言开发十分快速,简介,方便,但是也伴随着一些问题.比如说速度慢,或者无法接触系统底层,如果我们开发的应用,特别是企业级的一些应用需要去调用一些外部程序(系统命令或者exe等可执行文件).当应用需要调用一些外部程序时就会用到一些系统命令的函数.应用在调用这些函数执行系统命令的时候,如果将用户的输入作为系统命令的参数拼接到命令行中,在没有过滤用户的输入的情况下,就会造成命令执行漏洞
漏洞危害
- 继承Web服务器程序权限(Web用户权限),去执行系统命令
- 继承Web服务器权限,读写文件
- 反弹Shell
- 控制整个网站
- 控制整个服务器
相关函数和语句
system()
- system()能够将字符串作为OS命令执行,自带输出功能
<meta charset='gb2312'>
<?php
if(isset($_GET['cmd'])){
echo "<pre>";
system($_GET['cmd']);
}else{
echo"
?cmd=whoami
";
}
?>
exec()
- exec()函数能将字符串作为OS命令执行,需要输出执行结果
<meta charset="gb2312">
<?php
if(isset($_GET['cmd'])){
echo "<pre>";
print exec($_GET['cmd']);
}else{
echo"
?cmd=whoami
";
}
?>
shell_exec()
<?php
if(isset($_GET['cmd'])){
print shell_exec($_GET['cmd']);
}else{
echo"?cmd=whoami";
}
?>
passthru()
<?php
if(isset($_GET['cmd'])){
passthru($_GET['cmd']);
}else{
echo"?cmd=whoami";
}
?>
popen()
- popen()也能够执行OS命令,但是该函数并回是返回命令结果,而是返回一个文件指针.无论返回什么,我们关心的是命令执行了
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'].">> 1.txt";
popen($cmd,'r');
}else{
echo"?cmd=whoami";
}
?>
反引号
- 反引号内的字符串,也会被解析成OS命令
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
print `$cmd`;
}else{
echo"?cmd=whoami";
}
?>
漏洞利用
不论是哪种形式的注入漏洞,攻击者直接继承Web用户权限,在服务器上执行任意命令,危害特别大
- 防御方法
- 尽量不要使用eval等函数
- 如果使用的话一定要进行严格的过滤
preg_replace
放弃使用\e
修饰符disable_functions = assert
- 尽量减少命令执行函数的使用,并在
disable_functions
中禁用 - 在进入命令执行的函数或方法之前,对参数进行过滤
- 参数的值尽量使用引号包裹,并在拼接前调用
addslashes
进行转义
直接获取Shell
eval.php?code=system('whoami');
即可构成一句话木马
获取当前文件的绝对路径
__FILE__
是PHP预定义常量,其含义当前文件的路径.提交代码eval.php?code=echo __FILE__;
读写文件
我们可以利用
file_get_contents()
和file_put_contents()
函数读写服务器任意文件,前提是知道目标文件路径和读取权限
最后一次更新于2020-12-21 15:10
0 条评论