Fix XSS phase 1

This commit is contained in:
Theo Arends 2023-12-18 12:31:14 +01:00
parent c111bb963f
commit f65ae0694b
7 changed files with 36 additions and 31 deletions

View File

@ -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) ? "&#9660;" : "&#9650;") : ((ShutterWebButton>0) ? "&#9650;" : "&#9660;"))),
(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) ? "&#9660;" : "&#9650;") : ((ShutterWebButton>0) ? "&#9650;" : "&#9660;"))),
"");
} 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("<div><a href='/wi?scan='>%s</a></div><br>"), (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("></p>"));
} 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("<h3>"));
if (WIFI_TESTING == Wifi.wifiTest) {
WSContentSend_P(PSTR(D_TRYING_TO_CONNECT "<br>%s</h3></div>"), SettingsText(SET_STASSID1));
WSContentSend_P(PSTR(D_TRYING_TO_CONNECT "<br>%s</h3></div>"), SettingsTextEscaped(SET_STASSID1).c_str());
} else if (WIFI_TEST_FINISHED_BAD == Wifi.wifiTest) {
WSContentSend_P(PSTR(D_CONNECT_FAILED_TO " %s<br>" D_CHECK_CREDENTIALS "</h3></div>"), SettingsText(SET_STASSID1));
WSContentSend_P(PSTR(D_CONNECT_FAILED_TO " %s<br>" D_CHECK_CREDENTIALS "</h3></div>"), SettingsTextEscaped(SET_STASSID1).c_str());
}
// More Options Button
WSContentSend_P(PSTR("<div id=butmod style=\"display:%s;\"></div><p><form id=butmo style=\"display:%s;\"><button type='button' onclick='hidBtns()'>" D_SHOW_MORE_OPTIONS "</button></form></p>"),
@ -2163,7 +2167,7 @@ void HandleLoggingConfiguration(void) {
}
WSContentSend_P(PSTR("</select></p>"));
}
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&nbsp;")); // 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<br>" D_RSSI " %d%%, %d dBm<br>" D_MODE " 11%c<br>" D_CHANNEL " %d<br>" 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&nbsp;")); // 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

View File

@ -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();

View File

@ -516,7 +516,7 @@ void SonoffBridgeAddButton(void) {
for (uint32_t j = 0; j < 4; j++) {
idx++;
WSContentSend_P(PSTR("<td style='width:25%%'><button onclick='la(\"&k=%d\");'>%s</button></td>"), 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("</tr></table>"));

View File

@ -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("<div id='l1' name='l1'></div>"));

View File

@ -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("</tr></table>"));
}
}

View File

@ -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("</tr></table>"));
}
}

View File

@ -269,7 +269,7 @@ void LscMcAddFuctionButtons(void) {
WSContentSend_P(PSTR("<td style='width:%d%%'><button onclick='la(\"&lsc=%d\");'>%s</button></td>"), // &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("</tr></table>"));