Libinjection原理
Liblinjection运作流程
初始化变量state
通过libinjection_is_sqli()函数进行具体分析(在下面详细分析)
如果存在issqli,则将SQL注入识别特征复制进fingerprint变量并返回,如果不存在则将fingerprint变量设置为空并返回。
如下图所示:
判断用户输入的字符串长度是否合法,为零则返回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注入。
Liblinjection转换
typedefenum { 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注入漏洞。Libinjection特征匹配
[例]-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” ⇒ sUE1cLibinjection薄弱环节
除了上述3种sql注入情况,其实还有多种注入方法是没包括在内的。比如,在注释内注入sql攻击。 MYSQL和标准SQL的区别表区别/注释方式 | /**/ | --开头 | # |
标准sql | ok | ok | no |
mysql | ok | --后面跟空格 | ok |
在MySQL中支持三种注释方法:以下都可以是行内注释。
使用#作为开头,后面的全是注释。
使用–作为注释开头,但要注意,MySQL中这种注释方法和SQL Server等其他标准数据库注释语法稍有不同,MySQL要求第二个短线后面必须跟一个空白字符,如空格、制表符等。
使用/**/注释符。标准sql使用c风格的注释: /*this is a comment */.