SQL簡單語義分析概述
來自專欄信息安全入門筆記8 人贊了文章
SQL語義引擎總體概述
int libinjection_sqli(const char* input, size_t slen, char fingerprint[])
判斷字元串input是不是SQL注入語句,返回1是,0不是,fingerprint作為指紋出參,其中核心函數如下:
libinjection_sqli_init(&state, input, slen, 0);
issqli = libinjection_is_sqli(&state);
初始化函數:libinjection_sqli_init()
這個函數沒幹啥,主要註冊了一個回調函數
sf->lookup = libinjection_sqli_lookup_word;
處理函數:libinjection_is_sqli()
主要是這個函數判斷是不是SQL注入攻擊,核心函數如下:
libinjection_sqli_fingerprint()
(指紋識別函數)sql_state->lookup()
(初始化階段的回調函數)
首先概述指紋識別函數:
tlen =
libinjection_sqli_reset
(sql_state, flags);(狀態重置一下)libinjection_sqli_fold
(sql_state);(核心階段)
處理一下返回值,實際上核心數據都已經記錄在sql_state
if (tlen > 2 && sql_state->tokenvec[tlen-1].type == TYPE_BAREWORD && sql_state->tokenvec[tlen-1].str_open == CHAR_TICK && sql_state->tokenvec[tlen-1].len == 0 && sql_state->tokenvec[tlen-1].str_close == CHAR_NULL) { sql_state->tokenvec[tlen-1].type = TYPE_COMMENT; }
將所有 tokenvec
的 type
記錄在指紋 fingerprint
中,至此我們計算出字元串的指紋,調用回調函數判斷是否命中指紋庫即可。
for (i = 0; i < tlen; ++i) { sql_state->fingerprint[i] = sql_state->tokenvec[i].type; } sql_state->fingerprint[tlen] = CHAR_NULL;
判斷記錄指紋 fingerprint
中是否存在 TYPE_EVIL
(無法解析)
如果存在,那麼做如下處理:
if (strchr(sql_state->fingerprint, TYPE_EVIL)) { memset((void*)sql_state->fingerprint, 0, LIBINJECTION_SQLI_MAX_TOKENS + 1); memset((void*)sql_state->tokenvec[0].val, 0, LIBINJECTION_SQLI_TOKEN_SIZE); sql_state->fingerprint[0] = TYPE_EVIL; sql_state->tokenvec[0].type = TYPE_EVIL; sql_state->tokenvec[0].val[0] = TYPE_EVIL; sql_state->tokenvec[1].type = CHAR_NULL; }
返回值是計算出來的指紋
return sql_state->fingerprint;
接下來概述回調函數:
sql_state->lookup(sql_state, LOOKUP_FINGERPRINT, sql_state->fingerprint, strlen(sql_state->fingerprint))
回調函數返回非0,那麼就是SQL注入攻擊,
返回0,就不是。
char libinjection_sqli_lookup_word(struct libinjection_sqli_state *sql_state, int lookup_type, const char* str, size_t len){ if (lookup_type == LOOKUP_FINGERPRINT) { return libinjection_sqli_check_fingerprint(sql_state) ? X :