详细聊聊关于sql注入的一些零散知识点
零、本文涉及知识点
sqlmap写一句马的具体过程
堆叠注入
union injection(联合注入)
常见的注入绕过姿势
sql注入预编译与常见绕过姿势
一、sqlmap写一句马的过程(-- os-shell)
1.1 简述过程
先写一个文件上传的文件,名字为“ tmpujhum.php ”。
然后通过这个文件上传的木马,将shell(tmpbcluy.php)上传,
执行命令的木马名字为“ tmpbcluy.php ”
具体过程可以参考: https://xz.aliyun.com/t/7942
1.2 一个小问题
都可以直接通过命令写文件了,为什么还要先写一个上传文件的木马,在通过这个木马上传一句马?
*答:**
sqlmap官方这么写得代码,所在按照这个流程,开玩笑~~
主要原因是大多数waf的对命令直接写文件的监控比上传木马的监控严格。
即通过这种“多此一举”的思路,可以提高上传成功一句马的概率
二、堆叠注入:
2.1 什么是堆叠注入
在sql中,分号(;)是用来表示一条sql语句的结束。
试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?
因此这个想法也就造就了堆叠注入。
2.2 如何判断存在堆叠注入?
~“ id=1 ”正常
~试试“ id=1a ”,假设报错,说明数据没有被强转
~在试试“ id=1; ”假设没有报错,说明“;”没有被代入查询,而是当做了sql语句的结束符
~此时,此位置大概率存在堆叠注入
2.3 局限性
堆叠注入的局限性在于并不是每一个环境下都可以执行,
可能受到api或者数据库引擎不支持的限制,
当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。
三、union injection(联合注入)
3.1 原理
绝大多数的sql注入都是利用的此姿势,
详细不在赘述,可以直接参考之前的文章。
3.2 与堆叠注入的区别
区别就在于union 或者union all执行的语句类型是有限的,仅仅可以用来执行查询语句,
而堆叠注入可以执行的是任意的语句。
**例如以下这个例子,即堆叠可以执行成功,联合注入不能成功**
用户输入:1; delete from products服务器端生成的sql语句为:
select * from products where productid=1;delete from products
当执行查询后,第一条显示查询信息,第二条则将整个表进行删除。
四、常见的sql注入绕过姿势
4.1 waf特性:
绝大多数的waf都是通过正则匹配过滤/拦截请求
一般一个waf会同时上线n个规则,这些规则同时生效的情况下,仅仅饶过一个依旧会被拦截
4.2 绕waf的核心思路:
绕过waf正则匹配规则的同时,注入的sql语句可以被正常解析执行。
4.3 常见的思路
数据上:
大小写 、、很老的waf可以绕过
加解密、编码解码
等价函数 union select == union all select
特殊符号
反序列化
注释符混用 、、mysql特性:
database/**/() == database()
内联注释,如/*一个sql版本号sql执行内容*/,具体不在展开
方式:
更改提交方式 、、部分waf默认仅仅检测get(但是假设后端不接收post也没什么卵用);
变异
其他:
fuzz
、、模糊测试,使用脚本/工具生成大量payload,直接爆破waf,看看哪些语句可以过waf
数据库特性
、、mysql特性:
union%23a%0aselect 1,2,3#
== union#a(换号)select 1,2,3#
== union select 1,2,3#
、、mysql特性:
/*!select * from users*/ 会正常执行
垃圾数据溢出
http参数污染
、、多个参数的情况下,一般默认取最后一个
、、?id=1/**&id=-1%20union%20select%201,2,3%23*/
即“ 1/**-1 union select 1,2,3#*/ ”
在mysql之中“ /** 内容不会执行 */ ”所以waf认为是安全的,
但是因为apache的特性,
其最终接收的参数为:“ -1 union select 1,2,3#*/ ”
静态资源
、、即本来为php?id=1 改为 php/a.txt(b.js等)?id=1
结果不受影响,但是可以过一些老waf
用注释配合参数污染绕waf的成功率是比较高的
使用sqlmap注意,
~ua自带的要改一下,参数就可以改,可以改为百度等搜索引擎的ua
~可以设置绕waf脚本来提高成功率,而且脚本写也挺简单
~自己测试的时候,可以用参数将sqlmap的流量代理到burp,然后对比自己正常浏览器的流量,看看区别
~必要的时刻,连接代理池直接暴力配合开干
五、sql注入预编译与常见绕过姿势
5.1 概述
预编译一般在java的框架中使用,在提高sql语句效率的同时也可以拦截掉很多注入的情况,
但是仍可以被绕过的,
5.2 具体方式
5.2.1 asc/desc
应用场景:
当应用显示多条数据时,通常可以选择正向排序或者逆向排序,此时就会用到 asc/desc
asc/desc 是sql语句中影响语义的关键字,是不能用单引号引起来的
假设asc/desc是接收的前端传入,即存在被注入的风险。
如何处理:
比较安全的方式是使用白名单,排序方式也只有两种,可使用简单的条件判断语句
<?php if($_post['order'] === 'desc'){ $order = 'desc'; }else{ $order = 'asc' }
5.2.2 表名/字段名
应用场景:
表名与列名是不能被预编译的,这是由于在预编译生成语法树的过程中,
预处理器在检查解析后的语法树时,会确定数据表和数据列是否存在,
此两者必须为具体值,不能被占位符 ? 所替代
假设表名/字段名是接收的前端传参,即存在被注入的风险
如何处理:
参考下边order by的情况
5.2.3 order by
order by 用来指定某个字段作为排序依据,前面也解释了字段名不能使用预编译
假设order by后边的字段是接收的前端传参,即存在被注入的风险
具体的一些绕过方法可以搜索“ case when ”
如何处理:
为了避免直接拼接sql语句,可以将列名定义为常量,
再通过白名单的方式进行拼接,能够有效防止sql注入
当然,这里也可以单独对传入的语句配合正则匹配过滤,但是效果不如这种方式简洁有效。
前端表单:
<form action="" method="post"> <select name="order"> <option value="0">id</option> <option value="1">name</option> <option value="2">age</option> </select> <input type="submit" name="submit"> </form>
白名单函数:
<?php $i = $_post['order']; switch($i){ case 0: $order = "id"; break; case 1: $order = "name"; break; default: $order = "age"; break; }
5.2.4小结:
假设asc/desc是接收的前端传入,即存在被注入的风险。
假设表名/字段名是接收的前端传参,即存在被注入的风险
假设order by后边的字段是接收的前端传参,即存在被注入的风险
总结
到此这篇关于sql注入的一些零散知识点的文章就介绍到这了,更多相关sql注入零散知识点内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
上一篇: 数据库系统结构详解之三级模式结构
下一篇: 一次数据库查询超时优化问题的实战记录