mirror of
https://github.com/OISF/suricata.git
synced 2026-10-11 22:09:53 +00:00
swf: validate configured depth limits
SWF depth settings were previously limited only to values representable by uint32_t. This is not sufficient for the buffer-size calculations performed during SWF decompression. The decompressed output requires an additional 8-byte FWS header. The inspection buffer also grows by doubling a uint32_t size, so a required buffer larger than 2 GiB can cause the growth calculation to wrap. For LZMA input, a synthesized 13-byte header to the compressed data is used. The configured compressed-data limit must leave room for this header. This patch applies the following upper limits: - decompress-depth: 2147483640 bytes (2 GiB minus the 8-byte FWS header) - compress-depth: 4294967282 bytes (UINT32_MAX minus the 13-byte LZMA header Ticket: #8914
This commit is contained in:
committed by
Victor Julien
parent
e707b21e21
commit
ae4341eb5f
@@ -1729,11 +1729,11 @@ use of libhtp.
|
||||
# 2 types: 'deflate', 'lzma', 'both' will decompress deflate and lzma
|
||||
# compress-depth:
|
||||
# Specifies the maximum amount of data to decompress,
|
||||
# set 0 for unlimited.
|
||||
# set 0 for unlimited. The maximum is 4294967282 bytes.
|
||||
# decompress-depth:
|
||||
# Specifies the maximum amount of decompressed data to obtain. The
|
||||
# output buffer grows on demand up to this limit. Set 0 to use the
|
||||
# default limit of 50 MB.
|
||||
# default limit of 50 MB. The maximum is 2147483640 bytes.
|
||||
swf-decompression:
|
||||
enabled: yes
|
||||
type: both
|
||||
|
||||
@@ -872,11 +872,11 @@ setting.
|
||||
# 2 types: 'deflate', 'lzma', 'both' will decompress deflate and lzma
|
||||
# compress-depth:
|
||||
# Specifies the maximum amount of data to decompress,
|
||||
# set 0 for unlimited.
|
||||
# set 0 for unlimited. The maximum is 4294967282 bytes.
|
||||
# decompress-depth:
|
||||
# Specifies the maximum amount of decompressed data to obtain. The
|
||||
# output buffer grows on demand up to this limit. Set 0 to use the
|
||||
# default limit of 50 MB.
|
||||
# default limit of 50 MB. The maximum is 2147483640 bytes.
|
||||
swf-decompression:
|
||||
enabled: yes
|
||||
type: both
|
||||
|
||||
+11
-8
@@ -58,6 +58,7 @@
|
||||
#include "app-layer-events.h"
|
||||
|
||||
#include "util-debug.h"
|
||||
#include "util-file-decompression.h"
|
||||
#include "util-misc.h"
|
||||
|
||||
#include "util-unittest.h"
|
||||
@@ -2336,17 +2337,19 @@ static void HTPConfigParseParameters(HTPCfgRec *cfg_prec, SCConfNode *s, struct
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (strcasecmp("compress-depth", pval->name) == 0) {
|
||||
if (ParseSizeStringU32(pval->val, &cfg_prec->swf_compress_depth) < 0) {
|
||||
SCLogError("Error parsing swf-decompression.compression-depth "
|
||||
"from conf file - %s. Killing engine",
|
||||
p->val);
|
||||
if (ParseSizeStringU32(pval->val, &cfg_prec->swf_compress_depth) < 0 ||
|
||||
cfg_prec->swf_compress_depth > MAX_SWF_COMPRESS_DEPTH) {
|
||||
SCLogError("Invalid swf-decompression.compress-depth value %s: the "
|
||||
"maximum is %u bytes. Killing engine",
|
||||
pval->val, MAX_SWF_COMPRESS_DEPTH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (strcasecmp("decompress-depth", pval->name) == 0) {
|
||||
if (ParseSizeStringU32(pval->val, &cfg_prec->swf_decompress_depth) < 0) {
|
||||
SCLogError("Error parsing swf-decompression.decompression-depth "
|
||||
"from conf file - %s. Killing engine",
|
||||
p->val);
|
||||
if (ParseSizeStringU32(pval->val, &cfg_prec->swf_decompress_depth) < 0 ||
|
||||
cfg_prec->swf_decompress_depth > MAX_SWF_DECOMPRESS_DEPTH) {
|
||||
SCLogError("Invalid swf-decompression.decompress-depth value %s: the "
|
||||
"maximum is %u bytes. Killing engine",
|
||||
pval->val, MAX_SWF_DECOMPRESS_DEPTH);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -349,6 +349,30 @@ static int DetectFiledataSwfDecompressDepthTest02(void)
|
||||
PASS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \test SWF decompression rejects depth values above the supported limits.
|
||||
*/
|
||||
static int DetectFiledataSwfDecompressDepthTest03(void)
|
||||
{
|
||||
DetectEngineThreadCtx *det_ctx = SCCalloc(1, sizeof(*det_ctx));
|
||||
FAIL_IF_NULL(det_ctx);
|
||||
InspectionBuffer out_buffer = { 0 };
|
||||
|
||||
int r = FileSwfDecompression(swf_lzma_fixture, (uint32_t)sizeof(swf_lzma_fixture), det_ctx,
|
||||
&out_buffer, HTTP_SWF_COMPRESSION_LZMA, MAX_SWF_DECOMPRESS_DEPTH + 1, 0);
|
||||
FAIL_IF(r != 0);
|
||||
FAIL_IF_NOT_NULL(out_buffer.buf);
|
||||
|
||||
r = FileSwfDecompression(swf_lzma_fixture, (uint32_t)sizeof(swf_lzma_fixture), det_ctx,
|
||||
&out_buffer, HTTP_SWF_COMPRESSION_LZMA, 0, MAX_SWF_COMPRESS_DEPTH + 1);
|
||||
FAIL_IF(r != 0);
|
||||
FAIL_IF_NOT_NULL(out_buffer.buf);
|
||||
|
||||
SCAppLayerDecoderEventsFreeEvents(&det_ctx->decoder_events);
|
||||
SCFree(det_ctx);
|
||||
PASS;
|
||||
}
|
||||
|
||||
static int DetectEngineSMTPFiledataTest02(void)
|
||||
{
|
||||
DetectEngineCtx *de_ctx = DetectEngineCtxInit();
|
||||
@@ -401,6 +425,8 @@ void DetectFiledataRegisterTests(void)
|
||||
"DetectFiledataSwfDecompressDepthTest01", DetectFiledataSwfDecompressDepthTest01);
|
||||
UtRegisterTest(
|
||||
"DetectFiledataSwfDecompressDepthTest02", DetectFiledataSwfDecompressDepthTest02);
|
||||
UtRegisterTest(
|
||||
"DetectFiledataSwfDecompressDepthTest03", DetectFiledataSwfDecompressDepthTest03);
|
||||
UtRegisterTest("DetectEngineSMTPFiledataTest02", DetectEngineSMTPFiledataTest02);
|
||||
UtRegisterTest("DetectFiledataParseTest04", DetectFiledataParseTest04);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,10 @@ int FileSwfDecompression(const uint8_t *buffer, uint32_t buffer_len,
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
if (decompress_depth > MAX_SWF_DECOMPRESS_DEPTH || compress_depth > MAX_SWF_COMPRESS_DEPTH) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int compression_type = FileIsSwfFile(buffer, buffer_len);
|
||||
if (compression_type == FILE_SWF_NO_COMPRESSION) {
|
||||
return 0;
|
||||
@@ -160,7 +164,7 @@ int FileSwfDecompression(const uint8_t *buffer, uint32_t buffer_len,
|
||||
* | 5 bytes | 8 bytes | n bytes |
|
||||
* | LZMA properties | Uncompressed length | Compressed data |
|
||||
*/
|
||||
compressed_data_len += 13;
|
||||
compressed_data_len += SWF_LZMA_HEADER_LEN;
|
||||
uint8_t *compressed_data = SCCalloc(1, compressed_data_len);
|
||||
if (compressed_data == NULL) {
|
||||
DetectEngineSetEvent(det_ctx, FILE_DECODER_EVENT_NO_MEM);
|
||||
@@ -171,7 +175,8 @@ int FileSwfDecompression(const uint8_t *buffer, uint32_t buffer_len,
|
||||
/* put lzma end marker */
|
||||
memset(compressed_data + 5, 0xFF, 8);
|
||||
/* put compressed data */
|
||||
memcpy(compressed_data + 13, buffer + offset, compressed_data_len - 13);
|
||||
memcpy(compressed_data + SWF_LZMA_HEADER_LEN, buffer + offset,
|
||||
compressed_data_len - SWF_LZMA_HEADER_LEN);
|
||||
|
||||
/* the first 8 bytes represents the fws header, see 'FWS format' above.
|
||||
* data will start from 8th bytes
|
||||
|
||||
@@ -27,6 +27,12 @@
|
||||
|
||||
#include "detect.h"
|
||||
|
||||
#define SWF_HEADER_LEN 8
|
||||
#define SWF_LZMA_HEADER_LEN 13
|
||||
|
||||
#define MAX_SWF_DECOMPRESS_DEPTH (UINT32_MAX / 2 + 1 - SWF_HEADER_LEN)
|
||||
#define MAX_SWF_COMPRESS_DEPTH (UINT32_MAX - SWF_LZMA_HEADER_LEN)
|
||||
|
||||
enum {
|
||||
FILE_IS_NOT_SWF = 0,
|
||||
FILE_SWF_NO_COMPRESSION,
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#define MAX_SWF_DECOMPRESSED_LEN 50000000
|
||||
|
||||
#define SWF_HEADER_LEN 8
|
||||
#define SWF_DECOMPRESS_INITIAL_BUFFER_LEN 4096
|
||||
|
||||
uint8_t FileGetSwfVersion(const uint8_t *buffer, const uint32_t buffer_len);
|
||||
|
||||
+4
-3
@@ -1172,10 +1172,11 @@ app-layer:
|
||||
# Two types: 'deflate', 'lzma', 'both' will decompress deflate and lzma
|
||||
# compress-depth:
|
||||
# Specifies the maximum amount of data to decompress,
|
||||
# set 0 for unlimited.
|
||||
# set 0 for unlimited. The maximum is 4294967282 bytes.
|
||||
# decompress-depth:
|
||||
# Specifies the maximum amount of decompressed data to obtain,
|
||||
# set 0 for unlimited.
|
||||
# Specifies the maximum amount of decompressed data to obtain. The
|
||||
# output buffer grows on demand up to this limit. Set 0 to use the
|
||||
# default limit of 50 MB. The maximum is 2147483640 bytes.
|
||||
swf-decompression:
|
||||
enabled: no
|
||||
type: both
|
||||
|
||||
Reference in New Issue
Block a user