1.SQL注入
在输入的字符串之中注入恶意的SQL指令,这些注入的指令会被数据库误认为是正常的SQL指令进行执行,是系统遭到破坏。
例:
String selectid=“select”+id+” from StuInfo “;
或:String selectid=“select id from StuInfo where id=”+id;
上述两句SQL查询语句没有对输入进行限制,用户可以随意输入任意字符,从而给攻击者提供机会。例:id输入为:1 or 1=1,此时SQL语句为selectid from StuInfo where id=1 or 1=1该语句始终为真,因此or前的内容可以随意输入。
攻击过程:
程序中getParameter()获取用户的输入,将获取到的输入拼接到SQL语句中。
建议:
1)SQL语句使用参数化查询的方式,如:
PreparedStatement ps = conn.prepareStatement(“select * from tb_myinfo where name=?”);
ps.setString(1,’Anna’);
2)过滤特殊字符
①使用正则表达式过滤特殊字符
②使用添加全局过滤器
过滤类中将所有特殊字符通过replace替换成空字符,需要过滤的字符有:
and、or、select、update、drop、declare、insert、空格、||、|、’、”、+、&、;、%、@、-、#、//、<>、\’(转义单引号)、\”(转义双引号)、\等。
2.敏感信息泄露:JSP中的HTML注释(System Information Leak:HTML Commentin JSP)
某个.JSP网页文件里面有HTML注释,这样做有一个很大的风险是:可能把一些内部的信息泄露给用户。
虽然有的HTML注释记录的可能是一些不相关的信息,但是作为一个良好的习惯,不应该在网页文件里添加HTML注释。
建议:
使用JSP注释,JSP注释分为两种:显式注释(<!–显示注释 –>)、隐式注释(<%– 隐式注释 –%>),其中隐式注释在浏览器控制台不可见。
3.字符串比较(Erroneous String Compare)
程序采用 == 或!= 来比较两个字符串是否相等,实质是比较两个对象,而不是字符串的值。因此,若采用这个方法,两个引用将永远不会相等。
建议:使用equals比较两个字符串。
4.未释放资源:流(Unreleased Resource: Streams)
程序可能无法成功释放某一项系统资源。
可能会导致软件可靠性问题,如果攻击者能够故意触发资源泄漏,该攻击者就有可能通过耗尽资源池的方式发起DOS攻击。
例:
建议:
最好把资源定义放在try{}catch{}外,并且在finally{}里面进行统一释放。
上例中关闭时try/catch异常:
5.不安全随机数(Insecure Randomness)
在对安全性要求较高的环境中,使用一个能产生可预测数值的函数作为随机数据源,会产生 Insecure Randomness 错误。
电脑是一种具有确定性的机器,因此不可能产生真正的随机性。伪随机数生成器 (PRNG) 近似于随机算法,通常情况下,如果并未声明 PRNG 算法带有加密保护,那么它有可能就是一个统计学的 PRNG,不应在对安全性要求较高的环境中使用,其中随着它的使用可能会导致严重的漏洞(如易于猜测的密码、可预测的加密密钥、会话劫持攻击和 DNS 欺骗)。
例:
String GenerateReceiptURL(String baseUrl) {
Random ranGen = new Random();
ranGen.setSeed((newDate()).getTime());
return(baseUrl + Gen.nextInt(400000000) +”.html”);
}
这段代码使用Random.Next()函数为由其产生的收据页面生成“唯一”的标识符。因为 Random.nextInt()是一个统计学 PRNG,攻击者很容易就能猜到由它生成的字符串。尽管收据系统的底层设计也存在错误,但如果使用了一个不生成可预测收据标识符的随机数生成器(如密码学的 PRNG),会更安全一些。
建议:
使用SecureRandom函数产生随机数。Java 语言在 java.security.SecureRandom 中提供了一个加密 PRNG,SecureRandom提供了与某个特定算法集合相关的包,该包可以独立实现。
6.死代码:无用函数(Dead Code:Unused Method)
程序员申明的函数在整个程序中并未被只用,因此Fortify建议删除此类函数。
7. J2EE 不好的做法:残余调试代码(J2EE Bad Practices:Leftover Debug Code)
一些调试用的函数,如main(),是一些潜在入口,如果这类调试代码无意中被保留在应用程序中,则会导致应用程序向计划外的交互模式开放。这些后门入口点很容易产生安全隐患,因为它们不在当初的设计或者测试的考虑之内,并且不会出现在应用程序设计中的操作环境里。
遗忘调试代码中最常见例子出现在web应用程序中的main()
方法。尽管这在产品的开发过程中是完全可以接受的,但是属于J2EE(WEB)应用程序中的那部分类不应该定义main()
。
Fortify建议删除这些调试代码。
8. 代码正确性:双重检查锁定
Double-Checked Locking方法被广泛的使用于实现多线程环境下单例模式的懒加载方式实现,不幸的是,在JAVA中,这种方式有可能不能够正常工作。
例:
程序中出现同一变量两次为空判断,第二次为空判断多余。
建议:
去掉代码中第一个为空判断。
来源:freebuf.com 2019-03-11 09:18:40 by: 凯信特安全团队
请登录后发表评论
注册