Root From a World-Writable XML
Root From a World-Writable XML
Some vulnerabilities are subtle. This one is a world-writable XML file, an unsanitized string, and a root daemon that believes whatever the XML tells it. Chain those together and any app on a Honeywell CT47 — no permissions, no exploit primitives, no user interaction — gets uid=0. Verified on hardware.
The door
Honeywell's logger fleet is configured from /storage/IPSM/honeywell/persist/hxlogger.xml — sitting in a directory mounted world-writable, permissions 666, so the EZConfig app (a different UID) can edit it. That design decision means every app on the device can edit it too. This is the same class of mistake as the WWAN engineering mode: a legitimate OEM convenience feature that dissolved the trust boundary it was supposed to sit behind.
The injection
The HxLogger system app parses that XML and, for "dynamic log" commands, builds a shell command:
echo -n 'file <FileName> func <FuncName> +p'> /sys/kernel/debug/dynamic_debug/control
command.fileName is read straight from the XML with no sanitization. Close the quote, slip a command in, reopen:
FileName: "';id>/sdcard/p;echo -n '" FuncName: "foo" Shell parses as: echo -n 'file ' → prints "file " id>/sdcard/p → executes id, writes output echo -n ' func foo +p'> ... → completes the control-file write
Why this reaches root
service hxlogger_kerdynalog /system/bin/hxlogger_daemon_copy.sh kernel_dynamic_logs
class core
user root
group shell everybody system sdcard_rw log
The trigger is SystemProperties.set(), which fires the init.rc wildcard trigger on property:persist.vendor.hsm.kerdynalog.requestcmd=* — see the companion piece on wildcard triggers. init is PID 1. The service is declared user root. Whatever the XML says, init runs as root.
The 91-byte budget
Android's property service caps values at PROP_VALUE_MAX = 91 bytes. The full injected string must fit:
"echo -n 'file " = 14 bytes " func foo +p'> " = 15 bytes "/sys/kernel/debug/..." = 39 bytes → 68 bytes overhead, 23 for payload "/proc/dynamic_debug/..." = 28 bytes → 57 bytes overhead, 34 for payload Our payload: FileName ";id>/sdcard/p;" (15 chars) → total 70 bytes ✓
Thirty-four characters of command as root. You don't need more.
The restart problem — and the kgsl trick
The XML is only re-read on service start or when the HxLogger UI resumes. The obvious broadcast is a trap: honeywell.hxlogger.change.config.file triggers a write (config → XML), not a re-read. And the 91-byte overflow crash we tried as a state-reset doesn't reliably kill the service — the crash dialog appears, the process may live on.
So we made the OS do the murder. The CT47 runs a Qualcomm kgsl GPU driver, and /dev/kgsl-3d0 lets you allocate GPU buffers that are never drawn or released — a silent GPU memory leak. Android's Low Memory Killer reaps background services first. HxLogger dies, memory is freed, we relaunch clean:
1. Inject clean payload into hxlogger.xml 2. Open /dev/kgsl-3d0, allocate, never release → LMK kills hxlogger 3. am start -n honeywell.hxlogger/.activity.MainActivity 4. HxLogger re-reads XML → SystemProperties.set() → init fires root service 5. Verify: /data/local/tmp/p contains "uid=0(root)" ✓
SELinux saw the whole thing
The daemon's SELinux context is denied dac_override and blocked reading the /sdcard symlink — and it didn't matter, because writing to /data/local/tmp/ is allowed. The policy polices the edges of the blast radius, not the center. A root shell that can write where the policy permits is still a root shell.
user root from logger services that only need /sys/kernel/debug writes via a constrained helper; replace wildcard property triggers with exact values; and audit every path where config becomes command.One world-writable file. One unsanitized string. One root service. The most dangerous code on this device is the code that was trying to be convenient.
frankSx / frankhacks.blogspot.com — companion pieces: the WWAN engineering mode, the AutoInstall signature-hash collision, and the wildcard trigger / low-severity findings from the same device.
Comments
Post a Comment