New Xiaomi Router AC2100

Similar to the Rgv2/4A, can just flip bootdelay from off to 5 and then try and find some weakness..

~/RouterStuff/miwifi_rm2100 $ xxd ./nand_ac2100/ac2100.bin | grep bootdelay 
000255e0: 626f 6f74 6465 6c61 7900 0000 6f66 6600
00084010: 0062 6f6f 7464 656c 6179 3d35 0065 7468  .bootdelay=5.eth

Was fooling around a bit more, and came across this titbit while grepping strings


Could someone try the command injection?

Here's the boot log after factory reset:
I was unable to get a u-boot console, the bootdelay flag seems to be already in place.

1 Like

any news with this, I just ordered one :smiley:

maybe use Wireshark see what it expects to get over network?

@spyking I have one here too, soldered a pinheader on the serial port, and am thinking of buying a flashcat USB to dump/flash the NAND flash chip. But if it's possible to abuse the system through the LUCI webinterface, that would be awesome. With me the /cgi-bin/luci/;stok=d8a978fa56818ef9e091e4dcb7361c48/api/xqsystem url is available (different stok though). So is there a known command injection vulnerability there? If so, can you provide details/links? Cheers

Wait, I just realized, I have the redmi ac2100 (white with 6 external antennas), not the AC2100 (which is black). It is still based on the same chip though. Much of it seems the same. Here is my bootlog:

Should I open a new topic for that router, or since it seems to be (mostly) the same, keep it in this topic?

There is a topic about the redmi ac2100

I don't know if it makes sense to keep a different topic if both boxes are the same or very similar

would be also interested in this and how the injection would work - command wise ...

@dolfandringa, @thorsten97

Its going to be a bit harder to find injection weakpoints, as they use custom compiled lua code, instead of the old lua scripts. They seem to also use a custom luaL_loadfile implementation to load them and switch some bytes. Need to dig into it deeper.

But, it looks like if a ota firmware fails for some reason, console access can be enabled, with some button test points. Gotta dive into the binaries and look deeper - need to dig deeper!

       โ”‚ File: squashfs-root/lib/preinit/31_restore_nvram
   1   โ”‚ #!/bin/sh
   2   โ”‚
   3   โ”‚ . /lib/
   4   โ”‚
   5   โ”‚ xqdefaults="/usr/share/xiaoqiang/xiaoqiang-defaults.txt"
   6   โ”‚ hwv="`/sbin/hwversion`"
   7   โ”‚ do_xiaoqiang_defaults() {
   8   โ”‚     cat "${xqdefaults}" | while read line
   9   โ”‚     do
  10   โ”‚             nvram set "$line"
  11   โ”‚     done
  12   โ”‚ }
  13   โ”‚
  14   โ”‚
  15   โ”‚ do_nvram_corrupt() {
  16   โ”‚     cat "${xqdefaults}" | while read line
  17   โ”‚     do
  18   โ”‚         nvram set "$line"
  19   โ”‚     done
  20   โ”‚ }
  21   โ”‚
  22   โ”‚ do_flag_override() {
  23   โ”‚     local flag="$1"
  24   โ”‚     b_val=`bdata get $flag`
  25   โ”‚     n_val=`nvram get $flag`
  26   โ”‚     [ "$b_val" = "$n_val" ] && return 0
  27   โ”‚     [ "$b_val" = "1" ] && nvram set "$flag"=1
  28   โ”‚ }
  29   โ”‚
  30   โ”‚ flag_override() {
  31   โ”‚     do_flag_override uart_en
  32   โ”‚     do_flag_override ssh_en
  33   โ”‚     do_flag_override telnet_en
  34   โ”‚     do_flag_override boot_wait
  35   โ”‚ }
  36   โ”‚
  37   โ”‚ do_set_default_ssid() {
  38   โ”‚     num=`nvram get wl1_ssid | cut -b 7-10`
  39   โ”‚     temp=0x"$num"
  40   โ”‚     newnum="000"`printf "%x\n" $((0xffff-$temp))`
  41   โ”‚     pos=`expr length $newnum - 4`
  42   โ”‚     newnum=`echo ${newnum:$pos:4} | tr [a-z] [A-Z]`
  43   โ”‚     ssid2G=`nvram get wl1_ssid`
  44   โ”‚     result2G=`echo $ssid2G"_"$newnum`
  45   โ”‚     nvram set wl1_ssid=$result2G
  46   โ”‚
  47   โ”‚     has5G=`uci get misc.wireless.if_5G 2>/dev/null`
  48   โ”‚
  49   โ”‚     # D01 2/5G same ssid
  50   โ”‚     suf="_5G"
  51   โ”‚     model="`cat /proc/xiaoqiang/model`"
  52   โ”‚     [ "$model" = "D01" ] && {
  53   โ”‚         suf=""
  54   โ”‚     }
  55   โ”‚
  56   โ”‚     if [ -n "$has5G" ]; then
  57   โ”‚         ssid5G=`nvram get wl0_ssid | cut -b -10`
  58   โ”‚         result5G=`echo ${ssid5G}"_"${newnum}${suf}`
  59   โ”‚         nvram set wl0_ssid=$result5G
  60   โ”‚     fi
  61   โ”‚ }
  62   โ”‚
  63   โ”‚
  64   โ”‚ restore_nvram () {
  65   โ”‚     restore=`nvram get restore_defaults`
  66   โ”‚     if [ "$restore" = "1" ]; then
  67   โ”‚         flag_name=`uci get misc.mount_bind_etc.flag_name`
  68   โ”‚         nvram set $flag_name=1
  69   โ”‚         mtd erase overlay
  70   โ”‚         rec_mtd=$(find_mtd_part cfg_bak)
  71   โ”‚         [ -n "$rec_mtd" ] && mtd erase cfg_bak
  72   โ”‚     fi
  73   โ”‚
  74   โ”‚     ft_mode=`cat /proc/xiaoqiang/ft_mode`
  75   โ”‚     if [ "$ft_mode" != "1" ]; then
  76   โ”‚         sn=`nvram get SN`
  77   โ”‚         wl1_ssid=`nvram get wl1_ssid`
  78   โ”‚         countrycode=`nvram get CountryCode`
  79   โ”‚         if [ -z "$sn" -o -z "$wl1_ssid" -o -z "$countrycode" ]; then
  80   โ”‚             nvram_corrupt=1
  81   โ”‚         fi
  82   โ”‚     fi
  83   โ”‚
  84   โ”‚     # skip restore wifi radio flag from defaults if factory mode
  85   โ”‚     if [ "$ft_mode" = "1" ]; then
  86   โ”‚         wl1_val=`nvram get wl1_radio`
  87   โ”‚         wl0_val=`nvram get wl0_radio`
  88   โ”‚     fi
  89   โ”‚
  90   โ”‚     #restore: 1, ๆขๅคๅ‡บๅŽ‚่ฎพ็ฝฎ๏ผ›2๏ผŒotaๅ‡็บง
  91   โ”‚     #nvram_corrupt: 1, nvram่ขซ็ ดๅ
  92   โ”‚     if [ "$nvram_corrupt" = "1"  ]; then
  93   โ”‚         do_nvram_corrupt
  94   โ”‚         bdata sync
  95   โ”‚         nvram set nvram_corrupt=1
  96   โ”‚     fi
  97   โ”‚
  98   โ”‚     # restore to factory setting
  99   โ”‚     if [ "$restore" = "1" ]; then
 100   โ”‚         nvram unset nvram_corrupt
 101   โ”‚         nvram clear /usr/share/xiaoqiang/xiaoqiang-reserved.txt
 102   โ”‚         do_xiaoqiang_defaults
 103   โ”‚         bdata sync
 104   โ”‚         do_set_default_ssid
 105   โ”‚     fi
 106   โ”‚
 107   โ”‚     # OTA upgrade
 108   โ”‚     if [ "$restore" = "2" ]; then
 109   โ”‚         do_xiaoqiang_defaults
 110   โ”‚         flag_override
 111   โ”‚     fi
 112   โ”‚
 113   โ”‚     if [ "$ft_mode" = "1" ]; then
 114   โ”‚         [  "$wl1_val" != "" -a -n "$wl1_val" ] && nvram set wl1_radio=$wl1_val
 115   โ”‚         [  "$wl0_val" != "" -a -n "$wl0_val" ] && nvram set wl0_radio=$wl0_val
 116   โ”‚     fi
 117   โ”‚
 118   โ”‚     nvram commit
 119   โ”‚ }
 120   โ”‚
 121   โ”‚ boot_hook_add preinit_main restore_nvram
1 Like

I think if this script is run, and 5G SSID is set to

something123 ; telnetd ; something456

there is a chance that telnetd could be executed

1 Like

that seems pretty promising to me too. also more user-friendly than physically changing the bits on NAND.

i guess the question is "what is the default action?" to tftp-boot or to flash-from-tftp as in:

Please choose the operation:
   1: Load system code to SDRAM via TFTP.
   2: Load system code then write to Flash via TFTP.

if i were designing it, i'd probably have "option 1" be the default. (but then... who knows what sicks minds are out there).

given that this is a MT7621 with 128MB RAM and 128MB NAND, i'd probably try the initramfs.bin for the MIR3Gv2 for starters (it might keel over, it might not. i bet it will boot and get to the point where it starts probing for the SPI ;)). but porting this should be a real breeze. the real question is whether the "holding reset while booting" is going to work or not.

anyone feeling up to try this? (looks like we'll need to configure bootp+tftp server... not rocket science). i know at least some of you out there have openwrt routers :wink:

FWIW, here's (apparently) what worked for MIR3



as a guy who discovered another xiaomi device a few days ago (miwifi mesh), i can say that probably no telnetd is available inside the stock firmware
telnetd busybox applet for my device never run, no matter which value telnet_en 0 or 1, it just start and exit, probably telnet code replaced with dummy {} to prevent any kind of enabling it.
also no dropbear included in "stable" firmware usually, so uart is a single way to access device from inside, but as transmit to router disabled by default, you need to force it into tftp recovery mode using reset buttons and interrupt first boot at u-boot, enable uart_en, boot to stock firmware and modify any startup script to set uart_en to 1 at every boot (for example you can use /etc/rc.local)
to get a working telnetd, you need standalone static busybox binary with telnetd compiled for your target arch


i was just looking at the "miwifi mesh" forum, and i saw that you had managed to tftp boot but it wasn't clear what you were doing... it looks like you tftp booted the official firmware (and that did a lot of stuff) but it also looked like you tftp booted random initramfs images?

i'm asking because if you were able to boot initramfs images (ie, not only xiaomi-signed/verified binaries) then this should be a breeze.

as i said before, tftp recovery mode was required to get uart trasmit access (it enabled only first time after recovery), so after ive got working serial, ive booted initramfs images using bootp/bootm commands, no image signing required

1 Like

I've managed to flash the factory firmware using tftp but still unable to do anything at the uboot prompt at first boot :frowning:

And you still cant access command prompt at first boot after recovery?

I "binwalked" through the firmwareupdate file for the router and there is at least a link from telnetd to busybox:

thorsten@vsdaads:~/MOD/_miwifi_r2100_firmware_64288_2.0.376.bin.extracted/_2E4.extracted/_594080.extracted/cpio-root/usr/sbin$ ls -lh
total 1.6M
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 brctl -> ../../bin/busybox
-rwxrwxr-x 1 thorsten thorsten 4.2K Jan 29 00:12 btnd
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 dnsd -> ../../bin/busybox
-rwxrwxr-x 1 thorsten thorsten 594K Jan 29 00:12 hexdump
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 httpd -> ../../bin/busybox
-rwxr-xr-x 1 thorsten thorsten 883K Jan 29 00:12 mkxqimage
-rwxrwxr-x 1 thorsten thorsten  11K Jan 29 00:12 mtd
-rwxrwxr-x 1 thorsten thorsten  35K Jan 29 00:12 nanddump
-rwxr-xr-x 1 thorsten thorsten 7.5K Jan 29 00:12 nvram
-rwxr-xr-x 1 thorsten thorsten 4.0K Jan 29 00:12 rd
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 telnetd -> ../../bin/busybox
-rwxrwxr-x 1 thorsten thorsten  16K Jan 29 00:12 ubiattach
-rwxrwxr-x 1 thorsten thorsten  47K Jan 29 00:12 ubiformat
lrwxrwxrwx 1 thorsten thorsten   17 Jan 29 00:12 udhcpd -> ../../bin/busybox
-rwxr-xr-x 1 thorsten thorsten  691 Jan 29 00:12 xqled

My device also had it, but it was dummy