# A Firmware Modification Vulnerability During Firmware Update in TP-Link TL-WR941ND Wireless Routers ## Affected Products: We have tested on the following devices: - TP-Link TL-WR941ND V2/V3 (firmware version: 3.13.9 and earlier) - TP-Link TL-WR941ND V4 (firmware version: 3.12.8 and earlier) Also, we suspect it may also work on other models of TL-WR941ND/TL-WR941N series devices. ## Overview: An exploitable firmware modification vulnerability was discovered on the TP-Link TL-WR941ND V2 and V3 wireless routers. A specially crafted firmware update image can allow an attacker to bypass the firmware verification in the firmware update process and install a malicious firmware image, thus resulting in either denial-of-service (DoS) or malware or backdoor planting. This vulnerability could be triggered during a user performing a firmware update with a self-uploaded firmware image. During the firmware delivery, the attacker can replace the user-uploaded firmware image with the malicious firmware image. ## Details: When performing a firmware update, users can download a new firmware image from the vendor server and upload it via the web interface of the device. The firmware update web interface is shown below. ![](https://i.imgur.com/wETZCE1.png) *Fig. 1. The web interface for firmware update.* The structure of the firmware image is [header, bootloader, header, kernel, rootfs]. It is worth noting that each header contains an **MD5 checksum**, which is used to verify the data integrity of the firmware. When a firmware image is uploaded, the web server will calculate the image checksums and compare them with the checksum values in the headers. The decompiled function that is used to verify the firmware image is shown below. ``` undefined4 upgradeFirmware(int param_1,int param_2) { ... if (param_2 - 0x30000U < 0x7d0001) { iVar8 = check_filesize(param_2); if (iVar8 != 0) { iVar8 = isSysUpgradeNeedChecksum(); if (iVar8 != 0) { local_30 = *(undefined4 *)(param_1 + 0x4c); local_2c = *(undefined4 *)(param_1 + 0x50); local_28 = *(undefined4 *)(param_1 + 0x54); local_24 = *(undefined4 *)(param_1 + 0x58); pcVar11 = getMd5Key; if (*(int *)(param_1 + 0x94) != 0) { pcVar11 = getMd5Key_bootloader; } ... iVar8 = md5_verify_digest(&local_30,param_1,param_2); if (iVar8 == 0) { printf("image md5 checksum is not correct!\n\r"); *(undefined4 *)(param_1 + 0x58) = local_24; *(undefined4 *)(param_1 + 0x4c) = local_30; *(undefined4 *)(param_1 + 0x50) = local_2c; *(undefined4 *)(param_1 + 0x54) = local_28; return 0x4655; } *(undefined4 *)(param_1 + 0x50) = local_2c; *(undefined4 *)(param_1 + 0x4c) = local_30; *(undefined4 *)(param_1 + 0x54) = local_28; *(undefined4 *)(param_1 + 0x58) = local_24; } if (((DAT_10002810 != 0) && (iVar8 = isFreeUpdate(), iVar8 == 0)) && ((iVar8 = getProductId(), *(int *)(param_1 + 0x40) != iVar8 || (iVar8 = getProductVer(), *(int *)(param_1 + 0x44) != iVar8)))) { printf("Firmware version check failed"); return 0x4655; } ... } ``` However, the communication during firmware delivery uses the plain HTTP protocol, which does not provide any cryptographic protection of the uploaded contents. Also, there is no signature verification for the update firmware image. Therefore, an attacker with a privileged network position (which could be obtained via ARP spoofing, DNS spoofing, or other approaches) can exploit this issue in order to provide customized malicious firmware updates. Specifically, the attack could replace several bytes in the kernel with arbitrary bytes and replace the checksums in the header after calculating the checksums of the modified firmware image. In this way, a customized malicious firmware image is crafted. During the firmware update process, the attacker can replace the user-uploaded firmware with the crafted firmware, which then causes the device to no longer work or planted with backdoors or malware. The vulnerability has been successfully exploited by creating a proof-of-concept. Take a TL-WR941ND V3 (firmware version: 3.13.9) device as an example. In this case, we modified the 4 bytes (address range: 0x400 to 0x403) with value 0xBB50EA2C to 0x00000000. Then we modified the checksum fields in the firmware header, the firmware headers before and after modification are listed below. ![](https://i.imgur.com/8kPVCri.png) *Fig. 2. The original MD5 checksum field in the firmware header.* *The original firmware header information:* ``` Filename : wr941nv3_en_3_13_9_up(120201).bin Filesize : 0x003c0000 / 3932160 Image Vendor : TP-LINK Technologies Image Version : ver. 1.0 Image Size : 0x003c0000 / 3932160 Image Checksum : a0 b1 9a 0f 99 cf 9f 04 72 7d c8 d0 5b 07 62 a4 (Valid) Product Id : 0x09410002 (TL-WR941NDv2) Product Version : 0x00000002 Firmware Version : 3.13.9 Kernel Offset : 0x00000200 / 512 Kernel Length : 0x000ca8ed / 829677 Kernel Load Address: 0x80002000 Kernel Entry Point : 0x801ae000 Kernel Checksum : 53 5f 84 d5 d4 c7 c0 85 b6 57 1e 4d a5 45 a1 ad (Not Verified) Rootfs Offset : 0x00100000 / 1048576 Rootfs Length : 0x002c0000 / 2883584 ``` --- ![](https://i.imgur.com/RJR94at.png) *Fig. 3. The modified MD5 checksum field in the firmware header.* *The modified firmware header information:* ``` Filename : wr941nv3_en_3_13_9_up(120201).bin Filesize : 0x003c0000 / 3932160 Image Vendor : TP-LINK Technologies Image Version : ver. 1.0 Image Size : 0x003c0000 / 3932160 Image Checksum : b7 20 40 e9 f0 79 98 21 2b 1a b2 0d a7 eb 83 8b (Valid) Product Id : 0x09410002 (TL-WR941NDv2) Product Version : 0x00000002 Firmware Version : 3.13.9 Kernel Offset : 0x00000200 / 512 Kernel Length : 0x000ca8ed / 829677 Kernel Load Address: 0x80002000 Kernel Entry Point : 0x801ae000 Kernel Checksum : 53 5f 84 d5 d4 c7 c0 85 b6 57 1e 4d a5 45 a1 ad (Not Verified) Rootfs Offset : 0x00100000 / 1048576 Rootfs Length : 0x002c0000 / 2883584 ``` After replacing the original firmware image with the crafted firmware image during the firmware update procedure, the firmware verification is passed and then the malicious firmware is flashed into the device. Until now, the firmware modification attack is launched successfully.