On 27/05/2014 15:12, Konstantin Preißer wrote:
> 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-0099 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.

Yes, you need to have a content-length above Long.MAX_VALUE for problems
to occur. That would be unusual to say the least for most (all?)
applications in normal usage but easy for a malicious user to set.

If the proxy handles the header correctly, the attacker is going to have
to send a *lot* of data to get this to work. Where things would get
interesting is if the proxy and Tomcat both had parsing issues but ended
up with different values. That would make request smuggling a lot easier.

Something else to consider. If an attacker can trigger this
"request/response offset" then any subsequent requests they make could
receive responses that contain data from other users. Even if they can't
control what that data is, that is still information disclosure.

Mark


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

Reply via email to