Fantastiche interfacce RPC e come trovarle
Editoriale e contributi aggiuntivi di Tricia Howard
Introduzione
Negli ultimi mesi, il nostro team si è impegnato molto nella ricerca MS-RPC a causa della sua complessità e della natura in gran parte poco studiata. Potreste aver visto la moltitudine di post sulle vulnerabilità che abbiamo scoperto come risultato di questo lavoro, come ad esempio srvsvc e Wininit.exe, ad esempio: Data l'enorme quantità di dati e strumenti che abbiamo raccolto durante questa ricerca, abbiamo ritenuto che fosse sensato riunirli in un unico posto: il nostro kit di strumenti RPC.
Questo archivio open source contiene tutto ciò che vi serve per iniziare o proseguire il vostro percorso verso RPC: strumenti, articoli, post di blog e discorsi di conferenze, nonché informazioni sulla vulnerabilità RPC e PoC (Proof-of-Concept) di exploit. Questo archivio è stato creato nel tentativo di rendere le conoscenze su RPC più accessibili sia agli addetti alla sicurezza che ai ricercatori; dopo tutto, lavorare insieme aumenta la sicurezza per tutti. A chiunque abbia letto, utilizzato uno strumento o condiviso parte del nostro lavoro: Grazie! Siamo lieti che ne stiate usufruendo.
Uno degli strumenti del toolkit è il nostro RPC Interface Analyzer, che aiuta i professionisti della sicurezza come voi a identificare rapidamente e facilmente interfacce potenzialmente vulnerabili. Questo post del blog ha lo scopo di illustrarvi lo scopo e i risultati previsti, nonché fornire una panoramica di RPC e alcuni dei suoi meccanismi di sicurezza per coloro che potrebbero ancora non conoscerli.
Che cos’è un RPC e quali sono i suoi meccanismi di sicurezza?
Una chiamata di procedura remota (RPC) è una forma di comunicazione interprocesso (IPC) che consente al client di richiamare una procedura esposta da un server RPC. Il client chiama la funzione, come se fosse una normale chiamata di procedura, senza (quasi) dover codificare i dettagli per l'interazione remota. Il server può essere ospitato in un processo diverso sullo stesso computer o su un computer remoto.
MS-RPC, l'implementazione RPC di Microsoft viene ampiamente utilizzato da Windows per molti servizi diversi, ad esempio la pianificazione delle attività, la creazione dei servizi, le impostazioni delle stampanti e della condivisione, e la gestione dei dati crittografati memorizzati da remoto. Questa vasta gamma di usi e la natura remota dell'RPC come vettore è precisamente il motivo per cui ne stiamo discutendo oggi e per cui abbiamo investito così tante risorse nella ricerca sull'RPC. Contiene molte funzionalità e, quindi, attira molta attenzione dal punto di vista della sicurezza.
Nelle sezioni seguenti esamineremo i callback di sicurezza RPC e come utilizzare l'automazione per analizzarli e potenzialmente generare nuovi indicatori per la ricerca sulla sicurezza e sulle vulnerabilità.
Che cos'è un callback di sicurezza RPC e come funziona?
In breve, un callback di sicurezza è uno dei diversi modi per proteggere un'interfaccia RPC. È un callback personalizzato implementato dallo sviluppatore del server. La sua logica viene decisa dallo sviluppatore e consente allo sviluppatore di applicare il controllo degli accessi basato sull'utente, l'autenticazione, i tipi di trasporto o impedire l'accesso a funzioni specifiche esposte dal server.
Infine il callback restituisce RPC_S_OK per consentire la comunicazione del client con il server, o uno dei codici di errore RPC, come RPC_S_ACCESS_DENIED, per rifiutarla.
La decisione di accettare o rifiutare la richiesta di un cliente si baserà solitamente su un attributo (o più di uno) che descriveremo di seguito.
Sequenza del protocollo
Il client può comunicare con il server tramite diversi trasporti: TCP, named pipe, ALPC e altri. Il callback di sicurezza può controllare questo attributo per filtrare solo le richieste di connessione locale, solo le richieste remote, la comunicazione TCP, ecc.
Sebbene i valori della sequenza del protocollo non siano documentati, abbiamo mappato le sequenze del protocollo che vengono passate al callback di sicurezza all'interno della struttura RpcCallAttributes nei seguenti valori:
#define ncacn_ip_tcp 1
#define ncacn_np 2
#define ncalrpc 3
#define ncacn_http 4
Altre sequenze di protocollo (come ncacn_hvsocket) possono essere testate dal callback di sicurezza tramite un'analisi del binding di stringa.
Livello di autenticazione
Il controllo del livello di autenticazione Del cliente è abbastanza comune nei callback di sicurezza. In questo modo, il server può definire il livello minimo di autenticazione che si aspetta dai propri client.
Esistono più livelli di autenticazione, ognuno estende il suo livello precedente:
#define RPC_C_AUTHN_LEVEL_DEFAULT 0
#define RPC_C_AUTHN_LEVEL_NONE 1
#define RPC_C_AUTHN_LEVEL_CONNECT 2
#define RPC_C_AUTHN_LEVEL_CALL 3
#define RPC_C_AUTHN_LEVEL_PKT 4
#define RPC_C_AUTHN_LEVEL_PKT_INTEGRITY 5
#define RPC_C_AUTHN_LEVEL_PKT_PRIVACY 6
Ad esempio, un server si aspetterebbe un livello di autenticazione di RPC_C_AUTHN_LEVEL_PKT_PRIVACY per garantire che i dati di comunicazione siano visibili solo al client e al server, o si aspetterebbe il livello di autenticazione di RPC_C_AUTHN_LEVEL_NONE per indicare nessuna autenticazione.
Servizio di autenticazione
Il servizio di autenticazione specifica il servizio incaricato di convalidare la policy di autenticazione fornita dal livello di autenticazione.
I valori delle costanti del servizio di autenticazione sono:
#define RPC_C_AUTHN_NONE 0
#define RPC_C_AUTHN_DCE_PRIVATE 1
#define RPC_C_AUTHN_DCE_PUBLIC 2
#define RPC_C_AUTHN_DEC_PUBLIC 4
#define RPC_C_AUTHN_GSS_NEGOTIATE 9
#define RPC_C_AUTHN_WINNT 10
#define RPC_C_AUTHN_GSS_SCHANNEL 14
#define RPC_C_AUTHN_GSS_KERBEROS 16
#define RPC_C_AUTHN_DPA 17
#define RPC_C_AUTHN_MSN 18
#define RPC_C_AUTHN_DIGEST 21
#define RPC_C_AUTHN_NEGO_EXTENDER 30
#define RPC_C_NETLOGON 68 (Undocumented)
#define RPC_C_AUTHN_MQ 100
#define RPC_C_AUTHN_DEFAULT 0xffffffff
RPC_C_AUTHN_NONE, ad esempio, disattiverebbe l'autenticazione, mentre RPC_C_AUTHN_WINNT utilizzerà il protocollo NTLM.
L'elenco completo dei servizi di autenticazione e dei relativi valori è disponibile in questa pagina GitHub.
Sessione NULL
Una sessione NULL è una connessione anonima. In questo caso il client comunica con il server senza autenticazione; ovvero, nessun nome utente o password.
Nella maggior parte dei casi, se viene registrato un callback di sicurezza, le sessioni NULL vengono bloccate per impostazione predefinita a meno che non venga fornito il flag RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH alla registrazione del server (leggi altri casi qui). I callback di sicurezza possono anche verificare la presenza di sessioni NULLI.
Bloccando l'accesso a queste sessioni, il callback di sicurezza protegge l'interfaccia RPC da utenti non autenticati.
Numero di operazione (opnum)
Il numero di operazione rappresenta la funzione dell'interfaccia che il client richiede di eseguire. Più precisamente, il numero di operazione è l'indice nella tabella delle funzioni del server RPC.
Controllando il valore del numero di operazione, il server può limitare o bloccare l'accesso del client a funzioni specifiche, come funzioni che gestiscono dati sensibili per client remoti, funzioni che accedono alla memoria del kernel e/o funzionalità per client in modalità utente, ecc.
Akamai Security Research ha pubblicato un post sul blog di un esempio di un interessante callback di sicurezza che si basa su questo controllo.
Altri controlli di callback di sicurezza possono essere:
Origine del chiamante : per verificare se il chiamante proviene dalla modalità utente o dalla modalità kernel
PID client : per consentire solo processi specifici
Binding di stringa : per convalidare gli attributi di connessione RPC come la sequenza del protocollo, l'indirizzo di rete, le informazioni sull'endpoint, ecc.
Impersonificazione : per assicurarsi che il server possa eseguire il codice nel contesto di sicurezza del client
Esistono anche controlli complessi. Ad esempio, nel callback LsaCapRpcIfCallbackFn su lsasrv.dll, se il servizio di autenticazione è netlogon, il livello di autenticazione deve essere inferiore a RPC_C_AUTHN_LEVEL_PKT_INTEGRITY.
RPC Interface Analyzer: una guida pratica
RPC Interface Analyzer è uno strumento di automazione per la ricerca di interfacce RPC. Consente ai ricercatori di trovare e analizzare le interfacce RPC da due fonti diverse: file di definizione dell'interfaccia (IDL) o file PE.
File IDL
I file IDL sono i file che definiscono un'interfaccia RPC e le sue funzioni. Analizzando i file IDL pubblicamente disponibili, possiamo ottenere informazioni su un'interfaccia RPC e le funzioni che il suo server espone, insieme ai relativi parametri e tipi di valori restituiti. Con queste informazioni, un ricercatore può cercare funzioni potenzialmente vulnerabili; ad esempio, funzioni che ricevono un argomento di percorso, come nel caso di PetitPotam.
Per eseguire il nostro analizzatore IDL, eseguite i seguenti comandi:
1. Scaricate tutti i file IDL dal sito web di Microsoft sul vostro computer utilizzando lo script idl_scraper:
idl_scraper.py [-h] [-o OUTPUT] [-p PROTOCOL]
2. Quindi eseguite idl_parser per analizzare questi file IDL:
idl_parser.py [-h] [-r] input_path [output_path]
L'output che otterrete in cambio è un file CSV contenente i nomi dell'interfaccia RPC, gli identificatori univoci universali (UUID), i nomi delle funzioni esposte e le firme.
File PE
L'analisi dei file IDL può essere utile, ma potremmo perdere alcune interfacce RPC poiché abbiamo accesso solo ai file IDL disponibili pubblicamente. Un altro approccio consiste nel cercare le interfacce RPC nel nostro file system locale, nei file PE (file .exe o .dll). Reputiamo questo approccio preferibile al controllo dei processi in tempo reale, poiché in questo modo non possiamo perdere i server RPC non attivi o in esecuzione in processi protetti.
L' RPC PE Analyzer cercherà le interfacce RPC registrate dalla funzione RpcServerRegisterIf funzione (e le sue varianti) e analizzerà gli argomenti passati ad esso, nel caso in cui venga fornito un disassemblatore. Se viene eseguito senza di esso, nella modalità predefinita, l'analizzatore trova le interfacce RPC utilizzando regex. Questa discussione Descrive il processo di ricerca.
Per utilizzare RPC PE Analyzer nella sua modalità predefinita, eseguite il seguente comando:
pe_rpc_scraper.py <scrape_path> <output_path>
Questo comando vi fornirà l'output di base che include l'UUID dell'interfaccia, il suo ruolo (client/server) e i suoi nomi e indirizzi di funzione.
Se desiderate informazioni più dettagliate, potete fornire un disassemblatore e il suo percorso (se non è quello predefinito) allo script:
pe_rpc_scraper.py [-d {idapro,radare}] [-P DISASSEMBLER_PATH] <scrape_path> <output_path>
L'utilizzo dell'opzione del disassemblatore aggiungerà anche le informazioni di registrazione dell'interfaccia, tra cui:
Flag forniti nella registrazione del server
Il nome e l'indirizzo del callback di sicurezza dell'interfaccia
Il descrittore di sicurezza del server RPC (se ne ha uno)
Se la memorizzazione nella cache globale è abilitata per il callback di sicurezza
La nostra ultima funzione pubblicata insieme a questo post del blog fornisce anche un'analisi dello stesso callback di sicurezza.
Esempio di utilizzo
Supponiamo di voler scansionare tutte le interfacce RPC disponibili sul nostro PC. Possiamo eseguire RPC PE Analyzer, fornire una copia di C:\Windows\System32 come nostro scrape_path ed esaminare l'output.
pe_rpc_scraper.py -d idapro “C:\Users\User\Documents\System32_Copy”
Poiché l'output è in formato JSON, è facile scorrerlo e cercare informazioni specifiche. Ad esempio:
Trovare tutti i client/server RPC in un file DLL
Trovare tutti i client/server RPC su un PC
Trovare i client di una specifica interfaccia RPC
Trovare i callback di sicurezza RPC di un determinato server RPC
Trovare quali interfacce RPC utilizzano la memorizzazione nella cache a livello di interfaccia (leggete questo post del blog per ulteriori informazioni sul motivo per cui questo tipo di memorizzazione nella cache è problematico)
Questi sono solo alcuni dei numerosi usi di questo output. Siamo lieti di conoscere altri usi e idee.
Nuova funzione - Informazioni sul callback di sicurezza
Struttura di RpcCallAttributes
RPC_CALL_ATTRIBUTES è una struttura che contiene i dati relativi alla richiesta del cliente. Il callback di sicurezza dell'interfaccia sul lato server può ottenere queste informazioni chiamando la funzione RpcServerInqCallAttributes RpcServerInqCallAttributes .
typedef struct tagRPC_CALL_ATTRIBUTES_V3_W
{
unsigned int Version;
unsigned long Flags;
unsigned long ServerPrincipalNameBufferLength;
unsigned short *ServerPrincipalName;
unsigned long ClientPrincipalNameBufferLength;
unsigned short *ClientPrincipalName;
unsigned long AuthenticationLevel;
unsigned long AuthenticationService;
BOOL NullSession;
BOOL KernelModeCaller;
unsigned long ProtocolSequence;
RpcCallClientLocality IsClientLocal;
HANDLE ClientPID;
unsigned long CallStatus;
RpcCallType CallType;
RPC_CALL_LOCAL_ADDRESS_V1 *CallLocalAddress;
unsigned short OpNum;
UUID InterfaceUuid;
unsigned long ClientIdentifierBufferLength;
unsigned char *ClientIdentifier;
} RPC_CALL_ATTRIBUTES_V3_W;
Abbiamo già menzionato i test eseguiti dai callback di sicurezza. Possono interrogare singolarmente alcuni di questi valori (ad esempio, RpcStringBindingParseW per ricevere la sequenza del protocollo, RpcBindingInqAuthClient per le informazioni di autenticazione e altro), oppure usare questa struttura che contiene tutto e richiede solo una chiamata di funzione. In effetti, nella maggior parte dei callback di sicurezza che abbiamo analizzato, chiamano RpcServerInqCallAttributes e utilizzano la struttura RPC_CALL_ATTRIBUTES per interrogare tutti gli attributi contemporaneamente. Ciò rende questa struttura molto interessante se si desidera comprendere la logica del callback di sicurezza.
La struttura ha attualmente tre diverse versioni - 1, 2 e 3 - e ognuna è un'estensione della rispettiva versione precedente e ha versioni ANSI e Unicode. Le diverse versioni e i relativi membri sono disponibili su questa pagina GitHub.
Informazioni sul callback di sicurezza
La nuova aggiunta al nostro kit di strumenti RPC Toolkit sono le informazioni sul callback di sicurezza, che fanno parte di RPC PE Analyzer. Forniscono una panoramica dei controlli e delle verifiche che il callback di sicurezza esegue prima di approvare/rifiutare le richieste dei client.
L'analisi del callback di sicurezza di un'interfaccia RPC, e in particolare il suo accesso alla struttura RPC_CALL_ATTRIBUTES, può far luce sull'interfaccia. In questo modo, potete cercare i callback di sicurezza che controllano l'attributo del servizio di autenticazione se desiderate filtrare le interfacce RPC che utilizzano (o non utilizzano) un protocollo di autenticazione specifico Potete anche interrogare le interfacce RPC che non controllano le sessioni NULL prima che consentano le richieste dei client e i relativi flag di registrazione del server consentano le sessioni NULL, per scoprire interfacce RPC potenzialmente vulnerabili.
Come funziona?
Per ogni callback di sicurezza, l'analizzatore:
Trova quale versione della struttura RPC_CALL_ATTRIBUTES viene utilizzata e definisce la struttura pertinente nei tipi locali di IDA
Individua la variabile locale RpcCallAttribute e applica la struttura RPC_CALL_ATTRIBUTES come tipo
Analizza i controlli che il callback di sicurezza esegue utilizzando questa struttura e mostra quale membro viene testato, il valore con cui viene confrontato e con quale operatore (== / != / / / ecc.).><
In che modo è possibile utilizzarlo?
L'uso non è cambiato: ogni volta che viene eseguito RPC PE Analyzer con il flag del disassemblatore IDA, l'output per ogni interfaccia RPC ora includerà le relative informazioni di callback di sicurezza, se accede ai membri della struttura RpcCallAttributes e ciò che verifica.
Nota: questa aggiunta è attualmente disponibile solo per IDA, l'esecuzione dell'analizzatore con l'opzione Radare non includerà le informazioni di callback di sicurezza.
Una volta ottenuto l'output, è possibile utilizzarlo per trovare interfacce RPC potenzialmente vulnerabili e filtrarle in base alle proprie esigenze. Alcuni esempi includono
Individuare un'interfaccia RPC che utilizza solo il livello di autenticazione di RPC_C_AUTHN_LEVEL_PKT_PRIVACY
Individuare le interfacce RPC che prevedono connessioni locali
Individuare le interfacce che prevedono solo chiamanti in modalità kernel
Individuare le interfacce RPC che verificano la presenza di numeri di operazione, come nel caso di vulnerabilità della memorizzazione nella cache
Riepilogo
È diventato chiaro che RPC sia un terreno fertile per la ricerca, soprattutto considerando da quanto tempo esiste e i tanti processi critici in cui è integrato. Stiamo aggiungendo risorse nel nostro archivio da quasi un anno e c'è ancora molto da fare per realizzare il pieno potenziale di minaccia di RPC. È ancora in gran parte poco studiato e, sebbene recentemente abbia attirato maggiore attenzione, c'è ancora molto da scoprire sulla miriade di modi in cui gli aggressori potrebbero abusarne.
La natura intrinseca di RPC giustifica la ricerca di qualsiasi aspetto potenzialmente pericoloso. Ci auguriamo che la nostra continua ricerca e gli strumenti nel nostro archivio facciano più luce su questo vettore e ispirino anche altri ricercatori ad analizzarlo. Che siate esperti di sicurezza responsabili della protezione di RPC o ricercatori alla ricerca del prossimo obiettivo, RPC è ricco di potenziale di conoscenza e informazioni.
Pronti a iniziare? Consultate l' archivio, e fateci sapere su Twitter cosa trovate!