
PoC e analisi per Kibana Prototype Pollution RCE (CVE-2019-7609).
Le versioni di Kibana precedenti alla 5.6.15 e alla 6.6.1 contengono una vulnerabilità di esecuzione di codice arbitrario nel visualizzatore Timelion. Un attaccante con accesso all'applicazione Timelion potrebbe inviare una richiesta che tenta di eseguire codice JavaScript. Ciò potrebbe potenzialmente consentire a un attaccante di eseguire comandi arbitrari con i permessi del processo Kibana sul sistema host.
CVSS:

Blog: https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/
Payload: https://github.com/mpgn/CVE-2019-7609
Configurazione:
Utilizzo:
Dopo il parsing del foglio:

Dopo la pre-elaborazione del foglio, abbiamo un oggetto queries:

Quindi, iteriamo sull'array queries (che viene convertito in un array usando il metodo values) e passiamo a invoke il query.function e query.arguments per invocare la funzione.
Nella funzione invoke, prima otteniamo la definizione della funzione in base al suo nome (query.function):

Questa definizione di funzione include tre tipi di funzione: fn, originalFn e timelionFn. Poi, itera sugli args (che sono query.arguments) e risolve gli argomenti:

In questo caso, l'argomento in args è un oggetto con tipo 'literal', quindi restituisce semplicemente il valore letterale:

In realtà, il valore è avvolto in una promise.

L'argomento indicizzato è un argomento con un oggetto byName che contiene un array q al suo interno:

Dopodiché, la funzione invoke chiamerà functionDef.fn, che è una funzione della classe Timelion, con tutti gli argomenti indicizzati:

La funzione fn chiamerà originalFn, che proviene da config.fn dove config è tlConfig. E quella funzione è fn della classe Datasource extends Timelion:

Come possiamo vedere, chiama un altro originalFn chiamato esFn che restituisce un oggetto seriesList:

Quella funzione è usata per "Estrarre dati da un'istanza Elasticsearch" chiamando la funzione callWithRequest.
Il seriesList appare così in Datasource.fn:

E appare così in Timelion.fn:

Dopo la pre-elaborazione del foglio, la lista delle catene è:

E il codice chiamerà resolveChainList per risolvere la lista delle catene:

Ogni catena viene mappata a una Promise restituita da una funzione invocata con 'first' come fnName e la catena stessa come args.
La definizione della funzione viene ottenuta di nuovo tramite il nome:

Questa volta, resolveArguments riceve args come array e chiamerà resolveArguments ricorsivamente per risolvere ogni argomento. Ma abbiamo un solo argomento con indice 0. E quell'argomento è un oggetto con type == chain.
Quindi, nel ramo switch, chiamerà la funzione invokeChain e passerà l'oggetto catena al suo interno:

All'interno della catena di invocazione, eseguirà shift sull'array chain. La funzione shift restituirà l'elemento rimosso, quindi link sarà l'oggetto es:

Poiché il tipo di es non è 'chain' (è 'function') e !result è truthy, il codice chiama la funzione invoke con 'first' come fnName e l'oggetto es come args:
Questa volta, la procedura è la stessa di sopra, quindi saltiamo alla chiamata di invokeChain in cui link è l'oggetto props:

Ancora una volta, il codice chiama la funzione invoke con 'first' come fnName e l'oggetto props come args:

L'originalFn di props ora è firstFn invece di fn come per es e accetta solo un argomento:

Quella funzione originale finirà per chiamare la vulnerabile funzione unflatten. In realtà, chiamerà prima la fn di Timelion. Poi fn chiamerà l'originalFn di props:

La firstFn di props ometterà le proprietà inputSeries e global nell'oggetto byName di args:

Quindi il valore data passato a unflatten sarà:
{
label.__proto__.env.AAA: "a"
}
Prova:

Usa props(label.__proto__.env.AAA="a"). Il data apparirà così:
