威胁描述
程序会调用解析 double
类型的方法,这会导致线程被挂起。
威胁说明
在实施 java.lang.Double.parseDouble()
及相关方法时出现漏洞,会导致在解析 [2^(-1022) - 2^(-1075) : 2^(-1022) - 2^(-1076)]
范围内的任意数字时挂起线程。此缺陷可被攻击者用于执行拒绝服务 (DoS) 攻击。
例 1:下列代码使用了易受攻击的方法。
Double d = Double.parseDouble(request.getParameter("d"));
攻击者可以发送 d 参数值位于该范围(例如 0.0222507385850720119e-00306
)内的请求,致使程序在处理该请求时被挂起。
该漏洞在 Java 版本 6 Update 23 及更早版本中存在。Java 版本 6 Update 24 或更高版本不存在该漏洞。
修复建议
方案1:升级JDK至1.6 Update 24 以上,若JDK已经是1.6 Update 24以上,该类型漏洞可以关闭。
方案2:临时方案
public class ConvertDouble {
private final static Pattern NUMBER_PATTERN = Pattern.compile("^([+-]?\\d*\\.?\\d*([eE][+-]?)?\\d*).*");
public static double parseDouble(String value) {
String normalString = normalizeDoubleString(value);
int offset = normalString.indexOf('E');
BigDecimal base;
int exponent;
if (offset == -1) {
base = new BigDecimal(value);
exponent = 0;
} else {
base = new BigDecimal(normalString.substring(0,offset));
exponent = Integer.parseInt(normalString.charAt(offset+ 1) == '+'?
normalString.substring(offset +2) :
normalString.substring(offset +1));
}
returnbase.scaleByPowerOfTen(exponent).doubleValue();
}
public static String normalizeDoubleString(String strValue) {
// Clean-up string representation so that it could be understood
// by Java's BigDecimal. Not terribly efficient for now.
// 1. MRI allows d and D as exponent separators
strValue = strValue.replaceFirst("[edD]","E");
// 2. MRI allows underscores anywhere
strValue = strValue.replaceAll("_", "");
// 3. MRI ignores the trailing junk
strValue = NUMBER_PATTERN.matcher(strValue).replaceFirst("$1");
return strValue;
}
}