
Análise detalhada e exploit de prova de conceito para CVE-2017-9822, uma vulnerabilidade de XXE/desserialização insegura no DotNetNuke CMS que leva à execução remota de código via manipulação de cookies.
DotNetNuke (geralmente abreviado como DNN) é uma plataforma CMS (Content Management System) e framework de aplicação web baseada na tecnologia ASP.NET da Microsoft.
Produto afetado: DotNetNuke (DNN Platform) – um CMS/portal .NET popular.
Data de divulgação: Julho de 2017.
Nível: Crítico (CVSS ~9.8).
Tipo de vulnerabilidade: XML External Entity (XXE) / Desserialização Insegura → Execução Remota de Código (RCE).
Impacto: antes da versão 9.1.1, possibilidade de executar código remotamente através de cookie
Aqui estou usando o Windows 10 para configurar e depurar o programa. A versão que estou instalando é 9.1.0. Vocês podem consultar o guia de instalação Aqui. E o resultado após a conclusão é:


De acordo com os relatórios que li, essa vulnerabilidade está localizada no processamento de cookies do DotNetNuke
O DNN utiliza um método de desserialização insegura (unsafe deserialization) para o cookie DNNPersonalization

.dll ou .exe escritos em .NET. Pode ser instalado Aqui. Precisamos baixar duas versões para a depuração.
DotNetNuke.dll com a versão de 32 bits e selecione Edit Assembly Attributes (C#)
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default |
DebuggableAttribute.DebuggingModes.DisableOptimizations |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]

Depois, salve.
Attach to Process
w3wp.exe
O motivo de escolher w3wp.exe é:
w3wp.exe = IIS Worker Process.
É o processo de execução do Application Pool no IIS.
Quando uma solicitação HTTP é enviada ao site, o IIS cria ou reutiliza um w3wp.exe para processar essa solicitação (executar código ASP.NET, processar módulos, middleware, conexão com banco de dados...).
Cada Application Pool pode ter um ou mais processos w3wp.exe dependendo da configuração (web garden, recycling).
Em seguida, vá em Debug -> Window -> Modules

Depois disso, os Módulos aparecerão. Clique com o botão direito em qualquer um e selecione Open All Modules

E, por fim, todos os Assemblies relacionados ao DNN aparecerão

DotNetNuke.dll -> PersonalizationController#LoadProfile(int, int)
Essa função é usada para carregar dados de personalização (perfil) do usuário no portal DNN.
Se for um usuário logado → carrega o perfil do banco de dados + cache.
Se for um usuário anônimo (não logado) → carrega o perfil do cookie DNNPersonalization.
Aqui devemos nos concentrar em DNNPersonalization
Se o userId não for válido (usuário anônimo).
Verifica se a solicitação possui o cookie DNNPersonalization.
Se sim → obtém o valor XML desse cookie.
Enviaremos uma solicitação 404 para o site e usaremos qualquer DNNPersonalization, usando o dnSpy para definir um Breakpoint em DotNetNuke.dll –> PersonalizationController#LoadProfile(int, int) para depurar


PortalSettings
O que chama a atenção aqui é o uso de uma condição if para verificar se a solicitação atual já é IsAuthenticated ou não
E enquanto a solicitação que enviamos é 404 -> unauthenticated
Continue na parte de Call Stack, concentre-se em Handle404OrException

context.User atual é null; se for, atribui context.User ao usuário da thread atual

Vemos que em Handle404OrException, a variável IsAuthenticated agora tem valor true e o usuário é o do servidor IIS, portanto a solicitação é executada como um usuário autenticado.
A razão do problema está neste trecho de código
else if (transfer)
{
if (context.User == null)
{
context.User = Thread.CurrentPrincipal;
}
response.TrySkipIisCustomErrors = true;
IHttpHandler handler = new CDefault();
context.Handler = handler;
server.Transfer("~/" + text, true);
}
Se context.User não existir → atribui Thread.CurrentPrincipal (ou seja, a identidade atual da thread).
Isso faz com que a solicitação tenha informações de usuário/papel durante o processamento posterior.
=> Quando enviamos qualquer conteúdo para o cookie com a variável DNNPersonalization, ele será executado como um usuário normal.
Ainda em DotNetNuke.dll –> PersonalizationController#LoadProfile(int, int)
Vemos que a variável text recebe o valor do cookie e depois é passada como entrada para Globals.DeserializeHashTableXml()

Globals.DeserializeHashTableXml()