Skip to content

Instantly share code, notes, and snippets.

@throwaway96
Last active October 14, 2024 17:49
Show Gist options
  • Save throwaway96/b171240ef59d7f5fd6fb48fc6dfd2941 to your computer and use it in GitHub Desktop.
Save throwaway96/b171240ef59d7f5fd6fb48fc6dfd2941 to your computer and use it in GitHub Desktop.
LG WTA backdoor/vulnerability guide

WTA backdoor/vulnerability

Overview

There is a vulnerability/backdoor in webOS 5+ that allows you to easily run arbitrary commands as root during the boot process. The easiest way to exploit it simply involves putting a file on a USB drive and having it connected to your TV while it boots. There are two other methods that are more complex and require additional exploits.

LG has started patching the WTA vulnerability/backdoor.

This vulnerability was discovered by Mariotaku.

How to

Get a USB drive that is formatted with FAT32 or NTFS. Put a file named wta_usb.sh containing whatever you want to execute in the root directory of the drive. Reboot your TV while the USB drive is connected. Make sure the TV actually reboots. It may take a little while for it to actually execute.

The attached wta_usb.sh launches a telnet server on port 1234 with a root shell.

Homebrew Channel

If you have Homebrew Channel installed in Developer Mode, you can put the following commands in wta_usb.sh to root the TV:

/media/developer/apps/usr/palm/services/org.webosbrew.hbchannel.service/elevate-service
rm -rf /var/luna/preferences/devmode_enabled && mkdir -p /var/luna/preferences/devmode_enabled

Warning: After this runs (confirm by checking root status in Homebrew Channel), make sure to uninstall the Developer Mode app before rebooting the TV.

You can also just run these commands via the root telnet server.

Notes

  • It can be difficult to get a webOS TV to properly reboot. I don't feel like rewriting this, so see the crashd guide for more information.

  • If your wta_usb.sh is a script (it doesn't have to be), make sure it starts with a shebang line (e.g., #!/bin/sh) and has the correct line endings (i.e., LF). Permissions shouldn't matter since everything on a Windows filesystem is treated as executable.

  • If you're having trouble connecting to the telnet server and aren't sure the script is running, try using the attached wta_usb-toast.sh. Remember to rename it to wta_usb.sh. It will show a series of messages on your TV if it successfully runs. When you see the "hello" messages, the telnet server should already be running.

Patching

This table shows the first firmware version in which the WTA vulnerability/backdoor is known to have been patched. They are listed by (partial) OTAID. For help finding your OTAID, see the crashd guide.

YearOTAIDFirst patched inExamples
(not exhaustive)
PrereleaseRelease
2023 W23A03.30.3003.20.61NANO77; UR7x/UR8x
W23H03.30.3503.30.77A3/B3 OLED; NANO77; QNED8x; UR80/UR81
W23M03.30.4003.30.85QNED75; UR90
W23O03.30.3503.30.60C3/G3 OLED
W23P03.30.4003.30.76NANO77; UR7x/UR8x/UR90
2022 W22A04.40.40Various mid-range models
W22H04.40.35
13.30.13
04.40.75A2/B2 OLED; QNED8x; NANO75; UQ7x/UQ80/UQ90
W22L04.40.4504.40.90FHD models
W22O04.40.40
13.30.09
04.40.90C2/G2 OLED; Posé/Flex
W22P04.40.4004.40.85Various mid-range models
C22H04.40.7503.34.40Higher-end non-LG webOS (WEE 2.0)
C22P04.40.7003.34.40Lower-end non-LG webOS (WEE 2.0)
2021 W21A03.40.7003.40.70Various mid-range models
W21K03.40.5503.40.858K models
W21O03.40.8503.40.85C1/G1 OLED
W21P03.40.7003.40.70Various mid-range models
W21U03.40.7003.40.70A1/B1 OLED; QNED9x; NANO8x/NANO9x; UP80
N21D<03.43.11<03.43.11StanbyME
2020 W20H04.50.5604.50.56BX OLED; NANO8x/NANO9x; UN8x/UN90
W20L04.50.5604.50.56Certain Japanese FHD models
W20O04.50.5604.50.56CX/GX OLED
W20P04.50.56 (ARIB)04.50.56 (ARIB)Various mid-range models
C20P04.50.6104.50.61Non-LG webOS (WEE)

If you have a 2020+ OTAID that is not listed (e.g.: W20E, W20K, W22K, C22L, N22D, W23K, W23L), please contact us via Discord.

Mechanism

A script named wtaservice.sh searches for files named wta_usb.sh in the root directories of all partitions on all USB drives present during webOS boot. If one is found, it is executed.

Details

Starting with version 5, webOS has used systemd for initialization and service management. (Previous webOS versions used Upstart.)

Since the introduction of systemd, webOS has included a file named wtaservice.service that defines a systemd service. It is located in /lib/systemd/system, and its only action is running the shell script /lib/systemd/system/scripts/wtaservice.sh. The reason wtaservice.service runs is that there is a symbolic link to it in /lib/systemd/system/webos-rbd.target.wants, making it a dependency of webos-rbd.target. This means wtaservice will run when the target webos-rbd.target is requested. I haven't looked into what causes webos-rbd to run.

/lib/systemd/system/scripts/wtaservice.sh searches for files named wta_usb.sh using find on /tmp/usb with a maximum depth of 3. Since USB filesystems are mounted at e.g. /tmp/usb/sda/sda1, the maximum depth means only files in a USB filesystem's root directory will be found.

Note: Running a command with exec causes that command to replace the currently running script. Therefore no further commands from the script containing the exec will run.

If wta_usb.sh is found, it is executed with exec. Otherwise, wtaservice.sh now checks whether /var/luna/preferences/wta_enabled exists and terminates with no further action if it does not. If it does exist, the script checks whether /media/developer/com.lge.service.wta/service_ok exists. If service_ok exists, /media/developer/com.lge.service.wta/run.sh is executed, also with exec. If service_ok does not exist, a new shell is spawned (not sure why).

The new shell assigns a few default values to some environment variables then sources /var/luna/preferences/wta_enabled. This means that the commands contained in wta_enabled are run in such a way that any environment variables they set will be carried over to the containing shell. After wta_enabled is finished, the new shell enters an infinite loop in which it pings $SERVER_INTERNAL and $SERVER_EXTERNAL (in that order). The loop repeats every 60 seconds. The first time a server responds to a ping, that server's address is saved in the variable $SERVER and the loop exits. At this point a reverse shell (using /bin/bash) is launched, connecting to $SERVER on the port specified by $PORT (which defaults to 9001).

The defaults for $SERVER_INTERNAL and $SERVER_EXTERNAL are hewta.lge.com and wta.iptime.org, respectively. You can use /var/luna/preferences/wta_enabled to set $SERVER_INTERNAL and $SERVER_EXTERNAL to something you control. Or you can just run whatever commands you want in wta_enabled.

Mitigation

If you are worried about someone using this maliciously against you, there are a few ways you can mitigate the risk.

Ideally, you can eliminate the issue by updating to a firmware version that removes wtaservice.service. But that is only an option if such a version is available for your TV and you're not avoiding updates for other reasons.

For the USB route, some potential mitigations are:

  • Don't connect any USB drives to your TV. (Glue the ports shut?)
  • Don't have any USB drives connected to your TV at boot. Basically, unplug it when you're done.
  • Before connecting any USB drives to your TV, make sure their root directory doesn't contain a file named wta_usb.sh.
  • Don't let anyone you don't trust connect a USB drive to your TV.

For the other routes, another exploit would be required to create the wta_enabled file. There is not much you can do about it besides avoiding untrusted websites and apps.

What is WTA?

In wtaservice.service, WTA is described thusly:

WTA is a test agent service for ATS5

So WTA probably stands for "Wsomething Test Agent", but I have no idea what ATS5 is or how WTA is supposed to test it.

The mystery of wta.iptime.org

The default "external" server in wtaservice.sh is wta.iptime.org. ipTIME is a Korean router brand that offers a dynamic DNS (DDNS) service. This hostname was presumably created using said DDNS service.

At the time of writing (2024-01-07), wta.iptime.org resolves to 220.90.180.85. That IP belongs to Korea Telecom, a major Korean ISP. They probably have a wide range of customers, so that IP could be in use by any number of people or organizations.

It's possible that the WTA functionality has gone unused by LG for a long time now (e.g., if it was only used during development of webOS 5). Therefore the IP that wta.iptime.org is pointing to may not have been updated for years.

It is not clear why LG did not simply create a subdomain of one of their many domains like they did with hewta.lge.com. (The he refers to their Home Entertainment division, which is responsible for consumer TVs.)

It is also not clear why dynamic DNS would be necessary, as LG owns plenty of IP addresses. (165.186.0.0/16, 165.243.0.0/16, and 165.244.0.0/16 are just a few of the netblocks they own, with each having 65534 usable addresses). The answer may be that it is "external", but that only raises further questions: What exactly does "external" mean here? Assuming it just means "outside of LG's network", why would they need such a server for testing TVs?

There's probably a boring explanation for all of this, but unless LG wants to share it, we can only speculate.

License

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

#!/bin/sh
telnetd -l /bin/sh -p 1234
for i in $(seq 5); do
payload="$(printf '{"sourceId":"wta","message":"hello (%d)"}' "${i}")"
luna-send -n 1 'luna://com.webos.notification/createToast' "${payload}"
sleep 3
done
#!/bin/sh
telnetd -l /bin/sh -p 1234
@luisan1977
Copy link

luisan1977 commented Apr 15, 2024

Hi

This method in this version, it should not work. Is it right?. Is there any option or only to wait new vulneraties?

image

@Rutge-R
Copy link

Rutge-R commented May 17, 2024

The above method indeed shouldn't work (anymore). There are many options you could try of course. I guess it depends on how motivated you are to root your TV. But you could try above method and figure out in what way LG patched it's firmware to prevent the method from working. It usually takes LG a couple of updates before they've really succeeded in mitigating a root method.

@team-orangeBlue
Copy link

team-orangeBlue commented Jun 5, 2024

Worked great on a W21O on 03.00.60
Don't ask how I have a TV that old

edit the thing somehow updated to 03.40.87
i am extremely angry. had to use dejavuln and thankfully that worked

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment