[源代码审计]黑名单过滤绕过
今天发现一个绕过正则过滤的问题,很多应用使用正则表达式对输入数据做安全验证,比如,在修改设备名称时的过滤过则为:
String regex = "^.*[\\\\/:\\*\\?\"<>\\|'%&]+.*$"; //出现1个或多个”\/:*?"<>|'%&”字符表示不合法
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
但我们发现当输入回车换行符(\r\n)时该验证正则表达式即可被绕过(紧接着出现安全问题),比如输入”abc\r\n<>”是检测不到的,原因在于'.' 默认是不匹配象'\r','\n'等的,如果要匹配则使用OPTIONS Pattern.DOTALL,故应写:
Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
但是,没人能保证这样写就没有其它可以继续绕过的情况了,所以这个问题的本质原因并非错误地使用了方法,而是没有使用白名单进行过滤,即只允许指定的字符通过,其它都是不允许的,以下是OWASP ESAPI对文件名和目录名的白名单过滤规则,供大家参考:
Validator.FileName=^[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$ //[]内的字符是允许出现的白名单字符,长度为1-255,出现其它字符都是非法的
Validator.DirectoryName=^[a-zA-Z0-9:/\\\\!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$
同理地,我们也可以为设备名称等各种用户输入设定类似字符白名单,因此,强烈建议大家改用白名单的方式来做数据安全验证。