Let's look at the firmware.
Arduino/libraries/ESP8266mDNS/src/ESP8266mDNS_Legacy.cpp
Here is a classic remote buffer overflow.
void MDNSResponder::_parsePacket(){
int i;
char tmp;
bool serviceParsed = false;
bool protoParsed = false;
bool localParsed = false;
char hostName[255];
uint8_t hostNameLen;
char serviceName[32];
...
_conn_readS(hostName, hostNameLen);
hostName[hostNameLen] = '\0';
if(hostName[0] == '_'){
serviceParsed = true;
memcpy(serviceName, hostName+1, hostNameLen);
serviceNameLen = hostNameLen-1;
hostNameLen = 0;
}
This appears non exploitable due to the buffer overflow overflowing into an adjacent buffer.
There are other bugs too. The following probably will probably result in a Denial of Service.
void MDNSResponder::_parsePacket(){
int i;
char tmp;
bool serviceParsed = false;
bool protoParsed = false;
bool localParsed = false;
char hostName[255];
uint8_t hostNameLen;
char serviceName[32];
uint8_t serviceNameLen;
uint16_t servicePort = 0;
char protoName[32];
protoName[0] = 0;
uint8_t protoNameLen = 0;
...
_conn_readS(serviceName, tmp8);
serviceName[tmp8] = '\0';
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.printf(" %d ", tmp8);
for (int n = 0; n < tmp8; n++) {
DEBUG_ESP_PORT.printf("%c", serviceName[n]);
}
DEBUG_ESP_PORT.println();
+++ no validation on tmp8.. serviceName is buffer of 32
+++ this isn't the DoS bug.
...
uint16_t answerType = _conn_read16(); // Read type
uint16_t answerClass = _conn_read16(); // Read class
uint32_t answerTtl = _conn_read32(); // Read ttl
uint16_t answerRdlength = _conn_read16(); // Read rdlength
+++ andwerRdLength can be < 3
(void) answerClass;
(void) answerTtl;
if(answerRdlength > 255){
if(answerType == MDNS_TYPE_TXT && answerRdlength < 1460){
while(--answerRdlength) _conn->read();
} else {
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.printf("Data len too long! %u\n", answerRdlength);
#endif
_conn->flush();
return;
}
}
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.printf("type: %04x rdlength: %d\n", answerType, answerRdlength);
#endif
if (answerType == MDNS_TYPE_PTR) {
partsCollected |= 0x01;
_conn_readS(hostName, answerRdlength); // Read rdata
if(hostName[answerRdlength-2] & 0xc0){
memcpy(answerHostName, hostName+1, answerRdlength-3);
+++ int underflow when answerRdLength is < 3
answerHostName[answerRdlength-3] = '\0';
}