SQL注入与libinjection分析(3)源码分析之一些重要的结构体说明
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_sqli_state
libinjection_sqli_state 这个结构体主要输入sql字符串及令牌化后的所有涉及的信息
struct libinjection_sqli_state {
const char *s; /* 输入待检测的sql字符串 如 "1' OR 1=1" */
size_t slen; /* 输入待检测的sql字符串的长度 */
/* 输入字符串令牌化(如 s&1)后 去特征库查找的函数指针 在init时候赋值的 这个后面讨论
lookup =
typedef char (*ptr_lookup_fn)(struct libinjection_sqli_state*,
int lookuptype, const char* word, size_t len);
*/
ptr_lookup_fn lookup;
void* userdata; /* 貌似没啥用 */
/* flags 是每次检查的标志 它的结构体: sqli_flags
包括: 没有引号 , 单引号 , 双引号 ,标准sql , mysql */
int flags;
/* 字符串在令牌化过程中的指针位置 如 "1' OR 1=1"
每次往后移动一位去检测 pos 从0 自加*/
size_t pos;
/* 记录输入sql字符串对应的每个令牌结构 最大令牌是5个 这个8 为了字节对齐 */
struct libinjection_sqli_token tokenvec[8];
/* 用于代码中临时指向 tokenvec[i] 每一个令牌结构 用于判断处理 */
struct libinjection_sqli_token *current;
/* 存储输入sql字符串 令牌化后的 令牌 如 数字在令牌化后都变成 1(看 sqli_token_types ) ,
同上 最大令牌5个+一个结束符 NULL */
char fingerprint[8];
/* debug情况下记录 是否为sqli 的理由 即是在代码哪一行决定的 */
int reason;
/* mysql注释方式为 --加空格 模式
MYSQL和标准SQL的区别(注释)在上个博客中已经说明 */
int stats_comment_ddw;
int stats_comment_ddx; /* mysql中 --后面没有空格和-一个破折号 的非注释情况处理 */
int stats_comment_c; /* c语言模式注释 /x . x/ 未涉及 */
/* 处理# 其中,ANSI模式下#是个操作符, mysql模式下 #是个注释 后面跟注释 */
int stats_comment_hash;
int stats_folds; /* 用来统计sql输入字符串令牌化后的个数 令牌化一个就+1 */
/* 用于统计一共令牌化了几个字符串 如 "1' OR 1=1"
令牌化后就是 s&1 那么 stats_tokens = 3 */
int stats_tokens;
};
2. libinjection_sqli_token
libinjection_sqli_token 记录令牌的信息
struct libinjection_sqli_token {
size_t pos; /* 记录sql输入字符串被令牌化的位置 如果转换了 pos+1 */
size_t len; /* 记录sql输入字符串被令牌化长度 */
int count; /* 记录@符号开头的数量 */
/*
记录每个字符令牌化后的类型 类型在 sqli_token_types 中
如
TYPE_NUMBER = (int)'1' /*所有数字会被识别为1
TYPE_STRING = (int)'s' /*单引号和双引号
……等等
*/
char type;
/*
记录字符串开始字符是什么
如 CHAR_TICK '`'
CHAR_SINGLE '\''
或者其他具体字符等
记录字符串结束字符是什么
如 CHAR_NULL '\0'
或者其他具体字符等
*/
char str_open;
char str_close;
/* 记录输入字符串的每个字符的令牌 一般结尾+结束符\0 */
char val[32];
};
3. sqli_flags
sqli_flags 其中的标志位记录 libinjection_sqli_fingerprint 进行令牌/指纹化过程中的参数类型
分四种情况:
1. FLAG_QUOTE_NONE + FLAG_SQL_ANSI 无引号,标准SQL语法
2. FLAG_QUOTE_NONE + FLAG_SQL_MYSQL 无引号,MYSQL语法
3. FLAG_QUOTE_SINGLE + FLAG_SQL_MYSQL 单引号,MYSQL语法
4. FLAG_QUOTE_DOUBLE + FLAG_SQL_MYSQL 单引号,MYSQL语法
enum sqli_flags {
FLAG_NONE = 0
, FLAG_QUOTE_NONE = 1 /* 1 << 0 */
, FLAG_QUOTE_SINGLE = 2 /* 1 << 1 */
, FLAG_QUOTE_DOUBLE = 4 /* 1 << 2 */
, FLAG_SQL_ANSI = 8 /* 1 << 3 */
, FLAG_SQL_MYSQL = 16 /* 1 << 4 */
};
4. lookup_type
-
LOOKUP_WORD
/* 查找字符串对应的令牌类型
返回 sql_keywords 中字符对应的类型 对应的 sqli_token_types 表中的类型 */ -
LOOKUP_TYPE /* 未涉及 */
-
LOOKUP_OPERATOR
/* 查找字符串的操作符对应的令牌类型
返回 sql_keywords 中字符对应的类型 对应的 sqli_token_types 表中的类型 */ -
LOOKUP_FINGERPRINT
/* 输入sql字符串最终的令牌/指纹 进行特征库查找 */enum lookup_type { LOOKUP_WORD = 1 , LOOKUP_TYPE = 2 , LOOKUP_OPERATOR = 3 , LOOKUP_FINGERPRINT = 4 };
5. sqli_token_types
-
sqli_token_types 是规定的字符串对应的令牌/指纹的转换表
-
其中,TYPE_XXX 类型在 sql_keywords (就叫它一个特征库表吧)中给出
-
这个 sql_keywords 表一共列出了 9352 种特征情况,并给出每种情况的特征结果,结果就是 sqli_token_types key值
typedef enum { TYPE_NONE = 0 , TYPE_KEYWORD = (int)'k' // 关键字 多 如 SELECT ALTER IN FROM , TYPE_UNION = (int)'U' // 就几个 如 EXCEPT/返回两个结果集的差 UNION/并集 INTERSECT/交集 , TYPE_GROUP = (int)'B' // 分组 GROUP BY/进行分组 ORDER BY/对结果集进行排序 LIMIT/限制查询结果返回的数量 , TYPE_EXPRESSION = (int)'E' // 表达式 如 CASE/判断 SELECT/选择 UPDATE/修改 , TYPE_SQLTYPE = (int)'t' // sql类型 很多 具体 TYPE_SQLTYPE 参见下面解释 , TYPE_FUNCTION = (int)'f' // sql函数 很多 具体 TYPE_FUNCTION 参见下面解释 , TYPE_BAREWORD = (int)'n' // 裸词 如 BY DO DATABASE LOCK/LOCK IN FOR OUT WITH , TYPE_NUMBER = (int)'1' // Number 类型 FLOAT Double True/False也是的 , TYPE_VARIABLE = (int)'v' // sql 变量 如 CURRENT DATE/PATH/TIME 等 及 NULL UNKNOWN , TYPE_STRING = (int)'s' // 字符串 一般以 ' 和 '' 开头 , TYPE_OPERATOR = (int)'o' // 操作符 如 += >> 及 常用的BETWEEN IS NOT IS NULL等等 , TYPE_LOGIC_OPERATOR = (int)'&' // 逻辑操作符 暂时未涉及 , TYPE_COMMENT = (int)'c' // 注释处理 --空格 # /* */ , TYPE_COLLATE = (int)'A' // 排序 就一个 COLLATE collate在sql中是用来定义排序规则的 , 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 */ // Transact-SQL 是SQL的增强版常见 BEGIN GO GOTO CALL等 , TYPE_UNKNOWN = (int)'?' // 未知符号 , TYPE_EVIL = (int)'X' /* unparsable, abort */ // 不能解释的符号 , TYPE_FINGERPRINT = (int)'F' /* not really a token */ // 指纹符号 , TYPE_BACKSLASH = (int)'\\' // 反斜杠 \ } sqli_token_types;
其中,常见数据类型如下所示:
- TYPE_SQLTYPE 常见的有:整形,单精度,双精度,可变长度字符,固定长度字符,长型,日期等等。
Binary ·Varbinary ·Char·Varchar·Nchar·Nvarchar·Datetime ·Text ·Image ·Ntext
·Smalldatetime ·Decimal ·Numeric·Float·Real ·Int ·Smallint ·Tinyint
·Money ·Smallmoney ·Bit ·Cursor ·Sysname ·Timestamp ·Uniqueidentifier - TYPE_FUNCTION SQL 拥有很多可用于计数和计算的内建函数
函数的基本类型是:
Aggregate 合计函数/Aggregate functions AVG/平均值 COUNT/行数 MAX MIN SUM FIRST LAST
Scalar 函数 UCASE,LCASE/转大小写 LEN/长度 MOD/取余
6. char_parse_map
char_parse_map 列出了 ASCII表每个字符对于的解析函数
例如, ASCII前32个字符都通过 parse_white 函数处理,其不处理+1 往后进行
例如, ASCII 48到57 是数字 0-9 通过 parse_number 函数处理
其中 129-255 这写字符通过 parse_word 函数处理
这里为什么是255 ? 没整明白 不应该只有128吗?
typedef struct libinjection_sqli_state sfilter;
typedef size_t (*pt2Function)(sfilter *sf);
static const pt2Function char_parse_map[] = {
&parse_white, /* 0 */
……
&parse_white, /* 32 */
&parse_operator2, /* 33 */
&parse_string, /* 34 */
&parse_hash, /* 35 */
&parse_money, /* 36 */
&parse_operator1, /* 37 */
&parse_operator2, /* 38 */
&parse_string, /* 39 */
&parse_char, /* 40 */
&parse_char, /* 41 */
&parse_operator2, /* 42 */
&parse_operator1, /* 43 */
&parse_char, /* 44 */
&parse_dash, /* 45 */
&parse_number, /* 46 */
&parse_slash, /* 47 */
&parse_number, /* 48 */
……
&parse_operator2, /* 58 */
&parse_char, /* 59 */
&parse_operator2, /* 60 */
……
&parse_other, /* 63 */
&parse_var, /* 64 */
&parse_word, /* 65 */
&parse_bstring, /* 66 */
&parse_word, /* 67 */
&parse_word, /* 68 */
&parse_estring, /* 69 */
&parse_word, /* 70 */
……
&parse_word, /* 77 */
&parse_nqstring, /* 78 */
&parse_word, /* 79 */
&parse_word, /* 80 */
&parse_qstring, /* 81 */
&parse_word, /* 82 */
&parse_word, /* 83 */
&parse_word, /* 84 */
&parse_ustring, /* 85 */
&parse_word, /* 86 */
&parse_word, /* 87 */
&parse_xstring, /* 88 */
&parse_word, /* 89 */
&parse_word, /* 90 */
&parse_bword, /* 91 */
&parse_backslash, /* 92 */
&parse_other, /* 93 */
&parse_operator1, /* 94 */
&parse_word, /* 95 */
&parse_tick, /* 96 */
&parse_word, /* 97 */
&parse_bstring, /* 98 */
&parse_word, /* 99 */
&parse_word, /* 100 */
&parse_estring, /* 101 */
&parse_word, /* 102 */
……
&parse_word, /* 109 */
&parse_nqstring, /* 110 */
&parse_word, /* 111 */
&parse_word, /* 112 */
&parse_qstring, /* 113 */
&parse_word, /* 114 */
……
&parse_ustring, /* 117 */
&parse_word, /* 118 */
&parse_word, /* 119 */
&parse_xstring, /* 120 */
&parse_word, /* 121 */
&parse_word, /* 122 */
&parse_char, /* 123 */
&parse_operator2, /* 124 */
&parse_char, /* 125 */
&parse_operator1, /* 126 */
&parse_white, /* 127 */
&parse_word, /* 128 */
……
&parse_word, /* 255 */
};
7. sql_keywords
sql_keywords 列出了 9352 种特征对应的指纹/令牌字典表
由于篇幅,下表省略了许多。
static const keyword_t sql_keywords[] = {
{"!!", 'o'},
……
{"0&(1)O", 'F'},
……
{"0VUVOS", 'F'},
{"0X", 'F'},
{"::", 'o'},
……
{"ABORT", 'k'},
{"ABS", 'f'},
{"ADDDATE", 'f'},
{"ADDTIME", 'f'},
{"AND", '&'},
{"ANY", 'f'},
{"EXIT", 'k'},
……
{"FOR", 'n'},
{"TOP", 'k'},
{"TOTAL", 'f'},
{"UNION", 'U'},
……
{"WHEN", 'k'},
{"WHERE", 'k'},
……
{"_UTF8", 't'},
{"|/", 'o'},
{"|=", 'o'},
{"||", '&'},
{"~*", 'o'},
};
static const size_t sql_keywords_sz = 9352;
参考
源码托管在在github上:
https://github.com/Audi-1/sqli-labs
https://zhuanlan.zhihu.com/p/44292411
https://zhuanlan.zhihu.com/p/44537204
https://www.anquanke.com/post/id/86097