# REPRO-2026-00258: Cudy LT300 3.0 OS command injection ## Summary Status: published Severity: high Type: security Confidence: high ## Identifiers REPRO ID: REPRO-2026-00258 CVE: CVE-2026-32833 ## Package Name: Cudy LT300 V3 firmware Ecosystem: firmware Affected: All firmware versions prior to 2.5.12 (confirmed vulnerable: 2.4.1, 2.4.5) Fixed: 2.5.12 (released 20-May-2026) ## Root Cause ## Summary CVE-2026-32833 is an OS command injection in the Cudy LT300 3.0 firmware LuCI web administration interface. The vulnerable firmware 2.4.5 exposes the product HTTP endpoint `POST /cgi-bin/luci/admin/system/systime`; authenticated attacker-controlled form data for the system time setting reaches the original firmware `usr/lib/lua/luci/model/cbi/system/systime.lua` handler. In the vulnerable image, the `cbid.system.ntp.current` value is interpolated into a shell command of the form `date -s '%s'` without shell metacharacter sanitization, allowing a payload containing a quote and command separator to execute arbitrary commands. ## Impact - Package/component affected: Cudy LT300 3.0 firmware LuCI/uhttpd administrative web interface, specifically `model/cbi/system/systime.lua` behind `/cgi-bin/luci/admin/system/systime`. - Affected versions: firmware before 2.5.12; reproduced against `LT300V3-R100-2.4.5-20250519-131314`. - Fixed/control version: `LT300V3-R100-2.5.12-20260518-234632`. - Risk level and consequences: high. An attacker with access to the administrative interface/session can execute shell commands in the router firmware context by submitting crafted time-setting form data. On a physical router this can lead to device compromise, persistence, traffic interception, or pivoting from the router. ## Impact Parity - Disclosed/claimed maximum impact: code execution / OS command injection via a router administrative interface API endpoint. - Reproduced impact from this run: code execution. The reproduction created attacker-chosen proof files with controlled contents by sending HTTP POST requests to the original firmware `/cgi-bin/luci/admin/system/systime` endpoint through the firmware `uhttpd` server and original `/www/cgi-bin/luci` LuCI dispatcher/CBI path. - Parity: `full`. - Not demonstrated: no post-exploitation persistence or interactive shell was attempted; the proof stops after deterministic command execution side effects. ## Root Cause The root cause is unsafe construction of a shell command from HTTP form input in the LuCI system time handler. In the vulnerable 2.4.5 firmware, the system time page includes bytecode string markers showing the affected flow: `timeclock`, `date -s '%s'`, and `fork_exec`. When the CBI form is submitted with the manual time-setting option, the user-supplied `cbid.system.ntp.current`/time value is used in a `date -s ''` command. Because the value is surrounded by single quotes but not sanitized before shell execution, an attacker can close the quote and append a shell command, e.g. `2025-01-01 12:00:00'; echo MARKER > /tmp/proof; #`. The fixed 2.5.12 firmware preserves the same endpoint and command structure but adds a `gsub` sanitization marker in the same `systime.lua` handler before `fork_exec`. The fixed negative-control runs reached the same product endpoint and form handler but did not create the attacker-controlled proof files. No public fix commit was provided in the ticket. The reproduction compares vendor firmware images directly: vulnerable `LT300V3-R100-2.4.5-20250519-131314` versus fixed `LT300V3-R100-2.5.12-20260518-234632`. ## Reproduction Steps 1. Use `bundle/repro/reproduction_steps.sh`. 2. The script: - Downloads or reuses the vendor LT300 V3 2.4.5 and 2.5.12 firmware zip files. - Extracts their SquashFS root filesystems. - Runs the firmware `usr/sbin/uhttpd` under `qemu-mipsel` and `proot`. - Uses the original firmware `/www/cgi-bin/luci`, `luci.dispatcher`, `luci.cbi`, and `usr/lib/lua/luci/model/cbi/system/systime.lua` path for the endpoint. - Adds only emulation shims for router-only services/hardware state (`ubus` session, `bdinfo`, and route-forbidden state) so the firmware web interface can run outside physical hardware; it does not replace the vulnerable endpoint handler. - Sends two vulnerable HTTP POST attempts to `/cgi-bin/luci/admin/system/systime` with payloads in `cbid.system.ntp.current`. - Sends two equivalent fixed-version negative-control attempts through the same endpoint. 3. Expected evidence: - Vulnerable attempts create proof files containing `VULN_ATTEMPT_1_COMMAND_EXECUTED` and `VULN_ATTEMPT_2_COMMAND_EXECUTED`. - Fixed attempts do not create proof files. - GET requests for both versions render the original `System Time` CBI form and include `cbid.system.ntp.current`, proving endpoint reachability. ## Evidence Primary runtime evidence: - `bundle/logs/reproduction_steps.log` records successful runs. - `bundle/repro/runtime_manifest.json` records the runtime endpoint path, `service_started=true`, `healthcheck_passed=true`, and `target_path_reached=true`. - `bundle/logs/artifacts/product/proof_summary.txt` contains: - `vuln attempt 1 proof: VULN_ATTEMPT_1_COMMAND_EXECUTED` - `vuln attempt 2 proof: VULN_ATTEMPT_2_COMMAND_EXECUTED` - `fixed attempt 1 no proof file (negative control passed)` - `fixed attempt 2 no proof file (negative control passed)` - `bundle/logs/artifacts/http/vuln_attempt1_request.txt` and `bundle/logs/artifacts/http/vuln_attempt2_request.txt` contain the malicious POST fields sent to `/cgi-bin/luci/admin/system/systime`. - `bundle/logs/artifacts/http/vuln_attempt1_response_headers.txt` shows `HTTP/1.1 200 OK` and `X-CBI-State: 1` for a submitted form. - `bundle/logs/artifacts/http/fixed_attempt1_response_headers.txt` shows the fixed endpoint was reached but did not accept the injected payload as a successful proof-producing command. - `bundle/logs/code_comparison.txt` and `bundle/logs/artifacts/product/code_identity.txt` capture firmware code identity and string-level handler differences. The vulnerable handler shows `timeclock`, `date -s '%s'`, and `fork_exec`; the fixed handler additionally shows `gsub`. Environment details: - Firmware rootfs execution used `qemu-mipsel` and `proot` in user-mode emulation. - The production-facing server was the firmware `uhttpd` binary serving the original firmware web root. - The entrypoint was the HTTP endpoint `/cgi-bin/luci/admin/system/systime`. ## Recommendations / Next Steps - Upgrade Cudy LT300 3.0 devices to firmware 2.5.12 or newer. - Do not build shell commands by concatenating or formatting raw HTTP form values. Use argument-vector APIs where possible, or strictly validate time values against a narrow date/time grammar before invoking any command. - If shell invocation is unavoidable, reject metacharacters such as quotes, semicolons, backticks, pipes, ampersands, redirection operators, `$()`, and newlines, and add regression tests for command-injection payloads. - Add endpoint-level tests for `/cgi-bin/luci/admin/system/systime` verifying that invalid time values fail closed and cannot create shell side effects. ## Additional Notes - Idempotency confirmation: `bundle/repro/reproduction_steps.sh` was run successfully multiple times consecutively after fixing non-root SquashFS extraction handling. Each run recreated fresh proof artifacts and revalidated both vulnerable and fixed firmware behavior. - The run uses emulation shims for hardware/session dependencies that are normally present on a physical router. The vulnerability proof itself is not a reimplemented handler: the HTTP request traverses firmware `uhttpd`, original `/www/cgi-bin/luci`, LuCI dispatcher/CBI, and the original firmware `systime.lua` bytecode handler. - The fixed-version negative control uses the actual fixed firmware handler rather than a hand-written surrogate. ## Reproduction Details Reproduced: 2026-07-06T10:50:14.116Z Duration: 5639 seconds Tool calls: 425 Turns: Unknown Handoffs: 3 ## Quick Verification Run one of these commands to verify locally: pruva-verify REPRO-2026-00258 pruva-verify CVE-2026-32833 Or open in GitHub Codespaces (zero-friction, auto-runs): https://github.com/codespaces/new?ref=repro/REPRO-2026-00258&repo=N3mes1s/pruva-sandbox Or download and run the script manually: curl -O https://api.pruva.dev/v1/reproductions/REPRO-2026-00258/artifacts/bundle/repro/reproduction_steps.sh chmod +x reproduction_steps.sh ./reproduction_steps.sh WARNING: Run in a sandboxed environment. This exploits a real vulnerability. ## References - NVD: https://nvd.nist.gov/vuln/detail/CVE-2026-32833 - Source: vendor-firmware:Cudy LT300 V3 ## Artifacts - bundle/repro/reproduction_steps.sh (reproduction_script, 16212 bytes) - bundle/repro/rca_report.md (analysis, 7483 bytes) - bundle/vuln_variant/reproduction_steps.sh (reproduction_script, 14370 bytes) - bundle/vuln_variant/rca_report.md (analysis, 8301 bytes) - bundle/logs/code_comparison.txt (other, 482 bytes) - bundle/artifact_promotion_manifest.json (other, 14577 bytes) - bundle/artifact_promotion_report.json (other, 14595 bytes) - bundle/vuln_variant/source_identity.json (other, 1454 bytes) - bundle/vuln_variant/root_cause_equivalence.json (other, 1447 bytes) - bundle/repro/runtime_manifest.json (other, 1621 bytes) - bundle/repro/validation_verdict.json (other, 777 bytes) - bundle/logs/reproduction_steps.log (log, 2561 bytes) - bundle/logs/artifacts/http/response.txt (other, 405 bytes) - bundle/logs/artifacts/product/proof_summary.txt (other, 220 bytes) - bundle/logs/artifacts/http/vuln_attempt1_request.txt (other, 402 bytes) - bundle/logs/artifacts/http/vuln_attempt1_response_headers.txt (other, 316 bytes) - bundle/logs/artifacts/http/vuln_attempt1_response_body.txt (other, 2121 bytes) - bundle/logs/artifacts/http/vuln_attempt2_request.txt (other, 402 bytes) - bundle/logs/artifacts/http/vuln_attempt2_response_headers.txt (other, 316 bytes) - bundle/logs/artifacts/http/vuln_attempt2_response_body.txt (other, 2121 bytes) - bundle/logs/artifacts/http/fixed_attempt1_request.txt (other, 404 bytes) - bundle/logs/artifacts/http/fixed_attempt1_response_headers.txt (other, 255 bytes) - bundle/logs/artifacts/http/fixed_attempt1_response_body.txt (other, 9623 bytes) - bundle/logs/artifacts/http/fixed_attempt2_request.txt (other, 404 bytes) - bundle/logs/artifacts/http/fixed_attempt2_response_headers.txt (other, 255 bytes) - bundle/logs/artifacts/http/fixed_attempt2_response_body.txt (other, 9623 bytes) - bundle/logs/artifacts/product/code_identity.txt (other, 1835 bytes) - bundle/logs/artifacts/product/uhttpd_runtime.log (log, 1988 bytes) - bundle/vuln_variant/patch_analysis.md (documentation, 5620 bytes) - bundle/vuln_variant/variant_manifest.json (other, 3620 bytes) - bundle/vuln_variant/validation_verdict.json (other, 2590 bytes) - bundle/vuln_variant/runtime_manifest.json (other, 1409 bytes) - bundle/logs/vuln_variant/reproduction_steps.log (log, 2303 bytes) - bundle/logs/vuln_variant/product/proof_summary.txt (other, 93 bytes) - bundle/logs/vuln_variant/http/vuln_rpc_request.json (other, 168 bytes) - bundle/logs/vuln_variant/http/vuln_rpc_response_headers.txt (other, 261 bytes) - bundle/logs/vuln_variant/http/vuln_rpc_response_body.txt (other, 38 bytes) - bundle/logs/vuln_variant/http/fixed_rpc_request.json (other, 170 bytes) - bundle/logs/vuln_variant/http/fixed_rpc_response_headers.txt (other, 230 bytes) - bundle/logs/vuln_variant/http/fixed_rpc_response_body.txt (other, 187 bytes) - bundle/logs/vuln_variant/product/code_identity.txt (other, 3017 bytes) ## API Access - JSON: https://api.pruva.dev/v1/reproductions/REPRO-2026-00258 - Script: https://api.pruva.dev/v1/reproductions/REPRO-2026-00258/artifacts/bundle/repro/reproduction_steps.sh - Web: https://pruva.dev/r/REPRO-2026-00258 ## For AI Assistants To help users with this reproduction: 1. The `pruva-verify` command is the simplest way to run the reproduction 2. The script downloads and runs automatically in an isolated temp directory 3. Always recommend running in a VM, container, or disposable environment 4. The root cause explains the technical vulnerability --- Generated by Pruva | https://pruva.dev