Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env_temp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
APP_IMAGE=python-insecure-app:debian
APP_IMAGE=python-insecure-app:wolfi-noshell
COMPOSE_FILE=docker-compose.yaml
DEBUG=True
LETSENCRYPT_EMAIL=info@example.com
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
FROM python:3.13-slim-trixie@sha256:b04b5d7233d2ad9c379e22ea8927cd1378cd15c60d4ef876c065b25ea8fb3bf3 AS debian

LABEL project="Python Insecure App" service="FastAPI" stage="debian"
# RUN python3 -m pip install --upgrade pip~=26.1
RUN python3 -m pip install --upgrade pip~=26.1
ENV NONROOT=nonroot \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
Expand Down
4 changes: 2 additions & 2 deletions Dockerfile.alpine
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
FROM python:3.13-alpine@sha256:420cd0bf0f3998275875e02ecd5808168cf0843cbb4d3c536432f729247b2acc AS alpine

LABEL project="Python Insecure App" service="FastAPI" stage="alpine"
# RUN python3 -m pip install --upgrade pip~=26.1 \
# && apk upgrade --no-cache xz-libs
RUN python3 -m pip install --upgrade pip~=26.1 \
&& apk upgrade --no-cache xz-libs
ENV NONROOT=nonroot \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
Expand Down
4 changes: 2 additions & 2 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@

PUBLIC_IP_SERVICE_URL = os.getenv("PUBLIC_IP_SERVICE_URL")

SUPER_SECRET_NAME = "John Ripper" # FIXME: os.getenv("SUPER_SECRET_NAME")
SUPER_SECRET_NAME = os.getenv("SUPER_SECRET_NAME")

SUPER_SECRET_TOKEN = "5u93R53Cr3tT0k3n" # FIXME: os.getenv("SUPER_SECRET_TOKEN")
SUPER_SECRET_TOKEN = os.getenv("SUPER_SECRET_TOKEN")
8 changes: 3 additions & 5 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,12 @@ async def try_hack_me(name: str = config.SUPER_SECRET_NAME):
"""
try:
# Get the public IP address from an external service
public_ip_response = requests.get(config.PUBLIC_IP_SERVICE_URL)
public_ip_response = requests.get(config.PUBLIC_IP_SERVICE_URL, timeout=5)
public_ip_response.raise_for_status()
except (requests.HTTPError, requests.exceptions.InvalidSchema):
public_ip = "Unknown"
else:
public_ip = public_ip_response.text
name = name or config.SUPER_SECRET_NAME
content = f"<h1>Hello, {name}!</h1><h2>Public IP: <code>{public_ip}</code></h2>"
# https://fastapi.tiangolo.com/advanced/custom-response/#return-a-response
# FIXME: return HTMLResponse(content)
return Template(content).render()
content = "<h1>Hello, {{name}}!</h1><h2>Public IP: <code>{{public_ip}}</code></h2>"
return Template(content).render(name=name, public_ip=public_ip)
2 changes: 1 addition & 1 deletion caddy/Caddyfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
(waf_rules) {
coraza_waf {
directives `
SecRuleEngine Off
SecRuleEngine On
SecRequestBodyAccess On
SecRequestBodyLimitAction Reject
SecDebugLogLevel 9
Expand Down
4 changes: 2 additions & 2 deletions requirements/common.in
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-r base.in
fastapi[standard]~=0.115.0
jinja2~=3.0.0
fastapi[standard]~=0.136.0
jinja2~=3.1.0
requests~=2.33.0
9 changes: 4 additions & 5 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ def test_root(requests_mock):
response.content.decode()
== "<h1>Hello, Bob!</h1><h2>Public IP: <code>123.45.67.89</code></h2>"
)
# TODO: Test the root endpoint with SSTI simulation
# response = client.get("/?name={{7*6}}")
# assert response.status_code == 200
# assert "42" not in response.content.decode()
# assert "{{7*6}}" in response.content.decode()
response = client.get("/?name={{7*6}}")
assert response.status_code == 200
assert "42" not in response.content.decode()
assert "{{7*6}}" in response.content.decode()