# Controllable read beyond bounds in lua_websocket_readbytes() [zhbug_httpd_126]

mod_lua's lua_websocket_readbytes trusts ap_get_brigade/apr_bucket_read to return requested length, so a short websocket frame causes memcpy of uninitialized heap into the echoed buffer.

- Payout: hidden
- Severity: low
- Program: Internet Bug Bounty
- Found by (vendor credit): Ronald Crane (Zippenhop LLC)
- Found by: tdp3kel9g
- Disclosed: 2022-07-09
- CVE: CVE-2022-30556
- Write-up quality: 8/10
- Original: https://hackerone.com/reports/1595290
- Library page: https://bugbountylibrary.com/r/h1%3A1595290
- Tags: area:web domain:web impact:data-leak impact:dos kind:bounty platform:hackerone sev:low tech:linux tech:websocket technique:source-review vuln:info-disclosure vuln:memory-corruption

**Target:** mod_lua websocket read handler (lua_websocket_readbytes)
**Root cause:** Code assumes ap_get_brigade(AP_MODE_READBYTES) and apr_bucket_read(APR_BLOCK_READ) return the full requested length, but they may return a shorter bucket; memcpy(buffer, data, len) then copies len bytes from a shorter buffer.
**Steps:**
1. Enable mod_lua and deploy a Lua handler that does r:wsupgrade(), r:wsread(), r:wswrite(data).
2. Open TLS connection and send `GET /bug126/bug126.lua HTTP/1.1` with `Upgrade: websocket` and `Sec-Websocket-Key: aaa`.
3. Send websocket frame header `\x82\x7f\x00\x00\x00\x00\x00\x00\x40\x00` (FIN+binary, 8-byte length 0x4000) with no actual payload.
4. ap_get_brigade returns success with a 1-byte bucket; apr_bucket_read sets data_length=1; memcpy copies 0x4000 bytes from the 1-byte buffer.
5. Read echoed response to exfiltrate ~0x2000 bytes of heap per read; repeat for more.
**How found:** Code review of lua_websocket_readbytes noticed the memcpy uses the requested len rather than the actual data_length returned by apr_bucket_read, and that ap_get_brigade/apr_bucket_read do not guarantee full-length reads.
**Exploitation:** Attacker sends a websocket frame claiming a large payload but delivering little/no data; the Lua handler echoes the over-read buffer back over the websocket, leaking heap contents. Repeating with modest sizes avoids crashing httpd.
**Escalation:** Repeated reads leak arbitrary amounts of prior heap allocations; large requested lengths can also trigger access violation for DoS.
**Insight:** When auditing bucket-brigade consumers, always check whether code uses the requested length or the actual data_length from apr_bucket_read; AP_MODE_READBYTES/APR_BLOCK_READ can return short buckets, so memcpy with the requested size over-reads.
