Skip to content

Admin portal — S10-S12 security surface

AdminPortal.jsx is a React page integrated into the e-commerce frontend and publicly accessible via /admin. It is distinct from the chaos-admin instructor panel: its role is not to drive the platform but to serve as an exploitation surface for the chained security scenario S10 → S11 → S12 (Master level of Security Chaos). This is where pentesting students must arrive to demonstrate their exploitation.

Sources

frontend/src/pages/AdminPortal.jsx, backend/src/main/java/com/perfshop/controller/AdminPortalController.java, API endpoints /api/admin/portal/*

Deliberately vulnerable pedagogical interface

This page is deliberately poorly protected when Security Chaos is at level 4 (Master). It exposes flaws that students must identify, exploit and document. It is not a real admin interface.

Pedagogical context

Levels 1 to 3 of Security Chaos activate scattered flaws on the shop APIs (SQLi on search, IDOR on orders, XSS, timing attack, etc.). The Master level additionally unlocks a chained scenario that tells the story of a full pentest:

  1. S10 — Stats exposed without auth (OWASP A09 — Security Logging and Monitoring Failures) The student discovers GET /api/admin/portal/stats which returns, without authentication, a list of metrics including the administrator contact (admin@perfshop.fr). This simple information leak is already a warning sign.

  2. S11 — SQLi on admin login (OWASP A03 — Injection) The student exploits a classic SQL injection on POST /api/admin/portal/login to bypass authentication. The typical payload is ' OR '1'='1'-- in the email field. The controller naively concatenates the string into a SQL query when Security Chaos Master is active.

  3. S12 — IDOR for privilege escalation (OWASP A01 — Broken Access Control) Once authenticated (even with a standard account), the student can call PUT /api/admin/portal/accounts/{id}/promote without ownership verification. By targeting the superadmin's ID, they become superadmin and can then read the full list of admin accounts with their BCrypt hashes.

The portal exposes all this in a deliberately sober interface (dark background, monospace font, purple colors) that evokes an administration terminal. Students are expected to understand they are in a training ground and not on a real production interface.

See Security Chaos for the details of the exploitations.

Route and access

The page is exposed in App.jsx:

<Route path="/admin" element={<AdminPortal />} />

It is intentionally public — no authentication guard. It is up to the student to discover its existence (for example via a search in the JavaScript bundle, via a guessed URL, or via the exposed stats which mention adminContact).

Visual structure

The page is divided into three vertical sections aligned in a central container (maxWidth: 700px):

Section 1 — Stats

On load (useEffect(() => { fetchStats(); }, [])), the page calls GET /api/admin/portal/stats and displays the result as a key/value table. The endpoint returns an object of the form:

{
  "adminContact": "admin@perfshop.fr",
  "version": "0.1.0-beta",
  "accountsCount": 3,
  "ordersToday": 47,
  ...
}

The adminContact field is the first lead: it is an email that will be used in the next step (bruteforce, injection, or simply a target indication).

A "Reload" button re-runs fetchStats() on demand.

Section 2 — Authentication

An email/password form that sends POST /api/admin/portal/login. On success, the backend returns:

{
  "email": "admin@perfshop.fr",
  "adminToken": "abc123...",
  "message": "Authenticated"
}

The component stores adminToken in its local state and uses it for subsequent calls via the X-Admin-Token header. A green block displays the first 12 characters of the token as a visual confirmation.

This is where the SQLi exploitation (S11) applies. With a payload ' OR '1'='1'-- in the email field, the student can bypass password verification.

Section 3 — Account management

This section is initially grayed out (opacity: 0.35, pointerEvents: 'none') and is only activated after obtaining an adminToken. It exposes:

  • An "Account ID to promote" field (default: 1)
  • A Promote button
  • After successful promotion, a View admin accounts button appears
  • A final table listing all accounts with their columns: ID, Email, SuperAdmin, Password hash, Permissions

BCrypt password hashes are displayed truncated (29 characters + ) — this is enough to prove the disclosure but does not facilitate direct bruteforce. This is a pedagogical compromise: the student understands that credentials are leaked without really being given what is needed to crack the hashes.

API endpoints used

Method URL Auth Controller
GET /api/admin/portal/stats None (S10) AdminPortalController
POST /api/admin/portal/login None (vulnerable S11) AdminPortalController
PUT /api/admin/portal/accounts/{id}/promote X-Admin-Token but no ownership check (S12) AdminPortalController
GET /api/admin/portal/accounts Superadmin X-Admin-Token AdminPortalController

See the Admin portal API reference for the details of requests and responses.

Exploitation workflow

sequenceDiagram
  autonumber
  participant E as Student
  participant P as AdminPortal.jsx
  participant B as Backend

  E->>P: Navigates to /admin
  P->>B: GET /api/admin/portal/stats
  B-->>P: 200 { adminContact, ... }
  Note over E,P: S10 — admin contact exposed without auth

  E->>P: POST login with " ' OR '1'='1'-- "
  P->>B: POST /api/admin/portal/login
  B-->>P: 200 { adminToken, ... }
  Note over E,B: S11 — successful SQLi, auth bypassed

  E->>P: Promote ID=1 (superadmin target)
  P->>B: PUT /api/admin/portal/accounts/1/promote
  B-->>P: 200 { promoted, isSuperAdmin: true }
  Note over E,B: S12 — IDOR, privilege escalation

  E->>P: View admin accounts
  P->>B: GET /api/admin/portal/accounts
  B-->>P: 200 { accounts[] with passwordHash }
  Note over E,P: Mass disclosure

Difference with chaos-admin/gestion.html

The instructor panel gestion.html (see Chaos admin) is a real admin account management interface: it is protected by HTTP sessions, requires the superadmin role, and rigorously validates actions. AdminPortal.jsx on the other hand is a simulation of a vulnerable interface that is used only for the S10-S12 pedagogical exercise. The two pages use different backend endpoints (/api/admin/* vs /api/admin/portal/*) and share neither session nor token.

Security Chaos state

When Security Chaos is below Master level, the /api/admin/portal/* endpoints respond 403 Forbidden or 404 Not Found — the page then displays red errors. To use AdminPortal, you must:

  1. Activate a PerfShop license (without a license, POST /login returns 402)
  2. Activate Security Chaos at Master level from the instructor panel
  3. Navigate to /admin from the shop