From f65ae0694b99f454a0525bc387ef8cac0162b5d7 Mon Sep 17 00:00:00 2001
From: Theo Arends <11044339+arendst@users.noreply.github.com>
Date: Mon, 18 Dec 2023 12:31:14 +0100
Subject: [PATCH] Fix XSS phase 1
---
.../xdrv_01_9_webserver.ino | 47 ++++++++++---------
.../tasmota_xdrv_driver/xdrv_02_9_mqtt.ino | 10 ++--
.../tasmota_xdrv_driver/xdrv_06_snfbridge.ino | 2 +-
.../tasmota_xdrv_driver/xdrv_10_scripter.ino | 2 +-
.../xdrv_16_tuyamcu_v1.ino | 2 +-
.../xdrv_16_tuyamcu_v2.ino | 2 +-
.../tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino | 2 +-
7 files changed, 36 insertions(+), 31 deletions(-)
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino
index 79c953b72..df267b533 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_01_9_webserver.ino
@@ -477,6 +477,10 @@ static void WebGetArg(const char* arg, char* out, size_t max)
// out[max-1] = '\0'; // Ensure terminating NUL
}
+String SettingsTextEscaped(uint32_t index) {
+ return HtmlEscape(SettingsText(index));
+}
+
String AddWebCommand(const char* command, const char* arg, const char* dflt) {
/*
// OK but fixed max argument
@@ -865,7 +869,7 @@ void WSContentStart_P(const char* title, bool auth) {
WSContentBegin(200, CT_HTML);
if (title != nullptr) {
- WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsText(SET_DEVICENAME), title);
+ WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsTextEscaped(SET_DEVICENAME).c_str(), title);
}
}
@@ -909,7 +913,7 @@ void WSContentSendStyle_P(const char* formatP, ...) {
WebColor(COL_TEXT_WARNING),
#endif
WebColor(COL_TITLE),
- (Web.initial_config) ? "" : (Settings->flag5.gui_module_name) ? "" : ModuleName().c_str(), SettingsText(SET_DEVICENAME));
+ (Web.initial_config) ? "" : (Settings->flag5.gui_module_name) ? "" : ModuleName().c_str(), SettingsTextEscaped(SET_DEVICENAME).c_str());
// SetOption53 - Show hostname and IP address in GUI main menu
#if (RESTART_AFTER_INITIAL_WIFI_CONFIG)
@@ -1264,12 +1268,12 @@ void HandleRoot(void)
#ifdef USE_SONOFF_IFAN
if (IsModuleIfan()) {
WSContentSend_P(HTTP_DEVICE_CONTROL, 36, 1,
- (strlen(SettingsText(SET_BUTTON1))) ? SettingsText(SET_BUTTON1) : PSTR(D_BUTTON_TOGGLE),
+ (strlen(SettingsText(SET_BUTTON1))) ? SettingsTextEscaped(SET_BUTTON1).c_str() : PSTR(D_BUTTON_TOGGLE),
"");
for (uint32_t i = 0; i < MaxFanspeed(); i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("%d"), i);
WSContentSend_P(HTTP_DEVICE_CONTROL, 16, i +2,
- (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsText(SET_BUTTON2 + i) : stemp,
+ (strlen(SettingsText(SET_BUTTON2 + i))) ? SettingsTextEscaped(SET_BUTTON2 + i).c_str() : stemp,
"");
}
} else {
@@ -1281,13 +1285,13 @@ void HandleRoot(void)
int32_t ShutterWebButton;
if (ShutterWebButton = IsShutterWebButton(idx)) {
WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / cols, idx,
- (set_button) ? GetWebButton(idx -1) : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 2) /* is locked */ ? "-" : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))),
+ (set_button) ? HtmlEscape(GetWebButton(idx -1)).c_str() : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 2) /* is locked */ ? "-" : ((ShutterGetOptions(abs(ShutterWebButton)-1) & 8) /* invert web buttons */ ? ((ShutterWebButton>0) ? "▼" : "▲") : ((ShutterWebButton>0) ? "▲" : "▼"))),
"");
} else {
#endif // USE_SHUTTER
snprintf_P(stemp, sizeof(stemp), PSTR(" %d"), idx);
WSContentSend_P(HTTP_DEVICE_CONTROL, 100 / cols, idx,
- (set_button) ? GetWebButton(idx -1) : (cols < 5) ? PSTR(D_BUTTON_TOGGLE) : "",
+ (set_button) ? HtmlEscape(GetWebButton(idx -1)).c_str() : (cols < 5) ? PSTR(D_BUTTON_TOGGLE) : "",
(set_button) ? "" : (TasmotaGlobal.devices_present > 1) ? stemp : "");
#ifdef USE_SHUTTER
}
@@ -2078,15 +2082,15 @@ void HandleWifiConfiguration(void) {
}
WSContentSend_P(PSTR("
"), (limitScannedNetworks) ? PSTR(D_SHOW_MORE_WIFI_NETWORKS) : PSTR(D_SCAN_FOR_WIFI_NETWORKS));
- WSContentSend_P(HTTP_FORM_WIFI_PART1, (WifiIsInManagerMode()) ? "" : PSTR(" (" STA_SSID1 ")"), SettingsText(SET_STASSID1));
+ WSContentSend_P(HTTP_FORM_WIFI_PART1, (WifiIsInManagerMode()) ? "" : PSTR(" (" STA_SSID1 ")"), SettingsTextEscaped(SET_STASSID1).c_str());
if (WifiIsInManagerMode()) {
// As WIFI_HOSTNAME may contain %s-%04d it cannot be part of HTTP_FORM_WIFI where it will exception
WSContentSend_P(PSTR(">"));
} else {
#ifdef USE_CORS
- WSContentSend_P(HTTP_FORM_WIFI_PART2, SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME), SettingsText(SET_CORS));
+ WSContentSend_P(HTTP_FORM_WIFI_PART2, SettingsTextEscaped(SET_STASSID2).c_str(), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsTextEscaped(SET_HOSTNAME).c_str(), SettingsTextEscaped(SET_CORS).c_str());
#else
- WSContentSend_P(HTTP_FORM_WIFI_PART2, SettingsText(SET_STASSID2), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsText(SET_HOSTNAME));
+ WSContentSend_P(HTTP_FORM_WIFI_PART2, SettingsTextEscaped(SET_STASSID2).c_str(), WIFI_HOSTNAME, WIFI_HOSTNAME, SettingsTextEscaped(SET_HOSTNAME).c_str());
#endif
}
@@ -2099,9 +2103,9 @@ void HandleWifiConfiguration(void) {
WSContentSend_P(PSTR(""));
if (WIFI_TESTING == Wifi.wifiTest) {
- WSContentSend_P(PSTR(D_TRYING_TO_CONNECT "
%s
"), SettingsText(SET_STASSID1));
+ WSContentSend_P(PSTR(D_TRYING_TO_CONNECT "
%s"), SettingsTextEscaped(SET_STASSID1).c_str());
} else if (WIFI_TEST_FINISHED_BAD == Wifi.wifiTest) {
- WSContentSend_P(PSTR(D_CONNECT_FAILED_TO " %s
" D_CHECK_CREDENTIALS ""), SettingsText(SET_STASSID1));
+ WSContentSend_P(PSTR(D_CONNECT_FAILED_TO " %s
" D_CHECK_CREDENTIALS ""), SettingsTextEscaped(SET_STASSID1).c_str());
}
// More Options Button
WSContentSend_P(PSTR(""),
@@ -2163,7 +2167,7 @@ void HandleLoggingConfiguration(void) {
}
WSContentSend_P(PSTR(""));
}
- WSContentSend_P(HTTP_FORM_LOG2, SettingsText(SET_SYSLOG_HOST), Settings->syslog_port, Settings->tele_period);
+ WSContentSend_P(HTTP_FORM_LOG2, SettingsTextEscaped(SET_SYSLOG_HOST).c_str(), Settings->syslog_port, Settings->tele_period);
WSContentSend_P(HTTP_FORM_END);
WSContentSpaceButton(BUTTON_CONFIGURATION);
WSContentStop();
@@ -2198,10 +2202,10 @@ void HandleOtherConfiguration(void) {
WSContentSendStyle();
TemplateJson();
- WSContentSend_P(HTTP_FORM_OTHER, ResponseData(), (USER_MODULE == Settings->module) ? PSTR(" checked disabled") : "",
+ WSContentSend_P(HTTP_FORM_OTHER, HtmlEscape(ResponseData()).c_str(), (USER_MODULE == Settings->module) ? PSTR(" checked disabled") : "",
(Settings->flag5.disable_referer_chk) ? PSTR(" checked") : "", // SetOption128 - Enable HTTP API
(Settings->flag.mqtt_enabled) ? PSTR(" checked") : "", // SetOption3 - Enable MQTT
- SettingsText(SET_FRIENDLYNAME1), SettingsText(SET_DEVICENAME));
+ SettingsTextEscaped(SET_FRIENDLYNAME1).c_str(), SettingsTextEscaped(SET_DEVICENAME).c_str());
char stemp[32];
uint32_t maxfn = (TasmotaGlobal.devices_present > MAX_FRIENDLYNAMES) ? MAX_FRIENDLYNAMES : (!TasmotaGlobal.devices_present) ? 1 : TasmotaGlobal.devices_present;
@@ -2215,7 +2219,7 @@ void HandleOtherConfiguration(void) {
(i) ? stemp : "",
i,
(i) ? stemp : "",
- SettingsText(SET_FRIENDLYNAME1 + i));
+ SettingsTextEscaped(SET_FRIENDLYNAME1 + i).c_str());
}
#ifdef USE_EMULATION
@@ -2377,7 +2381,7 @@ void HandleInformation(void)
if (IsModuleIfan()) { maxfn = 1; }
#endif // USE_SONOFF_IFAN
for (uint32_t i = 0; i < maxfn; i++) {
- WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsText(SET_FRIENDLYNAME1 +i));
+ WSContentSend_P(PSTR("}1" D_FRIENDLY_NAME " %d}2%s"), i +1, SettingsTextEscaped(SET_FRIENDLYNAME1 +i).c_str());
}
WSContentSend_P(PSTR("}1}2 ")); // Empty line
bool show_hr = false;
@@ -2391,7 +2395,7 @@ void HandleInformation(void)
int32_t rssi = WiFi.RSSI();
WSContentSend_P(PSTR("}1" D_AP "%d " D_INFORMATION "}2" D_SSID " %s
" D_RSSI " %d%%, %d dBm
" D_MODE " 11%c
" D_CHANNEL " %d
" D_BSSID " %s"),
Settings->sta_active +1,
- HtmlEscape(SettingsText(SET_STASSID1 + Settings->sta_active)).c_str(),
+ SettingsTextEscaped(SET_STASSID1 + Settings->sta_active).c_str(),
WifiGetRssiAsQuality(rssi), rssi,
pgm_read_byte(&kWifiPhyMode[WiFi.getPhyMode() & 0x3]),
WiFi.channel(),
@@ -2460,14 +2464,14 @@ void HandleInformation(void)
WSContentSend_P(PSTR("}1" D_HTTP_API "}2%s"), Settings->flag5.disable_referer_chk ? PSTR(D_ENABLED) : PSTR(D_DISABLED)); // SetOption 128
WSContentSend_P(PSTR("}1}2 ")); // Empty line
if (Settings->flag.mqtt_enabled) { // SetOption3 - Enable MQTT
- WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsText(SET_MQTT_HOST));
+ WSContentSend_P(PSTR("}1" D_MQTT_HOST "}2%s"), SettingsTextEscaped(SET_MQTT_HOST).c_str());
WSContentSend_P(PSTR("}1" D_MQTT_PORT "}2%d"), Settings->mqtt_port);
#ifdef USE_MQTT_TLS
WSContentSend_P(PSTR("}1" D_MQTT_TLS_ENABLE "}2%s"), Settings->flag4.mqtt_tls ? PSTR(D_ENABLED) : PSTR(D_DISABLED));
#endif // USE_MQTT_TLS
- WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsText(SET_MQTT_USER));
+ WSContentSend_P(PSTR("}1" D_MQTT_USER "}2%s"), SettingsTextEscaped(SET_MQTT_USER).c_str());
WSContentSend_P(PSTR("}1" D_MQTT_CLIENT "}2%s"), TasmotaGlobal.mqtt_client);
- WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsText(SET_MQTT_TOPIC));
+ WSContentSend_P(PSTR("}1" D_MQTT_TOPIC "}2%s"), SettingsTextEscaped(SET_MQTT_TOPIC).c_str());
uint32_t real_index = SET_MQTT_GRP_TOPIC;
for (uint32_t i = 0; i < MAX_GROUP_TOPICS; i++) {
if (1 == i) { real_index = SET_MQTT_GRP_TOPIC2 -1; }
@@ -2634,7 +2638,7 @@ void HandleUpgradeFirmware(void) {
WSContentStart_P(PSTR(D_FIRMWARE_UPGRADE));
WSContentSendStyle();
- WSContentSend_P(HTTP_FORM_UPG, SettingsText(SET_OTAURL));
+ WSContentSend_P(HTTP_FORM_UPG, SettingsTextEscaped(SET_OTAURL).c_str());
#ifdef ESP32
if (EspSingleOtaPartition() && !EspRunningFactoryPartition()) {
WSContentSend_P(HTTP_FORM_RST_UPG_FCT, PSTR(D_START_UPGRADE));
@@ -3780,6 +3784,7 @@ void CmndWebCanvas(void) {
- WebCanvas linear-gradient(#F02 7%,#F93,#FF4,#082,#00F,#708 93%) // Gradient pride flag
- WebCanvas linear-gradient(#F02 16%,#F93 16% 33%,#FF4 33% 50%,#082 50% 67%,#00F 67% 84%,#708 84%) // Pride flag
- WebCanvas linear-gradient(90deg,#05A 33%,#FFF 33% 67%,#F43 67%) // Flag France
+ - WebCanvas linear-gradient(#000 33%,#D00 33% 67%,#FC0 67%) // Flag Germany
- WebCanvas linear-gradient(#059 33%,#FFF 33% 67%,#F43 67%) // Flag The Netherlands
- WebCanvas linear-gradient(#05B 50%,#FD0 50%) // Flag Ukraine
- WebCanvas linear-gradient(#FFF 33%,#07D 33% 67%,#F34 67%) // Flag Russia
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino
index 91eb1ef6d..7312135e8 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino
@@ -1974,16 +1974,16 @@ void HandleMqttConfiguration(void)
WSContentStart_P(PSTR(D_CONFIGURE_MQTT));
WSContentSendStyle();
WSContentSend_P(HTTP_FORM_MQTT1,
- SettingsText(SET_MQTT_HOST),
+ SettingsTextEscaped(SET_MQTT_HOST).c_str(),
Settings->mqtt_port,
#ifdef USE_MQTT_TLS
Mqtt.mqtt_tls ? PSTR(" checked") : "", // SetOption103 - Enable MQTT TLS
#endif // USE_MQTT_TLS
- Format(str, PSTR(MQTT_CLIENT_ID), sizeof(str)), PSTR(MQTT_CLIENT_ID), SettingsText(SET_MQTT_CLIENT));
+ Format(str, PSTR(MQTT_CLIENT_ID), sizeof(str)), PSTR(MQTT_CLIENT_ID), SettingsTextEscaped(SET_MQTT_CLIENT).c_str());
WSContentSend_P(HTTP_FORM_MQTT2,
- (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsText(SET_MQTT_USER),
- Format(str, PSTR(MQTT_TOPIC), sizeof(str)), PSTR(MQTT_TOPIC), SettingsText(SET_MQTT_TOPIC),
- PSTR(MQTT_FULLTOPIC), PSTR(MQTT_FULLTOPIC), SettingsText(SET_MQTT_FULLTOPIC));
+ (!strlen(SettingsText(SET_MQTT_USER))) ? "0" : SettingsTextEscaped(SET_MQTT_USER).c_str(),
+ Format(str, PSTR(MQTT_TOPIC), sizeof(str)), PSTR(MQTT_TOPIC), SettingsTextEscaped(SET_MQTT_TOPIC).c_str(),
+ PSTR(MQTT_FULLTOPIC), PSTR(MQTT_FULLTOPIC), SettingsTextEscaped(SET_MQTT_FULLTOPIC).c_str());
WSContentSend_P(HTTP_FORM_END);
WSContentSpaceButton(BUTTON_CONFIGURATION);
WSContentStop();
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino b/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino
index 9b34c497d..2b9988ec6 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_06_snfbridge.ino
@@ -516,7 +516,7 @@ void SonoffBridgeAddButton(void) {
for (uint32_t j = 0; j < 4; j++) {
idx++;
WSContentSend_P(PSTR(" | "), idx, // &k is related to WebGetArg("k", tmp, sizeof(tmp));
- (strlen(GetWebButton(idx -1))) ? GetWebButton(idx -1) : itoa(idx, number, 10));
+ (strlen(GetWebButton(idx -1))) ? HtmlEscape(GetWebButton(idx -1)).c_str() : itoa(idx, number, 10));
}
}
WSContentSend_P(PSTR(""));
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
index f18ba4bc7..98a9c352f 100755
--- a/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_10_scripter.ino
@@ -10325,7 +10325,7 @@ void ScriptFullWebpage(uint8_t page) {
}
WSContentBegin(200, CT_HTML);
- WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsText(SET_DEVICENAME), PSTR("Full Screen"));
+ WSContentSend_P(HTTP_HEADER1, PSTR(D_HTML_LANGUAGE), SettingsTextEscaped(SET_DEVICENAME).c_str(), PSTR("Full Screen"));
WSContentSend_P(HTTP_SCRIPT_FULLPAGE1, page , fullpage_refresh);
WSContentSend_P(HTTP_SCRIPT_FULLPAGE2, fullpage_refresh);
//WSContentSend_P(PSTR(""));
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino
index 5ea82165d..1c0e29315 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v1.ino
@@ -1624,7 +1624,7 @@ void TuyaAddButton(void) {
char stemp[33];
snprintf_P(stemp, sizeof(stemp), PSTR("" D_JSON_IRHVAC_MODE ""));
WSContentSend_P(HTTP_DEVICE_CONTROL, 26, TasmotaGlobal.devices_present + 1,
- (strlen(GetWebButton(TasmotaGlobal.devices_present))) ? GetWebButton(TasmotaGlobal.devices_present) : stemp, "");
+ (strlen(GetWebButton(TasmotaGlobal.devices_present))) ? HtmlEscape(GetWebButton(TasmotaGlobal.devices_present)).c_str() : stemp, "");
WSContentSend_P(PSTR(""));
}
}
diff --git a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino
index a85b7fe53..78d562546 100644
--- a/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino
+++ b/tasmota/tasmota_xdrv_driver/xdrv_16_tuyamcu_v2.ino
@@ -2432,7 +2432,7 @@ void TuyaAddButton(void) {
char stemp[33];
snprintf_P(stemp, sizeof(stemp), PSTR("" D_JSON_IRHVAC_MODE ""));
WSContentSend_P(HTTP_DEVICE_CONTROL, 26, TasmotaGlobal.devices_present + 1,
- (strlen(GetWebButton(TasmotaGlobal.devices_present))) ? GetWebButton(TasmotaGlobal.devices_present) : stemp, "");
+ (strlen(GetWebButton(TasmotaGlobal.devices_present))) ? HtmlEscape(GetWebButton(TasmotaGlobal.devices_present)).c_str() : stemp, "");
WSContentSend_P(PSTR(""));
}
}
diff --git a/tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino b/tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino
index 684c63cbb..4270fc665 100644
--- a/tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino
+++ b/tasmota/tasmota_xlgt_light/xlgt_07_lsc_mcsl.ino
@@ -269,7 +269,7 @@ void LscMcAddFuctionButtons(void) {
WSContentSend_P(PSTR(" | "), // &lsc is related to WebGetArg("lsc", tmp, sizeof(tmp));
100 / cols,
idx -1,
- (strlen(GetWebButton(idx))) ? GetWebButton(idx) : itoa(idx, number, 10));
+ (strlen(GetWebButton(idx))) ? HtmlEscape(GetWebButton(idx)).c_str() : itoa(idx, number, 10));
}
}
WSContentSend_P(PSTR(""));