mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-04-28 03:53:07 -07:00
Add content from: Weaponizing the Protectors: TeamPCP’s Multi-Stage Supply Cha...
This commit is contained in:
@@ -464,6 +464,21 @@ If other repositories where using **dependencies from this user repos**, an atta
|
||||
|
||||
GitHub Actions still encourages consumers to reference `uses: owner/action@v1`. If an attacker gains the ability to move that tag—through automatic write access, phishing a maintainer, or a malicious control handoff—they can retarget the tag to a backdoored commit and every downstream workflow executes it on its next run. The reviewdog / tj-actions compromise followed exactly that playbook: contributors auto-granted write access retagged `v1`, stole PATs from a more popular action, and pivoted into additional orgs.
|
||||
|
||||
This becomes even more useful when the attacker **force-pushes many existing tags at once** (`v1`, `v1.2.3`, `stable`, etc.) instead of creating a new suspicious release. Downstream pipelines keep pulling a "trusted" tag, but the referenced commit now contains attacker code.
|
||||
|
||||
A common stealth pattern is to place the malicious code **before** the legitimate action logic and then continue executing the normal workflow. The user still sees a successful scan/build/deploy, while the attacker steals secrets in the prelude.
|
||||
|
||||
Typical attacker goals after tag poisoning:
|
||||
|
||||
- Read every secret already mounted in the job (`GITHUB_TOKEN`, PATs, cloud creds, package-publisher tokens).
|
||||
- Drop a **small loader** in the poisoned action and fetch the real payload remotely so the attacker can change behavior without re-poisoning the tag.
|
||||
- Reuse the first leaked publisher token to compromise npm/PyPI packages, turning one poisoned GitHub Action into a wider supply-chain worm.
|
||||
|
||||
**Mitigations**
|
||||
|
||||
- Pin third-party actions to a **full commit SHA**, not a mutable tag.
|
||||
- Protect release tags and restrict who can force-push or retarget them.
|
||||
- Treat any action that both "works normally" and unexpectedly performs network egress / secret access as suspicious.
|
||||
|
||||
---
|
||||
|
||||
@@ -650,6 +665,16 @@ jobs:
|
||||
|
||||
Tip: for stealth during testing, encrypt before printing (openssl is preinstalled on GitHub-hosted runners).
|
||||
|
||||
- GitHub log masking only protects rendered output. If the runner process already holds plaintext secrets, an attacker can sometimes recover them directly from the **runner worker process memory**, bypassing masking entirely. On Linux runners, look for `Runner.Worker` / `runner.worker` and dump its memory:
|
||||
|
||||
```bash
|
||||
PID=$(pgrep -f 'Runner.Worker|runner.worker')
|
||||
sudo gcore -o /tmp/runner "$PID"
|
||||
strings "/tmp/runner.$PID" | grep -E 'gh[pousr]_|AKIA|ASIA|BEGIN .*PRIVATE KEY'
|
||||
```
|
||||
|
||||
The same idea applies to procfs-based memory access (`/proc/<pid>/mem`) when permissions allow it.
|
||||
|
||||
### Systematic CI token exfiltration & hardening
|
||||
|
||||
Once an attacker’s code executes inside a runner, the next step is almost always to steal every long-lived credential in sight so they can publish malicious releases or pivot into sibling repos. Typical targets include:
|
||||
@@ -668,6 +693,39 @@ With a single leaked credential the attacker can retag GitHub Actions, publish w
|
||||
- Disable npm lifecycle hooks in CI (`npm config set ignore-scripts true`) so compromised dependencies can’t immediately run exfiltration payloads.
|
||||
- Scan release artifacts and container layers for embedded credentials before distribution, and fail builds if any high-value token materializes.
|
||||
|
||||
#### Package-manager startup hooks (`npm`, Python `.pth`)
|
||||
|
||||
If an attacker steals a publisher token from CI, the fastest follow-up is often to publish a malicious package version that executes **during install** or **at interpreter startup**:
|
||||
|
||||
- **npm**: add `preinstall` / `postinstall` to `package.json` so `npm install` executes attacker code immediately on developer laptops and CI runners.
|
||||
- **Python**: ship a malicious `.pth` file so code runs whenever the Python interpreter starts, even if the trojanized package is never explicitly imported.
|
||||
|
||||
Example npm hook:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"preinstall": "python3 -c 'import os;print(os.getenv(\"GITHUB_TOKEN\",\"\"))'"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Example Python `.pth` payload:
|
||||
|
||||
```python
|
||||
import base64,os;exec(base64.b64decode(os.environ["STAGE2_B64"]))
|
||||
```
|
||||
|
||||
Drop the line above into a file such as `evil.pth` inside `site-packages` and it will execute during Python startup. This is especially useful in build agents that continuously spawn Python tooling (`pip`, linters, test runners, release scripts).
|
||||
|
||||
#### Alternate exfil when outbound traffic is filtered
|
||||
|
||||
If direct exfiltration is blocked but the workflow still has a write-capable `GITHUB_TOKEN`, the runner can abuse GitHub itself as the transport:
|
||||
|
||||
- Create a private repository inside the victim org (for example, a throwaway `docs-*` repo).
|
||||
- Push stolen material as blobs, commits, releases, or issues/comments.
|
||||
- Use the repo as a fallback dead-drop until network egress returns.
|
||||
|
||||
### AI Agent Prompt Injection & Secret Exfiltration in CI/CD
|
||||
|
||||
LLM-driven workflows such as Gemini CLI, Claude Code Actions, OpenAI Codex, or GitHub AI Inference increasingly appear inside Actions/GitLab pipelines. As shown in [PromptPwnd](https://www.aikido.dev/blog/promptpwnd-github-actions-ai-agents), these agents often ingest untrusted repository metadata while holding privileged tokens and the ability to invoke `run_shell_command` or GitHub CLI helpers, so any field that attackers can edit (issues, PRs, commit messages, release notes, comments) becomes a control surface for the runner.
|
||||
@@ -732,6 +790,32 @@ The way to find which **Github Actions are being executed in non-github infrastr
|
||||
|
||||
**Self-hosted** runners might have access to **extra sensitive information**, to other **network systems** (vulnerable endpoints in the network? metadata service?) or, even if it's isolated and destroyed, **more than one action might be run at the same time** and the malicious one could **steal the secrets** of the other one.
|
||||
|
||||
They also frequently sit close to container build infrastructure and Kubernetes automation. After initial code execution, check for:
|
||||
|
||||
- **Cloud metadata** / OIDC / registry credentials on the runner host.
|
||||
- **Exposed Docker APIs** on `2375/tcp` locally or on adjacent builder hosts.
|
||||
- Local `~/.kube/config`, mounted service-account tokens, or CI variables containing cluster-admin credentials.
|
||||
|
||||
Quick Docker API discovery from a compromised runner:
|
||||
|
||||
```bash
|
||||
for h in 127.0.0.1 $(hostname -I); do
|
||||
curl -fsS "http://$h:2375/version" && echo "[+] Docker API on $h"
|
||||
done
|
||||
```
|
||||
|
||||
If the runner can talk to Kubernetes and has enough privileges to create or patch workloads, a malicious **privileged DaemonSet** can turn one CI compromise into cluster-wide node access. For the Kubernetes side of that pivot, check:
|
||||
|
||||
{{#ref}}
|
||||
../../../pentesting-cloud/kubernetes-security/attacking-kubernetes-from-inside-a-pod.md
|
||||
{{#endref}}
|
||||
|
||||
and:
|
||||
|
||||
{{#ref}}
|
||||
../../../pentesting-cloud/kubernetes-security/abusing-roles-clusterroles-in-kubernetes/
|
||||
{{#endref}}
|
||||
|
||||
In self-hosted runners it's also possible to obtain the **secrets from the \_Runner.Listener**\_\*\* process\*\* which will contain all the secrets of the workflows at any step by dumping its memory:
|
||||
|
||||
```bash
|
||||
@@ -817,7 +901,6 @@ An organization in GitHub is very proactive in reporting accounts to GitHub. All
|
||||
- [OpenGrep PromptPwnd detection rules](https://github.com/AikidoSec/opengrep-rules)
|
||||
- [OpenGrep playground releases](https://github.com/opengrep/opengrep-playground/releases)
|
||||
- [A Survey of 2024–2025 Open-Source Supply-Chain Compromises and Their Root Causes](https://words.filippo.io/compromise-survey/)
|
||||
- [Weaponizing the Protectors: TeamPCP’s Multi-Stage Supply Chain Attack on Security Infrastructure](https://unit42.paloaltonetworks.com/teampcp-supply-chain-attacks/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user