Hi André,

> -----Original Message-----
> From: André Warnier [mailto:a...@ice-sa.com]
> Sent: Tuesday, May 27, 2014 3:06 PM
> 
> Mark Thomas wrote:
> > CVE-2014-0097 Information Disclosure
> >
> ...
> 
> >
> > Description:
> > The code used to parse the request content length header did not check
> > for overflow in the result. This exposed a request smuggling
> > vulnerability when Tomcat was located behind a reverse proxy that
> > correctly processed the content length header.
> >
> 
> I believe you, but I must admit that I don't really get what the problem is,
> here.
> If someone feels like explaining..

The fix for this issue also made me a bit curious (I don't know the background 
of the issue).

The old code for parsing the Content-Length header looked like this:

        long n = c - '0';
        long m;

        while (--len > 0) {
            if (!isDigit(c = b[off++])) {
                throw new NumberFormatException();
            }
            m = n * 10 + c - '0';

            if (m < n) {
                // Overflow
                throw new NumberFormatException();
            } else {
                n = m;
            }
        }

Where "b" is a byte-array containing ASCII decimal chars.

The code parses a decimal number like "123" by multiplying the current number 
(e.g. 12) by 10 (=120), then adding the next character (=123).

To check for an overflow, it checks if the "new" number is lower than the old 
one. Usually, when making a simple addition with positive numbers where the 
second one is low (0-9), this is enough as for an overflow, the first bit will 
go to 1, so the number is negative. E.g., when using signed bytes (8 bits):
0111111b (127) + 3 = 10000010b (-126)

However, the code above also does an multiplication by 10. For example, if the 
current number (signed long) is 6148914691236517205 (binary: 
101010101010101010101010101010101010101010101010101010101010101b) and the next 
character is '3', the calculation would be:

101010101010101010101010101010101010101010101010101010101010101b 
(6148914691236517205) * 1010b (10) = 
101010101010101010101010101010101010101010101010101010101010010b 
(6148914691236517202)

101010101010101010101010101010101010101010101010101010101010010b 
(6148914691236517202) + 11b (3) =
101010101010101010101010101010101010101010101010101010101010101b 
(6148914691236517205)

In this case, the new number would == the old number, so the code " if (m < n)" 
would not detect the overflow.

E.g., if you run following code:

        long a = 6148914691236517205L;
        long b = a * 10 + 3;
        System.out.println(a == b);

it will print "true".


However, I don't know if such example is really the one that causes issues, as 
this number is pretty high (but I did not found how smaller numbers could cause 
overflows not to be detected). Maybe someone could comment on that.


Thanks!


Regards,
Konstantin Preißer


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
For additional commands, e-mail: users-h...@tomcat.apache.org

Reply via email to