aboutsummaryrefslogtreecommitdiff
path: root/src/lib/protocols/fastcgi.c
diff options
context:
space:
mode:
authorToni <matzeton@googlemail.com>2022-08-30 11:38:36 +0200
committerGitHub <noreply@github.com>2022-08-30 11:38:36 +0200
commitf7907976c9234353c7b7ec81445ef4f219d93be3 (patch)
treec479c9d58d99026c07a56821a8bbe3ff9aa7d24f /src/lib/protocols/fastcgi.c
parentfe28d55801e589bdf74c32948002b797959bf0bd (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.c149
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)
{