Account Takeover and Systemic IDOR in National Agricultural Body Recruitment Platform
Agriculture / Public Sector
Summary
Self-initiated responsible disclosure uncovering critical authentication bypass enabling full account takeover, alongside systemic broken access control exposing applicant PII across multiple endpoints. Findings acknowledged within 72 hours.
Case Study: National Agricultural Body Recruitment Platform
Independent Application Security Assessment
Engagement Type: Responsible Disclosure (Self-Initiated)
Assessment Period: June 2026
Vulnerability Class: Authentication & Access Control
Executive Summary
In June 2026, while applying for a job through an online recruitment platform operated by a major Kenyan agricultural organisation, the researcher identified a security anomaly that prompted a structured responsible disclosure assessment.
The assessment confirmed six vulnerabilities across the platform, including a Critical authentication bypass that allows any registered applicant to take over any other applicant's account with no victim interaction required. A systemic broken access control flaw across the platform's profile management endpoints compounded the risk, enabling enumeration and manipulation of applicant personal data — including national ID numbers, employment histories, academic qualifications, and uploaded CV documents — using an email address as the only required identifier.
All findings were confirmed with working evidence. No data was extracted, no user accounts other than the researcher's own were accessed or harmed, and findings were disclosed privately and directly to the organisation before any publication.
The organisation acknowledged the disclosure within 24 hours and convened a technical review meeting within the week.
Scope and Authorization
Target: Online recruitment platform operated by a national Kenyan agricultural body.
Platform Type: Custom PHP web application running on Apache.
Engagement Type: Self-initiated responsible disclosure.
Scope: All functionality accessible through the recruitment subdomain.
Authentication: The researcher registered two applicant accounts for testing.
Discovery Context: The issues were identified while using the platform as a genuine job applicant.
The platform handles the full recruitment lifecycle: job listings, applicant registration, profile management (qualifications, employment history, referees), CV upload, and job application submission.
Methodology
The assessment followed a structured five-phase approach, operating strictly within the researcher's own registered accounts except where access control failures were demonstrated in a controlled and non-destructive manner.
Assessment Phases
Reconnaissance / Enumeration: Platform fingerprinting, technology stack identification, endpoint discovery, registration and activation flow analysis.
Analysis: Parameter mapping, session behaviour analysis, file upload validation, and password reset flow analysis.
Exploitation: Confirmed cross-account activation code reuse, validated the IDOR chain, and confirmed XSS.
Chain Validation: Constructed and validated the end-to-end attack chain from email address exposure to full account takeover.
Closure: Reporting, executive briefing, and coordinated disclosure.
Ground rules applied throughout:
- No access to accounts not controlled by the researcher
- No data extraction, retention, or third-party sharing
- Testing limited to confirming vulnerability existence
- No automated scanning or denial-of-service testing
Validated Vulnerabilities
Finding 1 — Account Takeover via Cross-Account Activation Code Reuse
Severity: Critical
Category: Authentication
CWE: CWE-639 — Authorization Bypass Through User-Controlled Key
Status: Confirmed
Technical Detail
The password reset endpoint does not validate that the activation code submitted in a reset request belongs to the account being reset. An authenticated attacker can generate a valid activation code for their own account and use it to overwrite the password of any other account on the platform. Activation codes are not invalidated after use and have no expiry window.
The reset endpoint accepts three key parameters: a personid (sequential integer identifying the target account), an activationcode (numeric token issued via email), and appid (mirrors personid in the POST body). The server validates that the activation code exists in the database but does not verify that it was issued for the account identified by personid.
Sub-finding: The same activation code successfully resets the same account on second and subsequent submissions — confirming no single-use enforcement and no expiry mechanism.
Account ID enumeration: Account IDs follow a sequential integer pattern, making enumeration of valid target accounts trivial.
Business Impact
Full account takeover of any registered applicant with no victim interaction. The attacker gains complete access to the victim's profile, personal data, CV document, job applications, and all associated PII. At scale, every registered applicant on the platform is vulnerable.
Scope Note
Demonstrated between two researcher-controlled accounts. No real applicant accounts were accessed.
Finding 2 — Systemic IDOR Across Profile Management Endpoints
Severity: High
Category: Broken Access Control
CWE: CWE-639 — Authorization Bypass Through User-Controlled Key
Status: Confirmed
Technical Detail
The platform's profile management API does not enforce server-side ownership validation on any endpoint. Any authenticated user can read, write, or delete profile data belonging to any other registered applicant by supplying a target identifier in the request body.
Read pattern — email address sufficient: The delete endpoints execute a SELECT using the supplied CreatedBy email to return remaining records, returning all records for the target account.
Write pattern — personid sufficient: The save endpoints accept an Applicant field set to any personid with no ownership check. False records are inserted into the target's profile.
Destructive pattern: Supplying a valid record id belonging to another user causes permanent deletion of that record with no ownership check.
Confirmed affected endpoints:
- Academic qualification (read, write, delete)
- Professional qualification (read, write, delete)
- Employment history (read, write, delete)
- Professional membership (read, write, delete)
- Referee details (read, write, delete)
- Personal details (read, write, delete)
Business Impact
An email-sufficient read vector means any applicant whose email address is publicly visible is fully exposed. The write vector enables data integrity attacks — a competing applicant could fabricate or destroy another's profile entries without detection. The email-to-personid resolution directly enables the Critical account takeover chain.
Scope Note
Read and write IDOR demonstrated against researcher-controlled accounts only. No third-party applicant data was accessed.
Finding 3 — Unauthenticated Access to Uploaded CV Documents
Severity: Medium
Category: Information Disclosure
CWE: CWE-425 — Direct Request ('Forced Browsing')
Status: Confirmed
Technical Detail
CV files uploaded by applicants are stored on the web server and served directly from a public path with no authentication or authorisation check. Any party who knows or can derive a file's URL can download the document without being logged in.
Business Impact
CV documents contain national ID numbers, home addresses, phone numbers, employment history, educational background, and personal references — a near-complete identity profile.
Scope Note
Confirmed on researcher's own uploaded CV only. No third-party CV files were accessed.
Finding 4 — Reflected XSS with Session Cookie Exposure
Severity: Medium
Category: Cross-Site Scripting
CWE: CWE-79 — Improper Neutralization of Input During Web Page Generation
Status: Confirmed
Technical Detail
The platform's error page reflects a URL parameter directly into the page response without sanitisation. The msg GET parameter is echoed into an <h4> tag without output encoding. A custom sanitiser targets only PHP open and close tags, leaving HTML and JavaScript entirely unfiltered.
The session cookie lacks HttpOnly and Secure flags, confirmed to be readable and exfiltrable by the injected script.
Business Impact
An attacker can craft a deceptive link that, when clicked by a logged-in applicant, silently steals their session cookie and grants the attacker full session access.
Scope Note
XSS execution and cookie exfiltration confirmed using researcher-controlled accounts and webhook endpoint only.
Finding 5 — Activation Tokens Have No Expiry and Are Not Invalidated After Use
Severity: Medium
Category: Authentication
CWE: CWE-613 — Insufficient Session Expiration
Status: Confirmed
Technical Detail
A reset code used to complete a password reset remained valid for subsequent submissions. Testing at 48-hour and 96-hour intervals confirmed the code remained valid throughout. No expiry timestamp or single-use flag was observed.
This compounds Finding 1: any historical activation code remains usable indefinitely.
Business Impact
Any activation code ever issued is a permanent credential for account password reset.
Scope Note
Confirmed on researcher-controlled accounts only.
Finding 6 — National ID Uniqueness Constraint Enforced Client-Side Only
Severity: Low
Category: Input Validation
CWE: CWE-602 — Client-Side Enforcement of Server-Side Security
Status: Confirmed
Technical Detail
The platform enforces national ID uniqueness at the frontend form validation layer only. A direct POST request bypasses this check and successfully inserts a duplicate national ID into the database.
Business Impact
If the platform uses national ID as an identity verification key, this failure could allow identity spoofing or duplicate account creation under a real person's ID number.
Scope Note
Demonstrated using the researcher's own national ID across two researcher-controlled accounts.
Security Controls Assessment
What Worked
✅ Injection defences — Entity encoding and Apache-level function blocking effectively defeats XSS and PHP injection across main application
✅ File upload validation — Server-side extension whitelist (doc, docx, pdf) — robust
✅ Password storage — No evidence of plaintext or weak hashing
What Failed
❌ Authorisation logic — Almost complete absence — every endpoint accepts user-supplied identifier without ownership verification
❌ Session cookie flags — HttpOnly absent, Secure absent
❌ Activation code lifecycle — No expiry, no single-use enforcement
❌ Access control model — No session-to-resource ownership validation on any endpoint
Architecture Intelligence
Recruitment Platform Stack: PHP / Apache 2.4.67.
Main Domain CMS: WordPress.
Database: MySQL (inferred).
Request Filtering: Apache-level blocking of PHP execution function names.
Input Sanitisation (Main Application): HTML entity encoding — effective.
Input Sanitisation (Error Page): PHP tag replacement only; JavaScript remained unfiltered.
File Upload Validation: Server-side extension whitelist — robust.
Session Cookie Flags: HttpOnly absent; Secure absent.
Account ID Scheme: Sequential integers — enumerable.
Activation Code Scheme: 8-digit numeric codes with no observed predictability pattern.
Activation Code Lifecycle: No expiry and no single-use enforcement.
Observed additional subdomains:
- Management portal (authenticated — no foothold obtained)
- Survey platform (leaks administrative contact email)
Observations on Program Quality
What worked well:
- Organisation's ICT leadership responded substantively within 24 hours
- Technical review meeting proposed and scheduled promptly
- ICT contact was candid about planned relaunch
What was challenging:
- No published security contact or VDP
- Multi-channel outreach required
- No formal remediation tracking mechanism
Programme gap — no VDP: The recommendation to establish one is included in the technical report.
Recommendations
Immediate
- Fix password reset endpoint — validate activation code belongs to
personidbeing reset; invalidate codes after use; implement expiry window - Enforce session ownership on all profile endpoints — derive target account identifier from session; remove
CreatedByandApplicantfrom client input
Short-Term
- Move CV files behind authenticated download handler
- Apply output encoding to error page —
htmlspecialchars(); setHttpOnlyandSecureflags on session cookie - Move national ID uniqueness enforcement server-side
Strategic
- Adopt least-privilege as design principle — every endpoint should verify session-to-resource ownership
- Commission independent security review before new platform launch
- Publish Vulnerability Disclosure Policy
Key Takeaways for Security Teams
1. Authorisation Is Not Authentication
Authenticated users are not authorised users. Every endpoint accepting an identifier must verify ownership independently. This platform had authentication but virtually no authorisation.
2. Token Lifecycle Matters
Activation codes without expiry or single-use enforcement are permanent credentials. This compounds any cross-account validation flaw.
3. Email Addresses Are Public Identifiers
Using email as a resource identifier in APIs means exposure boundaries are porous. Treat email as public information when designing access controls.
4. Client-Side Uniqueness Checks Are Not Security Controls
Any constraint enforced only in the browser is bypassable. Server-side validation is the only meaningful enforcement.
5. Direct File Access Is Always a Risk
Files uploaded by users should never be served directly from a web-accessible path. Authenticated download handlers are the minimum acceptable control.
Conclusion
The assessment confirmed six vulnerabilities across the platform, including a Critical authentication bypass and systemic broken access control across all profile management endpoints. The findings expose every registered applicant's personal data and enable complete account takeover of any user.
The organisation acknowledged the disclosure within 24 hours and convened a technical review meeting within the week. Implementation of the recommended remediation steps would substantially improve the security posture of the recruitment platform.
Assessment conducted under responsible disclosure principles. All testing performed ethically within defined scope boundaries. No real user data was accessed, modified, or exfiltrated.
Business Impact
Every registered applicant's personal data at risk — national ID numbers, contact details, employment history, qualifications, referee details, CV documents.
Any authenticated attacker can insert false qualifications or delete legitimate entries from any applicant's profile.
Findings
- Account Takeover via Cross-Account Activation Code ReuseSeverity: Critical
- Systemic IDOR Across Profile Management EndpointsSeverity: High
- Unauthenticated Access to Uploaded CV DocumentsSeverity: Medium
Key Lessons
- •Subdomain enumeration should be Phase 1 work. Two additional subdomains discovered late in engagement.
- •Characterise distribution immediately when sequential identifiers visible — account ID gap was observable but not analysed until Phase 3.
- •Verify authentication flow outcomes immediately. Account takeover was live from Phase 1 but not confirmed until session expiry revealed password change.
- •For organisations without VDP, identify secondary escalation path during recon. WhatsApp contact proved effective when email channels were slow.
- •Shared hosting requires explicit scope confirmation before testing — third-party tenants may be affected.