Comment by antihero

3 days ago

Attack is called "Hades - The End for the Damned", it exfiltrates secrets including ALL ORG GITHUB ACTIONS SECRETS via creating compromised actions, through GitHub public repos with encrypted payloads.

If you're saying it only impacts public repos, I don't think that's quite right. It appears to impact private ones as well. Source: first-hand experience. If you're claiming that the only export vector is via public repos then I can't refute that. But just trying to clarify here.

And after a quick glance I'm not seeing any correlation between "Hades - The End for the Dammed" and this worm; would also love a source for this claim.

  • Nope, the public repos are what the on-machine payload creates. Sorry, I worded that wrong, I meant it exfiltrates to.

    The main attack is using compromised repo keys to:

    * Create malicious actions to JSON dump and exfiltrate all GitHub org secrets.

    * Commit the payload delivering hooks/scripts to any repo/PR it has access to.

    * Mimics previous commits/timestamps, however you can see the key that did it by seeing the push in activity/audit logs.

  • Take the JS file and decode it!

    Decoded execution chain ----------------------- 1. Outer layer: - Starts with try{eval(function(s,n){...})([large numeric array].map(...).join(""),1)) - Converts numeric character codes into a string. - Applies a Caesar +1 shift to alphabetic characters. - eval() executes the decoded layer.

    2. First decoded layer: - Imports node:crypto. - Defines an AES-128-GCM decryptor. - Decrypts two embedded payloads: a) _b: small Bun bootstrap/loader b) _p: large obfuscated payload (~686 KB) - Writes _p to a temporary JS file under /tmp/p<random>.js. - If Bun is available, runs: bun run "<temp file>" - If Bun is unavailable, downloads Bun from GitHub releases and then runs the payload.

    3. Small loader payload: - Downloads Bun v1.3.13 from: https://github.com/oven-sh/bun/releases/download/bun-v1.3.13... - Uses curl and unzip. - Creates temporary directories under /tmp/b-* - Runs the large payload using Bun.

    4. Large payload: - Obfuscated JavaScript with a string-table decoder and a second custom encrypted string layer. - After decoding strings, the payload clearly contains credential and secret collection logic.

    Observed behaviour / capabilities --------------------------------- The payload appears to collect or search for: - GitHub tokens / PATs / GitHub Actions OIDC tokens - npm tokens and npm OIDC package exchange tokens - RubyGems API keys - AWS credentials, STS metadata credentials and Secrets Manager secrets - Azure credentials, service principals and Key Vault secrets - GCP service account tokens and Secret Manager secrets - Vault tokens and Vault secrets - Kubernetes service account tokens and kubeconfig - Docker credentials - SSH keys and config - Git credentials - .env files and common project secrets - Claude configuration and project files - OnePassword items via the op CLI - Slack, Discord, Signal, Telegram and Element local data - Crypto wallet files such as Exodus, Ledger Live, Ethereum keystores and Monero data - Shell and database history files

    Exfiltration / persistence style -------------------------------- The payload contains logic to: - Create or use GitHub repositories through GitHub API endpoints. - Commit collected data/content into repository files. - Add/update files such as: - .vscode/tasks.json - .claude/index.js - .claude/settings.json - .claude/setup.mjs - .vscode/setup.mjs - Use commit messages such as: - chore: update dependencies - create del-commit: - Create a GitHub repo with description: - Hades - The End for the Damned - Use api.anthropic.com with path v1/api as an apparent outbound endpoint. - Use a token/string: - IfYouYankThisTokenItWillNukeTheComputerOfTheOwnerFully

    Notable URLs / endpoints ------------------------ - https://api.github.com - https://api.github.com/graphql - https://github.com/ - https://github.com/actions/runner - https://github.com/oven-sh/bun/releases/download/bun-v1.3.13... - https://registry.npmjs.org/ - https://registry.npmjs.org/-/npm/v1/oidc/token/exchange/pack... - https://registry.npmjs.org/-/npm/v1/tokens - https://registry.npmjs.org/-/whoami - https://rubygems.org/api/v1/api_key.json - https://rubygems.org/api/v1/gems - https://cloudresourcemanager.googleapis.com/v1 - https://secretmanager.googleapis.com/v1 - https://graph.microsoft.com/v1.0/me - https://login.microsoftonline.com/ - https://vault.azure.net/.default - http://169.254.169.254/latest/api/token - http://169.254.169.254/latest/meta-data/iam/security-credent... - http://169.254.170.2 - http://127.0.0.1:8200 - api.anthropic.com / v1/api

    Files/globs targeted -------------------- - */.env - */.env.local - */.env.production - */.git/config - */config/database.yml - */wp-config.php - .env - .git-credentials - .npmrc - ~/.npmrc - ~/.pypirc - ~/.yarnrc - ~/.aws/config - ~/.aws/credentials - ~/.azure/accessTokens.json - ~/.azure/msal_token_cache.* - ~/.config/gcloud/access_tokens.db - ~/.config/gcloud/application_default_credentials.json - ~/.config/gcloud/credentials.db - ~/.docker/config.json - ~/.docker//config.json - /root/.docker/config.json - ~/.kube/config - /etc/rancher/k3s/k3s.yaml - /var/run/secrets/kubernetes.io/serviceaccount/token - ~/.terraform.d/credentials.tfrc.json - ~/.ssh/id - ~/.ssh/id_rsa - ~/.ssh/id_ed25519 - ~/.ssh/id_ecdsa - ~/.ssh/config - ~/.ssh/known_hosts - ~/.gitconfig - ~/.config/git/credentials - ~/.netrc - ~/.bash_history - ~/.zsh_history - ~/.python_history - ~/.psql_history - ~/.mysql_history - ~/.claude.json - ~/.claude/* - ~/.claude/projects/* - ~/.claude/mcp.json - %USERPROFILE%\.claude.json - %USERPROFILE%\.claude* - ~/.config/Slack/Cookies - ~/.config/discord/Local Storage/leveldb/* - ~/.config/Signal/* - ~/.local/share/TelegramDesktop/tdata/* - ~/.config/Element/Local Storage/* - ~/.config/Exodus/exodus.wallet/* - ~/.config/Ledger Live/* - ~/.ethereum/keystore/* - ~/.monero/* - ~/.local/share/keyrings/.keyring - ~/.kde/share/apps/kwallet/.kwl - ~/.config/filezilla/sitemanager.xml - ~/.config/filezilla/recentservers.xml

    Environment variables checked ----------------------------- - GITHUB_ACTIONS - GITHUB_REPOSITORY - GITHUB_REF - ACTIONS_ID_TOKEN_REQUEST_URL - ACTIONS_ID_TOKEN_REQUEST_TOKEN - TARGET_REPOS - AWS_ACCESS_KEY_ID - AWS_SECRET_ACCESS_KEY - AWS_SESSION_TOKEN - AWS_PROFILE - AWS_REGION - AWS_DEFAULT_REGION - AWS_WEB_IDENTITY_TOKEN_FILE - AWS_CONTAINER_CREDENTIALS_RELATIVE_URI - AWS_CONTAINER_CREDENTIALS_FULL_URI - AWS_CONTAINER_AUTHORIZATION_TOKEN - AZURE_TENANT_ID - AZURE_CLIENT_ID - AZURE_CLIENT_SECRET - AZURE_FEDERATED_TOKEN_FILE - AZURE_KEY_VAULT_NAME - GOOGLE_APPLICATION_CREDENTIALS - GOOGLE_CLOUD_PROJECT - GCP_PROJECT - GCLOUD_PROJECT - KUBECONFIG - VAULT_ADDR - VAULT_API_TOKEN - VAULT_TOKEN_FILE - VAULT_TOKEN_PATH - VAULT_AWS_ROLE - VAULT_ROLE - HOME - USERPROFILE - LANG / LANGUAGE / LC_ALL / LC_MESSAGES (edited)