T06 · System Persistence
Error
- Location
- SKILL.md:68
- Finding
- Persistent Privileged Network Bridge Exposes Host-Local Services to Containers<![CDATA[ ## Vulnerability Details **File Location**: `SKILL.md`, lines 68–88 **Vulnerability Type**: Persistent systemd service with host-level network access **Risk Level**: High ### Vulnerable Code ```bash sudo tee /etc/systemd/system/socat-<SOURCE_NETWORK>-<TARGET_SERVICE>-<PORT>.service > /dev/null << 'EOF' [Unit] Description=Socat bridge: <SOURCE_NETWORK> -> <TARGET_SERVICE>:<PORT> After=network.target docker.service [Service] Type=simple ExecStart=/usr/bin/socat TCP-LISTEN:<PORT>,bind=<GATEWAY_IP>,fork,reuseaddr TCP:127.0.0.1:<PORT> Restart=always RestartSec=5 [Install] WantedBy=multi-user.target EOF # Review the file before enabling: cat /etc/systemd/system/socat-<SOURCE_NETWORK>-<TARGET_SERVICE>-<PORT>.service sudo systemctl daemon-reload sudo systemctl enable --now socat-<SOURCE_NETWORK>-<TARGET_SERVICE>-<PORT> ``` ### Technical Analysis The instructions use root privileges to write a systemd unit under `/etc/systemd/system`, configure it with `Restart=always`, associate it with `multi-user.target`, and enable it immediately. Consequently, the network relay starts automatically after reboot and survives the individual Skill run. The relay forwards connections received on a Docker bridge gateway address to a service bound to host loopback. This deliberately crosses the isolation boundary that normally prevents containers from accessing services restricted to `127.0.0.1`. Although this behavior is disclosed and supports the declared bridge functionality, persistent startup registration is a high-impact host modification and is not necessary for one-time or temporary connectivity. Binding to a bridge IP reduces exposure compared with binding to `0.0.0.0`, but it does not establish per-container authorization. Any container or process able to reach the selected bridge and pass applicable firewall rules may access the forwarded service. Incorrect substitution of the gateway, network, or port placeholders may broaden the exposure. ### Attack Path ...[truncated 1885 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. **Default to nonpersistent operation.** Provide a foreground or manually started `socat` command for temporary use. Make persistent systemd installation an explicit, separately approved option. 2. **Require service-layer authentication.** Do not treat Docker bridge isolation or UFW rules as the sole access-control mechanism. Configure authentication and, where appropriate, TLS on the target service. 3. **Apply strict input validation.** Validate the gateway as an expected private Docker bridge address, require numeric ports in the valid range, and restrict service and network names to safe systemd-compatible characters before writing a unit file. 4. **Restrict network access precisely.** Limit firewall access by bridge interface and expected source subnet. Verify the interface belongs to the intended Docker network before applying the rule. 5. **Harden the systemd unit.** Where compatible with `socat`, add controls such as: ```ini NoNewPrivileges=yes PrivateTmp=yes ProtectSystem=strict ProtectHome=yes ProtectKernelTunables=yes ProtectKernelModules=yes ProtectControlGroups=yes RestrictSUIDSGID=yes RestrictAddressFamilies=AF_INET AF_INET6 CapabilityBoundingSet= AmbientCapabilities= ``` 6. **Use explicit startup dependencies.** Replace or supplement `After=docker.service` with appropriate network-online and Docker requirements so that failures do not cause an uncontrolled restart loop. 7. **Document complete teardown procedures.** Include commands to stop and disable the service, delete the unit, reload systemd, and remove the exact firewall rule: ```bash sudo systemctl disable --now socat-<SOURCE_NETWORK>-<TARGET_SERVICE>-<PORT> sudo rm /etc/systemd/system/socat-<SOURCE_NETWORK>-<TARGET_SERVICE>-<PORT>.service sudo systemctl daemon-reload sudo systemctl reset-failed sudo ufw delete allow in on br-<BRIDGE_ID> to any port <PORT> proto tcp ``` 8. **Continuously verify exposure.** Test from an intended container, an unrela ...[truncated 413 chars]
