2021SC@SDUSC
SQL注入处理
介绍
攻击者利用web应用程序对用户输入验证上的疏忽,在输入的数据中包含对某些数据库系统有特殊意义的符号或命令,让攻击者有机会直接对后台数据库系统下达指令,进而实现对后台数据库的入侵。
原理
SQL注入攻击的本质,服务端没有过滤用户输入的恶意数据,直接把用户输入的数据当作SQL语句执行,从而影响数据库安全和平台安全。
因此,在SQL注入时,应该对输入进行充分的检查,过滤用户的恶意数据
private final static String TABLE_DICT_SIGN_SALT = "20200501";
private final static String xssStr = "'|and |exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+|,";
在表中可看到上线修改值为20200501
xssStr中包含了执行SQL语句的命令关键字、执行存储过程的命令关键字等等,他们可能会影响数据库的安全和平台安全,被称为注入关键字,需要对其进行过滤增强安全机制
public static void checkDictTableSign(String dictCode, String sign, HttpServletRequest request) {
String accessToken = request.getHeader("X-Access-Token");
String signStr = dictCode + SqlInjectionUtil.TABLE_DICT_SIGN_SALT + accessToken;
String javaSign = SecureUtil.md5(signStr);
if (!javaSign.equals(sign)) {
log.error("表字典,SQL注入漏洞签名校验失败 :" + sign + "!=" + javaSign+ ",dictCode=" + dictCode);
throw new JeecgBootException("无权限访问!");
}
log.info(" 表字典,SQL注入漏洞签名校验成功!sign=" + sign + ",dictCode=" + dictCode);
}
针对表字典进行额外的sign签名校验,防止漏洞注入,增加安全机制
public static void filterContent(String value) {
if (value == null || "".equals(value)) {
return;
}
value = value.toLowerCase();
String[] xssArr = xssStr.split("\\|");
for (int i = 0; i < xssArr.length; i++) {
if (value.indexOf(xssArr[i]) > -1) {
log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
log.error("请注意,值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
}
}
return;
}
public static void filterContent(String[] values) {
String[] xssArr = xssStr.split("\\|");
for (String value : values) {
if (value == null || "".equals(value)) {
return;
}
// 统一转为小写
value = value.toLowerCase();
for (int i = 0; i < xssArr.length; i++) {
if (value.indexOf(xssArr[i]) > -1) {
log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
log.error("请注意,值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
}
}
}
将SQL注入数据统一转换成小写,通过for (int i = 0; i < xssArr.length; i++)
循环,对xxArr
中每一位数据进行检验,如果遇到注入关键字的话直接抛出异常
@Deprecated
public static void specialFilterContent(String value) {
String specialXssStr = " exec | insert | select | delete | update | drop | count | chr | mid | master | truncate | char | declare |;|+|";
String[] xssArr = specialXssStr.split("\\|");
if (value == null || "".equals(value)) {
return;
}
// 统一转为小写
value = value.toLowerCase();
for (int i = 0; i < xssArr.length; i++) {
if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
log.error("请注意,值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
}
}
return;
}
特殊方法,仅用于字典条件SQL参数,注入过滤,不仅能通过value.indexOf(xssArr[i]) > -1
进行判断,还可以通过value.startsWith(xssArr[i].trim())
进行判断
startsWith()
方法一般用于检测某请求字符串是否以指定的前缀开始的,如果含有注入关键字,则抛出异常。
@Deprecated
public static void specialFilterContentForOnlineReport(String value) {
String specialXssStr = " exec | insert | delete | update | drop | chr | mid | master | truncate | char | declare |";
String[] xssArr = specialXssStr.split("\\|");
if (value == null || "".equals(value)) {
return;
}
// 统一转为小写
value = value.toLowerCase();
for (int i = 0; i < xssArr.length; i++) {
if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
log.error("请注意,存在SQL注入关键词---> {}", xssArr[i]);
log.error("请注意,值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value);
}
}
return;
}
特殊方法(不通用) 仅用于Online报表SQL解析,注入过滤。其处理原理和字典条件SQL参数一样。
相关拓展:手工检测SQL注入漏洞