进入就是一个登陆界面,随便输入一个账号密码抓包看看
发现有数据库语句,便试试万能密码
1'or'1'='1'#
发现被过滤了,一般这种题有个register.php和一个地方可以读取到源码的,我们要寻找试试
发现有注册界面,注册登陆一下
发现进入一个user.php页面,翻一下没有跟我们输入有关的回显,我们关注到有个page参数,不知道可不可以帮助我们读取到源码,直接伪协议试试
?page=php://filter/read=convert.base64-encode/resource=user.php
发现返回的是200,但是没有内容,说明读取的文件格式或许有问题,我们试试把后缀删了瞅瞅
读取到源码,全部下载下来
没有upload.php,这个源码是后面要用的,这里不清楚(懒得删了)
在user.php的源码界面找到我们能够读取源码的地方
果然是自己拼接了.php后缀,不过关注点不在这里
将源码看了一遍后大概理清楚
function Filter($string)
{
global $mysqli;
$blacklist = "information|benchmark|order|limit|join|file|into|execute|column|extractvalue|floor|update|insert|delete|username|password";
$whitelist = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'(),_*`-@=+><";
for ($i = 0; $i < strlen($string); $i++) {
if (strpos("$whitelist", $string[$i]) === false) {//$string字符传必须是可见字符 strpos函数查找$string字符串在白名单中的位置
Hacker();
}
}
if (preg_match("/$blacklist/is", $string)) {//通过白名单后,也要通过黑名单
Hacker();
}
if (is_string($string)) {//字符串
return $mysqli->real_escape_string($string);//防止SQL攻击,进行转义
} else {
return "";
}
}
一个非常强大的过滤,在登陆和注册界面都调用了,因此暂时不用考虑sql注入了,可疑点
function filter_directory()//过滤
{
$keywords = ["flag","manage","ffffllllaaaaggg"];
$uri = parse_url($_SERVER["REQUEST_URI"]);//解析url并解析组成部分
parse_str($uri['query'], $query);//将查询字符串解析到变量中,query是数组名 $uri['query']代表的是传入参数
// var_dump($query);
// die();
foreach($keywords as $token)
{
foreach($query as $k => $v)
{
if (stristr($k, $token))//查找$k是否在$token出现
hacker();
if (stristr($v, $token))
hacker();
}
}
}
parse_url函数
对url进行解析,并且利用parse_str函数将传入的键值对当作关联数组传入$query数组,进行过滤没有$kewords才不会出来hacker();突破点就在这了,flag我还可以理解,但是后面两个我们看源码的时候怎么会用到,估计就是提示我们了,利用之前的include拼接读取源码,但是这里有个过滤需要绕过;幸运的是查询parse_url函数作用的时候跳出来了一个漏洞详情,我们便去看看
parse_url函数的解释和绕过_q1352483315的博客-CSDN博客_urlparse函数
可以猜想parse_url函数是利用一些特殊符号来分割不同属性的,如: / ?等
如果我们在path那里构造成两个//,第一个被解析为根目录,第二个/user就会报错flase了,与分割url方法不符,因此可以构造成
//user.php?page=php://filter/convert.base64-encode/resource=ffffllllaaaaggg
可以让parse_url函数报错(低版本的了)
继续读取
发现包含了一个什么文件,我们直接进入url瞅瞅,发现是一个上传文件
利用之前的读取源码瞅瞅
<?php
$allowtype = array("gif","png","jpg");
$size = 10000000;
$path = "./upload_b3bb2cfed6371dfeb2db1dbcceb124d3/";
$filename = $_FILES['file']['name'];
if(is_uploaded_file($_FILES['file']['tmp_name'])){
if(!move_uploaded_file($_FILES['file']['tmp_name'],$path.$filename)){
die("error:can not move");
}
}else{
die("error:not an upload fileï¼");
}
$newfile = $path.$filename;
echo "file upload success<br />";
echo $filename;
$picdata = system("cat ./upload_b3bb2cfed6371dfeb2db1dbcceb124d3/".$filename." | base64 -w 0");
echo "<img src='data:image/png;base64,".$picdata."'></img>";
if($_FILES['file']['error']>0){
unlink($newfile);
die("Upload file error: ");
}
$ext = array_pop(explode(".",$_FILES['file']['name']));
if(!in_array($ext,$allowtype)){
unlink($newfile);
}
?>
发现跟我们平常不一样的是:不是讲图片内容保存在哪个目录下面去,而是利用system命令进行cat打开我们传入的$filename文件名并且base64文件内容,然后输出一个字符串,后面过滤了必须要gif,png,jpg为后缀,我们抓包修改就行了,随便传一个图片看看效果
明显输出,我们可以看到linux命令的操作通道符
我们利用分号来进行闭合前面命令,在输入我们需要的命令,然后注释后面的
进行ls /查看上级目录
发现没用,可能是空格或者斜杠被过滤了,利用/**/代替空格还是如此,看来是斜杠被过滤了
如何返回上一级,因为有;的存在,我们可以先执行cd ..,再来ls,达到返回上一级的效果
接着cat flag文件即可