Retired Mobile Client Used in Cross-Tenant API Enumeration
Incident analysis of automated enumeration and missing object-level authorization identified through a reverse-engineered retired mobile client
On September 10, 2026, we investigated high-volume automated requests to a public API. Most of the traffic reproduced the User-Agent and request patterns of a retired mobile client. Analysis of the client and the observed requests indicated that the actor used an obsolete application build to identify API routes and reproduce expected client behavior.
Summary: Traffic from 182.16.62.190 arrived in four bursts and predominantly used the retired mobile application's User-Agent. The source queried at least nine tenant identifiers through a guest-facing availability API and received successful dynamic JSON responses from the origin.
Observed Traffic
The source address was associated with hosting infrastructure registered in Hong Kong. Cloudflare labeled the client country as the United States. The registry record and the source's mixed automation clients provided stronger support for the hosting-provider context, so the investigation treated geolocation as uncertain and did not use it for attribution.
Roughly 94% of sampled requests used the retired mobile client's User-Agent. Smaller groups used python-requests/2.32.3 and curl/8.5.0 for narrower probes. The exact retired-client string and version are omitted because they would identify the affected product.
| Observed client | Approximate share | Likely purpose |
|---|---|---|
| Retired mobile-client User-Agent | ~94% | Blend with expected application traffic and reach known routes |
python-requests/2.32.3 | ~4% | Send a local-file-inclusion-shaped probe |
curl/8.5.0 | ~2% | Probe an administrative interface |
We confirmed that the actor had obtained and reverse-engineered a retired application build. The build exposed route names and the application's User-Agent construction, supporting the assessment that it enabled precise route targeting and client impersonation.
Use of the Retired Mobile Client
flowchart TB
Build["Retired mobile build remains obtainable"]
Reverse["Actor reverse-engineers routes and client fingerprint"]
Impersonate["Requests impersonate the retired client"]
Query["Guest API receives caller-supplied tenant and room identifiers"]
Missing["Server does not enforce the apparent object boundary"]
Enumerate["At least nine tenant identifiers are queried"]
Response["Origin returns successful dynamic JSON responses"]
Build --> Reverse --> Impersonate --> Query --> Missing --> Enumerate --> Response
Cross-Tenant Enumeration
The availability endpoint accepted tenant and room identifiers supplied by the caller without evidence that the requested objects were bound to the caller's authorized scope. Security-event records show unmitigated 200 OK responses, dynamic origin processing, and JSON delivery for the observed enumeration activity.
The available evidence supports successful querying outside the requester's apparent scope. The investigation did not establish that every tenant or room was reachable, that authentication was required in every case, or the complete sensitivity of each response. Controlled reproduction of the full authorization boundary remained incomplete.
Assessment of Additional Probes
| Technique | Observed result | Assessment |
|---|---|---|
| Semicolon path-parameter injection | Approximately 35 requests targeted internal-style route names and returned 404 or 403. | No successful bypass observed. |
LFI-shaped probe using /etc/passwd | The original request returned 200 OK and 41,687 bytes; controlled reproduction returned the normal application shell. | False positive. No local file inclusion demonstrated. |
| Administrative-interface normalization probe | The original request returned 200 OK; reproduction led to an authenticated staff login flow. | Reconnaissance value only. No authentication bypass or disclosure observed. |
| Cross-tenant BOLA/IDOR enumeration | At least nine tenant identifiers produced successful, dynamic origin responses with JSON delivered. | Successful enumeration activity observed; complete response scope was not reconstructed. |
| Sentinel-value record lookup | The original event returned 200 OK and 946 bytes; later reproduction returned 404. | Inconclusive. The record may have expired, changed, or been remediated. |
The administrative-interface result identified a staff interface protected by authentication. It provides reconnaissance value only and does not demonstrate an authentication bypass.
Application-Layer Authorization Failure
The observed enumeration requests used valid routes, plausible client metadata, and ordinary identifiers. Cloudflare did not classify the requests as cross-site scripting, SQL injection, or remote-code execution because they did not contain those attack patterns.
A WAF can identify malicious syntax, but it generally cannot determine whether a caller is authorized to request a specific tenant or room. The application has the context needed to enforce that relationship. The observed issue is an application-layer authorization failure rather than a signature-detection failure.
flowchart TB
APK["Retired mobile build"]
Routes["Reverse engineering identifies API routes"]
Fingerprint["User-Agent construction is reproduced"]
Requests["Automated requests use retired-client metadata"]
API["Guest availability API"]
Identifiers["Caller supplies tenant and room identifiers"]
Responses["Origin returns dynamic JSON responses"]
Enumeration["At least nine tenant identifiers are queried"]
APK --> Routes --> Requests --> API --> Identifiers --> Responses --> Enumeration
APK --> Fingerprint --> Requests
Remediation Priorities
- Enforce object authorization on every request. Bind tenant and room identifiers to the authenticated caller's server-side scope before returning data.
- Audit sibling endpoints. Any API accepting a caller-supplied tenant, customer, room, project, or record identifier deserves the same authorization review.
- Retire clients on the server, not only in the app store. Enforce a minimum supported version and remove unnecessary public API compatibility for obsolete builds.
- Reduce route intelligence in unprivileged clients. Keep staff and back-office routes out of guest-facing distributions wherever practical.
- Alert on identifier diversity. A single client rapidly querying many tenant identifiers can be more meaningful than raw request volume alone.
- Correlate client claims with network behavior. A mobile User-Agent paired with hosting infrastructure or scripting-library fingerprints should increase risk, not trigger an automatic block by itself.
Country-based blocking would not be a reliable primary response because users can travel, use VPNs, or share geography with hosting providers. Hosting-ASN context, client-fingerprint inconsistencies, and enumeration behavior are more specific signals and are less likely to disrupt legitimate users.
Conclusion
The observed requests used valid routes and client metadata derived from a retired mobile build. The application accepted caller-supplied identifiers without enforcing the corresponding object relationship, allowing cross-tenant enumeration activity. A WAF cannot enforce this type of authorization without application-specific context.
Indicators of Compromise
| Observed indicators | |
|---|---|
| Source IP | 182.16.62.190 |
| Automation clients | python-requests/2.32.3 and curl/8.5.0 |
Glossary: Terms used in this post
- BOLA/IDOR: An authorization weakness that permits access to an object by changing its identifier without verifying the caller's permission for that specific object.
- LFI: Local File Inclusion, a vulnerability that can expose local server files. Supplying a filename without retrieving that file is not proof of LFI.
- Origin: The application server behind an edge or content-delivery service.
- WAF: A web application firewall that detects request patterns but normally lacks the business context to enforce per-object authorization.