作为sql注入原理、sql注入检测、防御系列学习的第三篇。本文主要关注了抽象语法树ast在sql注入检测上的应用开发、以及开源项目druid-sql-wall的学习,希望能给研究这一领域的朋友带来一点帮助,同时也希望能引发大家的共同讨论,共同学习、成长

上一篇文章中,我们学习了其他数据库 防火墙的一些基本知识

http://www.makaidong.com/littlehann/p/3505410.html

文章的接下来部分准备分为2部分进行学习:

1. sql注入语法防御规则

2. druid中sql注入防御模块sql-wall

相关学习资料

http://code.alibabatech.com/wiki/display/druid/wallfilter

http://code.alibabatech.com/wiki/display/druid/wallfilterconfig

http://code.alibabatech.com/wiki/display/druid/get+druid

其他数据库 防火墙位于前端应用开发层之后,前端的应用开发层可以是php、asp、java等,这些语言通过一些统一的访问接口(odbc、jdbc)对数据库系统发起访问请求

所以到了其他数据库 这一层的都是纯的sql请求,所以在其他数据库 这一层面要考虑的不是一些应用开发系统开发的oday、本地变量覆盖的漏洞,而应该明确我们所处的防御层面,我们要防御的是黑客针对其他数据库 发起的攻击。

1. 针对其他数据库 的缓冲区溢出攻击: 这个是实战中很少见,详见
2. 针对其他数据库 底层代码的极限领域的攻击,例如,这是在一个ctf中出现过的mysql attack topic:
<?php# goal: dump the info for the secret idrequire 'db.inc.php';$id = @(float)$_get['id'];die(var_dump($id));$secretid = 1;if($id == $secretid){echo 'invalid id ('.$id.').';}else{$query = 'select * from users where id = \''.$id.'\';';$result = mysql_query($query);$row = mysql_fetch_assoc($result);echo "id: ".$row['id']."</br>";echo "name:".$row['name']."</br>";}
?>
http://localhost/php4fun/index.php?id=1.0000000000001
攻击者的目标的是要查出id为1的admin的数据,这里的绕过思路是利用了mysql的精度范围和php的精度范围不同,精度小的会忽略不能支持的位数。也就是说,浮点型的精度有上限和下限3. 纯粹的拼接sql语法对数据进行注入攻击: 这是最常见的,我们接下来重点分析这方面内容

sql注入语法防御规则

目前,druid的防御重点主要放在拼接型的sql注入攻击,即利用注入点在原始的sql语句综合 的中间或后面"插入"、"拼接"上攻击性的sql payload,从而达到提取非法数据等目的,缓冲区溢出和特殊情况的攻击druid暂时没有实现,将放到未来的版本中逐渐完善,下面根据温少的文档、并 配合druid的源代码进行学习进行具体规则的学习:

0x1 只允许执行增删改查基本语句
\druid\src\main\java\com\alibaba\druid\wall\wallconfig.java(druid的源码和整体架构放在文章的后半部分)
....
//是否允许非以上基本语句的其他语句,缺省关闭,通过这个选项就能够屏蔽ddl。
private boolean             nonebasestatementallow      = false;
....
这是最严格模式,但是也最缺乏灵活性,基本上是不能开启的,在正常的用户业务需求中,必不可少会用到除了crud(增删改查)之外的需求,开启这条规则会导致大量的误报,故druid默认关闭这个开关

0x2 不允许一次执行多条语句 每次只允许执行一条sql,一次执行多条sql,是被认为可能正被sql注入攻击。

1. sql server 6.0在其架构中引入了服务端游标,从而允许在同一连接句柄上执行包含多条语句的字符串。所有6.0之后的sql server 版本均支持该功能且允许执行下列语句:

select id from users;select name from users;

客户端连接到sql服务器开发并依次执行每条语句,其他数据库 服务器开发向客户端返回每条语句发送的结果集。

http://database .51cto.com/art/201007/213806.htm

2. mysql在4.1及之后的版本中也引入了该功能,但是php自身限制了这种用法。

<?php$con = mysql_connect("127.0.0.1", "root" , "111");mysql_select_db("php4fun_", $con);$sql = "update users set level=2;update users set pass=3;"; $result = mysql_query($sql, $con); echo mysql_error(); if($result) { $result_array = mysql_fetch_array($result); var_dump($result_array); }
?>

result: you have an error in your sql syntax; check the manual that corresponds to your mysql server version for the right syntax to use near 'select 1,2,3,4 from dual' at line 1 而如果使用的pdo方式操作其他数据库

<?php $db = new pdo("mysql:host=localhost:3306;dbname=php4fun_", 'root', '111');$sql = "update users set level=2;update users set pass=3;";try { $db->query($sql); } catch(pdoexception $e) {echo $e->getmessage(); die();}
?> 

result: ok

3. oracle不支持多条语句,除非使用pl/sql \druid\src\main\java\com\alibaba\druid\wall\wallconfig.java .... private boolean multistatementallow = false; .... druid默认是禁止这种格式的sql语句综合 的,也即如果在传入的sql语句综合 中解析出了2条及以上的sqlstatement(一个sqlstatement抽象了一条sql语句综合 )就判断为注入攻击

0x3 不允许访问系统开发表
在之前的学习笔记

此文来自: 马开东博客 转载请注明出处 网址:

中,有总结过,从攻击者渠道的角度去理解,攻击者最终的目的是要获取信息 http://www.makaidong.com/littlehann/p/3495602.html 而"访问系统开发表"就是获取信息的渠道之一,故需要拦截之 但是druid对这种规则的判断更加细化,druid只拦截在子句中出现的连接系统开发表查询,举例说明: 1. select * from information_schema.columns; 这条语句druid认为是合法的,因为这条语句没有注入点的存在,sql语句综合 本身的唯一目的就是查询系统开发表,说明用户在进行正常的业务操作 2. select id
from admin
where id = 1
    and 5 = 6
union
select concat(0x5e252421, count(8), 0x2a5b7d2f)
from (select `column_name`, `data_type`, `character_set_name`
    from `information_schema`.`columns`
    where table_name = 0x73696e6765725f616c62756d
        and table_schema = 0x796971696c61695f757466
    ) t
这条语句druid认为是非法的注入攻击,因为sql在子句(可能是注入点的地方)采取了union拼接,进行了连接系统开发表的查询的操作 druid通过判断information_schema在ast层次结构中的位置,具体来说就是判断它的父节点是否为"sql表达式"(例如union select)、以及它的左节点是否为"from节点"。
即满足子句拼接的模式。以此来判断这条sql语句综合 是否有攻击性,在代码中的体现就是 druid\src\main\java\com\alibaba\druid\wall\spi\wallvisitorutils.java ..... boolean sametotopselectschema = false; if (parent instanceof sqlselectstatement) { sqlselectstatement selectstmt = (sqlselectstatement) parent; sqlselectquery query = selectstmt.getselect().getquery(); if (query instanceof sqlselectqueryblock) { sqlselectqueryblock queryblock = (sqlselectqueryblock) query; sqltablesource from = queryblock.getfrom(); while (from instanceof sqljointablesource) {   from = ((sqljointablesource) from).getleft(); } if (from instanceof sqlexprtablesource) { sqlexpr expr = ((sqlexprtablesource) from).getexpr(); if (expr instanceof sqlpropertyexpr) { sqlexpr schemaexpr = ((sqlpropertyexpr) expr).getowner(); if (schemaexpr instanceof sqlidentifierexpr) {   string schema = ((sqlidentifierexpr) schemaexpr).getname();   schema = form(schema);   if (schema.equalsignorecase(owner))   {   sametotopselectschema = true;   } }  } } } } if (!sametotopselectschema) { addviolation(visitor, errorcode.schema_deny, "deny schema : " + owner, x); } 而代码中的owner是从配置文件中读取的: string owner = ((sqlname) x).getsimlename(); owner = wallvisitorutils.form(owner); if (isintablesource(x) && !visitor.getprovider().checkdenyschema(owner)) { ... 配置文件被统一放在了: \druid\src\main\resources\meta-inf\druid\wall\mysql\deny-schema.txt information_schema mysql performance_schema 这样,druid就完成了对sql中的对系统开发敏感表的注入的智能检测

0x4 不允许访问系统开发对象
在sqlserver中有系统开发对象的概念。对敏感系统开发对象"sysobject"的检测也是同样的原理,即只检测子句的非法连接,并从配置文件中读取拦截列表,代码和对系统开发表的检测是类似的
0x5 不允许访问系统开发变量
系统开发敏感变量同样也是攻击者获取非法数据的一种渠道,druid采取智能判断的做法,举例说明:1. select @@basedir;
这条语句druid不做拦截,因为这里没有注入点的存在,也就不可能是黑客的注入攻击,应该归类于业务的正常需要2. select * from cnp_news where id='23' and len(@@version)>0 and '1'='1'
这条语句druid会做拦截,攻击者在子句中利用逻辑表达式进行非法的探测注入,目前druid的检测机制是"黑名单机制",把需要禁止的系统开发变量写在了配置文件中:
druid\src\main\resources\meta-inf\druid\wall\mysql\deny-variant.txt
basedir
version_compile_os
version
datadir
druid\src\main\java\com\alibaba\druid\wall\spi\wallvisitorutils.java
...
if (!checkvar(x.getparent(), x.getname()))
{boolean istop = wallvisitorutils.istopnonefromselect(this, x);if (!istop){boolean allow = true;if (wallvisitorutils.iswhereorhaving(x) && isdeny(varname)){allow = false;}if (!allow){violations.add(new illegalsqlobjectviolation(errorcode.variant_deny, "variable not allow : " + x.getname(), tosql(x)));}}
}
...
0x6 不允许访问系统开发函数
和"系统开发敏感表"、"系统开发敏感对象"、"系统开发敏感变量"一样,系统开发敏感函数也是攻击者用来获取非法信息的一种手段之一
druid中和禁用系统开发函数的配置文件:
druid\src\main\resources\meta-inf\druid\wall\mysql\deny-function.txt
version
load_file
database
schema
user
system_user
session_user
benchmark
current_user
sleep
xmltype
receive_message对于系统开发敏感函数的禁用,这里要注意一下,和系统开发表的防御思想类型,druid会智能地判断敏感函数在sql语句综合 中出现的位置,例如:
1. select load_file('\\etc\\passwd');
druid不会拦截这条语句,还是同样的道理,sql注入的关键在于注入点,这条语句没有注入点的存在,所以只能是用户正常的业务需求2. select * from admin where id =(select 1 from (select sleep(0))a);
druid会智能地检测出这个敏感函数出现在"where子句节点"中,而"where子句节点"经常被黑客用来当作一个sql注入点,故druid拦截之
代码如下:
druid\src\main\java\com\alibaba\druid\wall\spi\wallvisitorutils.java
public static void checkfunction(wallvisitor visitor, sqlmethodinvokeexpr x)
{final walltopstatementcontext topstatementcontext = walltopstatementcontextlocal.get();if (topstatementcontext != null && (topstatementcontext.fromsysschema || topstatementcontext.fromsystable)){return;}checkschema(visitor, x.getowner());if (!visitor.getconfig().isfunctioncheck()){return;}string methodname = x.getmethodname().tolowercase();wallcontext context = wallcontext.current();if (context != null){context.incrementfunctioninvoke(methodname);}if (!visitor.getprovider().checkdenyfunction(methodname)){boolean istopnonefrom = istopnonefromselect(visitor, x);if (istopnonefrom){return;}boolean isshow = x.getparent() instanceof mysqlshowgrantsstatement;if (isshow){return;}if (iswhereorhaving(x)){addviolation(visitor, errorcode.function_deny, "deny function : " + methodname, x);}}
}   
0x7 不允许出现注释
正常执行的sql是不应该附带注释的,有注释的sql都会被认为是危险操作。druid是默认"禁止"单行注释和多行注释。这里所谓的"禁止"是值druid会在解析前自动地去除原始sql语句综合 中的注释。
例如攻击者常用的绕过方式:
1) sel/**/ect us/**/er() from dual;  (黑客常用来绕过基于正则前端waf)
2) select * from admin where no=4 and 1=2 /!40001+union/ select 1,concat(database (),0x5c,user(),0x5c,version()),3,4,5,6,7
(mysql的comment dynamic execution bypass)
http://www.freebuf.com/articles/web/22041.html这里druid采取的防御思路是"规范化",代码自动会将注释的部分删除,重新拼接sql语句综合 后,对"规范化"后的语句再进行注入检测,删除注释的代码逻辑在词法解析器中:
druid\src\main\java\com\alibaba\druid\sql\parser\lexer.java
..
protected boolean      skipcomment  = true;
..
public final void nexttoken()
{..../*解析'#'注释符判断'#'解析出的节点是'单行注释'、或'多行注释'*/case '#':scansharp();if ((token() == token.line_comment || token() == token.multi_line_comment) && skipcomment){bufpos = 0;continue;}return;..../*检测是否是'--'这种单行注释符*/if (subnextchar == '-'){scancomment();if ((token() == token.line_comment || token() == token.multi_line_comment) && skipcomment){bufpos = 0;continue;}}.../*判断当前节点是否是 /*  */  这种类型的多行注释*/if (nextchar == '/' || nextchar == '*'){scancomment();if ((token() == token.line_comment || token() == token.multi_line_comment) && skipcomment){bufpos = 0;continue;}}
...
在对sql的词法解析的开发过程 中,druid就会自动地对

此文来自: 马开东博客 转载请注明出处 网址:

各种形式的注释符进行删除,删除了注释后,druid再去解析sql语句综合 ,这个时候会出现两个情况: 1) 解析失败抛异常,说明原本的sql语句综合 很有可能是攻击型的sql语句综合 ,黑客使用了注释绕过或者注释执行技术 2) 解析正常,说明这是正常的sql语句综合 ,不排除有的程序猿会把一些简短的注释写在sql语句综合 中,但是这个注释的删除对原本的执行没有影响,所以也就判定为合理sql语句综合 oracle hints的语法是/* + */,druid能够区分注释和hints

SQL注入检测模块开源项目DRUID-SQL-WALL学习小结相关推荐

  1. 基于AST抽象语法树的SQL注入检测 (2) -- 每周小结(01-02~01-08) - .Little Hann

    本周继续学习AST的SQL语法检测原理的学习,文章的接下来部分准备分为2部分进行学习: 1. SQL注入语法防御规则 2. druid中SQL注入防御模块sql-wall 1. 相关学习资料 http ...

  2. 使用Python打造基本WEB漏洞扫描器(一) 网站爬虫+SQL注入检测

    一.实验介绍 扫描器需要实现功能的思维导图: 1.1 实验内容 编写一个简单的多线程爬虫,用于对网站地址进行爬取,编写一个简单的sql注入工具,用于对网站地址进行sql注入的检测. 1.2 实验知识点 ...

  3. C#SQL注入检测——特别是对于旧版.NET代码

    目录 使用Decorator模式提供添加SQL注入检测的位置 SQL注入检测代码 究竟如何检测到SQL注入? SQLExtensions类中包含的格式化方法 自定义.NET异常类 用于检测SQL注入的 ...

  4. SQL注入-入门需了解项目

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 什么是SQL? 一.SQL注入 1.什么是SQL注入 2.SQL注入漏洞的原理是什么? 3.SQL注入漏洞产生的基本前提 4 ...

  5. python sql注入如何防止_Python如何防止sql注入

    Python如何防止sql注入.web漏洞之首莫过于sql了,不管使用哪种语言进行web后端开发,只要使用了关系型数据库,可能都会遇到sql注入攻击问题. 那么在Python web开发的过程中sql ...

  6. sql注入是什么意思以及防止sql注入?

    ----------------------------------------------应对方法-------------------------------------------------- ...

  7. php如何防sql注入,如何在PHP中防止SQL注入

    本篇文章将给大家介绍关于PHP中的SQL注入以及使用PHP-MySQLi和PHP-PDO驱动程序防止SQL注入的方法.下面我们来看具体的内容. 简单的SQL注入示例 例如,A有一个银行网站.已为银行客 ...

  8. SQL注入是什么,怎么防止SQL注入?

    SQL注入是什么,怎么防止SQL注入? 一.什么是SQL注入? SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录 ...

  9. 【机器人学】机器人开源项目KDL源码学习:(5)KDL如何求解几何雅克比矩阵

    这篇文章试图说清楚两件事:1. 几何雅克比矩阵的本质:2. KDL如何求解机械臂的几何雅克比矩阵. 一.几何雅克比矩阵的本质 机械臂的关节空间的速度可以映射到执行器末端在操作空间的速度,这种映射可以通 ...

最新文章

  1. Windows Server 2016-图形化备份域控制器
  2. 小程序云服务器选什么系统好,小程序云服务器操作系统选择
  3. mysqld与mysqld_safe的区别
  4. SAP Data Hub里的Constant Generator
  5. asp.net 中 SESSION和COOKIE的使用
  6. 一加到1亿。C语言_可能是今年最难选的2部手机:小米10详细对比一加8T
  7. python音频聚类_python实现鸢尾花三种聚类算法(K-means,AGNES,DBScan)
  8. java 查询后 jsonobject key 排序_商品品牌业务之后台Java代码的编写
  9. Matlab解析LQR与MPC的关系
  10. Mind+上传模式的第三方Arduino用户库实现 -DHT11温湿度模块
  11. 第四步_安装gcc交叉编译工具
  12. mysql表内容_5、mysql表内容操作
  13. 如何快速搭建在线教育知识付费系统(附带源码)
  14. 用android编写计数器前后台源代码,在Android中实现计数器
  15. C语言结业作业,2019年本科课程-C语言程序设计结业试卷(附答案).doc
  16. log4j WARN 和 SLF4J WARN 解决办法
  17. 项目落地 - 智慧海绵城市(物联网技术应用)
  18. sql 语句 将查询结果中数字等标示转成汉字
  19. 一文读懂5G R16标准究竟讲了些什么
  20. Docker测试环境笔记

热门文章

  1. springboot集成activiti汉化
  2. 整理了以BAT三巨头为例的薪资职别资料,写给想参加春招或想跳槽的学弟学妹们
  3. 漫画城之自动轮播+GridView
  4. 金匮要略重点复习资料
  5. linux服务器部署react项目步骤详解
  6. 怎样快速将pdf转换成txt格式
  7. django实训项目——图书管理系统
  8. 1-1计算机编程语言---翁恺
  9. 简单理解LDAP认证
  10. 微软十二月补丁星期二值得关注的漏洞