SQL注入与libinjection分析(2)Libinjection

SQL注入与libinjection分析(2)Libinjection

  • 1. Libinjection介绍
    • 1.1 什么是Libinjection?
    • 1.2 核心思想
      • 1.2.1. 转换
      • 1.2.2. 假设
    • 1.3 缺点:
    • 1.4 时间复杂度
  • 2. 源码
  • 3. Libinjection处理流程
    • 3.1 Libinjection总的框架
    • 3.2 libinjection_is_sqli() 处理
    • 3.3 libinjection对特征码的定义
  • 4. 举例子
  • 5. Libinjection总结
    • 5.1 Libinjection库的优点
  • 6. MYSQL和标准SQL的区别(注释)
    • 6.2 MySQL注释用法
    • 6.3 标准mysql
  • 参考

SQL注入与libinjection分析系列:
MYSQL命令大全
https://blog.csdn.net/lqy971966/article/details/104922862
SQL注入与libinjection分析(1)SQL注入
https://blog.csdn.net/lqy971966/article/details/105269658
SQL注入与libinjection分析(2)Libinjection
https://blog.csdn.net/lqy971966/article/details/105273753
SQL注入与libinjection分析(3)源码分析之一些重要的结构体说明
https://blog.csdn.net/lqy971966/article/details/106195224
SQL注入与libinjection分析(4)源码分析之整体框架解读
https://blog.csdn.net/lqy971966/article/details/106857168
SQL注入与libinjection分析(5)源码分析之指纹函数fingerprint和查找函数lookup_word剖析
https://blog.csdn.net/lqy971966/article/details/106902216

1. Libinjection介绍

1.1 什么是Libinjection?

  1. Libinjection是一个轻量级的C语言编写的sql注入攻击检测库
  2. 原理:
    其通过对用户输入进行词法分析生成指纹规则,然后通过二分查找算法,在特征库中进行匹配,匹配到则报SQL注入漏洞。
    SQL注入与libinjection分析(2)Libinjection_第1张图片

1.2 核心思想

1.2.1. 转换

libinjection通过将输入预处理,将sqli攻击解析为sql原始查询串。
就是将输入转换为令牌流。(lib自己定义了一套字符对于的令牌)

1.2.2. 假设

libinjection做了一个假设,它假设黑客只能通过三种方法来进行sql攻击

  1. 直接注入sql语句
  2. 在单引号内注入sql
  3. 在双引号内注入sql

1.3 缺点:

其实还有一种注入方法是在注释内注入sql攻击,但是 libinjection不支持这种攻击检测。

1.4 时间复杂度

libinjection内置8000多个特征库,令牌通过二分法与此特征库进行对比,算法时间复杂度是 log(8000)=13,一次匹配最多查找13次即可。
对于AC算法O(N)的时间复杂度来说,性能提高不少。

2. 源码

源码托管在github上:https://github.com/client9/libinjection

3. Libinjection处理流程

3.1 Libinjection总的框架

SQL注入与libinjection分析(2)Libinjection_第2张图片
分析:

  1. 初始化变量state
  2. 通过libinjection_is_sqli()函数进行具体分析(在下面详细分析)
  3. 如果存在issqli,则将SQL注入识别特征复制进fingerprint变量并返回
    如果不存在则将fingerprint变量设置为空并返回。

3.2 libinjection_is_sqli() 处理

SQL注入与libinjection分析(2)Libinjection_第3张图片

  1. 判断用户输入的字符串长度是否合法,为零则返回FALSE。(即没有发现SQL注入)
  2. 执行SQL注入识别函数(libinjection_sqli_fingerprint,无引号,标准SQL语法),获取字符串识别特征码
  3. 执行结构体内的查询函数(这里为libinjection_sqli_lookup_word,二分查找算法),对比第二步获取的识别特征是否与SQL注入识别特征匹配
  4. 如果第三步发现SQL注入特征匹配结果为真,则返回true,并将SQL注入识别特征匹配到的fingerprint写入结构体,
  5. 如果检测失败,则调用reparse_as_mysql()函数判断是否存在“(dash-dash-[notwhite]) 注释”或“’#’ 运算符号”,如果存在则再次执行SQL识别函数(libinjection_sqli_fingerprint,无引号,MYSQL语法),
  6. 同时执行结构体的分析函数(libinjection_sqli_lookup_word,二分查找算法)进行特征匹配检测,如果结果为真,则返回true,并将SQL注入识别特征匹配到的fingerprint写入结构体。
  7. 如果前面的判断没有返回结果,将扫描参数(即用户输入的字符串)查找是否存在单引号。如果为真接着重复上述检测步骤。
  8. 如果前面的判断依旧没有返回结果,将扫描参数(即用户输入的字符串)查找是否存在双引号。如果为真则接着执行SQL注入识别函数
    (libinjection_sqli_fingerprint,双引号,MYSQL语法
    同时执行结构体的分析函数(libinjection_sqli_lookup_word,二分查找算法)进行特征匹配检测结果为真,则返回true,并将SQL注入识别特征匹配到的fingerprint写入结构体。
  9. 如果前面三种判断均无结果则默认该参数(用户输入的字符串)不存在SQL注入。

3.3 libinjection对特征码的定义

typedef enum {
	TYPE_NONE        = 0   /*无实际意义,仅对位数进行填充*/
	, TYPE_KEYWORD     = (int)'k'  /*例如COLUMN,DATABASES,DEC等会被识别为该值*/
	, TYPE_UNION       = (int)'U'  /*EXCEPT,INTERSECT,UNION等会被识别为该值*/
	, TYPE_GROUP       = (int)'B'    /*GROUP BY,LIMIT,HAVING*/
	, TYPE_EXPRESSION  = (int)'E'   /*INSERT,SELECT,SET*/
	, TYPE_SQLTYPE     = (int)'t'  /*SMALLINT,TEXT,TRY*/
	, TYPE_FUNCTION    = (int)'f'   /*UPPER,UTL_HTTP.REQUEST,UUID*/
	, TYPE_BAREWORD    = (int)'n'  /*WAITFOR,BY,CHECK*/
	, TYPE_NUMBER      = (int)'1'   /*所有数字会被识别为1*/
	, TYPE_VARIABLE    = (int)'v'  /*CURRENT_TIME,LOCALTIME,NULL*/
	, TYPE_STRING      = (int)'s'   /*单引号和双引号*/
	, TYPE_OPERATOR    = (int)'o'  /*+=,-=,!>*/
	, TYPE_LOGIC_OPERATOR = (int)'&'   /*&&,AND,OR*/
	, TYPE_COMMENT     = (int)'c'     /*注释符*/
	, TYPE_COLLATE     = (int)'A'  /* COLLATE*/
	, TYPE_LEFTPARENS  = (int)'('     
	, TYPE_RIGHTPARENS = (int)')'  /* not used? */
	, TYPE_LEFTBRACE   = (int)'{'    
	, TYPE_RIGHTBRACE  = (int)'}'
	, TYPE_DOT         = (int)'.'
	, TYPE_COMMA       = (int)','
	, TYPE_COLON       = (int)':'
	, TYPE_SEMICOLON   = (int)';'
	, TYPE_TSQL        = (int)'T'  /* TSQL start */ /*DECLARE,DELETE,DROP*/
	, TYPE_UNKNOWN     = (int)'?'
	, TYPE_EVIL        = (int)'X'  /* unparsable, abort  */   /* “/*!*/”  */
	, TYPE_FINGERPRINT = (int)'F'  /* not really a token */
	, TYPE_BACKSLASH   = (int)'\\'
} sqli_token_types; 

libinjection将输入的数据依据上述的定义进行转换,之后就会得到SQL注入识别特征,或者说指纹,然后通过二分查找算法,在特征库中进行匹配,匹配到则报SQL注入漏洞。

4. 举例子

1. 这里我举个例子:
-1’ and 1=1 union /* foo */select load_file(’/etc/passwd’)–
你输入这个字符串,解析按空格分隔开,这里比较重要的点是没有闭合 ’或“也按字符串处理 -1’ 转换为特征码s(string);
第二个字串 and 关键字 特征码为 &;
1 = 1这里比较特殊它按数字来转了(具体可以跟代码来深入研究) 特征码为 1;
union 关键字联合查询 特征码为 U;
select 关键字特征码为 E;
所以合起来就是s&1UE;

  1. "1’
  2. OR 1=1" ==> s&1
  3. “’ order by 0–+” ==> sB1c
  4. “’ union select 1,2–djf” ⇒ sUE1c

5. Libinjection总结

5.1 Libinjection库的优点

  1. 语义分析库libinjection相比传统正则匹配识别SQL注入的好处在于速度快以及低误报,低漏报
  2. 速度快体现在该库全程比较耗性能的就一二分查找算法
  3. 库本身没有内存申请,使用的内存大小十分稳定
  4. 单线程

6. MYSQL和标准SQL的区别(注释)

MYSQL和标准SQL的区别表

区别/注释方式	/**/  --开头         #
标准sql          ok     ok			no
mysql	         ok	  --后面跟空格	ok

6.2 MySQL注释用法

在MySQL中支持三种注释方法:以下都可以是行内注释。

  1. 使用#作为开头,后面的全是注释。
  2. 使用–作为注释开头,但要注意,MySQL中这种注释方法和SQL Server等其他标准数据库注释语法稍有不同,MySQL要求第二个短线后面必须跟一个空白字符,如空格、制表符等。
  3. 使用/**/注释符。

6.3 标准mysql

  1. 标准sql使用c风格的注释: /* this is a comment */.
    mysql同样支持这种样式
  2. 标准sql的注释风格使用“–”开始,mysql使用#开始注释字符。
    mysql也支持–注释样式的变种。就是 --开始,但是 必须跟随一个space,或者一个控制字符,比如新行。space避免自动生成sql查询的一些问题
    参考:
    https://www.cnblogs.com/ck0074451665/p/10488772.html
    https://www.linuxidc.com/Linux/2017-10/148022.htm

参考

https://blog.csdn.net/zhangge3663/article/details/81509664
https://www.sohu.com/a/231529482_354899
https://www.cnblogs.com/yddsblog/p/12503348.html
https://zhuanlan.zhihu.com/p/44292411
http://tanjiti.lofter.com/post/1cc6c85b_10c4e359

你可能感兴趣的:(数据安全,Linux,开源)