SecureExam UTM
DIGITEX 2026 SilverSolo full-stack · FYP under Prof. Madya Ts. Dr. Siti Hajar Othman
A production examination platform where every request is treated as untrusted: eight defense-in-depth layers spanning TLS 1.3, an Nginx/UFW/fail2ban edge, per-request IP binding, JWT stage-machine MFA, and least-privilege RBAC — 26 mapped controls over 35+ endpoints, built solo and operated on a hardened DigitalOcean Singapore host.
- 11,700+
- LOC
- 26
- Controls
- 35+
- Endpoints
- 4
- RBAC roles
// the threat model
What SecureExam defends against
An online exam platform is a high-value target with two distinct adversaries: students motivated to cheat, and attackers motivated by the credentials and exam data behind the login. SecureExam treats every request as untrusted and defends in depth — no single control is load-bearing.
Exam integrity
Candidates attempting to cheat — leaving the exam window, copy/paste, dev tools, or sharing a live session.
Account takeover
Credential stuffing and password reuse against the login, and hijacking of stale or stolen sessions.
Data theft
Exfiltration of exam content, answers, or personal data through the app, the database, or the transport.
Tampering
Privilege escalation across roles, broken access control (IDOR), and injection against the API and database.
// zero-trust architecture
Trace a request through eight defense-in-depth layers
Select a layer to see the control it enforces and the threats it stops. Each layer is linkable directly.
layer 01 · client
Browser lockdown
Fullscreen lockdown, copy/paste + devtools restrictions, heartbeat tokens rotating through the session.
threats stopped
- Exam cheating
- Stale-session hijack
Zero-trust layers, in request order
- Layer 01, Browser lockdown (client): Fullscreen lockdown, copy/paste + devtools restrictions, heartbeat tokens rotating through the session. Threats stopped: Exam cheating, Stale-session hijack.
- Layer 02, TLS 1.3 (transport): End-to-end HTTPS (Let’s Encrypt) + HSTS. Threats stopped: Eavesdropping, Man-in-the-middle.
- Layer 03, Nginx reverse proxy (edge): App fronted behind UFW firewall, fail2ban, rate limiting; Node never publicly exposed. Threats stopped: Brute force, Port scanning, Direct app exposure.
- Layer 04, JWT + TOTP MFA (authn): Short-lived JWTs + TOTP multi-factor auth. Threats stopped: Credential stuffing, Password reuse.
- Layer 05, RBAC · 4 roles (authz): Least privilege across 4 roles and 35+ endpoints. Threats stopped: Privilege escalation, Broken access control (IDOR).
- Layer 06, Node + Express (app): Input validation + secure headers across 25+ mapped controls. Threats stopped: XSS, CSRF, Injection.
- Layer 07, MySQL 8 (data): Least-privilege DB user, parameterized queries, hardened auth. Threats stopped: SQL injection, Data exfiltration.
- Layer 08, Risk scorer (detection): Flask microservice (Control #26), Isolation Forest anomaly model, bound to localhost (127.0.0.1:8001). Threats stopped: Anomalous exam behaviour.
// deployment & hardening
I didn’t just build SecureExam — I shipped and operated it. The platform runs on a hardened DigitalOcean Singapore droplet:
- Nginx reverse proxy fronts the app — Node is never publicly exposed.
- UFW firewall + fail2ban + rate limiting at the edge.
- Let’s Encrypt TLS 1.3 with HSTS.
- PM2 runs two processes: secureexam-backend (Node) and risk-scorer (Flask) bound to 127.0.0.1:8001.
- Least-privilege MySQL user; parameterized queries throughout.
- SSH hardening (key-only auth, no root login).
// what I’d do next
- Move secrets out of env files into a managed vault.
- Add automated dependency and container scanning to CI.
- Train the risk scorer on labelled data and track precision/recall, not just anomaly scores.
- Add an automated IDOR/RBAC test suite over all 35+ endpoints.
Want to walk through any layer in an interview?