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:
-
S10 — Stats exposed without auth (OWASP A09 — Security Logging and Monitoring Failures) The student discovers
GET /api/admin/portal/statswhich returns, without authentication, a list of metrics including the administrator contact (admin@perfshop.fr). This simple information leak is already a warning sign. -
S11 — SQLi on admin login (OWASP A03 — Injection) The student exploits a classic SQL injection on
POST /api/admin/portal/loginto 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. -
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}/promotewithout 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:
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:
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:
- Activate a PerfShop license (without a license,
POST /loginreturns 402) - Activate Security Chaos at Master level from the instructor panel
- Navigate to
/adminfrom the shop