From 3a53d96526b193c541cd5f5c1a6213405cc9791f Mon Sep 17 00:00:00 2001 From: alexstanoev Date: Sat, 6 May 2017 00:07:16 +0100 Subject: [PATCH] Validate MQTT broker IP and escape quotes when displaying This commit implements address validation for the broker address in the MQTT configuration page of the CC26XX web demo example. Additionally, the Type ID, Org ID, Auth Token, Command Type and Event Type ID fields have quotes escaped (" -> ") to prevent XSS/broken page issues when displaying user-sourced input in HTML input fields. --- .../cc26xx/cc26xx-web-demo/httpd-simple.c | 45 +++++++++++++++++-- examples/cc26xx/cc26xx-web-demo/mqtt-client.c | 12 ++++- 2 files changed, 52 insertions(+), 5 deletions(-) diff --git a/examples/cc26xx/cc26xx-web-demo/httpd-simple.c b/examples/cc26xx/cc26xx-web-demo/httpd-simple.c index e23e78efe..17f62f0d7 100644 --- a/examples/cc26xx/cc26xx-web-demo/httpd-simple.c +++ b/examples/cc26xx/cc26xx-web-demo/httpd-simple.c @@ -137,6 +137,10 @@ PROCESS(httpd_simple_process, "CC26XX Web Server"); #define REQUEST_TYPE_GET 1 #define REQUEST_TYPE_POST 2 /*---------------------------------------------------------------------------*/ +/* Temporary buffer for holding escaped HTML used by html_escape_quotes */ +#define HTML_ESCAPED_BUFFER_SIZE 128 +static char html_escaped_buf[HTML_ESCAPED_BUFFER_SIZE]; +/*---------------------------------------------------------------------------*/ static const char *NOT_FOUND = "" "
" "

404 - file not found

" @@ -305,6 +309,31 @@ url_unescape(const char *src, size_t srclen, char *dst, size_t dstlen) return i == srclen; } /*---------------------------------------------------------------------------*/ +static char* +html_escape_quotes(const char *src, size_t srclen) +{ + size_t srcpos, dstpos; + memset(html_escaped_buf, 0, HTML_ESCAPED_BUFFER_SIZE); + for(srcpos = dstpos = 0; + srcpos < srclen && dstpos < HTML_ESCAPED_BUFFER_SIZE - 1; srcpos++) { + if(src[srcpos] == '\0') { + break; + } else if(src[srcpos] == '"') { + if(dstpos + 7 > HTML_ESCAPED_BUFFER_SIZE) { + break; + } + + strcpy(&html_escaped_buf[dstpos], """); + dstpos += 6; + } else { + html_escaped_buf[dstpos++] = src[srcpos]; + } + } + + html_escaped_buf[HTML_ESCAPED_BUFFER_SIZE - 1] = '\0'; + return html_escaped_buf; +} +/*---------------------------------------------------------------------------*/ void httpd_simple_register_post_handler(httpd_simple_post_handler_t *h) { @@ -675,7 +704,9 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s)) config_div_right)); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "value=\"%s\" ", - cc26xx_web_demo_config.mqtt_config.type_id)); + html_escape_quotes( + cc26xx_web_demo_config.mqtt_config.type_id, + MQTT_CLIENT_CONFIG_TYPE_ID_LEN))); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "name=\"type_id\">%s", config_div_close)); @@ -687,7 +718,9 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s)) config_div_right)); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "value=\"%s\" ", - cc26xx_web_demo_config.mqtt_config.org_id)); + html_escape_quotes( + cc26xx_web_demo_config.mqtt_config.org_id, + MQTT_CLIENT_CONFIG_ORG_ID_LEN))); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "name=\"org_id\">%s", config_div_close)); @@ -711,7 +744,9 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s)) config_div_right)); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "value=\"%s\" ", - cc26xx_web_demo_config.mqtt_config.cmd_type)); + html_escape_quotes( + cc26xx_web_demo_config.mqtt_config.cmd_type, + MQTT_CLIENT_CONFIG_CMD_TYPE_LEN))); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "name=\"cmd_type\">%s", config_div_close)); @@ -724,7 +759,9 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s)) config_div_right)); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "value=\"%s\" ", - cc26xx_web_demo_config.mqtt_config.event_type_id)); + html_escape_quotes( + cc26xx_web_demo_config.mqtt_config.event_type_id, + MQTT_CLIENT_CONFIG_EVENT_TYPE_ID_LEN))); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "name=\"event_type_id\">%s", config_div_close)); diff --git a/examples/cc26xx/cc26xx-web-demo/mqtt-client.c b/examples/cc26xx/cc26xx-web-demo/mqtt-client.c index e45378264..d3f3c0207 100644 --- a/examples/cc26xx/cc26xx-web-demo/mqtt-client.c +++ b/examples/cc26xx/cc26xx-web-demo/mqtt-client.c @@ -64,6 +64,9 @@ */ static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd"; /*---------------------------------------------------------------------------*/ +#define ADDRESS_CONVERSION_OK 1 +#define ADDRESS_CONVERSION_ERROR 0 +/*---------------------------------------------------------------------------*/ /* * A timeout used when waiting for something to happen (e.g. to connect or to * disconnect) @@ -350,13 +353,20 @@ ip_addr_post_handler(char *key, int key_len, char *val, int val_len) { int rv = HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; + /* + * uiplib_ip6addrconv will immediately start writing into the supplied buffer + * even if it subsequently fails. Thus, pass an intermediate buffer + */ + uip_ip6addr_t tmp_addr; + if(key_len != strlen("broker_ip") || strncasecmp(key, "broker_ip", strlen("broker_ip")) != 0) { /* Not ours */ return HTTPD_SIMPLE_POST_HANDLER_UNKNOWN; } - if(val_len > MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN) { + if(val_len > MQTT_CLIENT_CONFIG_IP_ADDR_STR_LEN + || uiplib_ip6addrconv(val, &tmp_addr) != ADDRESS_CONVERSION_OK) { /* Ours but bad value */ rv = HTTPD_SIMPLE_POST_HANDLER_ERROR; } else {