From 9db1e5f5fcb392e535b81ee4e170eb0656b7831a Mon Sep 17 00:00:00 2001 From: JoeMylinn <4973423+JoeMylinn@users.noreply.github.com> Date: Sat, 19 Jul 2025 20:24:46 +0200 Subject: [PATCH 1/4] Prevent re-encoding of redirection paths --- httplib.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/httplib.h b/httplib.h index 749fa61768..d935d429fc 100644 --- a/httplib.h +++ b/httplib.h @@ -8661,10 +8661,11 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { if (next_host.empty()) { next_host = host_; } if (next_path.empty()) { next_path = "/"; } - auto path = detail::decode_path(next_path, true) + next_query; + auto path = next_path + next_query; // Same host redirect - use current client if (next_scheme == scheme && next_host == host_ && next_port == port_) { + this->set_path_encode(false); //Disable path encoding, redirects should already be encoded return detail::redirect(*this, req, res, path, location, error); } @@ -8756,7 +8757,7 @@ inline void ClientImpl::setup_redirect_client(ClientType &client) { client.set_keep_alive(keep_alive_); client.set_follow_location( true); // Enable redirects to handle multi-step redirects - client.set_path_encode(path_encode_); + client.set_path_encode(false); //Disable encoding, redirects should already be encoded client.set_compress(compress_); client.set_decompress(decompress_); From f41e7eb9f7c124308fc357eab3531a04d2a5c481 Mon Sep 17 00:00:00 2001 From: JoeMylinn <4973423+JoeMylinn@users.noreply.github.com> Date: Sun, 20 Jul 2025 11:52:53 +0200 Subject: [PATCH 2/4] Add unit test for a redirect to an url with query parameters that contain a '+' --- test/test.cc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/test.cc b/test/test.cc index f7624bf365..db0db934f0 100644 --- a/test/test.cc +++ b/test/test.cc @@ -9942,6 +9942,37 @@ TEST(RedirectTest, RedirectToUrlWithQueryParameters) { } } +TEST(RedirectTest, RedirectToUrlWithPlusInQueryParameters) { + Server svr; + + svr.Get("/", [](const Request & /*req*/, Response &res) { + res.set_redirect(R"(/hello?key=AByz09+~-._%20%26%3F%C3%BC%2B)"); + }); + + svr.Get("/hello", [](const Request &req, Response &res) { + res.set_content(req.get_param_value("key"), "text/plain"); + }); + + auto thread = std::thread([&]() { svr.listen(HOST, PORT); }); + auto se = detail::scope_exit([&] { + svr.stop(); + thread.join(); + ASSERT_FALSE(svr.is_running()); + }); + + svr.wait_until_ready(); + + { + Client cli(HOST, PORT); + cli.set_follow_location(true); + + auto res = cli.Get("/"); + ASSERT_TRUE(res); + EXPECT_EQ(StatusCode::OK_200, res->status); + EXPECT_EQ("AByz09 ~-._ &?ΓΌ+", res->body); + } +} + TEST(VulnerabilityTest, CRLFInjection) { Server svr; From b4455762257464f8f20751851de6af90de14e489 Mon Sep 17 00:00:00 2001 From: JoeMylinn <4973423+JoeMylinn@users.noreply.github.com> Date: Sun, 20 Jul 2025 23:05:16 +0200 Subject: [PATCH 3/4] Fix formatting style --- httplib.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/httplib.h b/httplib.h index d935d429fc..ca39a3a6c9 100644 --- a/httplib.h +++ b/httplib.h @@ -8665,7 +8665,8 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { // Same host redirect - use current client if (next_scheme == scheme && next_host == host_ && next_port == port_) { - this->set_path_encode(false); //Disable path encoding, redirects should already be encoded + this->set_path_encode( + false); //Disable path encoding, redirects should already be encoded return detail::redirect(*this, req, res, path, location, error); } @@ -8757,7 +8758,8 @@ inline void ClientImpl::setup_redirect_client(ClientType &client) { client.set_keep_alive(keep_alive_); client.set_follow_location( true); // Enable redirects to handle multi-step redirects - client.set_path_encode(false); //Disable encoding, redirects should already be encoded + client.set_path_encode( + false); //Disable encoding, redirects should already be encoded client.set_compress(compress_); client.set_decompress(decompress_); From b32ef94f4bbb002d145c5cc0cf8c0303f600b70a Mon Sep 17 00:00:00 2001 From: JoeMylinn <4973423+JoeMylinn@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:14:14 +0200 Subject: [PATCH 4/4] Fix formatting style again --- httplib.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/httplib.h b/httplib.h index ca39a3a6c9..4f44b02e1c 100644 --- a/httplib.h +++ b/httplib.h @@ -8666,7 +8666,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { // Same host redirect - use current client if (next_scheme == scheme && next_host == host_ && next_port == port_) { this->set_path_encode( - false); //Disable path encoding, redirects should already be encoded + false); // Disable path encoding, redirects should already be encoded return detail::redirect(*this, req, res, path, location, error); } @@ -8759,7 +8759,7 @@ inline void ClientImpl::setup_redirect_client(ClientType &client) { client.set_follow_location( true); // Enable redirects to handle multi-step redirects client.set_path_encode( - false); //Disable encoding, redirects should already be encoded + false); // Disable encoding, redirects should already be encoded client.set_compress(compress_); client.set_decompress(decompress_);