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.
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.
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.
-
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 towta_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.
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.
Year | OTAID | First patched in | Examples (not exhaustive) | |
---|---|---|---|---|
Prerelease | Release | |||
2023 | W23A | 03.30.30 | 03.20.61 | NANO77; UR7x/UR8x |
W23H | 03.30.35 | 03.30.77 | A3/B3 OLED; NANO77; QNED8x; UR80/UR81 | |
W23M | 03.30.40 | 03.30.85 | QNED75; UR90 | |
W23O | 03.30.35 | 03.30.60 | C3/G3 OLED | |
W23P | 03.30.40 | 03.30.76 | NANO77; UR7x/UR8x/UR90 | |
2022 | W22A | 04.40.40 | – | Various mid-range models |
W22H | 04.40.35 13.30.13 | 04.40.75 | A2/B2 OLED; QNED8x; NANO75; UQ7x/UQ80/UQ90 | |
W22L | 04.40.45 | 04.40.90 | FHD models | |
W22O | 04.40.40 13.30.09 | 04.40.90 | C2/G2 OLED; Posé/Flex | |
W22P | 04.40.40 | 04.40.85 | Various mid-range models | |
C22H | 04.40.75 | 03.34.40 | Higher-end non-LG webOS (WEE 2.0) | |
C22P | 04.40.70 | 03.34.40 | Lower-end non-LG webOS (WEE 2.0) | |
2021 | W21A | 03.40.70 | 03.40.70 | Various mid-range models |
W21K | 03.40.55 | 03.40.85 | 8K models | |
W21O | 03.40.85 | 03.40.85 | C1/G1 OLED | |
W21P | 03.40.70 | 03.40.70 | Various mid-range models | |
W21U | 03.40.70 | 03.40.70 | A1/B1 OLED; QNED9x; NANO8x/NANO9x; UP80 | |
N21D | <03.43.11 | <03.43.11 | StanbyME | |
2020 | W20H | 04.50.56 | 04.50.56 | BX OLED; NANO8x/NANO9x; UN8x/UN90 |
W20L | 04.50.56 | 04.50.56 | Certain Japanese FHD models | |
W20O | 04.50.56 | 04.50.56 | CX/GX OLED | |
W20P | 04.50.56 (ARIB) | 04.50.56 (ARIB) | Various mid-range models | |
C20P | 04.50.61 | 04.50.61 | Non-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.
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.
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
.
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.
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 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.
This work
is licensed under a Creative Commons
Attribution-NonCommercial-ShareAlike 4.0 International License.
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