TeamPCP Used Malicious Telnyx Python SDK Versions to Steal Credentials

· Original article ↗

Summary

A technical report says TeamPCP uploaded malicious telnyx Python SDK versions 4.87.1 and 4.87.2 to PyPI. The packages triggered credential theft and persistent payloads across Windows, Linux, macOS, and Kubernetes environments before PyPI quarantined them.

Key points

  • The malicious versions were uploaded directly to PyPI using a valid publishing token and were not present in the project’s source repository; PyPI quarantined them after about four hours.
  • Importing the affected package triggered platform-specific loaders, which retrieved payloads concealed in WAV files or embedded in the package.
  • The report says the payloads targeted cloud, SSH, Kubernetes, database, CI/CD, and cryptocurrency secrets, then encrypted and exfiltrated collected data.
  • In Kubernetes environments, the harvester could use service-account tokens to access cluster secrets and deploy privileged pods that installed persistent backdoors on nodes.
  • The Windows payload used a Startup-folder dropper and a RAT; the report describes NTDLL unhooking, ETW patching, and process injection.
  • The report links the activity to TeamPCP through shared tooling and an RSA public-key fingerprint, and describes related compromises involving Trivy, Checkmarx, LiteLLM, and npm packages.
  • Organizations that installed the affected versions are advised to investigate, rotate exposed credentials, check for persistence, and review downstream systems.

Article Details

Attack Vectors
  • TeamPCP uploaded trojanized telnyx Python SDK versions 4.87.1 and 4.87.2 directly to PyPI using a valid PyPI token; the versions were not published in the source repository.
  • Importing the compromised package executes platform-specific loader code without further user interaction.
  • The loaders retrieve payloads concealed in WAV audio data; the Windows payload extracts a PE, while the Linux/macOS path runs a Python loader that retrieves a credential harvester.
  • The harvester collects credentials and secrets from files, environment variables, cloud metadata, and Kubernetes, then encrypts and exfiltrates collected data to C2 infrastructure.
  • With Kubernetes service-account tokens, the harvester retrieves cluster secrets and creates privileged pods on nodes to deploy a persistent systemd backdoor.
  • The Windows RAT uses early-bird APC process injection into dllhost.exe and communicates with C2 over HTTP.
Defensive Notes
  • Treat environments that installed telnyx 4.87.1 or 4.87.2 as potentially breached; investigate and rotate exposed credentials, tokens, keys, certificates, and secrets.
  • Block the reported C2 indicators and alert on outbound HTTP POST requests with the X-Filename: tpcp.tar.gz header.
  • Investigate HTTP WAV downloads from bare IP addresses on non-standard ports, and monitor for the reported Startup-folder, sysmon.py, and systemd persistence artifacts.
  • In Kubernetes, review privileged pods with hostPID, hostNetwork, or host filesystem mounts; restrict service-account access to cluster secrets and privileged pod creation.
  • Use short-lived, scoped publishing credentials and trusted publishers; inventory dependencies and avoid installing packages in environments with mounted production credentials.
  • Removing the compromised package alone may not remove persistence; inspect affected hosts and cluster nodes for the backdoor artifacts described in the article.

Indicators of compromise

TypeIndicatorContext
DOMAINcheckmarx[.]zoneC2 domain used for persistent-backdoor polling and listed campaign endpoints.
DOMAINmodels[.]litellm[.]cloudLiteLLM typosquat domain used as an exfiltration endpoint.
DOMAINscan[.]aquasecurtiy[.]orgTyposquat domain listed as the Trivy RAT variant's C2.
DOMAINtdtqy-oyaaa-aaaae-af2dq-cai[.]raw[.]icp0[.]ioICP blockchain canister C2 domain listed for CanisterWorm.
IPV445[.]148[.]10[.]212C2 IP listed for the Trivy RAT variant.
IPV483[.]142[.]209[.]11Resolved IP for checkmarx.zone, identified as C2 infrastructure.
IPV483[.]142[.]209[.]203Primary TeamPCP C2 used for payload delivery and exfiltration.
SHA256196b5e0e06424a02e360e28e08d7dcfab7ec8946af9477ca352c6cf6b7d4e9bdHash of the inner PE RAT extracted from the PNG carrier.
SHA25623b1ec58649170650110ecad96e5a9490d98146e105226a16d898fbe108139e5Hash of malicious _client.py from telnyx 4.87.1.
SHA256485952ba5347aa83f00537a4be0bebb274021f773a0203b65142f1b86dfda34dHash of a RAT dropper libcurl.dll variant listed with C2 45.148.10.212.
SHA2564eceb569b4330565b93058465beab0e6d5ea09cfba8e7f29d7be1b5a2abd958aHash of the RSA-4096 public key in PEM format, listed as a cross-campaign indicator.
SHA2565ce544a8db5d0b0953c966384858e4e8a017e7acba2f5f6d0ac8f529d59939d8Hash of the decoded Stage 3 credential harvester.
SHA2566cf223aea68b0e8031ff68251e30b6017a0513fe152e235c26f248ba1e15c92aHash of the sysmon.py persistence backdoor.
SHA2567290353a3bc2b18e9ea574d3294b09e28edaa6b038285bb101cf09760f187dcdHash of the malicious Windows msbuild.exe outer PE loader.
SHA2567321caa303fe96ded0492c747d2f353c4f7d17185656fe292ab0a59e2bd0b8d9Hash of malicious telnyx 4.87.1 wheel.
SHA2568395c3268d5c5dbae1c7c6d4bb3c318c752ba4608cfcd90eb97ffb94a910eac2Hash of a malicious LiteLLM 1.82.7 wheel listed as a cross-campaign package.
SHA25684edce66f09c55bbb44754411bde4b092288d172734df62fac20d6f794b3a2ecHash of the decoded Linux Stage 2 loader.
SHA2568eaf4c4d0b82620bcda29b97896e2da0a754205c035721479f7ceafb817e4466Hash of the Stage 3 harvester and loader wrapper.
SHA256a585277a67a176fe098edf90986670653a5039e03e4028d18dd0b607ed287caaHash of a RAT dropper DLL variant listed with C2 45.148.10.212.
SHA256a9235c0eb74a8e92e5a0150e055ee9dcdc6252a07785b6677a9ca831157833a5Hash of malicious telnyx 4.87.2 source archive.
SHA256ab4c4aebb52027bf3d2f6b2dcef593a1a2cff415774ea4711f7d6e0aa1451d4eHash of malicious _client.py from telnyx 4.87.2.
SHA256bc40e5e2c438032bac4dec2ad61eedd4e7c162a8b42004774f6e4330d8137ba8DER fingerprint of the RSA public key the article identifies as shared across TeamPCP campaign loaders.
SHA256cd08115806662469bbedec4b03f8427b97c8a4b3bc1442dc18b72b4e19395fe3Hash of malicious telnyx 4.87.2 wheel.
SHA256cd6af6c9ba149673ff89a1f1ccc8ec40a265a3b54ad455fbef28dc2967a98e45Hash of the CanisterWorm JavaScript variant listed among cross-campaign indicators.
SHA256d29deee2e8bec85d2fcaec427f17d677f7de4f8387e00566b0b45ff81157bd31Hash of a cross-campaign Python harvester Build B CRLF variant.
SHA256d2a0d5f564628773b6af7b9c11f6b86531a875bd2d186d7081ab62748a800ebbHash of a malicious LiteLLM 1.82.8 wheel listed as a cross-campaign package.
SHA256d6fc0ff06978742a2ef789304bcdbe69a731693ad066a457db0878279830d6a9Hash of a cross-campaign Python harvester variant identified as LiteLLM C2 Build B.
SHA256e4e3b176c1255666024d90392e09466a23bf6e8740bf589c6d1ccf2dfff451a4Hash of the position-independent shellcode stub used as a reflective PE loader.
SHA256e6912e3ec58120bf63edf2e4be6ff2f092c40cfbc655a12f4a463b2ef98d368eHash of the PNG steganographic payload carrier embedded in the Windows PE.
SHA256f66c1ea3b25ec95d0c6a07be92c761551e543a7b256f9c78a2ff781c77df7093Hash of malicious telnyx 4.87.1 source archive.
URLhxxp[:]//83[.]142[.]209[.]203:8080/C2 endpoint receiving exfiltration POSTs from Telnyx and LiteLLM variants.
URLhxxp[:]//83[.]142[.]209[.]203:8080/hangup[.]wavC2 URL serving the WAV-carried Windows PE payload.
URLhxxp[:]//83[.]142[.]209[.]203:8080/ringtone[.]wavC2 URL serving the WAV-carried Linux credential harvester.
URLhxxps[:]//checkmarx[.]zone/rawC2 polling URL used by sysmon.py to retrieve payload URLs.
URLhxxps[:]//checkmarx[.]zone/vsxExfiltration endpoint listed for the CanisterWorm JavaScript variant.
URLhxxps[:]//models[.]litellm[.]cloud/URL identified as a LiteLLM-variant exfiltration endpoint on a typosquat domain.

MITRE ATT&CK

T1005 · Data from Local SystemThe credential harvester collects secrets, configuration files, histories, and system information from infected hosts.T1027.003 · SteganographyPayloads are concealed in WAV audio data and a PNG embedded in the Windows PE, then decoded by the loaders.T1041 · Exfiltration Over C2 ChannelThe Linux loader sends the encrypted credential archive to C2 in an HTTP POST.T1055.004 · Asynchronous Procedure CallThe Windows loader queues shellcode as an APC in a suspended dllhost.exe process and resumes its thread.T1059.006 · PythonThe package runs Python loader code on import, including a decoded Python payload launched in a child process.T1071.001 · Web ProtocolsThe RAT beacons over HTTP, and sysmon.py polls an HTTP-accessible C2 URL for payloads.T1105 · Ingress Tool TransferThe loaders download WAV payloads and the persistent backdoor downloads follow-on binaries from C2.T1195.002 · Compromise Software Supply ChainTeamPCP used a valid PyPI token to publish trojanized versions of the telnyx Python SDK.T1543.002 · Systemd ServiceThe Kubernetes-deployed persistence script registers and starts a systemd user service on cluster nodes.T1547.001 · Registry Run Keys / Startup FolderThe Windows loader places msbuild.exe in the user's Startup folder for execution at login.T1552.001 · Credentials In FilesThe harvester searches files such as SSH keys, cloud credentials, Kubernetes configs, and environment files for secrets.T1552.005 · Cloud Instance Metadata APIThe harvester targets EC2 instance role credentials through the instance metadata service.T1562.001 · Disable or Modify ToolsThe Windows PE replaces loaded ntdll text with a clean copy and patches EtwEventWrite to impede endpoint monitoring.T1610 · Deploy ContainerWith Kubernetes service-account tokens, the harvester creates privileged pods across cluster nodes.T1611 · Escape to HostThe privileged pods mount the host root filesystem and use it to deploy persistence onto Kubernetes nodes.

Threat Actors

Vendors

Products

Countries

Related Articles