
Analisi dettagliata e proof-of-concept per CVE-2017-9822, una vulnerabilità XXE/deserializzazione non sicura in DotNetNuke CMS che porta all'esecuzione remota di codice tramite manipolazione dei cookie.
DotNetNuke (spesso abbreviato come DNN) è una piattaforma CMS (Content Management System) e un web application framework basato sulla tecnologia ASP.NET di Microsoft.
Prodotto interessato: DotNetNuke (DNN Platform) – un CMS/portal .NET molto diffuso.
Data di divulgazione: Luglio 2017.
Gravità: Critica (CVSS ~9.8).
Tipo di vulnerabilità: XML External Entity (XXE) / Deserializzazione non sicura → Remote Code Execution (RCE).
Impatto: prima della versione 9.1.1 è possibile eseguire codice in remoto tramite cookie
Qui sto usando Windows 10 per configurare e fare il debug del programma. La versione che sto installando è la 9.1.0; potete consultare la guida all'installazione Qui. E il risultato una volta completata è:


Secondo i report che ho letto, questa vulnerabilità si trova nel punto di elaborazione dei cookie di DotNetNuke
DNN usa un metodo di deserializzazione non sicura (unsafe deserialization) per il cookie DNNPersonalization

.dll o .exe scritti in .NET. Può essere installato Qui. Dobbiamo scaricare 2 versioni per poter eseguire il debug.
DotNetNuke.dll con la versione a 32 bit e seleziona Edit Assembly Attributes (C#)
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
Con
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default |
DebuggableAttribute.DebuggingModes.DisableOptimizations |
DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints |
DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]

Poi salva.
Attach to Process
w3wp.exe
Il motivo per cui si sceglie w3wp.exe è:
w3wp.exe = IIS Worker Process.
È il processo di esecuzione di un Application Pool in IIS.
Quando una richiesta HTTP arriva al sito, IIS crea o riutilizza un w3wp.exe per gestire quella richiesta (eseguire codice ASP.NET, gestire moduli, middleware, connessioni al database...).
Ogni Application Pool può avere uno o più processi w3wp.exe a seconda della configurazione (web garden, recycling).
Ora selezioniamo Debug -> Window -> Modules

Una volta comparsi i Modules, fai clic con il tasto destro su uno qualsiasi e seleziona Open All Modules

E infine appariranno tutti gli Assembly relativi a DNN.

DotNetNuke.dll -> PersonalizationController#LoadProfile(int, int)
Questa funzione serve a caricare i dati di personalizzazione (profilo) dell'utente nel portale DNN.
Se l'utente ha effettuato l'accesso → recupera il profilo da database + cache.
Se l'utente è anonimo (non autenticato) → recupera il profilo dal cookie DNNPersonalization.
Qui dovremmo concentrarci su DNNPersonalization
Se userId non è valido (utente anonimo).
Controlla se nella richiesta è presente il cookie DNNPersonalization.
Se presente → recupera il valore XML da questo cookie.
Invieremo una richiesta 404 al sito web con un qualsiasi DNNPersonalization, useremo dnSpy per impostare un breakpoint su DotNetNuke.dll –> PersonalizationController#LoadProfile(int, int) e potremo eseguire il debug.


PortalSettings
La cosa interessante è che qui viene usata una condizione if per verificare se la richiesta corrente è già IsAuthenticated o meno
E poiché la richiesta che inviamo è una 404 -> unauthenticated
Continuando con il Call Stack, concentriamoci su Handle404OrException

context.User della richiesta corrente è null; se lo è, assegna a context.User l'utente del thread corrente

Vediamo che in Handle404OrException la variabile IsAuthenticated ora ha valore true e l'utente è quello del server IIS; quindi la richiesta viene trattata come un utente autenticato.
Il motivo del problema sta in questo codice
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 non è presente → assegna Thread.CurrentPrincipal (cioè l'identità corrente del thread).
Questo fornisce alla richiesta le informazioni su utente/ruoli durante l'elaborazione successiva.
=> Quando passiamo qualsiasi contenuto nel cookie con la variabile DNNPersonalization, questo verrà eseguito come un utente normale.
Siamo sempre all'interno di DotNetNuke.dll –> PersonalizationController#LoadProfile(int, int)
Vediamo che la variabile text riceve il valore dal cookie e poi viene passata come input a Globals.DeserializeHashTableXml()