Writeup: WifineticTwo
Title: WifineticTwo
OS: Linux
Difficulty: Medium
Review: 3.6/5
HacktheBox Description:
WifineticTwo is a medium-difficulty Linux machine that features OpenPLC running on port 8080, vulnerable to Remote Code Execution through the manual exploitation of CVE-2021-31630. After obtaining an initial foothold on the machine, a WPS attack is performed to acquire the Wi-Fi password for an Access Point (AP). This access allows the attacker to target the router running OpenWRT and gain a root shell via its web interface.
External Enumeration:
As per routine, we can go ahead and scan the target IP provided. For my reconnaissance, I used Docker version of RustScan.
rustscan -a $IP -n --ulimit 70000 -t 5000 -- -A -Pn
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 48add5b83a9fbcbef7e8201ef6bfdeae (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC82vTuN1hMqiqUfN+Lwih4g8rSJjaMjDQdhfdT8vEQ67urtQIyPszlNtkCDn6MNcBfibD/7Zz4r8lr1iNe/Afk6LJqTt3OWewzS2a1TpCrEbvoileYAl/Feya5PfbZ8mv77+MWEA+kT0pAw1xW9bpkhYCGkJQm9OYdcsEEg1i+kQ/ng3+GaFrGJjxqYaW1LXyXN1f7j9xG2f27rKEZoRO/9HOH9Y+5ru184QQXjW/ir+lEJ7xTwQA5U1GOW1m/AgpHIfI5j9aDfT/r4QMe+au+2yPotnOGBBJBz3ef+fQzj/Cq7OGRR96ZBfJ3i00B/Waw/RI19qd7+ybNXF/gBzptEYXujySQZSu92Dwi23itxJBolE6hpQ2uYVA8VBlF0KXESt3ZJVWSAsU3oguNCXtY7krjqPe6BZRy+lrbeska1bIGPZrqLEgptpKhz14UaOcH9/vpMYFdSKr24aMXvZBDK1GJg50yihZx8I9I367z0my8E89+TnjGFY2QTzxmbmU=
| 256 b7896c0b20ed49b2c1867c2992741c1f (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBH2y17GUe6keBxOcBGNkWsliFwTRwUtQB3NXEhTAFLziGDfCgBV7B9Hp6GQMPGQXqMk7nnveA8vUz0D7ug5n04A=
| 256 18cd9d08a621a8b8b6f79f8d405154fb (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKfXa+OM5/utlol5mJajysEsV4zb/L0BJ1lKxMPadPvR
8080/tcp open http-proxy syn-ack Werkzeug/1.0.1 Python/2.7.18
|_http-server-header: Werkzeug/1.0.1 Python/2.7.18
| http-title: Site doesn't have a title (text/html; charset=utf-8).
|_Requested resource was http://10.10.11.7:8080/login
| http-methods:
|_ Supported Methods: HEAD OPTIONS GET
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 404 NOT FOUND
| content-type: text/html; charset=utf-8
| content-length: 232
| vary: Cookie
| set-cookie: session=eyJfcGVybWFuZW50Ijp0cnVlfQ.ZqGO2g.L_Xd2aoi5MJPt2OG1nOjgieE4zU; Expires=Wed, 24-Jul-2024 23:36:38 GMT; HttpOnly; Path=/
| server: Werkzeug/1.0.1 Python/2.7.18
| date: Wed, 24 Jul 2024 23:31:38 GMT
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
| <title>404 Not Found</title>
| <h1>Not Found</h1>
| <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
| GetRequest:
| HTTP/1.0 302 FOUND
| content-type: text/html; charset=utf-8
| content-length: 219
| location: http://0.0.0.0:8080/login
| vary: Cookie
| set-cookie: session=eyJfZnJlc2giOmZhbHNlLCJfcGVybWFuZW50Ijp0cnVlfQ.ZqGO2Q.pYMQqrvibM92UilLdrVagLlfyis; Expires=Wed, 24-Jul-2024 23:36:37 GMT; HttpOnly; Path=/
| server: Werkzeug/1.0.1 Python/2.7.18
| date: Wed, 24 Jul 2024 23:31:37 GMT
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
| <title>Redirecting...</title>
| <h1>Redirecting...</h1>
| <p>You should be redirected automatically to target URL: <a href="/login">/login</a>. If not click the link.
| HTTPOptions:
| HTTP/1.0 200 OK
| content-type: text/html; charset=utf-8
| allow: HEAD, OPTIONS, GET
| vary: Cookie
| set-cookie: session=eyJfcGVybWFuZW50Ijp0cnVlfQ.ZqGO2Q._Lc8R1sXhKANq-BG4CpOoG46Vkc; Expires=Wed, 24-Jul-2024 23:36:37 GMT; HttpOnly; Path=/
| content-length: 0
| server: Werkzeug/1.0.1 Python/2.7.18
| date: Wed, 24 Jul 2024 23:31:37 GMT
| RTSPRequest:
| HTTP/1.1 400 Bad request
| content-length: 90
| cache-control: no-cache
| content-type: text/html
| connection: close
| <html><body><h1>400 Bad request</h1>
| Your browser sent an invalid request.
|_ </body></html>
From the output, we see two open ports: SSH and HTTP. Based on this output, I determined that the initial vector will be HTTP, but I also noted SSH as a potential persistence mechanism.
Proceeding with the HTTP vector, we can navigate to port 8080 to determine the technology in use.
Seeing this login page, one of the first things we should try is default or weak login credentials. In this case, using openplc:openplc
will grant us access.
At this point, if we are not familiar with a specific piece of software, using Google to check for known exploits can help us find a path forward. Fortunately, searching for OpenPLC exploits led us to a promising CVE on GitHub.
Initial Access
Using this proof of concept (POC), we can obtain a simple shell with Netcat.
Now that we have a simple shell, we need to obtain a TTY shell to ensure we don’t accidentally lose access. We can accomplish this with the following commands:
python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm
#####Press Ctrl + Z######
stty raw -echo; fg
stty rows 38 columns 116
Internal Enumeration:
During internal enumeration, I encountered numerous rabbit holes. However, noting down the name of the box will help pinpoint the key abnormality to focus on, which is the presence of WLAN.
By noting this down, we can then scan the connection to reveal that WPS is present.
Now that we’ve identified this, we need to consider our next steps and the potential impact of exploiting it. Theoretically, if there is another wireless network, we might be able to compromise a virtual router, which is likely the direction they are aiming for.
With a clear path in mind, we can now research how to exploit WPS. HackTricks can provide specific guidance, particularly on the Pixie Dust attack with a one-shot method.
Pixie attack:
First, we need to download the tool and get it onto the target.
With the tool successfully installed on the host, we can now run it using Python.
We can now see the WPA password and the AP SSID, which we can leverage to access the wireless network.
After some Googling and trial and error, I found the simplest method, which is as follows:
wpa_passphrase plcrouter 'NoWWEDoKnowWhaTisReal123!' > /tmp/config
#Add the ssid and passowrd to config file
wpa_supplicant -B -c /tmp/config -i wlan0
#Enable wlan0
ifconfig wlan0 192.168.1.101 netmask 255.255.255.0
#Set an IP as we do not have dhcp
Privilege escalation:
Now that we are on the wireless network, obtaining root access was straightforward; we just needed to SSH into the root account on the virtual router.