SQL注入前奏-原理分析

SQL注入形成的原因

  1. 前端有可控参数
  2. 后端将可控得参数拼接到与数据库交互得SQL中
  3. 后端没有对用户提交得参数做严格得过滤防护

总结: 后端和数据库交互的SQL中, 拼接了前端用户可控的数据, 且未对该数据做严格的过滤过滤防护而导致的安全问题.

SQL注入得影响

  1. 数据库信息被窃取: 攻击者可以通过构造恶意得SQL来获取到数据库中得所有数据, root权限还可以进行跨库获取.
  2. 数据库内容被篡改: 通过构造update, 或者堆叠得形式, 进行对数据得修改, 删除.等操作。
  3. 登录认证被绕过: SQL注入得一个简单利用, select * from users where username='adnuin' or 1-- a and password='123' 导致登录认证逻辑不管怎么样, 都会返回有数据得状态.
  4. 其他,例如服务器文件读取(load_file)写入(into outfile)修改等...

SQL注入得分类

SQL注入得分类方式有很多, POST型, GET型, 字符型, 数字型等等等等...........只是获取数据得方式不同, 构造得SQL语句不同

就可以通过获取数据得方式来进行一个分类: 显注/盲注

  1. 显注: 代入到数据库中执行的SQL, 会把执行结果直接显示到前端页面, 例如联合查询/报错注入/dnslog等.
  2. 盲注: 不会直接在前端显示数据库执行结果, 需要其他语句结合zh执行效果来判定, 例如布尔型盲注/时间延迟等.

相同点

  1. 类型问题: 注入的参数可能是数字型, 字符型
  2. 注入判断: 判断是否存在注入的方式
  3. 闭合问题: 注入的参数可能被括号包裹, 闭合的方式是一样的
  4. 请求方式: GET/POST, 只要存在注入, 便不会影响注入结果
  5. 出现位置: 可注入的参数可能会是在请求的数据中, 请求头中, 如Cookie, ua头等
  6. 注入流程: 获取到库名->表名->字段名->具体数据.

不同点

在获取相关数据时, 显注可以很直接的吧SQL执行结果返回到前端来, 而盲注, 需要对数据进行逐一猜解, 才能获取到相关数据, 这个过程需要配合if length等等函数关键字

SQL注入判断方法

  1. and: and表示为连接条件, 代表为且, 也就是说, and左右两边的表达式, 返回结果必须都为true, 最终结果才是true
  2. or: 和and同样为表示为链接条件, 代表为或, or左右两边, 有一个为true, 整体结果便为true
  3. 引号报错: 在SQL语句中, 用户提交的参数有数字型和字符型, 不管是数字还是字符, 引号都是一个可以快速破坏SQL语句语法结构的存在.
  4. 延迟判断: sleep语句可以让数据库延迟执行, 通过页面的响应时间来判断是否存在SQL注入
  5. 加减法判断: 当参数是数字型的时候, 可以尝试用加减法来判断SQL注入

and 方式的判断

  1. and 1=1: 这个条件始终是为真的, 也就是说, 存在SQL注入的话, 这个and 1=1的返回结果必定是和正常页面时是完全一致的
  2. and 1=2: 只有and 1=1明显是不靠谱的, 如果是数字型, 涉及到类型转换问题后, and 1=1会被舍弃, 因此, and 1=2返回为假, 会强行吧整个查询条件建立成假. 导致查询无数据, 因此页面内容会和正常页面不同.
  http://127.0.0.1/sqli/Less-1/?id=1 正常
  http://127.0.0.1/sqli/Less-1/?id=1 and 1=1 正常
  http://127.0.0.1/sqli/Less-1/?id=1 and 1=2 不正常

or 方式的判断

  1. or是或条件, or两边条件只要有一个条件为真, 那么就整体的结果就是为真
    http://127.0.0.1/sqli/Less-1/?id=1 正常
    http://127.0.0.1/sqli/Less-1/?id=1 or 1=1 正常
    http://127.0.0.1/sqli/Less-1/?id=1 or 1=2 正常
  2. 上面那个一看, 好像并没有什么用, 全都是正常的, 无法判断, 如下改变一个小小的思路
    将id值改为-1或者一个数据库中不存在的数据, id字段一般都是设置为主键且自增长, 都是从1开始, 采用个负数测试是最常见的.
    http://127.0.0.1/sqli/Less-1/?id=-1 or 1 正常, 会返回数据库中的第一条数据(后端SQL中用了limit控制输出行数, 如果没采用limit, 会遍历整个表里得数据)
    http://127.0.0.1/sqli/Less-1/?id=-1 or 1=2 无结果返回

引号报错

在一个正常的SQL语句中, 接收前端传过来的参数, 代入到数据库中查询时, 一般要么像是id值这样的数字型, 或者是搜索关键字功能的字符型, 字符串都是被引号包裹的, 单引号或者双引号, 在注入点后面加上个引号, 就能快速破坏SQL结构, 导致SQL执行报错.

一般推荐单双引号一起加上去, 否则对方单引号的话, 双引号会被当作普通的字符串带进去执行, 而不会报错, 反之同理

http://127.0.0.1/sqli/Less-1/?id=1'"
   
mysql> select * from emails where id = '1"'   会被当作普通的字符代入查询, 类型转换的问题又直接取数字将其舍弃掉了.
+----+------------------+
| id | email_id         |
+----+------------------+
| 1 | Dumb@dhakkan.com |
+----+------------------+
1 row in set, 1 warning (0.00 sec)

延迟判断

在一个SQL注入中: select * from users where id = 1 and sleep(5),添加上该payload, 可以让页面延迟五秒响应, 在结合页面正常的响应时间, 来判断构造的SQL是否被执行, sleep测试方法可以用于全部的SQL注入测试中. 只要页面有延迟, 那就表示存在SQL注入. 非常好的快速测试是否存在SQL注入的方法.

并且, sleep()的返回值是0 因此在延迟执行完毕后, and sleep()等同于 and 0 强行吧条件变成假, 因此, 在测试insert update, delete时, 也不用担心数据被删除修改的风险.

delete from users where id = 1 and sleep(5)   # 当延迟执行完毕后.等同于: delete from users where id = 1 and 0, 因此不会删除数据. update insert同理.

加减法判断

在注入的参数是一个数字的时候, 可以尝试采用加减法的方式来判断, 让id值进行运算发生变化, 也是判断是否被代入执行的一种方式, 在MySQL中, 字符也是可以进行加法运算的, 会从字符串的左边开始一直取到不是数字位置: "123aa111", 运算时是123

mysql> select * from users;
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  1 | Dumb     | Dumb       |
|  2 | Angelina | I-kill-you |
|  3 | Dummy   | p@ssword   |
|  4 | secure   | crappy     |
|  5 | stupid   | stupidity |
|  6 | superman | genious   |
|  7 | batman   | mob!le     |
|  8 | admin   | 123456     |
|  9 | admin1   | admin1     |
| 10 | admin2   | admin2     |
| 11 | admin3   | admin3     |
| 12 | dhakkan | dumbo     |
| 14 | admin4   | admin4     |
| 15 | admin | 123123123 |
| 16 | 123     | 123       |
| 17 | 123     | 123       |
| 18 | 123     | 123       |
+----+----------+------------+
17 rows in set (0.00 sec)

mysql> select * from users where id = 1 + 1;
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  2 | Angelina | I-kill-you |
+----+----------+------------+
1 row in set (0.00 sec)

mysql> select * from users where id = '1' + '1';
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  2 | Angelina | I-kill-you |
+----+----------+------------+
1 row in set (0.00 sec)

mysql> select * from users where id = "1" + '1';
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  2 | Angelina | I-kill-you |
+----+----------+------------+
1 row in set (0.00 sec)

mysql> select * from users where id = "1" + "1";
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  2 | Angelina | I-kill-you |
+----+----------+------------+
1 row in set (0.00 sec)

SQL注入的防御方式

代码层最佳防御 sql 漏洞方案:采用 sql 语句预编译和绑定变量,是防御 sql 注入的最佳方法。

  1. 所有的查询语句都使用数据库提供的参数化查询接口,参数化的语句使用参数而不是将用户输入变量嵌入到 SQL 语句中。当前几乎所有的数据库系统都提供了参数化 SQL 语句执行接口,使用此接口可以非常有效的防止 SQL 注入攻击。
  2. 对进入数据库的特殊字符( ' <>&*; 等)进行转义处理,或编码转换。但需要注意二次注入问题.
  3. 确认每种数据的类型,比如数字型的数据就必须是数字,在后端层面可以对用户输入的数据进行int强转, 舍弃其他除数字以外的部分, 数据库中的存储字段必须对应为 int 型。
  4. 据长度应该严格规定,能在一定程度上防止比较长的 SQL 注入语句无法正确执行。
  5. 网站每个数据层的编码统一,建议全部使用 UTF-8 编码,上下层编码不一致有可能导致一些过滤模型被绕过。宽字节注入.
  6. 严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
  7. 避免网站显示 SQL 错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值