java代码安全规范_JAVA代码安全规范
申明:本⽂⾮笔者原创,原⽂转载⾃:github/SecurityPaper/SecurityPaper-
web/blob/master/_posts/2.SDL%E8%A7%84%E8%8C%83%E6%96%87%E6%A1%A3/2018-08-17-SDL-3-
java%E5%AE%89%E5%85%A8%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83.md
1输⼊验证和数据合法性校验
程序接受数据可能来源于未经验证的⽤户,⽹络连接和其他不受信任的来源,如果未对程序接受数据进⾏校验,则可能会引发安全问题。
1.1避免SQL注⼊
1.1.1  使⽤PreparedStatement预编译SQL,解决SQL注⼊问题,传递给PreparedStatement对象的参数可以被强制进⾏类型转换,确保在插⼊或查询数据时与底层的数据库格式匹配。
String sqlString = "select * from db_user where username=? and password=?";
PreparedStatement stmt = connection.prepareStatement(sqlString);
stmt.setString(1, username);
stmt.setString(2, pwd);
ResultSet rs = uteQuery();
1.1.2 Mybatis 使⽤#{ },相当于使⽤PreparedStatement
1.1.3 采⽤正则表达式将包含有 单引号('),分号(;) 和 注释符号(--)的语句给替换掉来防⽌SQL注⼊。还要⼩⼼ (OR)等敏感词汇。
1.1.4 增加过滤器。Druid连接池已经实现了此过滤器wallfilter触发后默认返回SQLException,只需要配置即可。
BOOT:github/alibaba/druid/tree/master/druid-spring-boot-starter
1.2避免XML注⼊
通过StringBulider 或 StringBuffer 拼接XML⽂件时,需对输⼊数据进⾏合法性校验。 对数量quantity 进⾏合法性校验,控制只能传⼊0-9的数字:
if (!Pattern.matches("[0-9]+", quantity)) {
// Format violation
}
String xmlString = "\nWidget\n" +
"500\n" +
"" + quantity + "";
outStream.Bytes());
outStream.flush();
1.3避免跨站点脚本(XSS)
web项⽬通过Filter +HttpServletRequestWrapper  过滤
对产⽣跨站的参数进⾏严格过滤,禁⽌传⼊
//定义需过滤的字段串
String s = "\uFE64" + "script" + "\uFE65";
// 过滤字符串标准化
s = alize(s, Form.NFKC);
// 使⽤正则表达式匹配inputStr是否存在
Pattern pattern = Patternpile(inputStr);
Matcher matcher = pattern.matcher(s);
if (matcher.find()) {
// Found black listed tag
throw new IllegalStateException();
} else {
// ...
}
1.4 CSRF跨站请求伪造
下⾯是CSRF的常见特性:
1. 依靠⽤户标识危害⽹站
java源代码加密2. 利⽤⽹站对⽤户标识的信任
3. 欺骗⽤户的浏览器发送HTTP请求给⽬标站点
4. 可以通过IMG标签会触发⼀个GET请求,可以利⽤它来实现CSRF攻击
⼀个简单的例⼦:
* 同⼀浏览器⽤户⼩z登录了⽹站A,同时打开⽹站B
* ⽹站B隐蔽的发送⼀个请求⾄⽹站A
* ⽹站A通过session、cookie等⾝份标记判断是⽤户⼩z,执⾏对应操作
这样⽹站B内的⾮法代码就盗⽤了⽤户⼩z的⾝份,在⼩z不知情的情况下执⾏了攻击者需要的操作,这就是跨站请求伪造。
防御CSRF可以通过动态token验证的⽅式来实现,每次请求⽣成⼀个动态token给前端,前端在后续的请求中附加该token,如果token不存在或不正确说明不是正常请求,予以屏蔽,从⽽达到解决CSRF问题的⽬的,以下是具体实现。
1.5 IP限流防刷
2声明和初始化
2.1避免类初始化的相互依赖
例:
错误的写法:
public class Cycle {
private final int balance;
private static final Cycle c = new Cycle();
private static final int deposit = (int) (Math.random() * 100); // Random deposit
public Cycle() {
balance = deposit - 10; // Subtract processing fee
}
public static void main(String[] args) {
System.out.println("The account balance is: " + c.balance);
}
}
类加载时初始化指向Cycle类的静态变量c,⽽类Cycle的⽆参构造⽅法⼜依赖静态变量deposit,导致⽆法预期的结果。 正确的写法:public class Cycle {
private final int balance;
private static final int deposit = (int) (Math.random() * 100); // Random deposit
private static final Cycle c = new Cycle();  // Inserted after initialization of required fields
public Cycle() {
balance = deposit - 10; // Subtract processing fee
}
public static void main(String[] args) {
System.out.println("The account balance is: " + c.balance);
}
}
3表达式
3.1不可忽略⽅法的返回值
忽略⽅法的放回值可能会导致⽆法预料的结果。
错误的写法:
public void deleteFile(){
File someFile = new File("");
someFile.delete();
}
正确的写法:
public void deleteFile(){
File someFile = new File("");
if (!someFile.delete()) {
// handle failure to delete the file
}
}
3.2不要引⽤空指针
当⼀个变量指向⼀个NULL值,使⽤这个变量的时候⼜没有检查,这时会导致。NullPointerException。
在使⽤变量前⼀定要做是否为NULL值的校验。
Object obj = getObject();
if (obj != null){
}
3.3使⽤Arrays.equals()来⽐较数组的内容
数组没有覆盖的Object. equals()⽅法,调⽤Object. equals()⽅法实际上是⽐较数组的引⽤,⽽不是他们的内容。程序必须使⽤两个参数Arrays.equals()⽅法来⽐较两个数组的内容
public void arrayEqualsExample() {
int[] arr1 = new int[20]; // initialized to 0
int[] arr2 = new int[20]; // initialized to 0
Arrays.equals(arr1, arr2); // true
}
4数字类型和操作
4.1防⽌整数溢出
使⽤java.lang.Number. BigInteger类进⾏整数运算,防⽌整数溢出。
基本操作 add,subtract,multiply,divide,compareTo
public class BigIntegerUtil {
private static final BigInteger bigMaxInt = BigInteger.valueOf(Integer.MAX_VALUE);
private static final BigInteger bigMinInt = BigInteger.valueOf(Integer.MIN_VALUE);
public static BigInteger intRangeCheck(BigInteger val) throws ArithmeticException {
if (valpareTo(bigMaxInt) == 1 || valpareTo(bigMinInt) == -1) {
throw new ArithmeticException("Integer overflow");
}
return val;
}
public static int addInt(int v1, int v2) throws ArithmeticException {
BigInteger b1 = BigInteger.valueOf(v1);
BigInteger b2 = BigInteger.valueOf(v2);
BigInteger res = intRangeCheck(b1.add(b2));
return res.intValue();
}
public static int subInt(int v1, int v2) throws ArithmeticException {
BigInteger b1 = BigInteger.valueOf(v1);
BigInteger b2 = BigInteger.valueOf(v2);
BigInteger res = intRangeCheck(b1.subtract(b2));
return res.intValue();
}
public static int multiplyInt(int v1, int v2) throws ArithmeticException {
BigInteger b1 = BigInteger.valueOf(v1);
BigInteger b2 = BigInteger.valueOf(v2);
BigInteger res = intRangeCheck(b1.multiply(b2));
return res.intValue();
}
public static int divideInt(int v1, int v2) throws ArithmeticException {
BigInteger b1 = BigInteger.valueOf(v1);
BigInteger b2 = BigInteger.valueOf(v2);
BigInteger res = intRangeCheck(b1.divide(b2));
return res.intValue();
}
}
4.2避免除法和取模运算分母为零
要避免因为分母为零⽽导致除法和取模运算出现异常。
if (num2 == 0) {
// handle error
} else {
result1= num1 /num2;
result2= num1 % num2;
}
5类和⽅法操作
5.1数据成员声明为私有,提供可访问的包装⽅法
攻击者可以⽤意想不到的⽅式操纵public或protected的数据成员,所以需要将数据成员为private,对外提供可控的包装⽅法访问数据成员。
5.2敏感类不允许复制
包含私⼈的,机密或其他敏感数据的类是不允许被复制的,解决的⽅法有两种:
1、类声明为final
final class SensitiveClass {
// ...

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。