T06 · System Persistence
Error
- Location
- scripts/generate_runbook.py:571
- Finding
- Unvalidated generation of privileged systemd installation and persistence commands<![CDATA[ ## Vulnerability Details **File Location**: `scripts/generate_runbook.py:381-382` and `scripts/generate_runbook.py:571-580` **Vulnerability Type**: T06: System Persistence, T09: Insecure Skill Coding Practices **Risk Level**: High ### Vulnerable Code ```python # Scan for systemd units for f in root.rglob(SYSTEMD_GLOB): if f.is_file() and "[Unit]" in f.read_text()[:200]: scanned.append(scan_systemd_unit(f)) ``` ```python if has_systemd: for s in scanned: if s["type"] == "systemd": unit_name = Path(s["path"]).name lines.append(f"### systemd Deploy ({unit_name})") lines.append("") lines.append("```bash") lines.append(f"sudo cp {s['path']} /etc/systemd/system/") lines.append("sudo systemctl daemon-reload") lines.append(f"sudo systemctl enable {unit_name}") lines.append(f"sudo systemctl start {unit_name}") lines.append("```") ``` ### Technical Analysis The scanner recursively accepts every `*.service` file whose first 200 characters contain `[Unit]`. It does not validate the unit's provenance, resolved location, `ExecStart` command, configured service account, executable ownership, or systemd hardening properties. For each accepted unit, the generated runbook recommends copying it into `/etc/systemd/system`, enabling it at boot, and starting it with `sudo`. Enabling a unit creates cross-session persistence. A service without an explicit `User=` directive ordinarily runs as root when installed as a system service. The generator does not itself execute these commands, so exploitation requires an operator or automation system to execute the generated runbook. Nevertheless, the commands are presented as standard deployment steps without a dedicated trust warning or mandatory review procedure. Repository-controlled paths and unit names are also embedded in shell commands without shell quoting. Spaces can break the commands ...[truncated 1700 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Do not generate `systemctl enable` or `systemctl start` commands by default. Treat installation and boot persistence as explicit, separately approved actions. 2. Add an option such as `--include-systemd-install`, disabled by default, and clearly explain that it produces privileged persistence commands. 3. Restrict systemd discovery to documented, approved directories rather than recursively trusting every `*.service` file. 4. Resolve every discovered path and verify that it remains inside the selected project root. 5. Reject symbolic links and unusual filenames by default. 6. Parse and validate `ExecStart`, `ExecStop`, `User`, `Group`, `EnvironmentFile`, and other security-sensitive directives before presenting deployment instructions. 7. Warn when `User=` is missing or set to `root`; recommend a dedicated unprivileged service account. 8. Generate a mandatory review step before installation, such as: ```bash systemd-analyze verify ./service-name.service sudo diff -u /etc/systemd/system/service-name.service ./service-name.service ``` 9. Use `shlex.quote()` for every repository-derived value embedded into a shell command. 10. Recommend systemd hardening directives where appropriate, including `NoNewPrivileges=true`, `PrivateTmp=true`, `ProtectSystem=strict`, and narrowly scoped `ReadWritePaths=`. 11. Explicitly state that generated commands must not be executed for an untrusted repository without manual security review. ]]>
