[SECCON Beginners CTF 2024] WEB Writeup

It wasn't a very good result, but I participated in the SECCON Beginners CTF 2024, so I'll leave a Writeup as a memo.

table of contents

ssrforfi

Check source

The folder structure after unzipping tar.gz is as follows:

$ find ./ ./ ./docker-compose.yml ./.env ./app ./app/app.py ./app/requirements.txt ./app/Dockerfile ./app/uwsgi.ini ./nginx ./nginx/Dockerfile ./nginx/nginx.conf

The contents of each file are as follows:

services: uwsgi: build: ./app env_file: - .env expose: - "7777" restart: always nginx: build: ./nginx links: - uwsgi ports: - "4989:80" environment: TZ: "Asia/Tokyo" restart: always
COPY nginx.conf /etc/nginx/nginx.conf CMD ["nginx", "-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"] 
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; keepalive_timeout 65; upstream uwsgi { server uwsgi:7777; } server { listen 80; merge_slashes off; location / { include uwsgi_params; uwsgi_pass uwsgi; } } }
FROM ubuntu:22.04 ENV DEBIAN_FRONTEND noninteractive RUN apt-get -y update --fix-missing && apt-get -y upgrade RUN apt-get -y install python3 python3-pip curl RUN mkdir /var/www WORKDIR /var/www COPY ./ ./ RUN pip3 install -r requirements.txt ENV LANG C.UTF-8 RUN chmod 755 -R /var/www RUN adduser -u 1000 ssrforlfi USER ssrforlfi CMD ["uwsgi", "--ini", "/var/www/uwsgi.ini"]  
Flask == 3.0.0 uWSGI == 2.0.23
[uwsgi] wsgi-file = app.py callable = app master = true processes = 4 threads = 4 socket = :7777 chmod-socket = 666 vacuum = true die-on-term = true py-autoreload = 1 
import os import re import subprocess from flask import Flask, request app = Flask(__name__) @app.route("/") def ssrforlfi(): url = request.args.get("url") if not url: return "Welcome to Website Viewer.<br> <code>?url=http://example.com/</code> " # Allow only az, ", (, ), ., /, :, ;, <, >, @, | if not re.match('^[az"()./:;<>@|]*$', url): return "Invalid URL ;(" # SSRF & LFI protection if url.startswith("http://") or url.startswith("https://"): if "localhost" in url: return "Detected SSRF ;(" elif url.startswith("file://"): path = url[7:] if os.path.exists(path) or ".." in path: return "Detected LFI ;(" else: # Block other schemes return "Invalid Scheme ;(" try: # RCE ? proc = subprocess.run( f"curl '{url}'", capture_output=True, shell=True, text=True, timeout=1, ) except subprocess.TimeoutExpired: return "Timeout ;(" if proc.returncode != 0: return "Error ;(" return proc.stdout if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=4989)

answer

What is the app doing is an app that makes a request to the URL specified by the URL parameter "?url=xxx" and returns the content as a response.

The content is very simple, but I had to break through the protections of SSRF and LFI and get the flag.

The first thing to note is the code below.
http and https are validating localhost. However, file does not validate localhost.

# SSRF & LFI protection if url.startswith("http://") or url.startswith("https://"): if "localhost" in url: return "Detected SSRF ;(" elif url.startswith("file://"): path = url[7:] if os.path.exists(path) or ".." in path: return "Detected LFI ;(" else: # Block other schemes return "Invalid Scheme ;("

The file:// scheme can access local files, so it may be possible to read environment variables and so on.
In other words, it seems that you can get the flag if possible ?url=file://localhost/[file where you can check environment variables]

This means that
the environment variables for the current process /proc/self/environ Finally, I'll try it with ?url=file://localhost/proc/self/environ

Now you get the flag.

I thought it was something to do command injection, but I was unable to solve the problem within the time limit.

Wooorker

RequestBin

Share if you like!

Who wrote this article

This is a blog I started to study information security. As a new employee, I would be happy if you could look with a broad heart.
There is also Teech Lab, which is an opportunity to study programming fun, so if you are interested in software development, be sure to take a look!

table of contents