当前位置:   article > 正文

SQL关键字检测持续优化,太难了

SQL关键字检测持续优化,太难了

麻烦死了,用正则是不是简单些

public class SQLParamChecker {
    // 关键字
    private static List<String> SPECIAL_WORDS;

    private static BloomFilter<String> FILTER;

    static {
        FILTER = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), 100000, 0.01);

        SPECIAL_WORDS = ZYFileUtils.readClassPathFile2List("sql_special_key.txt");
        // 单词的长短倒序,先判断长的,再判断误的,避免长的包含短的误关  如into  in这种,先判断into,再判断in
        SPECIAL_WORDS.sort(Comparator.comparing(String::length).reversed());
    }
    
  public static void main(String[] args) {
        String sql1 = "select Icollect'and(select*from(select+sleep(2))a/**/union/**/select+1)=' select";
        String sql2 = "select ";
        checkExistsIllegalSQL(sql1);
        checkExistsIllegalSQL(sql2);
        checkExistsIllegalSQL(sql2);
    }

    public static void checkExistsIllegalSQL(String context) {
        if (ZYStrUtils.isNull(context)) {
            return;
        }

        if (FILTER.mightContain(context)) {
            return;
        }

        // 统一转为小写
        String text = context.toLowerCase();
        
        if (text.contains("'")) {
            throw new IllegalSqlException();
        }

        // 检查是否存在关键字
        if (hasSpecialWord(text)) {
            throw new IllegalSqlException();
        }
        if (context.length() < 30) {
            //  小于30(经验值)的短参数直接跳过去,用布隆过滤器不知道有没有问题,会有一定的内存溢出风险,比起大量循环判断来说。还是值得一试
            FILTER.put(context);
        }
    }
    private static boolean hasSpecialWord(String text) {
        for (String specialWord : SPECIAL_WORDS) {
            // 等于关键字无所谓
            if (text.length() == specialWord.length()) {
                return false;
            }
            // 找到关键字索引
            List<Integer> indexs = findPlaceLocal(text, specialWord);
            if (indexs.size() == 0) {
                continue;
            }
            for (Integer index : indexs) {
                // 前置检查
                boolean isPreSpecialSymbol;
                if (index == 0) {
                    // 关键字开头
                    isPreSpecialSymbol = true;
                } else {
                    String preLatter = text.substring(index - 1, index);
                    // 前置字母被关键字包裹
                    isPreSpecialSymbol = isSpecialSymbol(preLatter);
                }

                // 后置检查
                int beginIndex = index + specialWord.length();
                int endIndex = beginIndex + 1;
                boolean isAfterSpecialSymbol;
                if (endIndex >= text.length()) {
                    // 关键字结尾
                    isAfterSpecialSymbol = true;
                } else {
                    String postLetter = text.substring(beginIndex, endIndex);
                    // 后置字母被关键字包裹
                    isAfterSpecialSymbol = isSpecialSymbol(postLetter);
                }

                // 检测到关键字,并且关键字的前后是非字母相连,判断为sql关键字   (select *这种 xxxselectxx 这种不算
                if (isPreSpecialSymbol && isAfterSpecialSymbol) {
                    return true;
                }
            }
        }
        return false;
    }

    private static List<Integer> findPlaceLocal(String text, String word) {
        int index = 0;
        List<Integer> placeIndexs = new ArrayList<>();
        while (index != -1) {
            index = ZYStrUtils.indexOf(text, word, index, false);
            if (index != -1) {
                placeIndexs.add(index);
                index = index + word.length();
            }
        }
        return placeIndexs;
    }


    private static boolean isSpecialSymbol(String letter) {
        char aChar = letter.toCharArray()[0];
        char line='_';
        // 数字、字母、下划线
        boolean isLatter =   aChar <= 9 || (aChar >= 97 && aChar <= 122) || aChar == line;;
        return !isLatter;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/神奇cpp/article/detail/1020834
推荐阅读
相关标签
  

闽ICP备14008679号