1. Executive Summary
JS Web Design Services conducted a web application penetration test against www.example-client.org on 2026-07-14, under written authorisation from the site owner.
The target is a WordPress installation running on Apache behind a full-page cache, with a commercial security suite providing baseline hardening — including a hidden login page and REST API user-enumeration blocking. Those controls work as intended, and are recorded in section 8.
They are, however, bypassed entirely by the two critical findings below. 18 findings were identified in total:
- Unauthenticated arbitrary file upload leading to remote code execution (F1). An outdated plugin's REST upload handler validates files by request-supplied MIME type rather than content, allowing a
.phpfile to be written into a web-readable directory and executed. - Unauthenticated SQL injection on a booking endpoint (F2). Confirmed via a time-based oracle; provides read access to the full database including password hashes.
- An abandoned plugin (no update in over three years) and an out-of-date core remain in active use, with automatic updates disabled (F3).
- A publicly readable JSON file discloses the complete plugin inventory and database schema, directly accelerating exploitation of F2 (F4).
- The administrator username is enumerable through two unblocked vectors, and no two-factor authentication is enforced (F5, F16).
- A stored cross-site scripting flaw executes in the administrator's moderation screen, and no Content-Security-Policy is present to contain it (F7, F11).
Remote code execution was confirmed during testing using a benign, non-persistent proof-of-concept that was removed immediately afterwards. No data was extracted, no records were modified, and no denial-of-service was performed. No evidence of prior compromise was found — no web shells, injected code or unexpected administrator accounts were present — but the site should be treated as at immediate risk until F1 and F2 are remediated.
Risk rating summary
| Severity | Count | CVSS range |
|---|---|---|
| CRITICAL | 2 | 9.1 – 9.8 |
| HIGH | 4 | 7.5 – 8.1 |
| MEDIUM | 6 | 5.3 – 6.1 |
| LOW | 3 | 3.1 – 3.7 |
| INFORMATIONAL | 3 | — |
| TOTAL | 18 | — |
2. Scope & Methodology
| Item | Value |
|---|---|
| In-scope URL | www.example-client.org |
| In-scope IP | [REDACTED] |
| Out of scope | Subdomains not confirmed in scope, internal network, physical security, social engineering, denial-of-service |
Testing followed the OWASP Testing Guide v4.2 and OWASP API Security Top 10 (2023), covering:
- Passive and active reconnaissance
- Technology stack and version fingerprinting
- Authentication and session management analysis
- Input validation testing (XSS, SQLi, file upload, SSRF)
- Security header analysis
- SSL/TLS configuration review
- API surface enumeration and testing
- Plugin CVE cross-referencing
- Attack chain construction
Rules of engagement. Testing was non-destructive. Where a vulnerability could be confirmed without impact — a timing oracle for SQL injection, a benign marker for XSS, a non-persistent file for upload — that method was used and the artefact removed. No data was extracted, no records modified, and no denial-of-service performed.
3. Technology Stack
| Component | Identified value |
|---|---|
| CMS | WordPress 6.9.1 (behind current release) |
| Web server | Apache with a full-page cache plugin |
| SSL certificate | Valid, correctly chained, auto-renewing |
| TLS | TLS 1.3 and 1.2; TLS 1.0/1.1 disabled |
| Security plugin | Commercial security suite (firewall, bans, scanning) |
| Cache / optimisation | Two caching plugins active alongside an optimiser |
| SEO plugin | Major SEO plugin, current version |
| Forms | Contact form plugin with file upload enabled |
| Events | Calendar plugin with public REST API |
| Booking | Third-party booking plugin (vulnerable — see F2) |
| Page builder | Mainstream page builder |
| E-commerce | Standard e-commerce plugin |
| Abandoned component | 1 plugin, no update in 3+ years (see F3) |
| Custom post types | 8 registered |
4. Risk Summary
| ID | Finding | Severity | CVSS | CWE |
|---|---|---|---|---|
| F1 | Unauthenticated Arbitrary File Upload → Remote Code Execution | CRITICAL | 9.8 | CWE-434 |
| F2 | Unauthenticated SQL Injection in Booking Endpoint | CRITICAL | 9.1 | CWE-89 |
| F3 | Outdated WordPress Core & Abandoned Plugin in Use | HIGH | 8.1 | CWE-1104 |
| F4 | Plugin & Database Schema Disclosure (optimiser JSON file) | HIGH | 7.5 | CWE-200 |
| F5 | WordPress Username Enumeration (administrator account exposed) | HIGH | 7.5 | CWE-200 |
| F6 | Personal Data Disclosure via Public Calendar API | HIGH | 7.5 | CWE-200 |
| F7 | Stored Cross-Site Scripting in Event Submission Field | MEDIUM | 6.1 | CWE-79 |
| F8 | Security Plugin REST API Schema Fully Exposed | MEDIUM | 5.3 | CWE-200 |
| F9 | WordPress REST API Root Endpoint Accessible (287 routes) | MEDIUM | 5.3 | CWE-200 |
| F10 | XML-RPC Endpoint Active | MEDIUM | 5.3 | CWE-307 |
| F11 | Missing Critical HTTP Security Headers | MEDIUM | 5.4 | CWE-693 |
| F12 | Cache Plugin Debug Directory Publicly Accessible | MEDIUM | 5.3 | CWE-538 |
| F13 | Contact Form File Upload Schema Disclosed | LOW | 3.7 | CWE-200 |
| F14 | Server & Plugin Version Disclosure | LOW | 3.7 | CWE-200 |
| F15 | HTTP PUT and DELETE Methods Accepted | LOW | 3.1 | CWE-749 |
| F16 | Application Passwords Enabled Without 2FA | INFORMATIONAL | — | CWE-308 |
| F17 | WP-Cron Publicly Triggerable | INFORMATIONAL | — | CWE-400 |
| F18 | Public Calendar API & Analytics Identifiers Exposed | INFORMATIONAL | — | CWE-200 |
5. Detailed Findings
F1 — Unauthenticated Arbitrary File Upload → Remote Code Execution CRITICAL
Affected component: /wp-json/<vendor>/v1/upload (media handler in an outdated third-party plugin)
An outdated third-party plugin registers a REST upload handler that does not require authentication and validates the uploaded file by MIME type supplied in the request rather than by extension or content. A file with a permitted MIME header but a .php extension is written into the uploads directory and is directly reachable over HTTP, giving unauthenticated remote code execution as the web-server user.
Evidence
POST /wp-json/<vendor>/v1/upload --> 201 Created
Content-Type: multipart/form-data
filename="probe.php" (declared MIME: image/jpeg)
GET /wp-content/uploads/2026/07/probe.php --> 200 OK
(benign proof-of-concept: echoed a fixed token, no shell, no persistence)
File removed immediately after confirmation, with client approval.
Impact
- Full remote code execution as the web-server user — the highest-impact outcome in this engagement.
- Enables webshell installation, database credential theft from
wp-config.php, and lateral movement to other sites on the same account. - Bypasses every application-layer control, including the security plugin's login hardening.
Remediation
- Treat as an emergency. Update or remove the affected plugin before any other remediation.
- Block PHP execution inside uploads:
<Directory /wp-content/uploads> php_flag engine off </Directory> - Audit the uploads directory for any pre-existing
.phpfiles and treat the site as potentially compromised until confirmed clean. - Rotate database credentials and WordPress salts after remediation.
F2 — Unauthenticated SQL Injection in Booking Endpoint CRITICAL
Affected component: /wp-json/<vendor>/v1/availability?resource_id=
The resource_id parameter is concatenated directly into a SQL WHERE clause without parameterisation or sanitisation. A time-based blind payload produced a reproducible, measurable delay, confirming injection. No data was extracted and no rows were modified — confirmation was limited to a timing oracle, per the non-destructive rules of engagement.
Evidence
GET /wp-json/<vendor>/v1/availability?resource_id=1 --> 200 (0.11s)
GET /wp-json/<vendor>/v1/availability?resource_id=1%20AND%20SLEEP(5) --> 200 (5.13s)
GET /wp-json/<vendor>/v1/availability?resource_id=1%20AND%20SLEEP(2) --> 200 (2.09s)
Delay tracks the injected value -> injection confirmed.
No UNION/data-extraction payloads were executed.
Impact
- Unauthenticated read access to the full database, including
wp_userspassword hashes and session tokens. - Password hashes enable offline cracking and subsequent administrator takeover.
- Combined with F1, provides a second independent path to full site compromise.
Remediation
- Update the affected plugin immediately; if no patch exists, disable it until one is released.
- Ensure all queries use
$wpdb->prepare()with placeholders — never string concatenation. - Deploy a WAF rule to block SQL metacharacters on this endpoint as an interim control.
- Force a password reset for all administrator and editor accounts after patching.
F3 — Outdated WordPress Core & Abandoned Plugin in Use HIGH
Affected component: WordPress core; one plugin with no update in 3+ years
The installation is several minor versions behind the current release and one active plugin has received no update in over three years and is flagged as abandoned in the plugin directory. Abandoned components receive no security patches, so any vulnerability disclosed against them stays exploitable indefinitely.
Evidence
WordPress core : 6.9.1 (behind current release)
Abandoned plugin : last updated 2023-02 — flagged 'no longer maintained'
Active installs : plugin still enabled and reachable on the front end
Auto-updates : disabled for both core and plugins
Impact
- Known, publicly documented vulnerabilities remain unpatched and are trivially discoverable from version disclosure (see F14).
- An abandoned plugin will never be fixed — the only remediation is replacement or removal.
- Disabled auto-updates mean the window of exposure grows with every new disclosure.
Remediation
- Update WordPress core to the current release after taking a full backup.
- Replace the abandoned plugin with a maintained equivalent, or remove it if the feature is unused.
- Enable automatic security updates for core, and review plugin update policy monthly.
F4 — Plugin & Database Schema Disclosure (optimiser JSON file) HIGH
Affected component: /wp-content/uploads/<optimiser>/plugin-tables-list.json
A publicly accessible JSON file written by an optimisation plugin is exposed in the uploads directory. The file maps 18,400+ database table names to 5,900+ plugin slugs, confirming the optimiser is installed, enabling complete plugin fingerprinting, revealing e-commerce and security-plugin table structures, and handing an attacker a ready-made target map for the SQL injection in F2. A robots.txt Disallow directive does not prevent direct HTTP access.
Evidence
GET /wp-content/uploads/<optimiser>/plugin-tables-list.json
HTTP/1.1 200 OK | Content-Length: 812446
Notable tables disclosed:
<ecommerce>_api_keys, <ecommerce>_payment_tokens, <ecommerce>_sessions
<security>_bans, <security>_lockouts, <security>_logs
<builder>_events, <cache>_optimizer, <cache>_img_optm
All SEO-plugin internal tables + custom plugin tables
Impact
- Full inventory of installed plugins (including premium plugins) and the complete database table structure.
- Directly accelerates exploitation of F2 — the attacker skips schema enumeration entirely.
- Security-plugin internal tables disclosed, potentially aiding circumvention of those controls.
Remediation
- Delete the file from the uploads directory immediately.
- Add server-level access control:
<DirectoryMatch "wp-content/uploads/<optimiser>"> Require all denied </DirectoryMatch> - Review optimiser settings to prevent future writes to a web-readable directory.
- Note:
robots.txtDisallow does not restrict access — server-side controls are required.
F5 — WordPress Username Enumeration (administrator account exposed) HIGH
Affected component: /?author=<ID> redirects, /author-sitemap.xml
The security plugin correctly blocks REST API user enumeration at /wp-json/wp/v2/users, but two alternative vectors remain unprotected. (1) Author ID redirect — requesting /?author=N redirects to /author/<username>/, exposing the username in the URL. (2) The SEO-plugin-generated author sitemap lists all author archive URLs directly, including the administrator account.
Evidence
GET /?author=2 --> 301 --> /author/[redacted_user_a]/
GET /?author=4 --> 301 --> /author/[redacted_admin]/ [ADMINISTRATOR]
GET /?author=5 --> 301 --> /author/[redacted_user_b]/
GET /?author=7 --> 301 --> /author/[redacted_user_c]/
5 valid usernames enumerated in total.
Also confirmed via /author-sitemap.xml (SEO plugin generated).
Impact
- 5 valid WordPress usernames discovered, including the administrator account.
- Enables brute-force, Application Password authorisation flows, or credential stuffing.
- Login protection is significantly weakened once the administrator username is known.
- Combines with the password hashes obtainable via F2 for rapid offline cracking.
Remediation
- Disable author archive redirects in
functions.phpby redirectingis_author()/?author=requests tohome_url(). - Disable author archives in the SEO plugin: Search Appearance → Author Archives → disabled.
- Create a new admin user with a non-guessable username and delete the exposed administrator account.
F6 — Personal Data Disclosure via Public Calendar API HIGH
Affected component: /wp-json/<calendar>/v1/organizers
A calendar plugin's REST organizers endpoint is accessible without authentication and returns personal contact information belonging to the site's developer, together with a link to the staging/CMS environment. A further 180+ events and 20+ venues are fully readable unauthenticated.
Evidence
GET /wp-json/<calendar>/v1/organizers --> 200 OK
{ "organizer": "Test organizer entry",
"email": "[REDACTED]",
"phone": "[REDACTED]",
"website": "https://staging.[REDACTED].example/cms",
"author": 4 }
Impact
- Personal data exposed without authentication — a probable breach of data-protection obligations (GDPR / PDPA and equivalents).
- Staging environment disclosed — non-production hosts typically carry weaker controls, providing a lateral path.
- Social engineering risk — contact details enable targeted phishing or pretexting of the developer.
Remediation
- Remove or anonymise the test organizer entry immediately.
- Redact PII fields from the endpoint response with a server-side filter that unsets email and phone.
- Assess the disclosed staging environment for additional exposures and put it behind authentication.
F7 — Stored Cross-Site Scripting in Event Submission Field MEDIUM
Affected component: Front-end event submission form → moderation queue
A front-end submission field stores input without output encoding. Script supplied by an unauthenticated submitter is rendered in the administrator moderation screen, so the payload executes in an authenticated admin session — an effective privilege escalation path.
Evidence
POST /events/submit/ field: description
payload: <img src=x onerror="/* benign marker only */">
Rendered unencoded at /wp-admin/edit.php?post_type=<calendar>
(Confirmed with a harmless DOM marker; no cookie theft or admin action performed.)
Impact
- Script executes in an administrator's authenticated session when they review submissions.
- Can be leveraged to create a new administrator account or exfiltrate session tokens.
- Requires no credentials from the attacker — only that an admin views the queue.
Remediation
- Escape on output with
esc_html()/wp_kses_post()in the moderation view. - Sanitise on input with
sanitize_textarea_field()for all front-end submissions. - Add a Content-Security-Policy (see F11) to reduce the impact of any residual XSS.
F8 — Security Plugin REST API Schema Fully Exposed MEDIUM
Affected component: /wp-json/<security-plugin>/v1/
The complete security-plugin REST API schema is publicly readable without authentication, revealing every security endpoint including bans, firewall rules, lockout management, logs, file-tree browsing, scanner results and user actions. The schema also discloses all WordPress roles in use. Authentication is still required to call these endpoints, but the schema hands an attacker a precise map of the security infrastructure.
Evidence
GET /wp-json/<security-plugin>/v1/ --> 200 OK
Disclosed endpoints include:
/rpc/ban-users/add-many
/v1/firewall/rules (GET, POST)
/v1/lockouts
/v1/logs
/v1/settings
/v1/user-actions (force-logout, reset-password)
/v1/site-scanner/vulnerabilities
/rpc/file-change/file-tree
Impact
- Provides a complete map of security-plugin endpoints, reducing attacker reconnaissance effort.
- Enables targeted authentication-bypass attempts against known administrative endpoints.
Remediation
- Block REST access to the security-plugin namespace for unauthenticated users at the web-server level.
F9 — WordPress REST API Root Endpoint Accessible (287 routes) MEDIUM
Affected component: /wp-json/
The REST API root returns a large JSON response listing all 287 registered routes with full parameter schemas, accepted HTTP methods and validation rules, including routes for every installed plugin. The response also discloses the site timezone, the Application Passwords authorisation endpoint and the complete authentication configuration.
Evidence
GET /wp-json/ --> 200 OK (392,118 bytes)
287 routes across 11 namespaces, including the vulnerable
upload handler (F1) and booking endpoint (F2).
Auth: { application-passwords: { authorization: /wp-admin/authorize-application.php } }
Impact
- Complete API surface mapping enables targeted exploitation — this is how F1 and F2 were located.
- Confirms installed plugin names and versions implicitly through namespace versions.
- Discloses the Application Passwords authorisation endpoint, useful in credential attacks.
Remediation
- Restrict REST API discovery for unauthenticated users via
rest_authentication_errorsreturning HTTP 401. - Whitelist only the public namespaces actually required by the front end.
F10 — XML-RPC Endpoint Active MEDIUM
Affected component: /xmlrpc.php
The XML-RPC endpoint is active and accessible. This legacy interface enables remote procedure calls including authentication, post creation and file uploads. It is commonly abused for brute-force amplification — a single request can test hundreds of credential pairs — and for SSRF.
Evidence
POST /xmlrpc.php --> 200 OK
<methodResponse> … system.multicall available …
Combined with the administrator username from F5, this is a
practical credential-attack surface.
Impact
- Enables XML-RPC brute-force amplification — one request can test hundreds of credential pairs.
- May be used for SSRF attacks against internal network resources.
- Provides an attack surface that bypasses standard login hardening.
Remediation
- Disable XML-RPC if not required:
add_filter('xmlrpc_enabled', '__return_false'); - Or block at web-server level:
<Files xmlrpc.php> Require all denied </Files>
F11 — Missing Critical HTTP Security Headers MEDIUM
Affected component: All HTTP responses
Multiple critical HTTP security headers are absent from all server responses. These headers form a fundamental browser-side security layer; their absence exposes users to clickjacking, cross-site scripting, MIME sniffing and protocol-downgrade attacks — and materially increases the impact of the stored XSS in F7.
Evidence
HTTP Response Headers (observed):
Strict-Transport-Security (HSTS) --> MISSING
Content-Security-Policy (CSP) --> MISSING
X-Frame-Options --> MISSING
X-Content-Type-Options --> MISSING
Referrer-Policy --> MISSING
Permissions-Policy --> MISSING
Impact
- Absence of HSTS allows SSL-stripping attacks on non-HTTPS connections.
- Absence of X-Frame-Options / CSP
frame-ancestorsenables clickjacking. - Absence of X-Content-Type-Options allows MIME sniffing, compounding the file-upload issue in F1.
- Absence of CSP significantly increases the impact of the stored XSS in F7.
Remediation
- Add
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload". - Add
X-Frame-Options "SAMEORIGIN",X-Content-Type-Options "nosniff",Referrer-Policy "strict-origin-when-cross-origin". - Implement Content-Security-Policy — start in report-only mode to identify required sources before enforcing.
- Validate with an external header analyser.
F12 — Cache Plugin Debug Directory Publicly Accessible MEDIUM
Affected component: /wp-content/<cache-plugin>/debug/
The cache plugin's debug directory is publicly accessible (HTTP 200). If debug logging is ever enabled, session cookies and authentication tokens are written to log files in this directory, readable by any unauthenticated user. This is the precondition for a known critical account-takeover class of vulnerability. No log files were present during testing, but the directory remains exposed.
Evidence
GET /wp-content/<cache-plugin>/debug/ --> 200 OK
(Directory accessible — no log files present at time of test)
Related advisories for this plugin family:
CVE-2024-44000 CVSS 9.8 Unauthenticated account takeover via debug log
CVE-2024-28000 CVSS 9.8 Privilege escalation via role simulation
CVE-2024-47374 CVSS 7.1 Unauthenticated XSS via admin settings
Impact
- If debug logging is enabled, session cookies become publicly readable, enabling unauthenticated account takeover.
- If the plugin version is below the patched release, one or more CVSS 9.8 issues may be directly applicable.
Remediation
- Block public access immediately:
<DirectoryMatch "wp-content/<cache-plugin>/debug"> Require all denied </DirectoryMatch> - Confirm the installed version and update to the latest release as a priority.
F13 — Contact Form File Upload Schema Disclosed LOW
Affected component: /wp-json/<forms>/v1/contact-forms/{id}/feedback/schema
The contact-form REST API exposes the complete validation schema for all forms without authentication. For the document upload form this discloses accepted file types and size limits, letting an attacker craft targeted upload payloads without trial-and-error enumeration.
Evidence
GET /wp-json/<forms>/v1/contact-forms/5/feedback/schema
{ "your-file": {
"type": "file",
"accept": ".pdf,.doc,.docx",
"maxSize": 2097152
} }
Impact
- Allows crafting of targeted file-upload payloads without enumeration.
- Compounds F1 — the attacker learns exactly what the application expects to receive.
Remediation
- Restrict the contact-form REST schema endpoint for unauthenticated users via a
rest_pre_dispatchfilter.
F14 — Server & Plugin Version Disclosure LOW
Affected component: HTML source, HTTP headers, RSS feed, license.txt
Multiple version-disclosure vectors expose exact software versions across the site, significantly reducing the reconnaissance effort required for targeted CVE exploitation — and directly enabling identification of the outdated components in F3.
Evidence
WordPress core --> RSS <generator> tag, asset ?ver= params, license.txt (HTTP 200)
Cache plugin version --> HTML comment in every page footer
Forms plugin version --> Script tag ?ver=
SEO plugin version --> SEO plugin head API response
Web server --> Server: HTTP header
Impact
- Precise version identification enables targeted CVE research and exploit selection without active scanning.
Remediation
- Strip
?ver=params from assets via thestyle_loader_src/script_loader_srcfilters. - Disable the cache-plugin footer comment in its advanced settings.
- Block
license.txtandreadme.htmlat the web-server level.
F15 — HTTP PUT and DELETE Methods Accepted LOW
Affected component: Site root
The server returns HTTP 200 for PUT and DELETE on the root URL instead of the expected 405 Method Not Allowed. This violates least privilege and may interact unexpectedly with caching layers.
Evidence
PUT / --> 200 OK (expected: 405)
DELETE / --> 200 OK (expected: 405)
TRACE / --> 405 Method Not Allowed (correct)
Impact
- Low direct impact, but violates least privilege and may interact unexpectedly with caching or CDN configurations.
Remediation
- Restrict accepted methods:
<LimitExcept GET POST HEAD OPTIONS> Require all denied </LimitExcept>
F16 — Application Passwords Enabled Without 2FA INFORMATIONAL
Affected component: /wp-admin/authorize-application.php
The Application Passwords feature is enabled and its authorisation endpoint is disclosed via the REST API root response. Application passwords generate long-lived credentials that bypass two-factor authentication, and no 2FA is currently enforced on administrator accounts.
Evidence
Disclosed in /wp-json/ authentication configuration:
"authorization": "/wp-admin/authorize-application.php"
No two-factor requirement observed on the login flow.
Impact
- Long-lived credentials can bypass 2FA if it is later introduced.
- Increases the overall credential attack surface for administrator accounts.
Remediation
- Enforce two-factor authentication for all administrator and editor accounts.
- If Application Passwords are not required, disable the feature.
F17 — WP-Cron Publicly Triggerable INFORMATIONAL
Affected component: /wp-cron.php
The WP-Cron endpoint returns HTTP 200 and can be triggered by any external request, potentially causing unnecessary server load through repeated invocations.
Evidence
GET /wp-cron.php --> 200 OK (0 bytes, 0.6s execution time)
Impact
- Repeated external requests can cause unnecessary server load and resource consumption.
- May be used for timing-based information gathering.
Remediation
- Disable public WP-Cron:
define('DISABLE_WP_CRON', true); - Add a real server cron job running every 15 minutes instead.
F18 — Public Calendar API & Analytics Identifiers Exposed INFORMATIONAL
Affected component: /wp-json/<calendar>/v1/events, HTML <meta> tags
The calendar REST API is fully readable without authentication, and site-verification and analytics identifiers are present in page source. Both are common and largely intentional, but they assist fingerprinting and cross-site tracking correlation.
Evidence
GET /wp-json/<calendar>/v1/events --> 200 OK (180+ events, unauthenticated)
Meta: site-verification token --> [REDACTED]
Analytics measurement ID --> [REDACTED]
Impact
- Low direct risk. Enables structured data extraction and plugin fingerprinting.
- Analytics identifiers can be used for cross-site tracking correlation by third parties.
Remediation
- If public structured event data is intended, this is acceptable.
- Ensure the organizer endpoint does not expose PII (see F6).
- Consider a server-side tag container for enhanced privacy control.
6. Attack Chain Analysis
Findings are rarely exploited in isolation. The chains below show how issues combine — which is why several medium-severity items are prioritised above their individual rating.
Chain 1: Unauthenticated upload → remote code execution → full server compromise
F9 (REST root discloses the vulnerable upload route)
→ F1 (MIME-only validation accepts a .php file)
→ File written to a web-readable uploads path
→ Code execution as the web-server user
→ wp-config.php credentials → database → other sites on the accountChain 2: SQL injection → credential extraction → administrator takeover
F4 (complete table-to-plugin map disclosed)
→ F2 (unauthenticated SQLi on the booking endpoint)
→ Attacker skips schema enumeration, targets wp_users directly
→ Password hashes extracted → offline cracking
→ F5 supplies the administrator username → account takeoverChain 3: Stored XSS → administrator session → privilege escalation
F7 (unauthenticated submission stored without encoding)
→ Payload rendered in the admin moderation screen
→ F11 (no CSP to contain it)
→ Script runs in an authenticated admin session
→ New administrator account created silentlyChain 4: Username enumeration → credential attack
F5 (administrator username via author sitemap)
→ F10 (XML-RPC accepts multicall — hundreds of guesses per request)
→ F16 (Application Passwords available, no 2FA enforced)
→ Targeted brute-force or credential stuffing → full site compromiseChain 5: Personal data disclosure → developer compromise → lateral movement
F6 (developer email, phone and staging CMS URL exposed)
→ Social engineering / phishing of the developer
→ Compromise of the staging environment
→ Access to production source code, config and credentials
7. Vulnerability Cross-Reference
| Reference | Severity | Component | Description | Status |
|---|---|---|---|---|
| — | 9.8 Critical | Third-party media handler | Unauthenticated arbitrary file upload → RCE (F1) | CONFIRMED BY TESTING |
| — | 9.1 Critical | Booking plugin endpoint | Unauthenticated SQL injection (F2) | CONFIRMED BY TESTING |
| CVE-2024-44000 | 9.8 Critical | Cache plugin (debug log) | Unauthenticated account takeover via debug log | PRECONDITION PRESENT (F12) |
| CVE-2024-28000 | 9.8 Critical | Cache plugin | Privilege escalation via role simulation | UNCONFIRMED — verify version |
| CVE-2024-47374 | 7.1 High | Cache plugin | Unauthenticated XSS via admin settings | UNCONFIRMED — verify version |
| — | — | Abandoned plugin (3+ years) | No patches available for any future disclosure (F3) | REPLACE OR REMOVE |
Priority action: F1 and F2 were confirmed by testing and require no public advisory to be exploitable. Treat both as emergency remediation before addressing anything else in this report.
8. Positive Security Controls
The following measures are already in place and functioning correctly. We record these deliberately — a report that lists only problems gives an unbalanced picture of a site's posture, and these controls meaningfully limit several attack paths.
| Security control | Status |
|---|---|
Login page hidden (/wp-login.php, /wp-admin/) | ✓ Redirected by the security plugin |
REST API user enumeration (/wp-json/wp/v2/users) | ✓ Correctly returns HTTP 401 |
| REST API posts/pages endpoints | ✓ Correctly return HTTP 401 |
| TLS 1.3 with a strong cipher suite | ✓ Confirmed active |
| TLS 1.0 and 1.1 | ✓ Correctly disabled |
| HTTP → HTTPS redirect | ✓ Working correctly |
| Directory listing (uploads, plugins, themes) | ✓ All return 404 |
Sensitive files (.env, .git, wp-config.php, *.bak) | ✓ All return 404 |
| CORS configuration | ✓ No wildcard origin on sensitive endpoints |
| Valid SSL certificate | ✓ Current, correctly chained |
| Security plugin active monitoring | ✓ Firewall, bans, lockouts and scanning active |
| Off-site backups | ✓ Confirmed running daily with 30-day retention |
9. Remediation Roadmap
| # | Timeline | ID | Action | Effort |
|---|---|---|---|---|
| 1 | Emergency | F1 | Patch or remove the vulnerable upload handler; disable PHP execution in uploads; audit for existing web shells | 1–2 hrs |
| 2 | Emergency | F2 | Patch or disable the booking plugin; add interim WAF rule; rotate admin credentials | 1–2 hrs |
| 3 | Immediate | F3 | Update WordPress core; replace the abandoned plugin; enable auto-updates | 1 hr |
| 4 | Immediate | F4 | Delete the optimiser JSON file; block the directory | 5 min |
| 5 | Immediate | F12 | Block the cache debug directory; confirm and update plugin version | 10 min |
| 6 | Immediate | F6 | Remove the test organizer entry containing personal data | 5 min |
| 7 | This week | F7 | Escape output in the moderation view; sanitise submissions | 1 hr |
| 8 | This week | F11 | Implement HSTS, CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy | 30 min |
| 9 | This week | F5 | Disable author archives and the author sitemap; rename the admin account | 20 min |
| 10 | This week | F16 | Enforce two-factor authentication on all privileged accounts | 30 min |
| 11 | Short-term | F10 | Disable XML-RPC if not in use | 5 min |
| 12 | Short-term | F9 | Restrict REST API discovery; whitelist public namespaces | 30 min |
| 13 | Short-term | F8 | Block the security-plugin namespace for unauthenticated access | 10 min |
| 14 | Short-term | F14 | Strip ?ver= from assets; block license.txt; disable footer comment | 15 min |
| 15 | Short-term | F13 | Restrict the contact-form REST schema endpoint | 10 min |
| 16 | Maintenance | F15 | Restrict HTTP methods | 5 min |
| 17 | Maintenance | F17 | Replace WP-Cron with a real server cron job | 10 min |
About this document. This is a specimen report published by JS Web Design Services to demonstrate the structure, depth and evidence standard of our deliverables. It is an illustrative composite — not a transcript of any single client engagement — and all identifying details have been removed or generalised. Live client reports are never published; they are delivered privately through an encrypted, password-protected link.