A closer look at the TCL Go Flip 4 5G and KaiOS 4.0

Posted by Tom Barrasso on (updated on )

The TCL Go Flip 4 5G (commercial reference T440W-EATBUS1-V for T-Mobile) is the first device to ship with KaiOS 4.0. Given that CVE-2023-33294 and CVE-2023-27108 were discovered on the original Alcatel Go Flip 4 running KaiOS 3.0, it was worth checking whether these issues carried forward to new hardware.

The short answer: KaiOS 4.0 is architecturally indistinguishable from KaiOS 3.0. Many of the known vulnerabilities have been partially addressed, but the surface area remains broad.

ADB & Developer Mode Access

Screenshots from the TCL Go Flip 4 5G
Screenshots from the TCL Go Flip 4 5G

Unlike previous Go Flip models, developer mode is surprisingly easy to enable! This may be an accident, since the build on my Flip 4 5G is signed using test-keys. Here’s the build fingerprint:

1ro.system_dlkm.build.fingerprint=TCL/gflip5gtmo/gflip5gtmo:14/UKQ1.241125.001/jenkins05072152:user/test-keys

Either way, I was able to use standard secret dialer codes:

  • *#*333284#*#* — developer mode
  • *#8378269# — launch Engmode app

Web2Dev (W2D) also works! WebActivity remains accessible from websites on the Browser app. See w2d.js.org for details.

1let w2d = new WebActivity("configure", {
2  target: "device",
3  section: "developer",
4});
5
6w2d.start()
7  .then(() => console.log("Developer Tools opened!"));

Making a surprising return is the secret Konami Code in the Settings app! Navigate to Settings > Device > Device Info > More Info. The following soft key sequence opens a hidden menu:

1SoftLeft SoftLeft SoftRight SoftLeft SoftRight SoftRight

Finally, another option from the Browser to launch the Engmode app (or any app for that matter) is to use the kind=app parameter passed to window.open using the Manifest URL of the target app.

1window.open(
2  "http://engmode.localhost/manifest.webmanifest",
3  "_blank",
4  "kind=app,noopener=yes"
5);

Limitations

Like previous KaiOS 3.0 devices, it’s not possible to access the device from Firefox’s Remote Debugger due to SELinux and permission issues accessing the debugger socket.

103-02 11:07:46.865  5108  5108 E adbd    : failed to connect to socket 'localfilesystem:/data/local/firefox-debugger-socket': could not connect to localfilesystem address 'localfilesystem:/data/local/firefox-debugger-socket'
203-02 11:07:46.860  5108  5108 W adbd    : type=1400 audit(0.0:61): avc:  denied  { write } for  name="firefox-debugger-socket" dev="dm-38" ino=5153 scontext=u:r:adbd:s0 tcontext=u:object_r:b2g_data_file:s0 tclass=sock_file permissive=0

The default Device Preference values match those from previous ROMs.

1pref("devtools.debugger.unix-domain-socket", "/data/local/firefox-debugger-socket");
2pref("devtools.debugger.remote-port", 6000);

CVE-2023-33294: tctweb_server Endures

CVE-2023-33294 documented that the /system/bin/tctweb_server binary on KaiOS 3.0 exposed an unauthenticated HTTP server on port 2929 that would execute arbitrary commands as root. This binary disappeared in KaiOS 3.1, but possibly because it’s TCL-specific and the only KaiOS 3.1 devices were from other vendors like Nokia.

On the Go Flip 4 5G, tctweb_server is back, again listening on http://127.0.0.1:2929. It runs as root and is accessible to installed apps and websites via the browser. However, this time it’s significantly hardened. For starters, SE Linux prevents you from reading or copying the binary. It also implements an internal command and property whitelist. Attempts to issue arbitrary shell commands or read files like /system/build.prop are rejected.

103-02 13:14:12.550  1487 11862 E tctweb_server: [mweb] not in whitelist cat /sys/class/power_supply/battery/temp,

The server still responds to name=query&api=... style requests for a restricted set of system properties, and cmd=shell&... commands limited to diagnostic operations. The broad cmdshell passthrough that made the original vulnerability so dangerous appears to no longer be present.

A second daemon, EsimAfterSalesServer (run using mozTCPSocket inside the System app), runs on port 8612 and handles eSIM provisioning commands (clear-profile, esim-status-check) via a basic HTTP parser. This provides a specific vector for interacting with carrier eSIM profiles, and once again is globally accessible including from the browser, but lacks general system access.

Consistent with other TCL devices like the Android-based Go Flip 2, this phone ships with a few extra binaries including mfg_util and its daemon counterpart, mfg_utild, which reads special flags from /dev/block/by-name/oembin. This may be useful in a future exploit as it appears to control the ro.boot.inproductionflag.

CVE-2023-27108: getCallLogList Fixed

CVE-2023-27108 documented that the getCallLogList Web Activity on KaiOS 3.0 returned call log data to any caller without any origin check.

In KaiOS 4.0, the Communications app manifest now includes an allowedOrigins restriction:

 1"getCallLogList": {
 2  "filters": {
 3    "type": {
 4      "required": true,
 5      "value": [
 6        "calllog/tel"
 7      ]
 8    }
 9  },
10  "allowedOrigins": [
11    "system",
12    "http://system.localhost"
13  ],
14  "returnValue": true
15}

This is exactly the mitigation recommended in the original CVE write-up. Calls to this activity from third-party apps or websites will now be rejected with the error NO_PROVIDER.

Engmode: Possible Command Injection

The following has yet to be confirmed. Like nearly every previous KaiOS version, the Engmode API (navigator.b2g.engmodeManager) is limited to Core apps with the engmode permission. It also appears to perform complex input sanitization before passing commands off to EngmodeService.

One potential target for command injection is the updateAtmPressure method, which constructs a shell command by string concatenation:

 1updateAtmPressure(pressure) {
 2  return this.createPromiseWithId(aResolverId => {
 3    const floatRegex = /^[+-]?[0-9]+\.[0-9]+$/;
 4    if (
 5      parseFloat(pressure) > 259.0 &&
 6      parseFloat(pressure) < 1261.0 &&
 7      floatRegex.test(JSON.stringify(pressure))
 8    ) {
 9      var command =
10        "mkdir /mnt/testbox_log/;" +
11        "./vendor/bin/pressure_test -sensor=pressure -sample_rate=5 " +
12        "-duration=5 -limit1=3 -limit2=-3 -offset=" + pressure +
13        " > mnt/testbox_log/atmpressure.txt";
14
15      Services.cpmm.sendAsyncMessage("Engmode:EngmodeTestCommand", {
16        param: command,
17        useShell: true,
18        operation: "start",
19        requestID: aResolverId,
20      });
21    } else {
22      this.takePromiseResolver(aResolverId).reject("invalid parameter");
23    }
24  });
25}

The pressure value is passed directly into the shell command string. The validation — a range check and a regex applied to JSON.stringify(pressure) — is intended to restrict input to a decimal number. However, the JSON.stringify call wraps string inputs in quotes, so the regex will reject string inputs that would otherwise pass the float check. If pressure is a Number rather than a String, the regex comparison behaves as intended.

Other Changes

Copy/Paste

KaiOS 4.0 supports copy-paste using its own API.

 1// Copy text and show transient UI
 2const copyActivity = new WebActivity("copy-content-view", {
 3  content: "copy this text",
 4});
 5
 6copyActivity.start();
 7
 8// Displays a dialog showing how copy-paste works
 9const tutorialDialog = new WebActivity("show-copyPaste-guide");
10
11tutorialDialog.start();

Both navigator.clipboard.writeText and navigator.clipboard.readText() appear to work, but haven’t been tested cross-process. This functionality is gated behind a boolean Device Setting, copypaste.enabled, which is enabled by default on the Flip 4 5G. It can be disabled from the Developer Menu.

Content Security Policy (CSP)

Unlike KaiOS 2.5, the content security policy (CSP) for apps is not determined by Device Settings. Instead, api-daemon is responsible for serving apps and sets one CSP for packaged apps.

1[vhost]
2root_path = "/data/local/webapps/vroot"
3csp = "default-src * data: blob:; script-src 'self' http://127.0.0.1 http://shared.localhost; object-src 'none'; style-src 'self' 'unsafe-inline' http://shared.localhost"

As user @Cyan2048 noted on Discord, the CSP notably does not include wasm-unsafe-eval. This effectively blocks packaged apps from using WebAssembly (Wasm) on KaiOS 4.0.

Random Finds

The System app once again offers a show-toast activity that draws an alert window at the top of the screen. In previous KaiOS versions, this was sometimes restricted. In KaiOS 4.0, any app (or website) can use it.

1const showToast = new WebActivity("show-toast", {
2  title: "Toast Title",
3  text: "This is a longer message...",
4  timeout: 5000,
5});
6
7showToast.start();

Another unusual one is the reboot-device activity, which lets apps (or websites) request to reboot the phone. This requires user confirmation, but could still be annoying.

1const reboot = new WebActivity("reboot-device", {
2  appName: "Secret"
3});
4
5reboot.start();

The KaiStore also offers many open activities including kaistore-get-silent-apps, used by the System app to silently pre-install apps that the user cannot later delete.

Kids Mode

The only time apps aren’t silently installed is when the phone is set to “Kids Mode” via the kids.mode.enabled boolean Device Setting. This can be toggled from Settings > Account > Kids Mode > On. Kids Mode enables age-based restrictions limiting the available apps (removes social media, games, and the KaiStore) as well as blocking certain access from the browser.

Special Keys

Like most TCL devices, there are several shortcut keys on the TCL Go Flip 4 5G including:

  • QdCall - the phone icon on the flip cover that launches the Camera when double clicked
  • Message - the message bubble icon used to launch SMS Messages
  • FavoriteContacts - the star button used to launch the Contacts app
  • MicrophoneToggle - the center “OK” button triggers this key, instead of Enter

Interestingly, apps and websites are able to intercept these keys. Apps can also preventDefault, but websites cannot.

Voice Input

Unlike earlier KaiOS versions, there is no system-wide speech-to-text (STT) on KaiOS 4.0. The Device Preference voice-input.enabled is set to false and there is no pre-installed application to respond to the voice-input activity.

Conclusion

KaiOS 4.0 on the TCL Go Flip 4 5G is pretty much identical to KaiOS 3.0 from a user perspective. From a security point-of-view, it appears prior vulnerabilities have been hardened. Yet, exposing HTTP services like the eSIM provisioning server circumvents permission and inter-process communication (IPC) safeguards, which is fundamentally poor design.