Fossil Forum

HT 400 Bad Request? Or vulnerability?
Login

HT 400 Bad Request? Or vulnerability?

HT 400 Bad Request? Or vulnerability?

(1) By ET. on 2022-03-21 13:03:35 [link] [source]

I came to report a problem with fossil, by searching for it first in the forum before posting, but I middle clicked and pasted my terminal rather than the error I wanted to search for. I got the following page with malformed status line:

HT 400 Bad Request
Connection: close
Date: Mon, 21 Mar 2022 12:08:27 GMT
Content-type: text/plain; charset=utf-8

This server does not understand the requested protocol

Search string(798 characters):

ngs.cc.defines:Add() if platform == 'linux' then settings.cc.defines:Add( 'xxxxxxxxx=LINUX', 'xxxxxxxxxxxxx' ) xxxxxxxxxxxx/xxxxxxxxx/xxxx') settings.cc.exe_c=cc settings.cc.defines:Add('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxxxx', --'USE_ZLIB', 'xxxxxxxxxxxxx',  --'xxxxxxxxxx', --'xxxxxxxxxxxxxx', --'SQLITE_THREADSAFE=1', --'SQLITE_ENABLE_FTS3', --'SQLITE_ENABLE_FTS3_PARENTHESIS', --'SQLITE_ENABLE_FTS4', 'SQLITE_ENABLE_FTS5', 'SQLITE_ENABLE_JSON1' --'SQLITE_OMIT_DEPRECATED' -- xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --'SQLITE_ENABLE_RTREE' --'SQLITE_ENABLE_FTS5', --'SQLITE_TEMP_STORE=2', --'xxxxxxxxxxxxxxxxxxxxxxxx'  ) if platform == 'linux' then settings.cc.defines:Add( 'xxxxxxxxxxxxxxxx', 'xxxxxxxxxxxxxx' ) end              |            >        |      > 
https://fossil-scm.org/forum/forum?s=ngs.cc.defines%3AAdd%28%29+if+platform+%3D%3D+%27linux%27+then+settings.cc.defines%3AAdd%28+%27xxxxxxxxx%3DLINUX%27%2C+%27xxxxxxxxxxxxx%27+%29+xxxxxxxxxxxx%2Fxxxxxxxxx%2Fxxxx%27%29+settings.cc.exe_c%3Dcc+settings.cc.defines%3AAdd%28%27xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx%27%2C+%27xxxxxxxxxxxxxxxx%27%2C+--%27USE_ZLIB%27%2C+%27xxxxxxxxxxxxx%27%2C++--%27xxxxxxxxxx%27%2C+--%27xxxxxxxxxxxxxx%27%2C+--%27SQLITE_THREADSAFE%3D1%27%2C+--%27SQLITE_ENABLE_FTS3%27%2C+--%27SQLITE_ENABLE_FTS3_PARENTHESIS%27%2C+--%27SQLITE_ENABLE_FTS4%27%2C+%27SQLITE_ENABLE_FTS5%27%2C+%27SQLITE_ENABLE_JSON1%27+--%27SQLITE_OMIT_DEPRECATED%27+--+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx+--%27SQLITE_ENABLE_RTREE%27+--%27SQLITE_ENABLE_FTS5%27%2C+--%27SQLITE_TEMP_STORE%3D2%27%2C+--%27xxxxxxxxxxxxxxxxxxxxxxxx%27++%29+if+platform+%3D%3D+%27linux%27+then+settings.cc.defines%3AAdd%28+%27xxxxxxxxxxxxxxxx%27%2C+%27xxxxxxxxxxxxxx%27+%29+end++++++++++++++%7C++++++++++++%3E++++++++%7C++++++%3E+

If you add a character to the string you get H 400 Bad Request.

If you remove a character you get HTT 400 Bad Request.

Is this a buffer overflow?(in fossil or althttpd?)

(2.1) By Stephan Beal (stephan) on 2022-03-21 13:24:27 edited from 2.0 in reply to 1 [link] [source]

Is this a buffer overflow?(in fossil or althttpd?)

It's definitely from althttpd. A quick glance doesn't reveal what the issue is but i will take a closer look as soon as i'm back at home in a couple of hours.

Edit: i can reproduce this with Firefox v96 on Linux.

(3) By Stephan Beal (stephan) on 2022-03-21 14:29:05 in reply to 2.1 [link] [source]

Is this a buffer overflow?(in fossil or althttpd?)

Edit: i can reproduce this with Firefox v96 on Linux.

Strangely enough, i can reproduce it via the original link to fossil-scm.org/forum, but not when doing the same thing locally or via the althttpd which runs my website, neither in http nor https modes. On both of those systems i get the expected response and the crazy request string shows up in the althttpd log. My initial thought was that it's perhaps a misinteraction with xinetd, but my remote site also runs althttpd via xinetd.

:-?

(4.1) By Richard Hipp (drh) on 2022-03-21 15:02:35 edited from 4.0 in reply to 2.1 [source]

It's definitely from althttpd.

Are you sure? Seems like it might also be generated from a call to fossil_print_error().

Edit: I now agree that the error is coming from althttpd.

(5) By Stephan Beal (stephan) on 2022-03-21 15:01:00 in reply to 4.0 [link] [source]

Are you sure? Seems like it might also be generated from a call to fossil_print_error().

The error text from the OP's post is the giveaway:

This server does not understand the requested protocol

That string is only found in althttpd.

(8) By Michael A. Cleverly (cleverly) on 2022-03-21 15:25:39 in reply to 4.1 [link] [source]

The issue occurs in line 892:

  nOut += althttpd_printf("%s %s\r\n",
                          zProtocol ? zProtocol : "HTTP/1.1",
                          zResultCode);

zProtocol is set in lines 2291-2293 by the third consecutive call to GetFirstElement of the zLine char[1000].

For the HTTP request:

GET /uri HTTP/x.y

GET plus a space will consume 4 characters, and space HTTP/x.y will need another 8.

That leaves 1000 - 12, or 988 characters for /uri. The URI in the initial post is 993 characters long. This leads to zProtocol being set to "HT" and used in the response instead of "HTTP/1.1" (which would only be used if zProtocol were NULL).

One way to approach the problem would be to increase the size of zLine. Another would be to test the result of fgets on zLine and if it does not end in HTTP/x.y and the length is 1,000 that means the request line exceeded 1000 characters and a different response (414 URI Too Long) instead.

(6) By Richard Hipp (drh) on 2022-03-21 15:11:52 in reply to 1 [link] [source]

Fixed.

This is not a vulnerability or buffer overrun. In fact, this shows that althttpd is resistant to buffer overruns.

The problem was that the request URI was longer than the (1000-byte) buffer that althttpd allocated for it. So it truncated the request and reserved the rest for the next request.

There is allowed to be a limit on the size of a request URI, if I recall correctly, but I do not know what that limit is. For althttpd, it was formerly 1000 bytes. I have now increased it to 10,000 bytes and that seems to resolve the issue for this particular test case.

(7) By Stephan Beal (stephan) on 2022-03-21 15:22:09 in reply to 6 [link] [source]

There is allowed to be a limit on the size of a request URI, if I recall correctly, but I do not know what that limit is.

That is the case and i've seen servers with as low as 1k (and some which outright crashed if that limit was violated). IIRC, Apache historically had a 4k limit.

(10.1) By Daniel Dumitriu (danield) on 2022-03-21 15:41:19 edited from 10.0 in reply to 7 [link] [source]

This is a good SO answer and suggests that common browsers stop around maximum 8 KB, so 10,000 chars is generous from althttpd ;-).

HTTP 1.1 itself does not limit the GET-Request URI length but does warn about overlong requests. Another point of interest might be "A server SHOULD return 414 (Request-URI Too Long) status if a URI is longer than the server can handle."

(9) By Michael A. Cleverly (cleverly) on 2022-03-21 15:28:16 in reply to 6 [link] [source]

Of course Richard would find and commit a fix while I was writing my reply above. :)

(11) By ET. on 2022-03-22 12:37:32 in reply to 6 [link] [source]

That was a quick fix, but it doesn't seem to fix the underlining issue. What if the URI was longer? The response status line is still malformed.

$ echo GET /`printf -- '.%.0s' {1..9991}` HTTP/1.0|./althttpd --root .
HT 400 Bad Request
Connection: close
Date: Tue, 22 Mar 2022 10:27:52 GMT
Content-type: text/plain; charset=utf-8

This server does not understand the requested protocol

Even an empty request returns no http version in the status line.

$ echo |./althttpd --root .
 400 Bad Request
Connection: close
Date: Tue, 22 Mar 2022 10:19:56 GMT
Content-type: text/plain; charset=utf-8

This server does not understand the requested protocol

Another quirk in responding with the http version the client sends:

$ echo GET / not-HTTP/3.141592|./althttpd  --root .
not-HTTP/3.141592 400 Bad Request
Connection: close
Date: Tue, 22 Mar 2022 10:05:38 GMT
Content-type: text/plain; charset=utf-8

RFC2145 states:

   An HTTP server SHOULD send a response version equal to the highest
   version for which the server is at least conditionally compliant, and
   whose major version is less than or equal to the one received in the
   request.  An HTTP server MUST NOT send a version for which it is not
   at least conditionally compliant.  A server MAY send a 505 (HTTP
   Version Not Supported) response if cannot send a response using the
   major version used in the client's request.

(12) By Richard Hipp (drh) on 2022-03-22 14:23:42 in reply to 11 [link] [source]

Updates applied to althttpd. Try it again, please.

(13) By ET. on 2022-03-23 06:33:14 in reply to 12 [link] [source]

Great stuff, looks all fixed to me. Case closed. Thanks.