
GitList est un visualiseur de référentiels Git moderne.
Dans les versions de GitList 0.6.0 et antérieures, une vulnérabilité transmet des entrées insuffisamment validées aux fonctions système, ce qui permet d'exécuter des commandes arbitraires avec les privilèges de l'utilisateur PHP.
Exécutez la commande suivante pour démarrer le serveur GitList 0.6.0.
docker compose up -d
Installez les dépendances avant d'exécuter poc.py.
pip install requests
Une fois l'environnement configuré, accédez à http://127.0.0.1:8080 et vérifiez qu'un référentiel de test nommé example existe.
GitList utilise git grep pour rechercher du code dans les référentiels.
public function searchTree($query, $branch)
{
if (empty($query)) {
return null;
}
$query = escapeshellarg($query);
try {
$results = $this->getClient()->run($this, "grep -i --line-number {$query} $branch");
} catch (\RuntimeException $e) {
return false;
}
Ici, $query désigne le mot-clé de recherche et $branch la branche cible de la recherche.
Si un attaquant transmet --open-files-in-pager=id; comme terme de recherche, la commande id est exécutée sur le système.
Cette vulnérabilité se produit pour deux raisons :
escapeshellarg()En théorie, une fois passée par le code $query = escapeshellarg($query);, l'entrée devient une chaîne entourée de guillemets simples. Cependant, bien que escapeshellarg() empêche l'injection du point de vue du shell, elle ne peut pas empêcher l'analyseur d'options de git lui-même d'interpréter les chaînes commençant par -- comme des options.
--open-files-in-pagerCette option de git grep permet de spécifier un programme de pagination (pager) externe pour afficher les résultats de recherche, et elle a la particularité d'exécuter directement la valeur qui lui est transmise comme commande système.
[repo_name]/tree/[keyword]/search) contient deux arguments : [repo_name] et [keyword].[repo_name] doit être un référentiel présent dans GitList, et [keyword] doit être un mot-clé de recherche produisant au moins un résultat de recherche.
(Dans cette reproduction, example a été utilisé comme référentiel et a comme mot-clé.)Exécutez poc.py avec la commande suivante.
Ce script exécute touch /tmp/success_dddo0, ce qui crée un fichier vide nommé success_dddo0 dans le répertoire /tmp du serveur.
python3 poc.py http://127.0.0.1:8080
Après l'envoi de la requête, vérifiez que success_dddo0 a bien été créé avec la commande suivante.
docker compose exec web ls -l /tmp/success_dddo0
Après l'exécution du PoC, on peut constater que la commande système arbitraire (touch /tmp/success_dddo0) a été exécutée avec succès à l'intérieur du serveur, créant ainsi le fichier.

docker compose down
Vous devez mettre à jour GitList vers la dernière version.
Modifications du code :
public function searchTree($query, $branch)
{
if (empty($query)) {
return null;
}
$query = preg_replace('/(--?[A-Za-z0-9\-]+)/', '', $query);
$query = escapeshellarg($query);
try {
$results = $this->getClient()->run($this, "grep -i --line-number -- {$query} $branch");
} catch (\RuntimeException $e) {
return false;
}
Pour corriger cette vulnérabilité, GitList utilise une expression régulière afin de supprimer les préfixes - illégaux du terme de recherche ($query), et ajoute -- (un indicateur marquant la fin des options) à la commande git grep, forçant ainsi toutes les entrées suivantes à n'être traitées que comme des chaînes ordinaires (termes de recherche) et non comme des options de commande.