Druid内置了语义级的waf,为何我们要把waf能力集成到应用中呢?
1)流量waf还是存在各种解析差异导致的bypass,类似于该 例子
2)k8s的逐渐流行,在应用中实现waf能力能减少架构层设计负担
缺点:
1)需要应用安全工程师不间断配合
2)对代码质量较好的开发团队会显得多此一举
本次使用springboot2、mysql5.7、Druid12.23
先看看输入接口
@RequestMapping("list2")
public User getList2(String name) {
if (name == null) {
name = "dato";
}
String x = CheckSqlInjection(name);
if (x != null) {
User u = new User();
u.setName(x);
return u;
}
//@Select("select * from user where name='${name}'")
return userMapper.getUserByName3(name);
}
其中 CheckSqlInjection 内容就是调用Druid进行语义分析的逻辑
public static String CheckSqlInjection(String sql) {
if (sql == null || sql.length() < 6) {
return null;
}
//首先开展基础的sql正则表达式检查
//正则表达式检查
//.......正则检查开始..........
//正则表达式检查结束
//启动druid检查
WallConfig config = new WallConfig("/");
MySqlWallProvider newSqlWallProvider = new MySqlWallProvider(config);
//入参类型包含无符号、单引号、双引号
//也隐藏包含了 SELECT `id`,`uid` from x WHERE `id` LIKE '%2%' 这种like注入
List < String > quotes = Arrays.asList("", "'", "\"");
String checksql;
String re;
for (String quote: quotes) {
checksql = "select id from x where id = " + quote + sql + quote;
WallCheckResult check_quote = newSqlWallProvider.check(checksql);
re = Violation_Message(checksql, check_quote);
if (re != null) {
return re;
}
}
//order by注入的情况下进行校验,order by情况下无单引号或双引号
//似乎和上面的无符号情况一致,可以省略?
/*
checksql = "select id,uid from x order by " + sql;
WallCheckResult check_order_by = newSqlWallProvider.check(checksql);
re = Violation_Message(checksql, check_order_by);
if (re != null) {
return re;
}
*/
//sql的in语句也可以形成sql注入,也需要小心
checksql = "Select id,uid,pid from x where id in (" + sql + ")";
WallCheckResult check_in = newSqlWallProvider.check(checksql);
re = Violation_Message(checksql, check_in);
if (re != null) {
return re;
}
return null;
}
private static String Violation_Message(String Sql, WallCheckResult check) {
List < Violation > violations = check.getViolations();
if (!violations.isEmpty()) {
int firstViolation = violations.get(0).getErrorCode();
//1001是sql语法不正确、未知错误为9999,它俩应忽略掉,因为正常的用户输入都不可能是sql注入
//错误码在druid/wall/violation/ErrorCode.java之中
if (firstViolation != 1001 && firstViolation != 9999) {
//System.out.println("sqlAtt&ck: " + violations.get(0).getMessage() + " : " + Sql + "\n---------");
return violations.get(0).getMessage();
}
}
return null;
}
通过sqlmap不断的测试发现Druid存在bug,无法解析RLIKE注入已经提交给官方,issues地址
所以也将sqlmap中涉及到root用户注入的敏感库和函数都放到了黑名单之中
总结:
1)这个库很成熟了,除了RLIKE这个bug,已经可以完全在输入时就完成语义sql注入校验
2)整体没有什么难度,可以很快就复现传达给同事
标签:checksql,String,waf,Druid,re,阿里,sql,return,check From: https://www.cnblogs.com/k4n5ha0/p/18226456