SQL注入与libinjection分析(2)Libinjection
- 1. Libinjection介绍
- 1.1 什么是Libinjection?
- 1.2 核心思想
- 1.3 缺点:
- 1.4 时间复杂度
- 2. 源码
- 3. Libinjection处理流程
- 3.1 Libinjection总的框架
- 3.2 libinjection_is_sqli() 处理
- 3.3 libinjection对特征码的定义
- 4. 举例子
- 5. 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?
- Libinjection是一个轻量级的C语言编写的sql注入攻击检测库。
- 原理:
其通过对用户输入进行词法分析生成指纹规则,然后通过二分查找算法,在特征库中进行匹配,匹配到则报SQL注入漏洞。
1.2 核心思想
1.2.1. 转换
libinjection通过将输入预处理,将sqli攻击解析为sql原始查询串。
就是将输入转换为令牌流。(lib自己定义了一套字符对于的令牌)
1.2.2. 假设
libinjection做了一个假设,它假设黑客只能通过三种方法来进行sql攻击
- 直接注入sql语句
- 在单引号内注入sql
- 在双引号内注入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总的框架
分析:
- 初始化变量state
- 通过libinjection_is_sqli()函数进行具体分析(在下面详细分析)
- 如果存在issqli,则将SQL注入识别特征复制进fingerprint变量并返回
如果不存在则将fingerprint变量设置为空并返回。
3.2 libinjection_is_sqli() 处理
- 判断用户输入的字符串长度是否合法,为零则返回FALSE。(即没有发现SQL注入)
- 执行SQL注入识别函数(libinjection_sqli_fingerprint,无引号,标准SQL语法),获取字符串识别特征码
- 执行结构体内的查询函数(这里为libinjection_sqli_lookup_word,二分查找算法),对比第二步获取的识别特征是否与SQL注入识别特征匹配。
- 如果第三步发现SQL注入特征匹配结果为真,则返回true,并将SQL注入识别特征匹配到的fingerprint写入结构体,
- 如果检测失败,则调用reparse_as_mysql()函数判断是否存在“(dash-dash-[notwhite]) 注释”或“’#’ 运算符号”,如果存在则再次执行SQL识别函数(libinjection_sqli_fingerprint,无引号,MYSQL语法),
- 同时执行结构体的分析函数(libinjection_sqli_lookup_word,二分查找算法)进行特征匹配检测,如果结果为真,则返回true,并将SQL注入识别特征匹配到的fingerprint写入结构体。
- 如果前面的判断没有返回结果,将扫描参数(即用户输入的字符串)查找是否存在单引号。如果为真接着重复上述检测步骤。
- 如果前面的判断依旧没有返回结果,将扫描参数(即用户输入的字符串)查找是否存在双引号。如果为真则接着执行SQL注入识别函数
(libinjection_sqli_fingerprint,双引号,MYSQL语法)
同时执行结构体的分析函数(libinjection_sqli_lookup_word,二分查找算法)进行特征匹配检测结果为真,则返回true,并将SQL注入识别特征匹配到的fingerprint写入结构体。
- 如果前面三种判断均无结果则默认该参数(用户输入的字符串)不存在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’
- OR 1=1" ==> s&1
- “’ order by 0–+” ==> sB1c
- “’ union select 1,2–djf” ⇒ sUE1c
5. Libinjection总结
5.1 Libinjection库的优点
- 语义分析库libinjection相比传统正则匹配识别SQL注入的好处在于速度快以及低误报,低漏报
- 速度快体现在该库全程比较耗性能的就一二分查找算法
- 库本身没有内存申请,使用的内存大小十分稳定
- 单线程
6. MYSQL和标准SQL的区别(注释)
MYSQL和标准SQL的区别表
区别/注释方式 /**/ --开头 #
标准sql ok ok no
mysql ok --后面跟空格 ok
6.2 MySQL注释用法
在MySQL中支持三种注释方法:以下都可以是行内注释。
- 使用#作为开头,后面的全是注释。
- 使用–作为注释开头,但要注意,MySQL中这种注释方法和SQL Server等其他标准数据库注释语法稍有不同,MySQL要求第二个短线后面必须跟一个空白字符,如空格、制表符等。
- 使用/**/注释符。
6.3 标准mysql
- 标准sql使用c风格的注释: /* this is a comment */.
mysql同样支持这种样式
- 标准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