
Laboratório Docker reproduzível + exploit de raw-socket para CVE-2015-3306 (cópia arbitrária de arquivos pré-autenticação no mod_copy do ProFTPD) — um exercício de aprendizado de patch-diffing
Um laboratório totalmente reproduzível e um exploit escrito à mão para a CVE-2015-3306 — construído como exercício de aprendizado em pesquisa de vulnerabilidades: análise de patches, disparo manual e desenvolvimento de exploits via socket bruto.
O módulo mod_copy do ProFTPD implementa o par de comandos SITE CPFR / SITE CPTO,
que copia arquivos no lado do servidor sem transferir dados para o cliente.
Na versão 1.3.5, nenhum dos handlers verificava se a sessão estava autenticada. O módulo simplesmente assumia "ninguém enviará comandos SITE antes de fazer login" — uma suposição equivocada que virou uma CVE. Qualquer cliente não autenticado podia copiar qualquer arquivo legível pelo processo do servidor para qualquer local gravável por ele.
A correção (commit 212d54271f, lançado na 1.3.5a) faz duas coisas:
copy_cpfrcopy_cptoauthenticated = get_param_ptr(cmd->server->conf, "authenticated", FALSE);
if (authenticated == NULL || *authenticated == FALSE) {
pr_response_add_err(R_530, _("Please login with USER and PASS"));
errno = EPERM;
return PR_ERROR(cmd);
}
CopyEngine on|off — anteriormente o módulo nem podia
ser desabilitado em builds que o incluíam.O diff unificado completo está em patch.diff. Ler patches é a
habilidade: a correção mostra onde estava a ferida.
O Dockerfile compila o ProFTPD 1.3.5 (a última versão vulnerável) a partir do
tarball oficial da fonte com mod_copy habilitado:
docker build -t proftpd-135 .
docker run -d --name lab135 -p 127.0.0.1:2121:21 -p 127.0.0.1:30000-30010:30000-30010 proftpd-135
docker exec lab135 chmod 777 /home/ftp
PassivePorts em proftpd.conf fixa o canal de dados — a arquitetura de dois canais
do FTP (controle + dados dinâmicos) é o motivo pelo qual mapeamentos ingênuos de
containers falham: a porta de controle funciona, a de dados não.
exploit.py usa sockets brutos — sem ftplib, porque bibliotecas escondem o
protocolo, e esconder o protocolo é exatamente o que estamos combatendo:
SITE CPFR /etc/segredo.txt -> 350 (nenhum USER/PASS enviado: este É o bug)
SITE CPTO /home/ftp/... -> 250 (cópia arbitrária executada)
USER ftp / PASS ... -> 230 (o login é apenas o caminho de exfiltração)
PASV / RETR -> 150 -> 226 (flag capturada)
DELE -> 250 (limpeza: nenhum IOC deixado para trás)
AllowOverwrite, mapeamentos de porta) decide o impacto final.time.time_ns(), não time.time()), e nenhuma dependência
de estado residual.RETR responde duas vezes: 150,
depois 226. Esgote ambas antes do próximo comando.-d10) mostra exatamente
qual verificação foi acionada.Apenas para fins educacionais e uso em laboratório autorizado. Executar isso contra sistemas que você não possui ou sem permissão por escrito para testar é ilegal.