libinjection 语义分析通用绕过分析
字数 919 2025-08-20 18:17:47

Libinjection 语义分析通用绕过分析

1. 概述

Libinjection 是一个用于检测 SQL 注入攻击的开源库,它通过语义分析而非简单的模式匹配来识别恶意输入。本文详细分析了一种绕过 libinjection 检测的方法,并深入探讨了其工作原理。

2. 测试环境搭建

2.1 示例代码

#include <stdio.h>
#include <strings.h>
#include <errno.h>
#include "libinjection.h"
#include "libinjection_sqli.h"

int main(int argc, const char* argv[]) {
    struct libinjection_sqli_state state;
    int issqli;
    const char* input = argv[1];
    size_t slen = strlen(input);
    
    libinjection_sqli_init(&state, input, slen, FLAG_NONE);
    issqli = libinjection_is_sqli(&state);
    
    if (issqli) {
        fprintf(stderr, "sqli detected with fingerprint of '%s'\n", state.fingerprint);
    }
    return issqli;
}

2.2 编译与测试

# 编译
gcc -o bin example1.c libinjection_sqli.c

# 测试1 - 被检测到的SQL注入
./bin "1' and 1=1"
# 输出: sqli with fingerprint of 's&1'

# 测试2 - 未被检测到的SQL注入
./bin "ad1n'-- %a%0aunion select 1,database(),user() -- "
# 输出: not sqli

3. Libinjection 工作原理

3.1 运行流程

Libinjection 内部分为六种解析模式:

  1. 无符号 标准SQL 模式
  2. 无符号 MySQL 模式
  3. 单引号 标准SQL 模式
  4. 单引号 MySQL 模式
  5. 双引号 MySQL 模式
  6. 双引号 标准模式

3.2 核心函数分析

libinjection_sqli_tokenize 是转换内部字符的主要入口函数:

int libinjection_sqli_tokenize(struct libinjection_sqli_state* sf) {
    pt2Function fnptr;
    size_t* pos = &sf->pos;
    stoken_t* current = sf->current;
    const char* s = sf->s;
    const size_t slen = sf->slen;
    
    if (slen == 0) {
        return FALSE;
    }
    
    // 初始化
    st_clear(current);
    sf->current = current;
    
    if (*pos == 0 && (sf->flags & (FLAG_QUOTE_SINGLE | FLAG_QUOTE_DOUBLE))) {
        *pos = parse_string_core(s, slen, 0, current, flag2delim(sf->flags), 0);
        printf("单引号双引号进入");
        sf->stats_tokens += 1;
        return TRUE;
    }
    
    while (*pos < slen) {
        const unsigned char ch = (unsigned char)(s[*pos]);
        fnptr = char_parse_map[ch];
        *pos = (*fnptr)(sf);
        
        if (current->type != CHAR_NULL) {
            sf->stats_tokens += 1;
            return TRUE;
        }
    }
    return FALSE;
}

4. 绕过原理分析

4.1 示例payload解析

"ad1n'-- %a%0aunion select 1,database(),user() -- " 的解析过程:

  1. ad1n' 首先进入无符号的标准SQL模式
  2. 发现单引号后转到单引号的标准SQL模式
  3. 获取 ad1n' 后 break
  4. 遇到 -- 进入 parse_dash 函数

4.2 parse_dash 函数分析

static size_t parse_dash(struct libinjection_sqli_state* sf) {
    const char* cs = sf->s;
    const size_t slen = sf->slen;
    size_t pos = sf->pos;
    
    if (pos + 2 < slen && cs[pos + 1] == '-' && char_is_white(cs[pos + 2])) {
        return parse_eol_comment(sf);
    }
    else if (pos + 2 == slen && cs[pos + 1] == '-') {
        return parse_eol_comment(sf);
    }
    else if (pos + 1 < slen && cs[pos + 1] == '-' && (sf->flags & FLAG_SQL_ANSI)) {
        sf->stats_comment_ddx += 1;
        return parse_eol_comment(sf);
    }
    else {
        st_assign_char(sf->current, TYPE_OPERATOR, pos, 1, '-');
        return pos + 1;
    }
}

4.3 parse_eol_comment 函数分析

static size_t parse_eol_comment(struct libinjection_sqli_state* sf) {
    const char* cs = sf->s;
    const size_t slen = sf->slen;
    size_t pos = sf->pos;
    const char* endpos = (const char*)memchr((const void*)(cs + pos), '\n', slen - pos);
    
    if (endpos == NULL) {
        st_assign(sf->current, TYPE_COMMENT, pos, slen - pos, cs + pos);
        return slen;
    }
    else {
        st_assign(sf->current, TYPE_COMMENT, pos, (size_t)(endpos - cs) - pos, cs + pos);
        return (size_t)((endpos - cs) + 1);
    }
}

4.4 st_assign 函数分析

static void st_assign(stoken_t* st, const char stype, size_t pos, size_t len, const char* value) {
    const size_t MSIZE = LIBINJECTION_SQLI_TOKEN_SIZE;
    size_t last = len < MSIZE ? len : (MSIZE - 1);
    
    st->type = (char)stype;
    st->pos = pos;
    st->len = last;
    memcpy(st->val, value, last);
    st->val[last] = CHAR_NULL;
}

5. 绕过关键点

  1. admin' 被转换为 S 类型
  2. -- 注释后的内容被简单地标记为 TYPE_COMMENT (C)
  3. 最终得到的匹配规则为 SC,这种组合不在 libinjection 的检测规则库中
  4. 注释处理过于简单,没有深入分析注释后的SQL语句

6. 防御建议

  1. 改进注释处理逻辑,对注释后的内容进行更严格的分析
  2. 更新指纹库,添加 SC 这种组合的检测规则
  3. 结合其他检测方法,如语法分析,提高检测准确性
  4. 对URL编码的内容进行解码后再分析

7. 总结

这种绕过方法利用了 libinjection 对注释处理的不足,通过构造特定的注释格式来隐藏恶意SQL语句。理解这种绕过技术有助于改进SQL注入检测机制,提高Web应用的安全性。

Libinjection 语义分析通用绕过分析 1. 概述 Libinjection 是一个用于检测 SQL 注入攻击的开源库,它通过语义分析而非简单的模式匹配来识别恶意输入。本文详细分析了一种绕过 libinjection 检测的方法,并深入探讨了其工作原理。 2. 测试环境搭建 2.1 示例代码 2.2 编译与测试 3. Libinjection 工作原理 3.1 运行流程 Libinjection 内部分为六种解析模式: 无符号 标准SQL 模式 无符号 MySQL 模式 单引号 标准SQL 模式 单引号 MySQL 模式 双引号 MySQL 模式 双引号 标准模式 3.2 核心函数分析 libinjection_sqli_tokenize 是转换内部字符的主要入口函数: 4. 绕过原理分析 4.1 示例payload解析 "ad1n'-- %a%0aunion select 1,database(),user() -- " 的解析过程: ad1n' 首先进入无符号的标准SQL模式 发现单引号后转到单引号的标准SQL模式 获取 ad1n' 后 break 遇到 -- 进入 parse_dash 函数 4.2 parse_ dash 函数分析 4.3 parse_ eol_ comment 函数分析 4.4 st_ assign 函数分析 5. 绕过关键点 admin' 被转换为 S 类型 -- 注释后的内容被简单地标记为 TYPE_COMMENT (C) 最终得到的匹配规则为 SC ,这种组合不在 libinjection 的检测规则库中 注释处理过于简单,没有深入分析注释后的SQL语句 6. 防御建议 改进注释处理逻辑,对注释后的内容进行更严格的分析 更新指纹库,添加 SC 这种组合的检测规则 结合其他检测方法,如语法分析,提高检测准确性 对URL编码的内容进行解码后再分析 7. 总结 这种绕过方法利用了 libinjection 对注释处理的不足,通过构造特定的注释格式来隐藏恶意SQL语句。理解这种绕过技术有助于改进SQL注入检测机制,提高Web应用的安全性。