Skip to content

Commit

Permalink
headers: put a configurable limit on their numbers
Browse files Browse the repository at this point in the history
So as to avoid quadratic complexity

Ticket: 7191
  • Loading branch information
catenacyber authored and victorjulien committed Sep 25, 2024
1 parent 09d8110 commit 0d550de
Show file tree
Hide file tree
Showing 6 changed files with 41 additions and 0 deletions.
8 changes: 8 additions & 0 deletions htp/htp_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ static unsigned char bestfit_1252[] = {
0xff, 0x5d, 0x7d, 0xff, 0x5e, 0x7e, 0x00, 0x00, 0x00
};

#define HTP_HEADERS_LIMIT 1024

htp_cfg_t *htp_config_create(void) {
htp_cfg_t *cfg = calloc(1, sizeof (htp_cfg_t));
if (cfg == NULL) return NULL;
Expand All @@ -163,6 +165,7 @@ htp_cfg_t *htp_config_create(void) {
cfg->response_lzma_layer_limit = 1; // default is only one layer
cfg->compression_bomb_limit = HTP_COMPRESSION_BOMB_LIMIT;
cfg->compression_time_limit = HTP_COMPRESSION_TIME_LIMIT_USEC;
cfg->number_headers_limit = HTP_HEADERS_LIMIT;
cfg->allow_space_uri = 0;

// Default settings for URL-encoded data.
Expand Down Expand Up @@ -547,6 +550,11 @@ void htp_config_set_compression_time_limit(htp_cfg_t *cfg, size_t useclimit) {
}
}

void htp_config_set_number_headers_limit(htp_cfg_t *cfg, uint32_t limit) {
if (cfg == NULL) return;
cfg->number_headers_limit = limit;
}

void htp_config_set_log_level(htp_cfg_t *cfg, enum htp_log_level_t log_level) {
if (cfg == NULL) return;
cfg->log_level = log_level;
Expand Down
8 changes: 8 additions & 0 deletions htp/htp_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,14 @@ void htp_config_set_compression_time_limit(htp_cfg_t *cfg, size_t useclimit);
*/
void htp_config_set_max_tx(htp_cfg_t *cfg, uint32_t limit);

/**
* Configures the maximum number of headers LibHTP will accept per request or response.
*
* @param[in] cfg
* @param[in] limit
*/
void htp_config_set_number_headers_limit(htp_cfg_t *cfg, uint32_t limit);

/**
* Configures the desired log level.
*
Expand Down
3 changes: 3 additions & 0 deletions htp/htp_config_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@ struct htp_cfg_t {

/** Maximum number of transactions. */
uint32_t max_tx;

/** Maximum number of headers. */
uint32_t number_headers_limit;
};

#ifdef __cplusplus
Expand Down
1 change: 1 addition & 0 deletions htp/htp_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ enum htp_file_source_t {
#define HTP_REQUEST_INVALID 0x100000000ULL
#define HTP_REQUEST_INVALID_C_L 0x200000000ULL
#define HTP_AUTH_INVALID 0x400000000ULL
#define HTP_HEADERS_TOO_MANY 0x800000000ULL

#define HTP_MAX_HEADERS_REPETITIONS 64

Expand Down
11 changes: 11 additions & 0 deletions htp/htp_request_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,17 @@ htp_status_t htp_process_request_header_generic(htp_connp_t *connp, unsigned cha
bstr_free(h->value);
free(h);
} else {
if (htp_table_size(connp->in_tx->request_headers) > connp->cfg->number_headers_limit) {
if (!(connp->in_tx->flags & HTP_HEADERS_TOO_MANY)) {
connp->in_tx->flags |= HTP_HEADERS_TOO_MANY;
htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Too many request headers");
}
bstr_free(h->name);
bstr_free(h->value);
free(h);
// give up on what comes next
return HTP_ERROR;
}
// Add as a new header.
if (htp_table_add(connp->in_tx->request_headers, h->name, h) != HTP_OK) {
bstr_free(h->name);
Expand Down
10 changes: 10 additions & 0 deletions htp/htp_response_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,16 @@ htp_status_t htp_process_response_header_generic(htp_connp_t *connp, unsigned ch
bstr_free(h->value);
free(h);
} else {
if (htp_table_size(connp->out_tx->response_headers) > connp->cfg->number_headers_limit) {
if (!(connp->out_tx->flags & HTP_HEADERS_TOO_MANY)) {
connp->out_tx->flags |= HTP_HEADERS_TOO_MANY;
htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Too many response headers");
}
bstr_free(h->name);
bstr_free(h->value);
free(h);
return HTP_ERROR;
}
// Add as a new header.
if (htp_table_add(connp->out_tx->response_headers, h->name, h) != HTP_OK) {
bstr_free(h->name);
Expand Down

0 comments on commit 0d550de

Please sign in to comment.