一、前言
记录自己在阅读《SQL注入与防御》中学习到的一些SQL注入小姿势
二、检索嵌入在数据库返回错误中的信息
1.将字符串转为整数来产生错误
例:发送0/@@version作为部分注入代码(SQL Server),数据库将会尝试将@@version的结果转换为一个数字,当该操作失败时,数据库会显示出变量的内容。
可尝试使用该技术显示数据库任何变量
2.HAVING 和 GROUP BY 语句结合
GROUP BY 语句要求select 语句选择的字段是某个聚合函数的结果或包含在GROUP BY子句中。如果该条件不满足,那么数据库将返回一个错误,显示出现该问题的第一列,
我们可以尝试使用该技术枚举select 语句中的所有列
例:?id=2' group by productid having 1'='1
三、应用响应
应用在收到数据库错误时会做出不同的响应,所以有时候SQL注入的识别是比较困难的。
记住!操纵参数产生的错误可能与SQL注入无关(比如查询语法错误)
返回错误一般有:
1.通用错误 :可以通过向参数中插入不会触发应用错误的SQL代码来测试
比如注入永真语句或永假语句
2.HTTP代码·错误
列出常见的HTTP返回代码
HTTP 200 :OK
HTTP 302::重定位
HTTP 500:服务器内部错误
收到302或500会是个好现象,意味着我们已经以某种方式干预了应用的正常行为
3.不同响应大小
通常出现在 不显示任何结果,或 差异不明显、不容易引起注意的脚本
四、数据库注释语法
SQL server 和 Oracle
--:单行注释
/**/:多行注释
MYSQL:
--:单行注释
#:单行注释
/**/:多行注释
对于应用对空格的过滤,可以添加不带内容的多行注释来避免使用空格
也可以使用SQL注释来确认是否存在漏洞,比如?id=45/*hello world*/,如果得到与id=45相同的结果,那么说明可能存在SQL注入漏洞
使用SQL注释进行SQL语句的终止
对于简单的登陆表单(一个用户名,一个密码,一个提交)在这里我们仅讨论最简单的情况
假设这里的sql查询语句是
select *
from adminstrators
where username = ' ' and password = ' ';
1.单行注释终止
向username字段注入代码并终结语句
:1' or 1=1;-- (如此一来密码为空也可登录,因为密码的查询语句已被注释掉)
可以将后面的查询内容注释掉,如果能成功执行将返回所有用户的相关信息
也可以使用admin';--来冒充已知用户admin
还可以使用如
1' or 1=1 or '1'='1 语句来进行注入,会形成如同
username='1' or 1=1 or '1'='1' and password=''
的语句,由于and的优先级比or高,因此需要两个or语句,使得永真条件成立
也可以在password语句中进行注入
如password='' or '1'='1' ;
这里提供一些测试字符串(字符型注入),数字型的测试字符串举一反三即可
测试字符串 | 变种 | 预期结果 |
' | 触发错误,如果成功,数据库将返回一个错误 | |
1' or '1'='1 | 1') or ('1'='1 | 永真条件。如果成功,将返回表中所有的行 |
value' or '1'='2 | value') or ("1'='2 | 空条件。如果成功,则返回与原来的值相同的结果 |
1' and '1'='1 | 1') and ('1'='1 | 永假条件,如果成功,则不返回表中任何行 |
1' or 'ab'='a'+'b | 1') or ('ab'='a'+'b | SQL Server串联,如果成功,则返回与永真条件相同的信息 |
1' or 'ab'='a''b | 1') or ('ab'='a''b | MYSQL串联,如果成功,则返回与永真条件相同的信息 |
1' or 'ab'='a'||'b | 1') or ('ab'='a'||'b | Oracle串联,如果成功,则返回与永真条件相同的信息 |
五、杂
获取列数时,使用order by 比 union select 1,2....要快,其次,使用order by 还可以使用二分法加快猜测速度
有时候会对输入数据类型做出限制,我们可以采取类型转换运算符进行操作,比如要求输入数据必须为字符串,我们使用下列函数执行强制性的类型转换
数据库服务器 | 查询 |
Microsoft SQL Server | SELECT CAST('123' AS varchar) |
MySQL | SELECT CAST('123' AS char) |
Oracle | SELECT CAST(1 AS varchar) FROM dual |
寻找自己感兴趣的表,使用 LIKE 配合通配符使用
MYSQL 查询数据库文件保存路径:select @@datadir;
MYSQL提取数据库中特定表的内容:
select load_file('databasename/tablename.MYD'); 需要注意的是,load_file允许检索的字节数有个最大值,该值由@@max_allowed_packet变量指定。所以该技术不适用于存储了大量数据的表
进行盲注的小技巧
:为字节的8个位发出8个并行请求,得到二进制值后计算可得ascll码值(位运算)
例:ascll(substring(system_user,1,1)) & 128=128-- 如果结果为true 则1XXXXXXX 否则为 0XXXXXXX 以此类推
常见转义技术:十六进制编码
从文件系统读取二进制文件时,可使用MYSQL内置的HEX函数。向文件系统写入二进制文件,可以使用相反的操作——使用MYSQL内置的unhex()函数
如果SQL注入入口点过滤了单引号,可以考虑使用CHAR函数来向利用中放置字符串(例如'admin'),char函数可接受每个字符的ASCII编码
小姿势:很多WAF会检查每个请求参数的值,但不会验证参数名,我们可以通过将payload放到参数名中来利用漏洞,HTTP头部也是一个容易被忽略的入口点
并不是所有SQL语句都可以参数化,特别是只能参数化数据值
使用数据库时常见的问题,是对包含在数据库中的数据的内在信任。
处理不常见输入时可以考虑只进行一次输入解码,接下来如果数据中仍然包含经过编码的字符则拒绝他