Security #8642
Updated by Jason Ish 14 days ago
h2. Summary
Suricata's HTTP SWF decompression path can trigger a heap buffer overflow when
@swf-decompression.decompress-depth@ is configured to a @uint32_t@ value that
wraps after the internal SWF header adjustment. An ASAN-enabled build aborts in
@FileSwfDecompression()@ with a 4 GiB zero-fill write.
h2. Affected code
Confirmed on Suricata @9.0.0-dev@, commit @0eda09f302@ from 2026-06-03, built
with ASAN.
Relevant files:
* @src/util-file-decompression.c@
* @src/detect-file-data.c@
The vulnerable path is reached from HTTP to-client @file_data@ inspection when
SWF decompression is enabled:
* @FiledataGetDataCallback()@ calls @FileSwfDecompression()@ for HTTP1
to-client file data if @htp_state->cfg->swf_decompression_enabled@ is true
and the file data starts with a compressed SWF signature.
* @FileSwfDecompression()@ computes @decompressed_data_len@ from the configured
@decompress_depth@, then unconditionally adds 8 bytes for the generated FWS
header.
h2. Root cause
In @FileSwfDecompression()@:
<pre>
uint32_t decompressed_data_len =
(decompress_depth == 0) ? decompressed_swf_len : decompress_depth;
decompressed_data_len += 8;
SCInspectionBufferCheckAndExpand(out_buffer, decompressed_data_len);
...
out_buffer->len = decompressed_data_len;
...
memset(out_buffer->buf + 8, 0, decompressed_data_len - 8);
</pre>
With @decompress-depth=4294967295@, @decompressed_data_len += 8@ wraps to @7@.
The inspection buffer is only expanded to the default 4096-byte allocation, but
the later @memset(out_buffer->buf + 8, 0, decompressed_data_len - 8)@ underflows
the length argument to @4294967295@ and writes zeros past the heap allocation.
h2. Reproducer
The full reproducer will be provided in a suricata-verify test submitted
separately. That test includes a pcap with a single HTTP transaction returning a
small zlib-compressed @CWS@ SWF file, plus a @file_data@ rule that reaches the
HTTP file-data inspection path.
After the suricata-verify test is submitted, run from a Suricata ASAN build
using the pcap from that test:
<pre>
ASAN_OPTIONS=abort_on_error=1:detect_leaks=0 \
src/suricata \
-c suricata.yaml \
-S <suricata-verify-test>/test.rules filedata-swf.rules \
-r <suricata-verify-test>/input.pcap \
-l /tmp/suri-swf-depth-wrap \
--runmode single \
-k none \
--set app-layer.protocols.http.libhtp.default-config.swf-decompression.enabled=yes \
--set app-layer.protocols.http.libhtp.default-config.swf-decompression.decompress-depth=4294967295
</pre>
h2. Observed result
Suricata aborts with ASAN:
<pre>
ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 4294967295
#1 FileSwfDecompression src/util-file-decompression.c:149
#2 FiledataGetDataCallback src/detect-file-data.c:456
0 bytes after 4096-byte region allocated by:
#2 SCInspectionBufferCheckAndExpand src/detect-engine-inspect-buffer.c:227
#3 FileSwfDecompression src/util-file-decompression.c:132
</pre>
h2. Expected result
Suricata should not perform an out-of-bounds write or abort when processing the
traffic under this configuration.
h2. Impact
This is config-dependent. A packet alone is not sufficient; the vulnerable path
requires:
* HTTP SWF decompression enabled.
* A rule or other detection path that inspects HTTP to-client @file_data@.
* A wrapping @swf-decompression.decompress-depth@ value.
The demonstrated impact is denial of service / memory safety violation. No
credible RCE path was identified from this primitive: the overwrite is a huge
zero-fill, the byte value is fixed, and the size is controlled by configuration
rather than packet contents.
h2. Validation
* With @decompress-depth=4294967295@, the ASAN build aborts with exit 134.
* With normal SWF decompression depth, the same pcap and rule complete cleanly
and emit one @file_data@ alert, confirming reachability of the SWF
decompression path.
* A suricata-verify regression test has been prepared locally at
@/home/jason/oisf/dev/verify/master/tests/security-swf-decompression-depth-wrap@
and will be submitted separately.