## Summary
A distinct alternate trigger was confirmed for the same Cudy LT300 3.0 time-setting command injection sink: authenticated HTTP JSON-RPC `POST /cgi-bin/luci/rpc/app` with method `system.setclock` reaches `usr/lib/lua/luci/apprpc/system.lua` and passes attacker-controlled JSON data into `date -s '%s'`. This is not a bypass of the fixed firmware: the same JSON-RPC payload was tested against LT300 V3 firmware `2.5.12-20260518-234632` and did not create the command-execution proof file. The fixed firmware covers both the originally reproduced CBI endpoint and this RPC entrypoint by adding quote handling/validation in the relevant time-setting handlers.

## Fix Coverage / Assumptions
- The original fix appears to rely on removing the ability for a user-controlled time string to break out of the single-quoted `date -s '%s'` shell argument.
- The fixed 2.5.12 firmware explicitly covers:
  - `usr/lib/lua/luci/model/cbi/system/systime.lua`, the original `/cgi-bin/luci/admin/system/systime` CBI form path. String markers show `date -s '%s'`, `gsub`, and `fork_exec` in the fixed handler.
  - `usr/lib/lua/luci/apprpc/system.lua`, the JSON-RPC application API path. String markers show `date -s '%s'`, `gsub`, and `fork_exec` in the fixed handler.
- The fixed RPC endpoint returned an application-level error for the malicious parameter: `Invalid Parameter`, and no proof file was created.
- No `SECURITY.md` or detailed threat-model file was present inside the firmware rootfs. Cudy has a public “Report Vulnerability” page, but the extracted page did not publish exclusions that would make authenticated administrative command injection out of scope. The tested path crosses the same network administrative trust boundary as the parent issue, not a local-file or self-attack boundary.
- The fix does not remove shell use entirely; it still leaves shell-command construction (`date -s '%s'`) present. However, the tested quote-breakout data path is covered in both observed time-setting handlers in 2.5.12.

## Variant / Alternate Trigger
The confirmed alternate path is the LuCI JSON-RPC application endpoint rather than the CBI HTML form endpoint:

- Parent entrypoint: `POST /cgi-bin/luci/admin/system/systime`, form field `cbid.system.ntp.current`, CBI model `usr/lib/lua/luci/model/cbi/system/systime.lua`.
- Variant entrypoint: `POST /cgi-bin/luci/rpc/app`, JSON-RPC method `system.setclock`, JSON `params[0]`, application RPC module `usr/lib/lua/luci/apprpc/system.lua`.
- Sink: `luci.sys.call()` invoking `date -s '%s'` with the attacker-controlled time string in vulnerable firmware.

The variant reproducer sends JSON like:

```json
{"jsonrpc":"2.0","id":1,"method":"system.setclock","params":["2025-01-01 12:00:00'; echo VULN_RPC_SETCLOCK_VARIANT_EXECUTED > /root/vuln_rpc_variant_proof; #"]}
```

On firmware 2.4.5 this creates `/root/vuln_rpc_variant_proof` in the emulated firmware root. On firmware 2.5.12 the same request does not create `/root/fixed_rpc_variant_proof`.

## Impact
- Package/component affected: Cudy LT300 3.0 firmware LuCI web administration stack, specifically the JSON-RPC application API (`luci.controller.rpc` → `luci.jsonrpc` → `luci.app` → `luci.apprpc.system.setclock`).
- Affected version tested: `LT300V3-R100-2.4.5-20250519-131314`.
- Fixed/control version tested: `LT300V3-R100-2.5.12-20260518-234632`.
- Risk level and consequences: high for affected firmware. An authenticated attacker with access to the router administrative web/RPC interface can execute shell commands in the router firmware context via JSON-RPC, leading to device compromise, persistence opportunities, traffic interception, or lateral movement from the router.

## Impact Parity
- Disclosed/claimed maximum impact for the parent: OS command injection / code execution through the router administrative interface.
- Reproduced impact from this variant run: command execution through a different HTTP entrypoint. The vulnerable 2.4.5 run created `VULN_RPC_SETCLOCK_VARIANT_EXECUTED` via JSON-RPC.
- Parity: `full` for the vulnerable-version alternate trigger; `none` for bypass against fixed 2.5.12.
- Not demonstrated: persistence, interactive shell, unauthenticated access, and post-exploitation actions were not attempted. The fixed firmware did not execute the payload.

## Root Cause
The same underlying bug class is reachable from a second LuCI time-setting surface in the vulnerable firmware. In `usr/lib/lua/luci/apprpc/system.lua`, the exported `setclock` function accepts a time string from JSON-RPC and passes it to a shell command template containing `date -s '%s'`. Because vulnerable 2.4.5 does not sanitize a single quote in that string, the input closes the shell quote and appends an attacker command. The fixed 2.5.12 firmware keeps the command template but adds quote handling/validation (`gsub` marker and runtime `Invalid Parameter` response), preventing the tested breakout. No public source-code fix commit was supplied; analysis compares vendor firmware images directly.

## Reproduction Steps
1. Run `bundle/vuln_variant/reproduction_steps.sh`.
2. The script:
   - Acquires or reuses vendor LT300 V3 firmware images for 2.4.5 and 2.5.12.
   - Extracts their SquashFS root filesystems.
   - Runs the original firmware `uhttpd` and LuCI RPC stack under `qemu-mipsel`/`proot`.
   - Adds only emulation shims for router-only session/hardware dependencies.
   - Sends the same JSON-RPC `system.setclock` command-injection payload to vulnerable and fixed firmware.
3. Expected evidence:
   - Vulnerable 2.4.5 creates `vuln_rpc_variant_proof` containing `VULN_RPC_SETCLOCK_VARIANT_EXECUTED`.
   - Fixed 2.5.12 does not create `fixed_rpc_variant_proof` and returns an invalid-parameter style response.
   - The script exits `1` because this is an alternate trigger on the vulnerable version, not a fixed-version bypass.

## Evidence
Primary evidence files:
- `bundle/logs/vuln_variant/reproduction_steps.log` records the successful side-by-side test.
- `bundle/logs/vuln_variant/product/proof_summary.txt` contains:
  - `vuln proof: VULN_RPC_SETCLOCK_VARIANT_EXECUTED`
  - `fixed no proof file (negative control passed)`
- `bundle/logs/vuln_variant/http/vuln_rpc_request.json` contains the malicious JSON-RPC request to `/cgi-bin/luci/rpc/app`.
- `bundle/logs/vuln_variant/http/vuln_rpc_response_body.txt` shows a JSON-RPC response with `result:null` from the vulnerable target.
- `bundle/logs/vuln_variant/http/fixed_rpc_response_body.txt` shows the fixed target returned `Invalid Parameter` for the same payload.
- `bundle/logs/vuln_variant/product/code_identity.txt` records firmware versions and hashes for `uhttpd`, `/www/cgi-bin/luci`, `luci/controller/rpc.lua`, `luci/app.lua`, `luci/apprpc/system.lua`, and `model/cbi/system/systime.lua`.
- `bundle/vuln_variant/runtime_manifest.json` records the runtime endpoint and tested versions.

Environment details:
- Runtime used Cudy firmware rootfs, firmware `uhttpd`, LuCI JSON-RPC dispatcher, `qemu-mipsel`, and `proot`.
- Firmware versions came from `/etc/rom_version`: vulnerable `2.4.5-20250519-131314`, fixed `2.5.12-20260518-234632`.

## Recommendations / Next Steps
- Keep the 2.5.12 fix coverage for both `model/cbi/system/systime.lua` and `luci/apprpc/system.lua`; regression tests should include both `/admin/system/systime` and `/rpc/app` `system.setclock`.
- Prefer eliminating shell interpolation entirely: call date-setting functionality without `/bin/sh`, or strictly parse time input into numeric year/month/day/hour/min/sec components before execution.
- Add a centralized helper for time-setting input validation so future LuCI, RPC, mobile-app, or setup-wizard paths cannot reintroduce separate quoting logic.
- Add negative tests for quotes, semicolons, backticks, pipes, redirection, `$()`, newlines, and encoded variants for every administrative endpoint that reaches shell execution.

## Additional Notes
- Idempotency was confirmed by running `bundle/vuln_variant/reproduction_steps.sh` twice; both runs completed and produced the same verdict.
- This is a meaningful alternate entrypoint but not a fixed-version bypass. The coding stage should treat it as evidence that the complete fix must cover all time-setting APIs, not only the originally reported CBI page.
