TeamPCP Credential Validation and Discovery
An adversary validates stolen cloud credentials and enumerates cloud infrastructure using offensive tools like TruffleHog or specialized Boto3 scripts following a supply chain compromise.
Based on research by Wiz 2026-09-20 10 steps · 4 queries T1078 T1082 T1083 T1087 T1090.003 T1195
Brief
Why this hunt matters
The recent research by Wiz, Tracking TeamPCP: post-compromise attacks seen in the wild (https://www.wiz.io/blog/tracking-teampcp-investigating-post-compromise-attacks-seen-in-the-wild), details how attackers use supply chain compromises to harvest secrets. Once an adversary gains access to a developer workstation or CI/CD runner, they move quickly. They validate the stolen credentials and map the cloud environment before defenders even realize a package was compromised. We built this hunt to catch that transition from the local environment to the cloud control plane.
How the hunt flows
The hunt begins with a scoping exercise across the software inventory. It identifies hosts running packages targeted by TeamPCP, such as Trivy, KICS, LiteLLM, or Telnyx. These hosts represent the potential beachheads where an adversary likely harvested secrets. This step narrows the search space for the rest of the investigation.
Once the hunt establishes the host scope, it pivots into a parallel analysis of network and authentication logs. One query checks for sign-ins from known TeamPCP IP addresses and VPN exit nodes. Simultaneously, another query searches for HTTP traffic containing user-agent signatures for offensive tools like TruffleHog or Kali-based Boto3 scripts. These signals provide the first direct evidence of credential validation attempts.
The final data collection phase moves to the cloud control plane. The hunt uses AWS IAM Access Advisor to find principals that recently accessed a broad range of discovery-related services, including IAM, S3, Secrets Manager, and RDS. By filtering for the specific principals involved in the suspicious sign-ins found earlier, the hunt highlights identities exhibiting unusual enumeration patterns.
An automated agent then correlates these independent signals. It looks for a sequence where a host running a vulnerable package connects to a known-bad IP, followed by an AWS identity from that same IP performing wide-scale service discovery. This correlation allows an analyst to distinguish between legitimate developer activity and a compromise.
What the hunt cannot see
This hunt relies on AWS IAM Access Advisor, which indicates whether a service was accessed but does not provide object-level details. We cannot see exactly which S3 objects or Secrets Manager values the adversary retrieved through these queries. To determine the full extent of data exfiltration, an analyst must perform a follow-up forensic audit of CloudTrail logs. Additionally, if the adversary rotates to a fresh VPN exit node not included in our known IP list, the hunt relies on the rarity of the authentication origin rather than a direct threat intelligence match.
Steps
-
Affected supply chain package inventory
Query · scopingIdentify hosts that have the packages targeted by TeamPCP installed, as these are the likely sources of stolen credentials.
reads hb_software_inventorysqlSELECT DISTINCT device_hostname, package_name, package_version FROM hb_software_inventory WHERE LOWER(package_name) IN ('trivy', 'kics', 'litellm', 'telnyx')What a hit looks like. A list of hosts running the vulnerable scanners or libraries. The analyst uses the resulting hostnames to populate the scope_hosts parameter in the offensive-tool-traffic query.
-
Rare and known-bad authentication origins
Query · baselineFind authentications originating from the reported TeamPCP IPs or other rare sources that only access a few accounts.
reads hb_auth_signinsqlSELECT src_endpoint_ip, actor_user_name, COUNT(*) AS auth_events, MIN(time) AS first_auth FROM hb_auth_signin WHERE (instr(',' || '{{teampcp_ips}}' || ',', ',' || src_endpoint_ip || ',') > 0 OR time >= datetime('now', '-1 days')) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY src_endpoint_ip, actor_user_name HAVING auth_events > 0 ORDER BY auth_events DESCWhat a hit looks like. Authentication attempts from TeamPCP IPs or suspicious one-off IPs. The analyst uses these identities to populate the compromised_principals parameter for service reconnaissance.
-
TruffleHog and Kali tool signatures
Query · detection candidateIdentify network traffic containing signatures of offensive tools used for credential validation, scoped to the vulnerable scanner hosts.
reads hb_http_activitysqlSELECT device_hostname, user_agent, url_hostname, src_endpoint_ip, time FROM hb_http_activity WHERE (LOWER(user_agent) LIKE '%trufflehog%' OR LOWER(user_agent) LIKE '%kali%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') ORDER BY time DESCWhat a hit looks like. Direct hits on TruffleHog or Kali-based Boto3 user agents originating from hosts in the environment or reaching out to cloud APIs.
-
AWS IAM service enumeration
Query · enrichmentFind AWS principals that have recently authenticated to multiple discovery-related services, specifically filtering for principals involved in the suspicious authentication events.
reads aws_iam_access_advisorsqlSELECT principal_arn, service_name, last_authenticated FROM aws_iam_access_advisor WHERE ('{{compromised_principals}}' = '' OR instr(',' || '{{compromised_principals}}' || ',', ',' || principal_arn || ',') > 0) AND last_authenticated >= datetime('now', '-{{lookback_days}} days') AND LOWER(service_name) IN ('iam', 'ec2', 's3', 'ecs', 'secretsmanager', 'lambda', 'rds', 'route53')What a hit looks like. A principal that has recently accessed several discovery services in a short window. The agent will weigh if this principal is also linked to suspicious IPs or user agents.
-
Triage validation and discovery
Agent triageCorrelate the inventory presence, suspicious network origins, and cloud service enumeration to confirm a post-compromise scenario.
-
Route based on investigation verdict
DecisionAutomate containment if the agent finds clear evidence of credential abuse.
-
Revoke compromised IAM identities
Response actionHalt the adversary progress by deactivating the credentials they are using for enumeration.
-
Forensic audit of AWS activity
Analyst taskPerform a deep dive into the actions taken by the compromised principal that automated queries cannot fully capture.
-
Close out
Analyst taskFinalize the hunt for a negative result.
Coverage
Scenario coverage
| Stage | Covered | How, or why not |
|---|---|---|
| Automated credential validation via TruffleHog T1078 |
Yes | rare-auth-origins, offensive-tool-traffic |
| Cloud and identity enumeration T1087 · T1082 · T1083 |
Yes | iam-service-recon |
| Supply chain compromise of developer tools T1195 |
Out of scope | This stage focuses on the initial injection into the target repositories, which is covered by vulnerability scanning and artifact integrity hunts. |
| Malicious GitHub workflow execution T1059.007 |
Out of scope | Belongs to another part of the 'Tracking TeamPCP: post-compromise attacks seen in the wild' series. |
| Interactive container access via ECS Exec T1609 |
Out of scope | Belongs to another part of the 'Tracking TeamPCP: post-compromise attacks seen in the wild' series. |
| Mass exfiltration from repositories and cloud storage T1041 · T1021.001 |
Out of scope | Belongs to another part of the 'Tracking TeamPCP: post-compromise attacks seen in the wild' series. |
Blind spots
- Needs detailed CloudTrail and aws_iam_access_advisor. While Access Advisor shows that a service was accessed, it does not detail which specific high-value secrets were retrieved, masking the extent of data exfiltration. It would answer which specific secrets or objects were accessed in S3 and Secrets Manager.
- Needs fresh IP intelligence for VPN exit nodes. The prevalence check helps find rare IPs, but a sophisticated attacker rotating IPs rapidly may evade detection if the baseline is not sufficiently narrow. It would answer whether the adversary has rotated to a new VPN node not in the known list.
Parameters & data
Parameters
| Parameter | Type | Default | What it is |
|---|---|---|---|
compromised_principals | list[string] | — | Identities discovered in the authentication step to narrow the service access search. |
lookback_days | number | 14 | Days of history to examine for post-compromise activity. |
scope_hosts | list[host] | — | Hostnames discovered in the inventory step to narrow the HTTP signature search. |
teampcp_ips | list[ip] | 105.245.181.120, 138.199.15.172, 154.47.29.12, 163.245.223.12, 170.62.100.245, 185.77.218.4, 193.32.126.157, 209.159.147.239, 23.234.107.104, 34.205.27.48 | Known TeamPCP IP addresses and VPN exit nodes. |
Telemetry
| Source | Category | Telemetry |
|---|---|---|
| Endpoint telemetry (hb_ surfaces) | endpoint | endpoint |
| Identity / sign-in telemetry | identity | identity |
| Web server / proxy logs | siem | network |
Source
---
analysis: A standard rule might detect a single malicious IP or user agent; this hunt
correlates the host-side presence of specific packages with the cloud-side behavior
of credential validation and broad discovery, which allows for a much more confident
triage of valid-account abuse.
blind_spots:
- id: missing-aws-audit-visibility
question: which specific secrets or objects were accessed in S3 and Secrets Manager
requires: detailed CloudTrail and aws_iam_access_advisor
risk: While Access Advisor shows that a service was accessed, it does not detail
which specific high-value secrets were retrieved, masking the extent of data exfiltration.
stage: cloud-infrastructure-discovery
- id: ip-rotation-mullvad
question: whether the adversary has rotated to a new VPN node not in the known list
requires: fresh IP intelligence for VPN exit nodes
risk: The prevalence check helps find rare IPs, but a sophisticated attacker rotating
IPs rapidly may evade detection if the baseline is not sufficiently narrow.
stage: credential-validation-trufflehog
coverage:
- stage: credential-validation-trufflehog
status: covered
steps:
- rare-auth-origins
- offensive-tool-traffic
- stage: cloud-infrastructure-discovery
status: covered
steps:
- iam-service-recon
- reason: This stage focuses on the initial injection into the target repositories,
which is covered by vulnerability scanning and artifact integrity hunts.
stage: initial-access-supply-chain
status: out_of_scope
- reason: 'Belongs to another part of the ''Tracking TeamPCP: post-compromise attacks
seen in the wild'' series.'
stage: github-workflow-abuse
status: out_of_scope
- reason: 'Belongs to another part of the ''Tracking TeamPCP: post-compromise attacks
seen in the wild'' series.'
stage: container-command-execution
status: out_of_scope
- reason: 'Belongs to another part of the ''Tracking TeamPCP: post-compromise attacks
seen in the wild'' series.'
stage: bulk-data-exfiltration
status: out_of_scope
guardrails:
claims: no_unsupported
evidence: citation_required
missing_data: not_benign
telemetry: untrusted
hunt:
applicability: campaign-specific
handoff: keep-as-periodic-hunt
justification: TeamPCP uses supply chain compromises to harvest secrets that are
then validated and abused within hours. Identifying this enumeration phase prevents
massive exfiltration of repository contents and database information.
methodology: model-assisted
trigger: intel-report
hypothesis: An adversary validates stolen cloud credentials and enumerates cloud infrastructure
using offensive tools like TruffleHog or specialized Boto3 scripts following a supply
chain compromise.
labels:
- hunt
- attack.t1078
- attack.t1087
- attack.t1082
- attack.t1083
- attack.t1090.003
- attack.t1195
name: TeamPCP Credential Validation and Discovery
parameters:
compromised_principals:
default: []
description: Identities discovered in the authentication step to narrow the service
access search.
type: list[string]
lookback_days:
default: '14'
description: Days of history to examine for post-compromise activity.
type: number
scope_hosts:
default: []
description: Hostnames discovered in the inventory step to narrow the HTTP signature
search.
type: list[host]
teampcp_ips:
default:
- 105.245.181.120
- 138.199.15.172
- 154.47.29.12
- 163.245.223.12
- 170.62.100.245
- 185.77.218.4
- 193.32.126.157
- 209.159.147.239
- 23.234.107.104
- 34.205.27.48
description: Known TeamPCP IP addresses and VPN exit nodes.
from:
kind: article
observed: '2024-03-27'
ref: https://www.wiz.io/blog/tracking-teampcp-investigating-post-compromise-attacks-seen-in-the-wild
type: list[ip]
provenance:
authors:
- name: Huntbase hunt generation
org: huntbase.io
generated:
by: huntbase-hunt-generation
from: https://www.wiz.io/blog/tracking-teampcp-investigating-post-compromise-attacks-seen-in-the-wild
gates:
- dry-run
- lint
model: hb_google/gemini-3-flash-preview
rationale: First identify build servers, CI/CD runners, and developer workstations
where Trivy or KICS might be installed. These are the highest probability targets
for initial secret harvesting.
references:
- name: 'Tracking TeamPCP: post-compromise attacks seen in the wild'
url: https://www.wiz.io/blog/tracking-teampcp-investigating-post-compromise-attacks-seen-in-the-wild
related:
- hunt: github-supply-chain-workflow-abuse
reason: Abuse of GitHub Actions and PATs for code execution and repository cloning
belongs to a sibling hunt focusing on the VCS plane.
relation: out-of-scope-alternative
scenario:
stages:
- name: Supply chain compromise of developer tools
observables:
- Malicious versions of Trivy, KICS, LiteLLM, and Telnyx packages
- Injected code in GitHub Actions and container images
- 'Targeted projects: Aqua Security Trivy, Checkmarx KICS, LiteLLM PyPI'
slug: initial-access-supply-chain
tactic: initial-access
techniques:
- T1195
- name: Automated credential validation via TruffleHog
observables:
- sts:GetCallerIdentity API calls
- 'User agent: Trufflehog'
- 'Source IPs: 105.245.181.120, 185.77.218.4, 209.159.147.239, 23.234.107.104,
34.205.27.48'
- Mullvad VPN exit nodes
- InterServer VPS hosts
slug: credential-validation-trufflehog
tactic: initial-access
techniques:
- T1078
- name: Cloud and identity enumeration
observables:
- 'IAM: ListUsers, ListRoles, ListAttachedUserPolicies'
- 'EC2: DescribeInstances'
- 'S3: ListBuckets, GetBucketPublicAccessBlock'
- 'Secrets Manager: ListSecrets'
- 'ECS: ListClusters, ListTaskDefinitions'
- 'User agent: Boto3/1.42.73 md/Botocore#1.42.73 ua/2.1 os/linux#6.17.10+kali-amd64'
- 'Resource names: pawn, massive-exfil'
slug: cloud-infrastructure-discovery
tactic: discovery
techniques:
- T1087
- T1082
- T1083
- name: Malicious GitHub workflow execution
observables:
- Creation of pull requests with malicious workflows
- 'Tool: Nord Stream'
- 'Branch name: dev_remote_ea5Eu/test/v1'
- Deletion of workflow logs
- 'Source IP: 138.199.15.172'
- 'Source IP: 163.245.223.12'
slug: github-workflow-abuse
tactic: persistence
techniques:
- T1059.007
- name: Interactive container access via ECS Exec
observables:
- ExecuteCommand calls on ECS tasks
- Execution of Bash commands and Python scripts via SSM Agent
- Execution from SSMSession context
slug: container-command-execution
tactic: execution
techniques:
- T1609
- name: Mass exfiltration from repositories and cloud storage
observables:
- Mass git.clone operations
- 'User agent: git/2.43.0'
- Bulk GetSecretValue from Secrets Manager
- Bulk GetObject from S3 buckets
- 'Source IP: 193.32.126.157'
slug: bulk-data-exfiltration
tactic: exfiltration
techniques:
- T1041
- T1021.001
summary: TeamPCP conducts supply chain attacks against developer tools and libraries
(Trivy, KICS, LiteLLM) to harvest cloud credentials and CI/CD secrets. Following
theft, the actor rapidly validates credentials using TruffleHog and explores victim
AWS and GitHub environments to exfiltrate bulk data or execute commands via ECS
Exec and malicious workflows.
series:
index: 1
slug: tracking-teampcp-post-compromise-attacks-seen-in-the-wild
title: 'Tracking TeamPCP: post-compromise attacks seen in the wild'
total: 2
severity: high
targets:
analyst:
name: Tier-2 analyst
role: analyst
aws:
category: siem
huntbase:
product: aws
name: aws
endpoint:
category: endpoint
name: Endpoint telemetry (hb_ surfaces)
telemetry:
- endpoint
hunter:
agent: true
name: Hunt agent
identity:
category: identity
name: Identity / sign-in telemetry
telemetry:
- identity
web:
category: siem
name: Web server / proxy logs
telemetry:
- network
tlp: clear
type: investigation
---
# TeamPCP Credential Validation and Discovery
The adversary validates stolen cloud credentials and enumerates cloud infrastructure using offensive tools like TruffleHog or Boto3 scripts. This hunt targets the early post-compromise activity of TeamPCP by identifying hosts running compromised software, then looks for signs of credential validation and broad AWS infrastructure enumeration. By correlating the presence of the compromised software with anomalous cloud-side activity and known malicious IPs, the analyst identifies where secrets have been harvested and used.
## find-potential-beachheads
<!-- Affected supply chain package inventory -->
Identify hosts that have the packages targeted by TeamPCP installed, as these are the likely sources of stolen credentials.
```sqlite target=endpoint role=scoping
~~~yaml
expected: A list of hosts running the vulnerable scanners or libraries. The analyst
uses the resulting hostnames to populate the scope_hosts parameter in the offensive-tool-traffic
query.
reads:
- device_hostname
- package_name
- package_version
silence: not_evidence_of_absence
source: hb_software_inventory
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT DISTINCT device_hostname, package_name, package_version FROM hb_software_inventory WHERE LOWER(package_name) IN ('trivy', 'kics', 'litellm', 'telnyx')
```
## parallel-leads
<!-- Fan-out to cloud and network evidence -->
parallel:
- → rare-auth-origins
- → offensive-tool-traffic
- → iam-service-recon
join: → investigation-agent
## rare-auth-origins
<!-- Rare and known-bad authentication origins -->
Find authentications originating from the reported TeamPCP IPs or other rare sources that only access a few accounts.
```sqlite target=identity role=baseline params=(teampcp_ips=teampcp_ips, lookback_days=lookback_days)
~~~yaml
baseline:
compare: new_this_window
window: 1d
expected: Authentication attempts from TeamPCP IPs or suspicious one-off IPs. The
analyst uses these identities to populate the compromised_principals parameter for
service reconnaissance.
prevalence:
by: actor_user_name
key:
- src_endpoint_ip
rare_below: 2
reads:
- src_endpoint_ip
- actor_user_name
- time
silence: not_evidence_of_absence
source: hb_auth_signin
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT src_endpoint_ip, actor_user_name, COUNT(*) AS auth_events, MIN(time) AS first_auth FROM hb_auth_signin WHERE (instr(',' || '{{teampcp_ips}}' || ',', ',' || src_endpoint_ip || ',') > 0 OR time >= datetime('now', '-1 days')) AND time >= datetime('now', '-{{lookback_days}} days') GROUP BY src_endpoint_ip, actor_user_name HAVING auth_events > 0 ORDER BY auth_events DESC
```
## offensive-tool-traffic
<!-- TruffleHog and Kali tool signatures -->
Identify network traffic containing signatures of offensive tools used for credential validation, scoped to the vulnerable scanner hosts.
```sqlite target=web role=detection-candidate params=(lookback_days=lookback_days, scope_hosts=scope_hosts)
~~~yaml
expected: Direct hits on TruffleHog or Kali-based Boto3 user agents originating from
hosts in the environment or reaching out to cloud APIs.
reads:
- device_hostname
- user_agent
- url_hostname
- src_endpoint_ip
- time
silence: not_evidence_of_absence
source: hb_http_activity
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT device_hostname, user_agent, url_hostname, src_endpoint_ip, time FROM hb_http_activity WHERE (LOWER(user_agent) LIKE '%trufflehog%' OR LOWER(user_agent) LIKE '%kali%') AND ('{{scope_hosts}}' = '' OR instr(',' || '{{scope_hosts}}' || ',', ',' || device_hostname || ',') > 0) AND time >= datetime('now', '-{{lookback_days}} days') ORDER BY time DESC
```
## iam-service-recon
<!-- AWS IAM service enumeration -->
Find AWS principals that have recently authenticated to multiple discovery-related services, specifically filtering for principals involved in the suspicious authentication events.
```sqlite target=aws role=enrichment params=(lookback_days=lookback_days, compromised_principals=compromised_principals)
~~~yaml
expected: A principal that has recently accessed several discovery services in a short
window. The agent will weigh if this principal is also linked to suspicious IPs
or user agents.
reads:
- principal_arn
- service_name
- last_authenticated
silence: not_evidence_of_absence
source: aws_iam_access_advisor
verified: dry-run
verified_at: '2026-09-20'
~~~
SELECT principal_arn, service_name, last_authenticated FROM aws_iam_access_advisor WHERE ('{{compromised_principals}}' = '' OR instr(',' || '{{compromised_principals}}' || ',', ',' || principal_arn || ',') > 0) AND last_authenticated >= datetime('now', '-{{lookback_days}} days') AND LOWER(service_name) IN ('iam', 'ec2', 's3', 'ecs', 'secretsmanager', 'lambda', 'rds', 'route53')
```
## investigation-agent
<!-- Triage validation and discovery -->
```agent target=hunter
cite: required
context:
- find-potential-beachheads
- rare-auth-origins
- offensive-tool-traffic
- iam-service-recon
max_iterations: 6
objective: Determine if any identities or hosts show signs of TeamPCP post-compromise
activity, specifically looking for broad discovery (IAM, S3, Secrets Manager) linked
to validation signatures or known-bad IPs.
success_criteria: A verdict of malicious | suspicious | benign per host/principal,
citing specific rows for service enumeration and IP/UA matches.
tools:
- aws
- endpoint
- identity
- web
```
## route-on-triage
<!-- Route based on investigation verdict -->
if~: "the agent verdict is malicious for at least one AWS principal or host" (confidence: high, judge=hunter)
then: → revoke-compromised-identities
indeterminate: → manual-forensic-review
unavailable: → manual-forensic-review (blind_spot: missing-aws-audit-visibility)
else: → close-out
## revoke-compromised-identities
<!-- Revoke compromised IAM identities -->
```action target=identity
~~~yaml
approval: required
~~~
Revoke the IAM access keys or temporary credentials for the principals identified by the agent. Disable the user or role until a full forensic audit is complete.
```
→ manual-forensic-review
## manual-forensic-review
<!-- Forensic audit of AWS activity -->
```manual target=analyst
Examine AWS CloudTrail for the identified principals. Look for high-volume S3 GetObject, SecretsManager GetSecretValue, and RDS snapshot events. Search for IPs outside the parameter list that exhibit the same pattern.
```
→ end
## close-out
<!-- Close out -->
```manual target=analyst
Record that no evidence of TeamPCP post-compromise validation or discovery was found. Schedule a re-run for next month.
```
→ 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.