Key takeaways
- JA3 TLS fingerprints distinguish legitimate mobile client libraries from interception proxies in a way HTTP headers alone cannot.
- Concurrent successful authentication from two or more geographic regions inside a five-minute window is the clearest token-theft signal a gateway produces.
- Sigma 2.0 value_count correlation rules alert on multi-country token grants without requiring a full SIEM aggregation pipeline.
- Enabling JA3 logging on nginx, Kong and AWS ALB each requires a single module or configuration change and no code deployment.
- A completed pentest leaves labelled attack traffic in gateway logs, which is the best training data you will get for rule tuning.
Why the API gateway sees everything first
Every request a mobile client sends passes through the API gateway before it reaches a service. That places the gateway ahead of application logs, which never see malformed TLS, and ahead of the backend, which only sees what the gateway forwards.
A mobile app pentest exercises the full stack: the app binary, the device, the TLS channel and the APIs behind it. Each stage leaves a signal. The gateway captures the channel-level signals that application logs discard entirely, including TLS client fingerprints, raw certificate negotiation and connection patterns that differ between a production device and an interception proxy.
The MITRE ATT&CK framework maps credential access through token theft as a distinct tactic, and the gateway log is where that tactic becomes observable before it reaches any application tier. The six signal categories this article covers are: TLS client fingerprints (JA3), certificate validation anomalies, concurrent authentication from disparate geography, token replay outside the original device fingerprint, automated request cadence, and API method abuse against undocumented paths. Each has a Sigma rule and at least one platform-native query you can drop into a working deployment.
Mobile client
App binary on a physical or emulated device
TLS channel
JA3 fingerprint identifies the client library in use
API gateway
Records fingerprint, source IP, user agent and timing
SIEM
Correlates events across sessions and geography
SOC alert
Fires on anomalies: concurrent geography, replay, cadence
JA3 fingerprinting and how to enable it at each gateway
JA3 is a method of fingerprinting TLS client hello messages by hashing the negotiated cipher suites, extensions and elliptic curves into a 32-character MD5 string. A production iOS app using the system TLS stack produces a consistent JA3 hash. Frida-gadget, Burp Suite and mitmproxy each produce a different one. That gap is the detection signal.
The OWASP Mobile Application Security Project documents TLS layer controls as a network-level countermeasure for exactly this reason: when a client library changes, the hash changes, and no amount of spoofed HTTP headers will reproduce the original value.
On **nginx**, JA3 requires the nginx-module-njs scripting module or the purpose-built nginx-module-ja3 third-party module. Once installed, add $ja3 to your log_format directive and reload the process. The hash appears in every access log line with no changes to upstream services.
On **Kong Gateway**, a custom Lua plugin reads the JA3 hash from the ngx.var.ssl_ja3 variable, which is exposed by an underlying OpenResty build compiled with JA3 support. The Kong deck configuration deploys the plugin once and applies it to all routes matching a service selector, with no gateway restart.
On **AWS ALB**, native JA3 support arrived in 2023. Enable it under the load balancer attributes in the console or via the CLI by adding tls_ja3_fingerprint to the ALB access log format string. The field appears as tls.ja3_fingerprint in delivered log records. No redeployment of target groups is required. All three options are summarised in the table below.
With JA3 logging in place, build a baseline of hashes your production clients produce over two to four weeks. Alert on any hash outside that set during a pentest window, or continuously once you have confidence in the baseline. The hash does not change between app releases unless the TLS library changes, so a new app version is the right trigger to refresh the allowlist. mTLS and token binding go a step further: mTLS requires the client to present a certificate the gateway validates, and token binding cryptographically ties an access token to the TLS channel so a stolen token cannot be replayed from a different connection. Both are worth pursuing once gateway-level fingerprint logging is stable. The API pentest service page covers how these controls are tested.
| Gateway | Mechanism | Config change required |
|---|---|---|
| nginx | nginx-module-ja3 or njs scripting module | Add $ja3 to log_format, reload process |
| Kong Gateway | Custom Lua plugin reading ngx.var.ssl_ja3 | Deploy plugin via deck, no gateway restart |
| AWS ALB | Native attribute, available since 2023 | Add tls_ja3_fingerprint to log format in console or CLI |
Concurrent geography and token replay
Token theft is the aim of several mobile attack paths covered in what a mobile app leaves on the phone. Once a bearer token is extracted from device storage or traffic, an attacker uses it from their own machine. The legitimate user and the attacker are then authenticating from different countries inside the same session window.
The detection condition is: two successful authentication events for the same user identity, from source IPs that geolocate to different countries, within five minutes. That window is tight enough to exclude legitimate VPN roaming and wide enough to catch a replay that follows immediately after interception.
Token replay without concurrent geography is harder to detect at the gateway alone, because the token is valid. The signal shifts to device fingerprint mismatch: the User-Agent, JA3 hash and device identifier on the replayed request will differ from the token's originating session. Record all three fields on the token grant and compare them on subsequent requests.
The mobile app pentest process deliberately generates both patterns. Cert-pinning bypass, described in detail in breaking the pin: reading a mobile app's API traffic, creates a JA3 mismatch. Replaying captured tokens from a different host creates the concurrent geography condition. That makes a pentest window a calibration run for both rules.
Sigma rules and platform-native queries
The rules below use logsource.category: proxy for gateway logs. This is a documented Sigma taxonomy category covering reverse proxies and API gateways. The category form is portable across Kong, nginx and ALB; a product-specific source (product: nginx, service: access) is more precise when the deployment is single-vendor and may match more backend SIEM pipelines. The field name api_gateway is not a standard Sigma taxonomy entry and should not be used as a product value.
The first rule detects a JA3 hash not in the production allowlist. The filter block names two example production hashes; replace them with the baseline you collected from two to four weeks of clean traffic. The mobile app pentest process will generate hashes outside this set from its first request, which is what makes the rule a reliable pentest-window signal.
The second rule is a Sigma 2.0 value_count correlation. It fires when the same user authenticates successfully from more than one distinct country within five minutes. The type: value_count form counts distinct values of a nominated field within the group-by and timespan window, then applies the threshold condition. The SPL and EQL equivalents below are deployable directly into Splunk and Elastic respectively.
title: Mobile API - JA3 fingerprint outside production allowlist
name: mobile_api_ja3_unknown
status: test
description: Fires when a TLS client hello hash is not in the set produced by known production client libraries. Indicates a potential interception proxy such as Burp Suite, mitmproxy or Frida-gadget.
logsource:
category: proxy
detection:
selection:
http.method:
- GET
- POST
- PUT
- DELETE
tls.ja3: '*'
filter_production:
tls.ja3|contains:
- 'e7d705a3286e19ea42f587b344ee6865'
- '6734f37431670b3ab4292b8f60f29984'
# extend with hashes from your two-week baseline
condition: selection and not filter_production
falsepositives:
- New app release with an updated TLS library
- Corporate HTTPS proxy on managed devices
level: mediumtitle: Mobile API - Concurrent authentication from distinct geographies
name: mobile_api_concurrent_geography
status: test
description: Correlates successful authentication events for the same user from more than one geographic region within five minutes. Indicates probable token theft followed by replay from a different host.
type: value_count
rules:
mobile_auth_grant:
title: Mobile API token grant success
logsource:
category: proxy
detection:
selection:
http.method: POST
url.path|contains: /auth/token
http.response.status_code: 200
condition: selection
group-by:
- user.id
field: source.geo.country_iso_code
timespan: 5m
condition: gte(2)
falsepositives:
- User connected through a VPN exit node in a different country
- Multi-region active-active deployment routing the same session through different regions
level: highindex=proxy sourcetype=access_log http_method=POST uri_path="*/auth/token" status=200
| iplocation src_ip
| bin _time span=5m
| stats dc(Country) as country_count values(Country) as countries by user_id _time
| where country_count >= 2
| table user_id _time country_count countries/* Two auth successes for the same user, different source countries, within 5 minutes */
sequence by user.id with maxspan=5m
[any where event.dataset == "nginx.access"
and url.path : "*/auth/token"
and http.response.status_code == 200
and source.geo.country_iso_code == "AE"]
[any where event.dataset == "nginx.access"
and url.path : "*/auth/token"
and http.response.status_code == 200
and not source.geo.country_iso_code == "AE"]Automated cadence and undocumented path enumeration
A penetration tester using an automated scanner against a mobile app backend produces a request rate no human user generates. The gateway log captures both the request-per-second rate and the spread of paths hit. Normal mobile users access a small set of paths in bursts tied to screen transitions. A scanner hits every path the OpenAPI specification exposes, plus a dictionary of common paths the spec does not name.
The gateway-level detection condition is: more than 100 distinct URL paths from one source IP within 60 seconds, or more than 20 requests to paths that return 404 from the same source within 30 seconds. Both thresholds are conservative enough to exclude legitimate client retries. See how a mobile app pentest is run for the testing phases that generate this traffic pattern and the typical tooling behind them.
Path enumeration against undocumented endpoints matters because mobile apps frequently call internal or staging API versions that were never removed from the gateway routing table. Those paths appear in the gateway log whether or not the app binary still references them, and a tester who finds one may find a version without authentication checks.
Alert on 404 bursts before alerting on volume alone. A slow scan that stays under the rate threshold but accumulates 404s is a path enumeration in progress. That signal is in the gateway log on every platform, with no JA3 or geolocation dependency.
Turning pentest traffic into permanent detection rules
A completed mobile app pentest leaves a window of labelled attack traffic in your gateway logs. That is the best training data available for rule tuning, because you know exactly which events were attacker-generated and which were production. NIST SP 800-115 frames security testing as a cycle of discovery, attack and reporting, and the detection tuning step belongs in that cycle rather than after it.
Export the pentest window and run your candidate rules against it. Each rule should fire on the attack traffic and not fire on production traffic from the same period. A rule that fires on both needs a tighter condition. A rule that fires on neither missed the technique entirely.
After tuning, run each confirmed rule through a purple teaming session against the same techniques, with the detection team watching. A tester runs the technique, the detection team watches for the alert, and the rule is refined until it fires reliably without flooding the queue.
Rules that survive that loop are promoted to production. A detection that passed labelled pentest traffic and a live purple team run is materially different from a rule written from a document and never validated. The assumed-breach format runs a similar loop for internal lateral movement rules, using the same gateway log signals when the initial foothold involves a compromised mobile token.
Mobile API detection for Abu Dhabi and Dubai deployments
Financial institutions regulated by the CBUAE, Dubai government entities under DESC, and Abu Dhabi healthcare organizations under ADHICS each operate mobile applications that connect to backend APIs. For CBUAE-regulated banks, the resilience and security controls required under the CBUAE Operational Risk Regulation directly address application-level monitoring, and gateway log retention is a standard audit expectation during examination.
Abu Dhabi and Dubai deployments frequently route through a mix of on-premises gateways and regional cloud load balancers. That architecture means JA3 logging configuration may differ between the two layers, and a gap in either one leaves the concurrent geography rule partially blind. A mobile app pentest that tests both paths will expose the gap; the detection tuning that follows must cover both layers to satisfy a full-stack monitoring obligation.
DESC-regulated suppliers to Dubai government entities are obligated to demonstrate security testing and ongoing monitoring as part of their supplier qualification. Gateway log evidence showing that a mobile app attack was detected, correlated and alerted on within a pentest window is exactly the kind of artefact a DESC audit examination will ask for. Organizations that complete a mobile app pentest and deploy the resulting detection rules produce that evidence record in the process.
The UAE Information Assurance Regulation, applicable to federal entities under NESA, requires documented monitoring of application-layer events. Gateway logs that capture the signal categories described in this article, retained for the period the regulation specifies and queryable in the event of an incident, satisfy that monitoring obligation for the mobile API surface without tooling beyond what the gateway already records.
Frequently asked questions
What is a JA3 fingerprint and why does it matter for mobile app detection?
JA3 is a method of fingerprinting TLS client hello messages by hashing the negotiated cipher suites, extensions and elliptic curves. A production mobile app uses a consistent TLS library that produces a stable hash. An interception proxy such as Burp Suite or mitmproxy produces a different hash. That difference is a reliable signal that someone has inserted themselves between the app and the API gateway, without requiring any changes to the app or the backend.
How does concurrent geography detection differ from standard impossible travel alerts?
Impossible travel checks whether the same account authenticated from two locations that are physically impossible to travel between in the elapsed time, using distance divided by time. Concurrent geography is a narrower, gateway-level version of the same idea: two successful token grants for the same user, from IPs in different countries, within a five-minute window. It does not require travel time calculation and fires on token replay even when the two requests arrive seconds apart.
Which Sigma logsource category should I use for API gateway logs?
Use `logsource.category: proxy` for rules that should work across multiple gateway products. This is a documented Sigma taxonomy category covering reverse proxies and API gateways. If your deployment is single-vendor, `logsource.product: nginx` or `logsource.product: kong` with `logsource.service: access` is more precise and may match more SIEM pipelines. The value `api_gateway` is not a standard Sigma taxonomy product name and should not be used.
Does AWS ALB support native JA3 logging without a third-party module?
Yes. AWS ALB added native JA3 fingerprint logging in 2023. The `tls_ja3_fingerprint` field is available in the ALB access log format and is enabled through the load balancer attributes in the console or via the AWS CLI. No changes to target groups or backend services are required, making it the simplest of the three common gateway configurations to enable.
What is Sigma 2.0 value_count and when should I use it for gateway detection?
Sigma 2.0 introduced correlation rule types including `value_count`, which counts the number of distinct values a nominated field takes across events grouped by a key field within a time window. Use it when the detection condition spans multiple events, such as the same user authenticating from more than one country. It maps cleanly to Splunk `dc()`, Elasticsearch cardinality aggregations and similar SIEM constructs, so the Sigma rule and the platform query describe the same logic.
How do I build a JA3 allowlist without blocking legitimate users?
Collect two to four weeks of gateway logs from production traffic and extract the distinct JA3 hashes, grouped by user agent to understand which client versions produce which hashes. Update the list after any app release that updates the TLS library. Run the allowlist rule in alert-only mode for one additional week before converting it to a blocking rule, to catch any legitimate client variant the baseline period missed.
What is the difference between JA3 detection and mTLS for mobile API security?
JA3 detection is passive: it records what TLS fingerprint the client presents and alerts when it falls outside the expected set, but it does not prevent an attacker from connecting. mTLS is active: the gateway requires the client to present a certificate it controls, and a request without that certificate is rejected before any application logic runs. JA3 detection is a monitoring control; mTLS is a preventive one. Both can run in parallel.
What causes false positives in concurrent geography rules?
The main sources are corporate VPN users who exit through a node in a different country, and multi-region active-active deployments that route requests from the same session through different regions. Both are addressable: allowlist known VPN exit IP ranges and exclude internal service-to-service calls from the rule scope. After those exclusions, genuine false positives are rare in production.
What should the SOC do when a concurrent geography alert fires during a scheduled pentest?
Correlate the source IP against the pentest authorization letter to confirm it is the tester's IP range. If it matches, log it as a true positive generated by authorized testing and use the event to validate the rule threshold. If the IP is not in the authorized range, treat it as an incident regardless of the pentest window, because a third party may be opportunistically targeting the same surface.






