reject crlf in the request target in write_request_line#2495
reject crlf in the request target in write_request_line#2495metsw24-max wants to merge 2 commits into
Conversation
|
@metsw24-max could you please take a look at CI errors? |
split.py strips `inline` and moves the definition into httplib.cc, so detail::write_request_line is not visible from the split httplib.h and test_split failed to compile. Re-declare it in test.cc, matching what the base64_encode and getaddrinfo_with_timeout tests already do.
|
Sorry about that. The failure was Pushed a fix that re-declares it in test.cc, the same way the |
|
Thanks for this @metsw24-max — the fix is correct and I've carried it forward in #2501 with your two commits unchanged, so your authorship is preserved. While reviewing I found the guard needs one more thing to fully take effect: Closing in favor of #2501. Thank you again for finding and reporting this. |
the client builds each request line in write_request_line by concatenating the method, the target and " HTTP/1.1\r\n" and writing it to the socket with no check on the target, so a target carrying CR/LF splits the request line and injects a header or a whole request. the neighbouring writers already guard this. check_and_write_headers runs is_field_value over every header value, and perform_websocket_handshake runs it over the path before the identical "GET " + path build, but the ordinary request path was left out. it becomes reachable when following a redirect with path encoding disabled: ClientImpl::redirect decodes the Location path through decode_path_component, so a wire-safe %0D%0A turns into a raw CR/LF, and under set_path_encode(false) that decoded target reaches write_request_line verbatim (the default encode_path re-encodes it, so only the disabled case leaks). the same writer also emits the CONNECT target, so guarding it once covers every request line the client sends. the change rejects a target that fails is_field_value there, matching the other two writers; a valid target is always field-value-clean, so i don't think anything legitimate is refused. added RequestLineInjectionTest.RejectsCRLFInTarget.