Mobile Device Watering Hole and Exploitation
An adversary has redirected users to a watering hole or compromised supply chain to profile mobile devices and deliver n-day exploits based on browser versions.
Based on research by Sekoia 2026-11-05 11 steps · 3 queries T1041 T1190 T1195 T1566
Brief
Why now
A recent report by Sekoia — Poisoned Source: APT29 Watering Holes Targets Mobile Devices (https://www.sekoia.com/blog/poisoned-source-apt29-watering-holes-targets-mobile-devices-with-n-day-exploits) — describes a campaign where the adversary compromised the Plerdy web analytics service. This supply-chain attack allowed the actor to inject profiling scripts into legitimate websites. These scripts identify the visitor browser and mobile OS to deliver targeted n-day exploits like DarkSword. This hunt focuses on the footprint left by these redirection and profiling stages.
How the hunt flows
The hunt begins by baselining HTTP activity. The first query searches for interaction with known redirection domains and unusual JavaScript loads from the Plerdy analytics service. It isolates script paths that deviate from standard organizational behavior. An analyst or agent reviews these hits to confirm if any host accessed the campaign infrastructure.
Once the lead confirms suspicious traffic, the hunt enters a forensic fan-out phase. It simultaneously queries the vulnerability surface and the HTTP telemetry surface. The vulnerability query identifies hosts that possess specific browser or mobile CVEs known to be targeted by this campaign. The traffic query looks for the specific profiling script 'temfp.js' and connections to known command-and-control (C2) IP addresses.
The final triage phase correlates these findings. The hunt prioritizes hosts where a known vulnerability exists and malicious HTTP traffic occurred. This intersection suggests a high probability of successful exploitation rather than just exposure. If the hunt confirms a compromise, it provides an action to isolate the host and revoke cloud sessions.
What the hunt cannot see
This hunt has two primary blind spots. First, because much of this activity occurs over HTTPS, the specific paths of profiling scripts are invisible without TLS inspection. In such cases, the hunt relies on domain-level visibility. Second, the hunt cannot see activity on unmanaged or personal mobile devices that are not enrolled in an MDM or EDR solution. If a user accesses a watering hole from a personal device while off the corporate VPN, the telemetry will not reach the enterprise surfaces.
Steps
-
Redirection traffic and unusual analytics scripts
Query · detection candidateFind known redirection indicators and baseline JS script loads from analytics providers like Plerdy.
reads hb_http_activitysqlSELECT device_hostname, url_hostname, url_path, COUNT(*) AS requests, MIN(time) AS first_seen FROM hb_http_activity WHERE (instr(',' || '{{malicious_domains}}' || ',', ',' || LOWER(url_hostname) || ',') > 0 OR (LOWER(url_hostname) = 'a.plerdy.com' AND LOWER(url_path) LIKE '%.js')) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, url_hostname, url_pathWhat a hit looks like. A row indicates interaction with malicious infrastructure or a script load from Plerdy. Unusual script paths should stand out from baseline patterns.
-
Evaluate lead activity
Agent triageReview the lead results to decide if a deeper forensic investigation is required.
-
Gate: Malicious traffic confirmed
DecisionRestrict the hunt to forensic queries only when the lead indicates a potential intrusion.
-
Host vulnerability for targeted CVEs
Query · enrichmentIdentify hosts in the estate that are vulnerable to the specific n-day exploits used by the campaign.
reads hb_vulnerability_findingsqlSELECT d.hostname AS device_hostname, vf.cve_uid, vf.severity, vf.resource_uid FROM hb_vulnerability_finding AS vf JOIN hb_devices AS d ON vf.device_uid = d.device_uid AND vf.provider = d.provider WHERE instr(',' || '{{target_cves}}' || ',', ',' || vf.cve_uid || ',') > 0What a hit looks like. A list of hostnames matching the campaign's target browser or mobile vulnerabilities.
-
Profiling script delivery and C2 traffic
Query · baselineDetect the profiling script 'temfp.js' and potential exfiltration to known campaign IPs.
reads hb_http_activitysqlSELECT device_hostname, url_hostname, url_path, dst_endpoint_ip, COUNT(*) AS count, MIN(time) AS first_seen FROM hb_http_activity WHERE (LOWER(url_path) LIKE '%temfp.js%' OR instr(',' || '{{c2_ips}}' || ',', ',' || dst_endpoint_ip || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, url_hostname, url_path, dst_endpoint_ipWhat a hit looks like. Hits on the profiling script path or specific C2 IPs (109.104.106.107). Rare hits are suspicious.
-
Correlate exploitation evidence
Agent triageIdentify hosts where the intersection of vulnerability and malicious traffic suggests successful exploitation.
-
Route on triage verdict
DecisionIsolate confirmed breaches and send suspicious activity to manual review.
-
Isolate host
Response actionPrevent further exfiltration from a compromised device.
-
Analyst forensic review
Analyst taskPerform deep manual analysis of the HTTP exfiltration patterns and vulnerability context.
-
Close out
Analyst taskDocument findings and negative results.
Coverage
Scenario coverage
| Stage | Covered | How, or why not |
|---|---|---|
| Watering Hole and Supply Chain Redirection T1190 · T1195 · T1566 |
Yes | redirection-and-script-lead |
| Client-Side Profiling and Exploitation | Yes | vulnerability-check, http-deep-dive |
| Mobile Data and Cookie Exfiltration T1041 |
Yes | http-deep-dive |
Blind spots
- Needs TLS inspection or transparent proxy logs. Without TLS inspection, the specific script paths like 'temfp.js' are invisible to hb_http_activity, leaving only domain-level visibility. It would answer The specific path and contents of the profiling script delivered over HTTPS.
- Needs Mobile EDR or specialized mobile telemetry. Exploitation of personally-owned or unmanaged mobile devices using corporate credentials will not be visible in endpoint-level surfaces. It would answer Whether a non-enrolled mobile device was compromised while off the corporate VPN.
Parameters & data
Parameters
| Parameter | Type | Default | What it is |
|---|---|---|---|
c2_ips | list[ip] | 109.104.106.107 | Infrastructure IPs for delivery and exfiltration. |
lookback_days | number | 14 | Days of history to examine. |
malicious_domains | list[domain] | static.flux-telemetry.com, america250.holiday, america250.org, theowo.club, a.plerdy.com, edge-ord.clouds-stacks.com, ads-it-assets.com, cdn.adv-static.com | Redirection and profiling domains named in the report. |
target_cves | list[string] | CVE-2024-27808, CVE-2024-27833, CVE-2024-27834, CVE-2025-14174, CVE-2025-24201, CVE-2025-27038, CVE-2025-31277, CVE-2025-43510, CVE-2025-43520, CVE-2025-43529, CVE-2026-20700, CVE-2026-3910 | Mobile and browser CVEs exploited in the campaign. |
Telemetry
| Source | Category | Telemetry |
|---|---|---|
| Endpoint telemetry (hb_ surfaces) | endpoint | endpoint |
| Web server / proxy logs | siem | network |
Source
---
analysis: A static rule would only fire on known domains. This hunt uses a behavioral
baseline for analytics script loading and correlates redirection with vulnerability
findings to confirm actual exploitation risk.
blind_spots:
- id: encrypted-traffic-blindness
question: The specific path and contents of the profiling script delivered over
HTTPS
requires: TLS inspection or transparent proxy logs
risk: Without TLS inspection, the specific script paths like 'temfp.js' are invisible
to hb_http_activity, leaving only domain-level visibility.
stage: watering-hole-redirection
- id: mobile-os-telemetry-gap
question: Whether a non-enrolled mobile device was compromised while off the corporate
VPN
requires: Mobile EDR or specialized mobile telemetry
risk: Exploitation of personally-owned or unmanaged mobile devices using corporate
credentials will not be visible in endpoint-level surfaces.
stage: client-side-profiling-and-exploitation
coverage:
- stage: watering-hole-redirection
status: covered
steps:
- redirection-and-script-lead
- stage: client-side-profiling-and-exploitation
status: covered
steps:
- vulnerability-check
- http-deep-dive
- stage: mobile-data-exfiltration
status: covered
steps:
- http-deep-dive
guardrails:
claims: no_unsupported
evidence: citation_required
missing_data: not_benign
telemetry: untrusted
hunt:
applicability: campaign-specific
handoff: keep-as-periodic-hunt
justification: APT29's use of mobile exploit kits via high-profile watering holes
targets high-value credentials and sensitive data (Wi-Fi passwords, cookies);
a negative result confirms lack of exposure to this infrastructure.
methodology: model-assisted
trigger: intel-report
hypothesis: An adversary has redirected users to a watering hole or compromised supply
chain to profile mobile devices and deliver n-day exploits based on browser versions.
labels:
- hunt
- attack.t1190
- attack.t1195
- attack.t1566
- attack.t1041
- execution
- exfiltration
- initial access
name: Mobile Device Watering Hole and Exploitation
parameters:
c2_ips:
default:
- 109.104.106.107
description: Infrastructure IPs for delivery and exfiltration.
from:
kind: article
observed: '2026-10-29'
ref: https://www.sekoia.com/blog/poisoned-source-apt29-watering-holes-targets-mobile-devices-with-n-day-exploits
type: list[ip]
lookback_days:
default: '14'
description: Days of history to examine.
type: number
malicious_domains:
default:
- static.flux-telemetry.com
- america250.holiday
- america250.org
- theowo.club
- a.plerdy.com
- edge-ord.clouds-stacks.com
- ads-it-assets.com
- cdn.adv-static.com
description: Redirection and profiling domains named in the report.
from:
kind: article
observed: '2026-10-29'
ref: https://www.sekoia.com/blog/poisoned-source-apt29-watering-holes-targets-mobile-devices-with-n-day-exploits
type: list[domain]
target_cves:
default:
- CVE-2024-27808
- CVE-2024-27833
- CVE-2024-27834
- CVE-2025-14174
- CVE-2025-24201
- CVE-2025-27038
- CVE-2025-31277
- CVE-2025-43510
- CVE-2025-43520
- CVE-2025-43529
- CVE-2026-20700
- CVE-2026-3910
description: Mobile and browser CVEs exploited in the campaign.
from:
kind: article
observed: '2026-10-29'
ref: https://www.sekoia.com/blog/poisoned-source-apt29-watering-holes-targets-mobile-devices-with-n-day-exploits
type: list[string]
provenance:
authors:
- name: Huntbase hunt generation
org: huntbase.io
generated:
by: huntbase-hunt-generation
from: https://www.sekoia.com/blog/poisoned-source-apt29-watering-holes-targets-mobile-devices-with-n-day-exploits
gates:
- dry-run
- lint
model: hb_google/gemini-3-flash-preview
rationale: Start with corporate endpoints that frequently access international news
or government services. Focus on mobile devices enrolled in MDM first.
references:
- name: "Sekoia \u2014 Poisoned Source: APT29 Watering Holes Targets Mobile Devices"
url: https://www.sekoia.com/blog/poisoned-source-apt29-watering-holes-targets-mobile-devices-with-n-day-exploits
related:
- hunt: mobile-mdm-vulnerability-audit
reason: This hunt looks for active exploitation; a posture audit would proactively
find every vulnerable mobile device.
relation: alternative
scenario:
stages:
- name: Watering Hole and Supply Chain Redirection
observables:
- a.plerdy.com
- america250.holiday
- theowo.club
- america250.org
- ads-it-assets.com
- cdn.adv-static.com
- window.onload
- document.createElement('script')
- script.src
slug: watering-hole-redirection
tactic: initial-access
techniques:
- T1190
- T1195
- T1566
- name: Client-Side Profiling and Exploitation
observables:
- static.flux-telemetry.com
- edge-ord.clouds-stacks.com
- module/5b4c8fea5cbcee273e8d830f52-temfp.js
- UltimateFingerprinter
- DarkSword
- CVE-2024-27808
- CVE-2024-27833
- CVE-2024-27834
- CVE-2025-14174
- CVE-2025-24201
slug: client-side-profiling-and-exploitation
tactic: execution
- name: Mobile Data and Cookie Exfiltration
observables:
- exfiltration of cookies
- exfiltration of Wi-Fi passwords
- exfiltration of Chrome data
- 109.104.106.107
slug: mobile-data-exfiltration
tactic: exfiltration
techniques:
- T1041
summary: APT29 conducted a large-scale watering hole campaign targeting iOS and
Android devices through compromised legitimate websites, AiTM proxy domains, and
a supply chain compromise of the Plerdy analytics service. The campaign used an
'UltimateFingerprinter' script to profile victims and serve tailored n-day exploit
chains (including the DarkSword iOS kit) to exfiltrate cookies, Chrome data, and
Wi-Fi passwords without establishing persistence.
severity: high
targets:
analyst:
name: Tier-2 analyst
role: analyst
endpoint:
category: endpoint
name: Endpoint telemetry (hb_ surfaces)
telemetry:
- endpoint
hunter:
agent: true
name: Hunt agent
web:
category: siem
name: Web server / proxy logs
telemetry:
- network
tlp: clear
type: investigation
---
# Mobile Device Watering Hole and Exploitation
This hunt identifies a sophisticated watering hole campaign attributed to APT29 that targets mobile devices through compromised web analytics and reverse proxies. The campaign uses several infection vectors, including a supply-chain compromise of the Plerdy analytics service, to deliver profiling scripts and n-day exploit chains like DarkSword. The hunt begins with a behavioral lead query that baselines script inclusions from analytics providers and checks for known redirection domains. If suspicious traffic is confirmed, it fans out to correlate the exposure of browser and mobile CVEs on affected hosts with detailed HTTP telemetry for specific profiling script paths and exfiltration patterns. An agent weighs the intersection of these findings to identify successful exploitation.
## redirection-and-script-lead
<!-- Redirection traffic and unusual analytics scripts -->
Find known redirection indicators and baseline JS script loads from analytics providers like Plerdy.
```sqlite target=web role=detection-candidate params=(malicious_domains=malicious_domains, lookback_days=lookback_days)
~~~yaml
baseline:
compare: new_this_window
window: '{{lookback_days}}d'
expected: A row indicates interaction with malicious infrastructure or a script load
from Plerdy. Unusual script paths should stand out from baseline patterns.
prevalence:
by: device_hostname
key:
- url_hostname
- url_path
rare_below: 5
reads:
- device_hostname
- url_hostname
- url_path
- time
silence: not_evidence_of_absence
source: hb_http_activity
verified: dry-run
verified_at: '2026-11-05'
~~~
SELECT device_hostname, url_hostname, url_path, COUNT(*) AS requests, MIN(time) AS first_seen FROM hb_http_activity WHERE (instr(',' || '{{malicious_domains}}' || ',', ',' || LOWER(url_hostname) || ',') > 0 OR (LOWER(url_hostname) = 'a.plerdy.com' AND LOWER(url_path) LIKE '%.js')) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, url_hostname, url_path
```
## lead-agent
<!-- Evaluate lead activity -->
```agent target=hunter
cite: required
context:
- redirection-and-script-lead
max_iterations: 3
objective: Determine if any host shows interaction with malicious domains or unexpected
script inclusions from the Plerdy supply chain.
success_criteria: A verdict citing specific hosts and malicious/behavioral indicators.
tools:
- endpoint
- web
```
## gate
<!-- Gate: Malicious traffic confirmed -->
if~: "the lead-agent verdict confirms at least one host queried a malicious domain or loaded an unusual script from a.plerdy.com" (confidence: high, judge=hunter)
then: → fan-out
indeterminate: → analyst-review
unavailable: → analyst-review (blind_spot: encrypted-traffic-blindness)
else: → close-out
## fan-out
<!-- Forensic fan-out -->
parallel:
- → vulnerability-check
- → http-deep-dive
join: → triage
## vulnerability-check
<!-- Host vulnerability for targeted CVEs -->
Identify hosts in the estate that are vulnerable to the specific n-day exploits used by the campaign.
```sqlite target=endpoint role=enrichment params=(target_cves=target_cves)
~~~yaml
expected: A list of hostnames matching the campaign's target browser or mobile vulnerabilities.
reads:
- device_uid
- cve_uid
- severity
- resource_uid
silence: not_evidence_of_absence
source: hb_vulnerability_finding
verified: dry-run
verified_at: '2026-11-05'
~~~
SELECT d.hostname AS device_hostname, vf.cve_uid, vf.severity, vf.resource_uid FROM hb_vulnerability_finding AS vf JOIN hb_devices AS d ON vf.device_uid = d.device_uid AND vf.provider = d.provider WHERE instr(',' || '{{target_cves}}' || ',', ',' || vf.cve_uid || ',') > 0
```
## http-deep-dive
<!-- Profiling script delivery and C2 traffic -->
Detect the profiling script 'temfp.js' and potential exfiltration to known campaign IPs.
```sqlite target=web role=baseline params=(c2_ips=c2_ips, lookback_days=lookback_days)
~~~yaml
baseline:
compare: new_this_window
window: '{{lookback_days}}d'
expected: Hits on the profiling script path or specific C2 IPs (109.104.106.107).
Rare hits are suspicious.
prevalence:
by: device_hostname
key:
- url_path
- dst_endpoint_ip
rare_below: 3
reads:
- device_hostname
- url_hostname
- url_path
- dst_endpoint_ip
- time
silence: not_evidence_of_absence
source: hb_http_activity
verified: dry-run
verified_at: '2026-11-05'
~~~
SELECT device_hostname, url_hostname, url_path, dst_endpoint_ip, COUNT(*) AS count, MIN(time) AS first_seen FROM hb_http_activity WHERE (LOWER(url_path) LIKE '%temfp.js%' OR instr(',' || '{{c2_ips}}' || ',', ',' || dst_endpoint_ip || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY device_hostname, url_hostname, url_path, dst_endpoint_ip
```
## triage
<!-- Correlate exploitation evidence -->
```agent target=hunter
cite: required
context:
- lead-agent
- vulnerability-check
- http-deep-dive
max_iterations: 5
objective: Identify the intersection of hosts that both visited the redirection infrastructure
and possess the relevant browser or mobile CVEs to prioritize confirmed compromises.
success_criteria: A verdict of malicious | suspicious | benign per host, prioritizing
those where vulnerability findings overlap with malicious HTTP traffic.
tools:
- endpoint
- web
```
## route
<!-- Route on triage verdict -->
if~: "the triage verdict is malicious for at least one host showing the intersection of vulnerability and traffic" (confidence: high, judge=hunter)
then: → isolate
indeterminate: → analyst-review
unavailable: → analyst-review (blind_spot: mobile-os-telemetry-gap)
else: → analyst-review
## isolate
<!-- Isolate host -->
```action target=endpoint
~~~yaml
approval: required
~~~
Isolate the host and revoke its cloud sessions while forensics proceed.
```
→ analyst-review
## analyst-review
<!-- Analyst forensic review -->
```manual target=analyst
Review cited rows from http-deep-dive; look for POST requests to 109.104.106.107 suggesting cookie or password exfiltration. Verify the mobile OS version via hb_devices.
```
→ end
## close-out
<!-- Close out -->
```manual target=analyst
Record the negative results; if redirection was seen but no vulnerability exists, note for future patching priority.
```
→ end
Run it
Take this hunt into your environment.
Open it in Huntbase to run every step against your own connections, with Scout weighing the evidence and your analysts in command. Or take the open hunt.md file anywhere that reads the format.
Machine-drafted by huntbase-hunt-generation using hb_google/gemini-3-flash-preview, gated by dry-run, lint, then reviewed by a person.