AppSec Blog

Taming the Beast - The Floating Point DoS Vulnerability

Originally posted as Taming the Beast

The recent multi-language numerical parsing DOS bug has been named the "Mark of the Beast". Some claim that this bug was first reported as early as 2001.This is a significant bug in (at least) PHP and Java. Similar issues have effected Ruby in the past. This bug has left a number of servers, web frameworks and custom web applications vulnerable to easily exploitable Denial of Service.

Oracle has patched this vuln but there are several non-Oracle JVM's that have yet to release a patch. Tactical patching may be prudent for environment.

Here are three approaches that may help you tame this beast of a bug.

1) ModSecurity Rules

Ryan Barnett deployed a series of ModSecurity rules and documented several options at

2) Java-based Blacklist Filter

Bryan Sullivan from Adobe came up with the following Java-based blacklist filter.

This rule is actually quite accurate in *rejecting input* in the DOSable JVM numeric range. This fix, while simple, does indeed reject a series of normally good values.

public static boolean containsMagicDoSNumber(String s) { return s.replace(".", "").contains("2225073858507201"); }

3) Double Parsing Code

The following Java "safe" Double parsing code was based on a proof of concept by Brian Chess at HP/Fortify. This approach detects the evil range before trying to call parseDouble and returns the IEEE official value ( 2.2250738585072014E-308 ) for any double in the dangerous range.
private static BigDecimal bigBad; private static BigDecimal smallBad; static { BigDecimal one = new BigDecimal(1); BigDecimal two = new BigDecimal(2); BigDecimal tiny = one.divide(two.pow(1022)); // 2^(-1022) 2^(-1076) bigBad = tiny.subtract(one.divide(two.pow(1076))); //2^(-1022) 2^(-1075) smallBad = tiny.subtract(one.divide(two.pow(1075))); } public static Double parseSafeDouble(String input) throws InvalidParameterException { if (input == null) throw new InvalidParameterException("input is null"); BigDecimal bd; try { bd = new BigDecimal(input); } catch (NumberFormatException e) { throw new InvalidParameterException("cant parse number"); } if (bd.compareTo(smallBad) >= 0 && bd.compareTo(bigBad) <= 0) { // if you get here you know you're looking at a bad value. The final // value for any double in this range is supposed to be the following safe # //return safe number System.out.println("BAD NUMBER DETECTED - returning 2.2250738585072014E-308"); return new Double("2.2250738585072014E-308"); } //safe number, return double value return bd.doubleValue(); }

Post a Comment


* Indicates a required field.