Ask Your Question

Where do I even look to find the reason for a "400 Bad Request" ?

asked 2021-09-15 11:35:23 +0000

ullix gravatar image

I had expected wireshark providing an answer, but I have reached my limit in interpreting wireshark's output and don't even know where to look further. I hope you can help.

I have a device, a Geiger counter, which is programmed to issue a HTTP request on my local network to an Apache server on that same network. This server always answers with "400 Bad request". Consistent with that, Apache's error log says: "AH00566: request failed: malformed request line".

Then, using wireshark, I copied the "malformed" line taken from its output, and entered this line into a browser (both Firefox and Chrome used): The server now gives a 200 response, and of course no error. So seemingly the HTTP request is proper. Why is it not when coming from the Geiger counter?

I am attaching the 2 lines from wireshark, the request and the response, fully expanded, hoping that this contains the things I need to look out for. If more/other data are needed, please tell me!

Also, I have now added the mod_log_forensic module to my Apache server. This is supposed to give me all header info before and after processing them. The bummer is, it gives me all header info when the request succeeds, but none whatsoever when it fails as in my cases with "malformed requests". I don't see any options to set for this module :-((

I am confident the answer is in wireshark, but where do I even look?

(Sorry, I am not allowed to attach a file, so I resort to putting the lines here as text)

    HTTP request of device at to server at
Frame 67003: 165 bytes on wire (1320 bits), 165 bytes captured (1320 bits) on interface 0
    Interface id: 0 (enp3s0)
        Interface name: enp3s0
    Encapsulation type: Ethernet (1)
    Arrival Time: Sep  4, 2021 10:28:38.486223543 CEST
    [Time shift for this packet: 0.000000000 seconds]
    Epoch Time: 1630744118.486223543 seconds
    [Time delta from previous captured frame: 0.317684532 seconds]
    [Time delta from previous displayed frame: 63.093693181 seconds]
    [Time since reference or first frame: 3654.295052488 seconds]
    Frame Number: 67003
    Frame Length: 165 bytes (1320 bits)
    Capture Length: 165 bytes (1320 bits)
    [Frame is marked: False]
    [Frame is ignored: False]
    [Protocols in frame: eth:ethertype:ip:tcp:http]
    [Coloring Rule Name: HTTP]
    [Coloring Rule String: http || tcp.port == 80 || http2]
Ethernet II, Src: Espressi_36:ac:ba (a0:20:a6:36:ac:ba), Dst: AsustekC_c3:68:12 (ac:22:0b:c3:68:12)
    Destination: AsustekC_c3:68:12 (ac:22:0b:c3:68:12)
        Address: AsustekC_c3:68:12 (ac:22:0b:c3:68:12)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Source: Espressi_36:ac:ba (a0:20:a6:36:ac:ba)
        Address: Espressi_36:ac:ba (a0:20:a6:36:ac:ba)
        .... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
        .... ...0 .... .... .... .... = IG bit: Individual address (unicast)
    Type: IPv4 (0x0800)
Internet Protocol Version 4, Src ...
edit retag flag offensive close merge delete


You can post the capture in a public share and then add a link to it back here.

I can't spot the issue, but you could compare the request made by the device and the request made by your browser to see the differences.

grahamb gravatar imagegrahamb ( 2021-09-15 12:44:27 +0000 )edit

1 Answer

Sort by ยป oldest newest most voted

answered 2021-09-15 14:48:49 +0000

Chuckc gravatar image

updated 2021-09-15 15:29:57 +0000

It should probably be flagged as missing a proper CRLF sequence. (not malformed but noted)

rfc7230:3.5. Message Parsing Robustness

" Although the line terminator for the start-line and header fields is the sequence CRLF, a recipient MAY recognize a single LF as a line terminator and ignore any preceding CR."

" When a server listening only for HTTP request messages, or processing what appears from the start-line to be an HTTP request message, receives a sequence of octets that does not match the HTTP-message grammar aside from the robustness exceptions listed above, the server SHOULD respond with a 400 (Bad Request) response. "

GET /?AID=0123&GID=4567&CPM=22&ACPM=20.39&uSV=0.14 HTTP/1.1\n
  [Expert Info (Chat/Sequence): GET /?AID=0123&GID=4567&CPM=22&ACPM=20.39&uSV=0.14 HTTP/1.1\n]

tvb_find_line_end() in tvbuff.c just wants to find a \r or \n. (Called in packet-http.c)

     * Look either for a CR or an LF.

edit flag offensive delete link more


@Chuckc: Bingo! Many thanks!

When I made my comparisons of proper and improper http requests even using meld, I found no differences apart from time stamps, and I ignored those "irrelevancies" like CR, LF, CRLF. Except that those latter ones can be crucial!

So, the Geiger counter sends a LF-only in its http request. This typically goes to a Microsoft server, which accepts such a request as properly formed.

However, when I direct the request to an Apache server, it expects an CRLF, and rejects the LF-only request with a 400 because of a "malformed" request.

In the Apache docs this is explained as a security issue (, scroll to "important: Apache HTTP Request Parsing Whitespace Defects (CVE-2016-8743)"). One can work around this by entering into apache2.conf :

HttpProtocolOptions Unsafe

(The default being HttpProtocolOptions Strict).

I did this in my local server, and ...(more)

ullix gravatar imageullix ( 2021-09-16 07:25:01 +0000 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower


Asked: 2021-09-15 11:35:23 +0000

Seen: 48 times

Last updated: Sep 16