1.数字型注入
例如PHP代码
“ Select username from users where id''$_GET[id]
可以注意到,用户的输入ID字段没有任何过滤的,被直接拼接在了SQL查询语句中,由于ID没有被引号包裹,而且类型为数字,我们称这种注入为数字型注入
我们可以使用在语句中加入运算符的方法来测试这种注入是否存在,比如测试id=1和id=2-1,如果两者都查询到了且结果相同,说明PHP文件将2-1作为一个表达式执行,如果这种情况,说明有可能是一个数字型SQL注入,此时只能得到用户名,想要更多的信息,需要使用一个SQL关键字union
2.Union注入
Union可以将两个select语句的结果合并到一个结果集中,但是要求两个select语句拥有相同的列数
例如输入id=0 union select password from users,(空格的URL编码为%20)
表示从users表中读password列(在打出这个例子是已知有users表和password列)
在这里写ID=0列,是因为要使第一个select结果为空,让第二个select语句查询的password显示出来,还可以用limit关键字查询其他行
3.字符型注入
“ Select id from users where username=' ”.$_GET['username'].” ' ''
用户输入username被单引号包裹了起来,这样一来用户的所有输入都会被当做字符串处理,无法使用之前数字型注入的payload进行注入了。但是如果我们的输入中也存在一个引号,这样就可以将前面的引号闭合,使得后面的内容从字符串中逃逸出来,最后还需要将后面的引号注释掉,以免引发语法错误
比如我们可以使用一个单引号,将字符串闭合,最后用井号将后面的单引号注释掉
例如username='or1=1#(单引号,空格,井号都需要URL编码)
在where语句中,or连接两个表达式,第一个返回假,第二个返回真,or操作后返回真,整个操作返回所有的结果集
4.布尔盲注
当服务器不显示查询结果,只返回是否查询成功时,我们就无法使用union直接回显数据,这时就需要进行盲注,这里先操作布尔盲注
既然只返回两种状态,存在或不存在,就可以通过这两种状态注入出数据
Username='or substr (password ,1,1)='1'#
Substr是一个字符串截取函数,第一个参数是要截取的字符串,第二个是截取开始的位置,第三个是截取长度,例如上面语句的意思是从第一个字符开始截取password字段的一个字符,并判断等不等于1,这个数字自己一个一个尝试太麻烦,可通过爆破来进行,直到达到某一位,我们无法遍历出其真正的值时,就意味着我们可能已经猜测完成,也可以提前使用length函数猜测一下这个字符串的长度
5.时间盲注
有回显时用Union带出数据,只显示是否时可用布尔盲注得出数据,那如果没有任何输出时?
比如无论查询什么,都显示success,同一个回应,无法直接从服务器注入出任何数据,但是我们可以利用MySQL内置的延时函数sleep,人为的制造出差异
为了测试sql执行的延时,需要使用BP这款软件,输入username='or sleep(1)#
(注:or前面的为false时才会执行后面的)
运用到注入时可以使用if函数来进行条件判断,当if第一个参数为真时进行延时,输入username='or if(1=1,sleep(1),1)#
第一个条件为真时,延时
(注:if里含3个函数,第一个参数为真时,返回第二个参数,为假时,返回第三个参数)
例:username='or if(substr(password,1,1),sleep(1),1)#
sleep为一种延时函数,有5种函数
五种:sleep(),benchmark(t,exp),笛卡尔积,GET_LOCK() RLIKE正则
以下是对这几个 MySQL 特性的详解:
[111]、SLEEP()函数
1. 作用:
- 使 MySQL 服务器暂停执行指定的时间(以秒为单位)。
2. 语法:
- SLEEP(duration) ,其中 duration 是要暂停的时间长度,为整数。
3. 示例:
- SELECT SLEEP(5); :这条 SQL 语句会使数据库暂停执行 5 秒钟后再返回结果。
[222]、BENCHMARK()函数
1. 作用:
- 重复执行表达式一定次数,可用于测试性能,但不是真正意义上的延时函数。它可以用来衡量特定表达式的执行时间,但会消耗大量的系统资源。
2. 语法:
- BENCHMARK(count, expression) ,其中 count 是重复执行的次数, expression 是要执行的表达式。
3. 示例:
- SELECT BENCHMARK(1000000,NOW()); :这里会执行 NOW() 函数 1000000 次。可以通过比较执行前后的时间来了解函数的性能消耗。
[333]、笛卡尔积
1. 作用:
- 笛卡尔积是两个或多个表之间的一种组合结果集的方式,它会将一个表中的每一行与另一个表中的每一行进行组合,生成所有可能的组合结果。
2. 语法:
- 当使用多个表进行查询而没有指定连接条件时,就会产生笛卡尔积。例如, SELECT * FROM table1, table2; 。
3. 示例:
- 假设有两个表 table1 和 table2 ,分别有 3 行和 4 行数据。如果进行笛卡尔积操作,结果集将有 3 * 4 = 12 行数据。
- 笛卡尔积通常不是期望的结果,在实际查询中应该使用适当的连接条件来避免产生不必要的笛卡尔积,以提高查询性能和结果的准确性。
[444]、GET_LOCK()函数
1. 作用:
- 用于获取一个命名的锁,以实现同步机制,防止多个并发连接同时执行特定的代码块。
2. 语法:
- GET_LOCK(str,timeout) ,其中 str 是锁的名称, timeout 是等待获取锁的超时时间(以秒为单位)。如果在超时时间内无法获取锁,函数将返回 0;如果成功获取锁,返回 1。
3. 示例:
- SELECT GET_LOCK('my_lock',10); :尝试获取名为 my_lock 的锁,等待时间为 10 秒。如果成功获取锁,可以在后续的代码中执行需要同步的操作,完成后使用 RELEASE_LOCK() 函数释放锁。
[555]、RLIKE 正则表达式匹配
1. 作用:
- RLIKE (或 REGEXP )用于在 MySQL 中进行正则表达式匹配,以判断一个字符串是否与指定的正则表达式模式相匹配。
2. 语法:
- column_name RLIKE regex_pattern ,其中 column_name 是要进行匹配的列名, regex_pattern 是正则表达式模式。
3. 示例:
- SELECT * FROM my_table WHERE column_name RLIKE '^[a-z]+$'; :这条 SQL 语句将从 my_table 表中选择所有 column_name 列的值为纯小写字母组成的字符串的行。
- 正则表达式可以用于各种复杂的字符串匹配场景,例如匹配特定格式的电话号码、邮箱地址等。但在使用正则表达式时,需要注意性能问题,特别是对于大型数据集,复杂的正则表达式可能会导致查询性能下降。
6.报错注入
在某些情况下,服务器会返回SQL执行错误信息,我们可以利用这个错误信息进行有回显的注入,比如服务器不会返回查询结果,但如果发生SQL执行错误,会将错误输出
有很多可以使MySQL报错的函数
以ExtractValue举例
ExtractValue是一个使用xpath从xml中提取元素的函数,原型为ExtractValue(xml_data, xpath_expression)。其中,xml_data 是包含 XML 内容的列或表达式,xpath_expression 是用于指定要提取节点的 XPath 表达式。
例如,如果有一个存储 XML 数据的列 xml_col,要提取其中某个特定节点的值,可以使用如下语句:SELECT ExtractValue(xml_col, '/root/node_name');
正常的用法
select extractvalue('〈a〉〈b〉text〈/b〉〈/a〉','/a/b')
如果xpath参数有语法错误,整个参数就会被回显在错误信息中
select extractvalue('〈a〉〈b〉bbbb〈/b〉〈/a〉','~text')
我们可以利用一特性,将需要回显的信息插入到xpath参数中,在最前面插入一个'~',波浪号,使其发生语法错误,可以实现Union直接回显一样的效果,
12种报错函数
1. extractvalue() :可用于从 XML 文档中提取特定节点的值。通过构造恶意输入,可以使其产生错误信息并返回部分数据库内容。
- 示例: SELECT extractvalue(NULL,concat(0x3a,(SELECT database())));
2. updatexml() :用于更新 XML 文档中的特定节点。同样可以被利用进行报错注入。
- 示例: SELECT updatexml(NULL,concat(0x3a,(SELECT user())),NULL);
3. floor() :与随机数生成函数结合,可通过产生错误来暴露信息。
- 例如: SELECT FLOOR(RAND(0)*2)+(SELECT IF((SELECT COUNT(*) FROM information_schema.tables)>0,1,0));
4. exp() :指数函数,可用于报错注入场景。
- 示例: SELECT exp((SELECT (CASE WHEN (SELECT COUNT(*) FROM information_schema.tables)>0 THEN 1 ELSE 0 END)));
5. geometrycollection() :在特定情况下可被利用进行报错注入。
- 例如: SELECT ST_GeometryFromText('GEOMETRYCOLLECTION('||(SELECT (CASE WHEN (1=1) THEN 'POINT(1 1)' ELSE NULL END))||')');
6. polygon() :与几何相关的函数,可用于报错注入。
- 示例: SELECT ST_PolygonFromText('POLYGON((0 0,0 1,1 1,1 0,0 0),(0.5 0.5,0.5 0.6,0.6 0.6,0.6 0.5,0.5 0.5))')||(SELECT (CASE WHEN (1=1) THEN 'POINT(1 1)' ELSE NULL END));
7. multipoint() :多点几何函数,可能被用于报错注入。
- 例如: SELECT ST_MultiPointFromText('MULTIPOINT((0 0),(1 1))')||(SELECT (CASE WHEN (1=1) THEN 'POINT(1 1)' ELSE NULL END));
8. linestring() :线串几何函数,可用于报错注入。
- 示例: SELECT ST_LineFromText('LINESTRING(0 0,1 1)')||(SELECT (CASE WHEN (1=1) THEN 'POINT(1 1)' ELSE NULL END));
9. name_const() :可用于构造报错注入语句。
- 例如: SELECT * FROM users WHERE id=(SELECT name_const((SELECT user()),1)) OR 1=1;
10. cast() :类型转换函数,可在报错注入中发挥作用。
- 示例: SELECT CAST((SELECT user()) AS SIGNED);
11. concat() :字符串连接函数,常用于构造报错注入的输入。
- 例如: SELECT CONCAT('Error: ', (SELECT database()));
12. substring() :子字符串提取函数,可用于报错注入以获取特定部分的信息。
- 示例: SELECT SUBSTRING((SELECT user()),1,5);
7.堆叠注入
1、查看数据库
';show databases;
1
2、查看表格
';show tables;
1
3、查看列
';show columns from `a`;
1
4、查看数据
';select flag from `a`;
注入点
根据用户插入数据的位置不同,可以有不同的SQL注入点,比较常见的有where,比如查询判断用户名之类的,还有一种是order by,会让用户选择以哪一列目标进行排序,在order by和where后会有一点区别,Union只能用在HAVING和order by之间,limit也是一样的作用
INSERT注入(insert)
UPDATE注入(update)
DELETE注入(delete)
一、ORDER BY 子句
如果应用程序允许用户指定排序字段,例如 SELECT * FROM table ORDER BY column_name ,攻击者可以通过修改 column_name 的值来进行 SQL 注入。例如,输入 column_name;(SELECT * FROM sensitive_table)-- ,可能会导致数据库执行恶意查询并返回敏感信息。
二、LIMIT 子句
在分页查询中,LIMIT 子句用于限制返回的记录数。如果应用程序允许用户指定 LIMIT 的参数,攻击者可以通过修改这些参数来进行 SQL 注入。例如, SELECT * FROM table LIMIT offset, count ,攻击者可以将 offset 或 count 的值修改为恶意的 SQL 表达式,如 offset;(SELECT * FROM sensitive_table)-- 。
三、INSERT 语句
如果应用程序允许用户输入数据并将其插入到数据库中,例如 INSERT INTO table (column1, column2) VALUES (value1, value2) ,攻击者可以通过修改 value1 和 value2 的值来进行 SQL 注入。例如,输入 value1'; DROP TABLE other_table;-- 可能会删除其他表。
四、UPDATE 语句
当应用程序允许用户更新数据库中的数据时,例如 UPDATE table SET column1 = value1 WHERE condition ,攻击者可以通过修改 value1 的值或者 condition 的值来进行 SQL 注入。例如,将 value1 设置为 '; DROP TABLE another_table;-- 可能会删除另一个表。