PHP代码注入

PHP代码注入是指应用程序过滤不严,用户可以通过请求将代码注入到应用中执行.代码注入类似于SQL注入漏洞,SQLi是将SQL语句注入到数据库中执行,而代码执行则是可以把代码注入到应用中最终由服务器运行它.这样的漏洞如果没有特殊的过滤,相当于直接有一个Web后门的存在

  1. 程序中含有可以执行PHP代码的函数或者语言结构
  2. 传入第一点中的参数,客户端可控,直接修改或者影响.

漏洞危害

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();";
}
?>

QQ截图20201221132123.png

assert()

  • assert()会将字符串当作PHP代码执行
<?php
if(isset($_GET['code'])){
    $code=$_GET['code'];
    assert($code);
}else{
    echo "Please submit code!<br />?code=phpinfo()";
}
?>
  • 在php7中运行没有回显,已经与php5有所差异

QQ截图20201221133707.png

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修饰符

QQ截图20201221134557.png

QQ截图20201221134307.png

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&amp;para=phpinfo()";
}
?>
  • 该函数不会被允许执行eval(),所以使用低版本的php进行测试

QQ截图20201221134856.png

动态函数

由于PHP的特性原因,PHP的函数支持直接由拼接的方式调用

<?php
if(isset($_GET['a'])){
    $a=$_GET['a'];
    $b=$_GET['b'];
    $a($b);
}else{
    echo "
    ?a=assert&amp;b=phpinfo()
    ";
}
?>
  • 在php7中使用eval会直接返回500

QQ截图20201221135501.png

命令注入

使用脚本语言(比如PHP)开发应用程序过程中,脚本语言开发十分快速,简介,方便,但是也伴随着一些问题.比如说速度慢,或者无法接触系统底层,如果我们开发的应用,特别是企业级的一些应用需要去调用一些外部程序(系统命令或者exe等可执行文件).当应用需要调用一些外部程序时就会用到一些系统命令的函数.应用在调用这些函数执行系统命令的时候,如果将用户的输入作为系统命令的参数拼接到命令行中,在没有过滤用户的输入的情况下,就会造成命令执行漏洞

漏洞危害

  1. 继承Web服务器程序权限(Web用户权限),去执行系统命令
  2. 继承Web服务器权限,读写文件
  3. 反弹Shell
  4. 控制整个网站
  5. 控制整个服务器

相关函数和语句

system()

  • system()能够将字符串作为OS命令执行,自带输出功能
<meta charset='gb2312'>
<?php
if(isset($_GET['cmd'])){
    echo "<pre>";
    system($_GET['cmd']);
}else{
    echo"
    ?cmd=whoami
    ";
}
?>

QQ截图20201221143529.png

exec()

  • exec()函数能将字符串作为OS命令执行,需要输出执行结果
<meta charset="gb2312">
<?php
if(isset($_GET['cmd'])){
    echo "<pre>";
    print exec($_GET['cmd']);
}else{
    echo"
    ?cmd=whoami
    ";
}
?>

QQ截图20201221150552.png

shell_exec()

<?php
if(isset($_GET['cmd'])){
    print shell_exec($_GET['cmd']);
}else{
    echo"?cmd=whoami";
}
?>

QQ截图20201221150600.png

passthru()

<?php
if(isset($_GET['cmd'])){
    passthru($_GET['cmd']);
}else{
    echo"?cmd=whoami";
}
?>

QQ截图20201221150611.png

popen()

  • popen()也能够执行OS命令,但是该函数并回是返回命令结果,而是返回一个文件指针.无论返回什么,我们关心的是命令执行了
<?php
if(isset($_GET['cmd'])){
    $cmd=$_GET['cmd'].">> 1.txt";
    popen($cmd,'r');
}else{
    echo"?cmd=whoami";
}
?>

QQ截图20201221150637.png

反引号

  • 反引号内的字符串,也会被解析成OS命令
<?php
if(isset($_GET['cmd'])){
    $cmd=$_GET['cmd'];
    print `$cmd`;
}else{
    echo"?cmd=whoami";
}
?>

QQ截图20201221150650.png

漏洞利用

不论是哪种形式的注入漏洞,攻击者直接继承Web用户权限,在服务器上执行任意命令,危害特别大

  • 防御方法
  1. 尽量不要使用eval等函数
  2. 如果使用的话一定要进行严格的过滤
  3. preg_replace放弃使用\e修饰符
  4. disable_functions = assert
  5. 尽量减少命令执行函数的使用,并在disable_functions中禁用
  6. 在进入命令执行的函数或方法之前,对参数进行过滤
  7. 参数的值尽量使用引号包裹,并在拼接前调用addslashes进行转义

直接获取Shell

  • eval.php?code=system('whoami');即可构成一句话木马

QQ截图20201221140233.png

获取当前文件的绝对路径

__FILE__是PHP预定义常量,其含义当前文件的路径.提交代码eval.php?code=echo __FILE__;

QQ截图20201221140511.png

读写文件

我们可以利用file_get_contents()file_put_contents()函数读写服务器任意文件,前提是知道目标文件路径和读取权限

QQ截图20201221140941.png

QQ截图20201221141221.png