diff options
author | Toni <matzeton@googlemail.com> | 2022-08-30 11:38:36 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-30 11:38:36 +0200 |
commit | f7907976c9234353c7b7ec81445ef4f219d93be3 (patch) | |
tree | c479c9d58d99026c07a56821a8bbe3ff9aa7d24f /src/lib/protocols/fastcgi.c | |
parent | fe28d55801e589bdf74c32948002b797959bf0bd (diff) |
FastCGI: dissect PARAMS (#1715)
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Signed-off-by: lns <matzeton@googlemail.com>
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
Signed-off-by: lns <matzeton@googlemail.com>
Diffstat (limited to 'src/lib/protocols/fastcgi.c')
-rw-r--r-- | src/lib/protocols/fastcgi.c | 149 |
1 files changed, 141 insertions, 8 deletions
diff --git a/src/lib/protocols/fastcgi.c b/src/lib/protocols/fastcgi.c index e49e8e508..fdbb91c09 100644 --- a/src/lib/protocols/fastcgi.c +++ b/src/lib/protocols/fastcgi.c @@ -29,12 +29,12 @@ PACK_ON struct FCGI_Header { - unsigned char version; - unsigned char type; + u_int8_t version; + u_int8_t type; u_int16_t requestId; u_int16_t contentLength; - unsigned char paddingLength; - unsigned char reserved; + u_int8_t paddingLength; + u_int8_t reserved; } PACK_OFF; enum FCGI_Type { @@ -55,23 +55,113 @@ enum FCGI_Type { FCGI_MAX = 11 }; +PACK_ON +struct FCGI_Params { + u_int8_t key_length; + u_int8_t value_length; +} PACK_OFF; + +struct fcgi_one_line_mapping { + char const * const key; + struct ndpi_int_one_line_struct * const value; +}; + +static int ndpi_search_fastcgi_extra(struct ndpi_detection_module_struct *ndpi_struct, + struct ndpi_flow_struct *flow); + static void ndpi_int_fastcgi_add_connection(struct ndpi_detection_module_struct * const ndpi_struct, - struct ndpi_flow_struct * const flow) + struct ndpi_flow_struct * const flow, + ndpi_protocol_match_result * const match) { NDPI_LOG_INFO(ndpi_struct, "found fastcgi\n"); ndpi_set_detected_protocol(ndpi_struct, flow, NDPI_PROTOCOL_FASTCGI, - NDPI_PROTOCOL_UNKNOWN, + (match != NULL ? match->protocol_id : NDPI_PROTOCOL_UNKNOWN), NDPI_CONFIDENCE_DPI); + + if (flow->extra_packets_func == NULL) + { + flow->max_extra_packets_to_check = 5; + flow->extra_packets_func = ndpi_search_fastcgi_extra; + } +} + +static int fcgi_parse_params(struct ndpi_flow_struct * const flow, + struct ndpi_packet_struct * const packet) +{ + size_t i, j; + struct fcgi_one_line_mapping mappings[] = { + { "SCRIPT_URL", &packet->http_url_name }, + { "HTTP_HOST", &packet->host_line }, + { "HTTP_ACCEPT", &packet->accept_line }, + { "HTTP_USER_AGENT", &packet->user_agent_line }, + { "HTTP_ACCEPT_ENCODING", &packet->http_transfer_encoding }, + { "SERVER_SOFTWARE", &packet->server_line }, + { "REQUEST_METHOD", &packet->http_method } + }; + + i = sizeof(struct FCGI_Header); + while (i + sizeof(struct FCGI_Params) < packet->payload_packet_len) + { + struct FCGI_Params const * const params = (struct FCGI_Params const *)&packet->payload[i]; + + i += sizeof(*params); + if (i + params->key_length + params->value_length > packet->payload_packet_len) + { + return 1; + } + + for (j = 0; j < NDPI_ARRAY_LENGTH(mappings); ++j) + { + if (strlen(mappings[j].key) == params->key_length && + strncmp((char const *)&packet->payload[i], mappings[j].key, params->key_length) == 0) + { + mappings[j].value->ptr = &packet->payload[i + params->key_length]; + mappings[j].value->len = params->value_length; + if (packet->parsed_lines < NDPI_MAX_PARSE_LINES_PER_PACKET) + { + packet->line[packet->parsed_lines].ptr = &packet->payload[i + params->key_length]; + packet->line[packet->parsed_lines].len = params->value_length; + packet->parsed_lines++; + } + break; + } + } + + i += params->key_length + params->value_length; + }; + + if (i != packet->payload_packet_len) + { + return 1; + } + + flow->http.method = ndpi_http_str2method((const char*)packet->http_method.ptr, + (u_int16_t)packet->http_method.len); + ndpi_hostname_sni_set(flow, packet->host_line.ptr, packet->host_line.len); + ndpi_user_agent_set(flow, packet->user_agent_line.ptr, packet->user_agent_line.len); + + if (flow->http.url == NULL && packet->http_url_name.len > 0) + { + flow->http.url = malloc(packet->http_url_name.len + 1); + if (flow->http.url != NULL) + { + strncpy(flow->http.url, (char const *)packet->http_url_name.ptr, packet->http_url_name.len); + flow->http.url[packet->http_url_name.len] = '\0'; + } + } + + return 0; } void ndpi_search_fastcgi(struct ndpi_detection_module_struct *ndpi_struct, struct ndpi_flow_struct *flow) { - struct ndpi_packet_struct const * const packet = &ndpi_struct->packet; + struct ndpi_packet_struct * const packet = &ndpi_struct->packet; struct FCGI_Header const * fcgi_hdr; enum FCGI_Type fcgi_type; u_int16_t content_len; + ndpi_protocol_match_result ret_match; NDPI_LOG_DBG(ndpi_struct, "search fastcgi\n"); @@ -103,12 +193,55 @@ void ndpi_search_fastcgi(struct ndpi_detection_module_struct *ndpi_struct, return; } + if (fcgi_type == FCGI_PARAMS) + { + if (content_len == 0) + { + flow->max_extra_packets_to_check = 0; + flow->extra_packets_func = NULL; + return; + } + + if (fcgi_parse_params(flow, packet) != 0) + { + ndpi_set_risk(ndpi_struct, flow, NDPI_MALFORMED_PACKET, "Invalid FastCGI PARAMS header"); + ndpi_int_fastcgi_add_connection(ndpi_struct, flow, NULL); + } else { + ndpi_match_host_subprotocol(ndpi_struct, flow, + flow->host_server_name, + strlen(flow->host_server_name), + &ret_match, NDPI_PROTOCOL_FASTCGI); + ndpi_check_dga_name(ndpi_struct, flow, + flow->host_server_name, 1); + if(ndpi_is_valid_hostname(flow->host_server_name, + strlen(flow->host_server_name)) == 0) { + char str[128]; + + snprintf(str, sizeof(str), "Invalid host %s", flow->host_server_name); + ndpi_set_risk(ndpi_struct, flow, NDPI_INVALID_CHARACTERS, str); + + /* This looks like an attack */ + ndpi_set_risk(ndpi_struct, flow, NDPI_POSSIBLE_EXPLOIT, NULL); + } + ndpi_int_fastcgi_add_connection(ndpi_struct, flow, &ret_match); + } + return; + } + if (flow->packet_counter > 2) { - ndpi_int_fastcgi_add_connection(ndpi_struct, flow); + ndpi_int_fastcgi_add_connection(ndpi_struct, flow, NULL); } } +static int ndpi_search_fastcgi_extra(struct ndpi_detection_module_struct * ndpi_struct, + struct ndpi_flow_struct * flow) +{ + ndpi_search_fastcgi(ndpi_struct, flow); + + return flow->extra_packets_func != NULL; +} + void init_fastcgi_dissector(struct ndpi_detection_module_struct *ndpi_struct, u_int32_t *id, NDPI_PROTOCOL_BITMASK *detection_bitmask) { |