IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Race condition fopen


Sujet :

C

  1. #1
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut Race condition fopen
    Bonjour,

    en lisant un livre sur le fuzzing, je suis tombé sur un problème intéressant de race condition :

    Imaginons un programme utilisant le setuid linux. Il effectue une écriture dans un fichier avec un code ressemblant à celui-la :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include <stdio.h>
    #include <string.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/types.h>
     
    int checkAccess(char* _filename)
    {
    	struct stat results;
    	stat(_filename, &results);
     
    	if (results.st_mode & S_IWUSR) return 1;
    	else return 0;
    }
     
    int main(char argc, char* argv[])
    {
    	FILE* fp;
    	char* filename = "leg_file.txt";
     
    	pid_t pid = getpid(); 
    	printf("PID %d\n", pid);
     
    	while(1)
    	{	
    		if(checkAccess(filename) == 1)
    		{
    			printf("10 second for exploit\n");
    			sleep(10);
    			fp = fopen(filename, "a+");
    			printf("New open\n");
    			fwrite("a\n", 1, 2, fp);
    			fclose(fp);
    			printf("Now is close\n");
    		}
    	}
     
    	return 1;
    }
    En exécutant ce logiciel, on remarque qu'il y a un laps de temps entre le check des droits et l'écriture dans le fichier..

    On peut donc utiliser ce lap de temps pour remplacer le fichier légitime :
    - leg_file.txt
    par
    - cp -s /etc/passwd leg_file.txt

    Mon soucis est que je ne trouve aucune parade (en code uniquement) pour lutter contre cette race condition.

    p.s. Evidemment le sleep est la pour simplifier l'exploit, mais on peut imaginer un bruteforce.

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    En théorie, ne serait-ce pas au système de fichier de bloquer les appels à fopen() sur des fichiers invalides?

  3. #3
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut
    En théorie, ne serait-ce pas au système de fichier de bloquer les appels à fopen() sur des fichiers invalides?
    Dans ce cas , l'ouverture du fichier est valide (il y a le sticky bit) et on ouvre un fichier qui est possédé par root.

    On peut régler/limiter le problème, en gérant efficacement les droits sur notre filesysteme :

    - Selinux
    - chdir
    - user dédié
    - ...

    Mais c'est un exemple, imaginons que le système de fichier ne peut être modifié. Et que l'on doit régler le problème en C.

    Par exemple existe-t-il un moyen de "locker" un fichier ?

  4. #4
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    "locker" depuis un programme X pour que tous les autres ne puissent pas y accéder... ça signifie effets de bords... et hormis le FS, je ne pense pas qu'il existe autre chose pour bloquer un fichier...
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Pas a ma connaissance. Si tu ne peux pas te fier au système, où va-t-on?

    Cela dit, ton système de fichier sera modifié, puisque tu va y placer ton exécutable…

  6. #6
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Je dirais tu commences par ouvrir le fichier, puis tu fais un stat() ou fstat() dessus...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  7. #7
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 481
    Par défaut
    Citation Envoyé par manticore Voir le message
    Par exemple existe-t-il un moyen de "locker" un fichier ?
    Il existe des verrous fichiers sous UNIX (voir flock(), lockf() et fcntl() avec F_GETLK, F_SETLK et F_SETLKW) mais ceux-ci sont consultatifs par défaut. Il faut activer une option spéciale au montage du système de fichiers (sous Linux, voir Documentation/filesystems/mandatory-locking.txt dans les sources du noyau). En bref : c'est une fausse bonne idée.

    Dans le cas qui te préoccupe, tu n'es absolument pas obligé de faire un test préalable avec stat() avant d'ouvrir ton fichier : tu peux faire un open() directement qui échouera avec le code d'erreur idoine si tu n'as pas les droits de le faire. Dans ce cas, l'atomicité est garantie. Tu peux même éventuellement faire un stat() après l'ouverture si tu as toujours besoin de connaître ces infos.

    Cela dit, cela ne règle pas ton problème du tout : n'importe quel utilisateur pourra lui-aussi ouvrir ton fichier et écrire dedans MÊME si tu l'as ouvert. Donc, que cela se passe pendant le délai de grâce accordé à l'exploit ou pendant le déroulement du programme ne change rien.

    Ensuite, je ne vois pas où tu veux en venir avec « cp -s /etc/passwd leg_file.txt ». En faisant ceci, tu copies le fichier /etc/passwd dans le tien mais le fichier /etc/password original reste intact.

    Enfin, à titre indicatif, si tu remplaces l'entrée du fichier par un lien symbolique ou même si tu le supprimes pendant qu'il est utilisé, il ne se passe rien non plus. Le fichier initialement ouvert restera sur le disque tant qu'un programme au moins aura un handle valide dessus. Le système l'effacera automatiquement et définitivement dès lors que le dernier programme à l'avoir ouvert le refermera et qu'il n'y aura plus de référence existante sur le volume qui le contient (autrement dit : plus de liens durs).

  8. #8
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Bonjour,

    Je ne vois pas non plus le probleme...
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  9. #9
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut
    Pas a ma connaissance. Si tu ne peux pas te fier au système, où va-t-on?
    C'est surtout une question d'élévation de privilège, je te donne un accès user et tu peux monter en root à cause de ton application c'est pas très propre.

    Ensuite, je ne vois pas où tu veux en venir avec « cp -s /etc/passwd leg_file.txt ». En faisant ceci, tu copies le fichier /etc/passwd dans le tien mais le fichier /etc/password original reste intact.
    cp -s créer un lien symbolique je préfère cette forme à ln à cause du sens des opérateurs.


    Cela dit, cela ne règle pas ton problème du tout : n'importe quel utilisateur pourra lui-aussi ouvrir ton fichier et écrire dedans MÊME si tu l'as ouvert. Donc, que cela se passe pendant le délai de grâce accordé à l'exploit ou pendant le déroulement du programme ne change rien.
    En faite il faut checker que l'utilisateur qui lance le binaire aille les droits d'ouvrir le fichier par le fopen(). Car vu que le binaire est lancé avec le sticky bit lui aura les droits.

    En faite pour faire correctement cette ouverture :
    1. fopen()
    2. Check si l'utilisateur qui lance le binaire peut écrire dans le fichier
    3. Si ok -> écriture
    4. Si non exception
    Juste pour illustrer le problème si on ne check pas les droits.

    1. fopen()
    2. On supprime le fichier légitime et on le remplace par un lien symbolique sur /etc/passwd
    3. fwrite() écrit dans /etc/passwd avec les droits root
    Si on peut contrôler ce qui est écrit on peut s'ajouter un utilisateur root.

  10. #10
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Hum... ok, je vois un peu mieux...

    M'est avis qu'avant de trouver une attaque par ce biais, il existe tellement d'autres failles que le systeme est deja par terre. Mais bon, concentrons-nous sur l'exercice du moment.

    En fait, j'ai fait le test, et le systeme fait la verification a ma place :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    > ./a.out
    PID 10642
    10 second for exploit
    New open
    Memory fault(coredump)
    Si on regarde plus finement ce qui se passe pendant ce temps la :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
         stat("leg_file.txt", {st_mode=S_IFREG|0644, st_size=2031, ...}) = 0
         write(1, "10 second for exploit\n", 22) = 22
         rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
         rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
         rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
         nanosleep({10, 0}, {10, 0})             = 0
         brk(0)                                  = 0x1b810000
         brk(0x1b831000)                         = 0x1b831000
         open("leg_file.txt", O_RDWR|O_CREAT|O_APPEND, 0666) = -1 EACCES (Permission denied)
         write(1, "New open\n", 9)               = 9
         --- SIGSEGV (Segmentation fault) @ 0 (0) ---
         +++ killed by SIGSEGV (core dumped) +++
    Tu peux dormir tranquille, le systeme veille au grain.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  11. #11
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    En fait tu veux faire des trucs dans le style de l'impersonation Windows ?
    Pas sûr que tu puisses faire grand chose, intéresses-toi peut être à getuid() et geteuid()...

    Je fais confiance à gangsoleil pour son test en effet...
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  12. #12
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Citation Envoyé par Metalman Voir le message
    Je fais confiance à gangsoleil pour son test en effet...
    Test sous une RedHat. Je verrai si je peux faire des tests sous d'autres OS demain.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  13. #13
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut
    En fait tu veux faire des trucs dans le style de l'impersonation Windows ?
    Pas sûr que tu puisses faire grand chose, intéresses-toi peut être à getuid() et geteuid()
    M'est avis qu'avant de trouver une attaque par ce biais, il existe tellement d'autres failles que le systeme est deja par terre. Mais bon, concentrons-nous sur l'exercice du moment.
    C'est vraiment un exercice, comme je te l'ai dis, j'ai vu l'exemple dans un livre, et je me suis posé des questions. D'ailleurs ils disent bien que c'est une attaque très rarement exploitable.

    Sinon étrange, de mon côté le système ne fait pas de contrôle (bon j'ai fais ça sur centOS ). Mais la je vois pas pourquoi tu as cette erreur.

    Quels droits as-tu mis sur des fichiers ?

    Moi j'ai ceux-ci :

    -r--. 1 manticore manticore 2 Apr 17 17:18 leg_file.txt
    -rw-rw-r--. 1 manticore manticore 66 Apr 17 13:21 exploit_race.sh
    -rw-r--r--. 1 root root 0 Apr 17 17:19 falseFile.txt
    -rwsr-xr-x. 1 root root 5.3K Apr 17 17:18 test
    Comme il y a le sticky bits, le binaire à le droit d'écrire.

    J'ai fais des tests de mon côté et cela fonctionne. Pour contrer cet effet de bord il faut dans un premier temps faire le fopen puis tester le fd. Comme Médinoc l'a dit.


    Puis-ce que j'ai 10 minutes à attendre voila l'extrait du livre : Fuzzing for software security testing and quality assurance.

    Race conditions

    Race conditions are vulnerabilities that arise due to unforeseen timing events. A standard example can be seen from the foolowing code except from an application running at higher privileges.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    if (!access(tempfilename, W_OK)){
    fp = fopen(tempfilename, "a+");
    fwrite(user_supplied_info, 1, strlen(user_supplied_info), fp);
    fclose(fp);
    }
    else
    {
    error("User does not have write permission to temp file\n";
    }

    Suppose this application is SETUID root, i.e., running at a higher privilege level than the user who is using it. In this code, a temporary file is first checked to make sure the user has permission to write to it. If so, it appends some user-supplied data to the file. The problem here is the small amount of time that occurs between the permission check in access() call and the use of the file in the fopen() call. This is sometimes called a time-ofcheck-to-time-of-use bug. During that small window, the user can create a symbolic link from the temporary file to a file he or she sould not have access to, such as /etc/passwd. If timed just right, this will allow an attacker to append arbitrary data to this file and thus add a login account with super user privileges. This example shows that race conditions can be particularly difficult to exploit, but with a little patience and the fact the attacker can overload the system by fully utilizing system ressources, attacks of this nature are possible.

    p.s. Sinon j'ai remarqué que le test des droits utilisateurs fonctionnent pas dans mon code.

  14. #14
    Membre Expert
    Avatar de Metalman
    Homme Profil pro
    Enseignant-Chercheur
    Inscrit en
    Juin 2005
    Messages
    1 049
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Enseignant-Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 1 049
    Par défaut
    Je pense que ta réponse est bien là : Lien
    Avec getuid et geteuid.

    Je cite :
    L'UID réel correspond à celui du processus appelant, l'UID effectif dépend de l'état du bit Set-UID du fichier exécuté.
    Du coup : ton bash/sh/... avec ton login en UID lancera l'appli => UID réel = ton login, UID effectif = root

    EDIT : getuid + le stat précédemment expliqué pour faire la comparaison

    EDIT2 : évidemment.... certains FS réseaux utilisent des droits plus avancés... et voir aussi le fonctionnement des droits ACL par rapport aux simples uid/gid/chmod
    --
    Metalman !

    Attendez 5 mins après mes posts... les EDIT vont vite avec moi...
    Les flags de la vie : gcc -W -Wall -Werror -ansi -pedantic mes_sources.c
    gcc -Wall -Wextra -Werror -std=c99 -pedantic mes_sources.c
    (ANSI retire quelques fonctions comme strdup...)
    L'outil de la vie : valgrind --show-reachable=yes --leak-check=full ./mon_programme
    Et s'assurer que la logique est bonne "aussi" !

    Ma page Developpez.net

  15. #15
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    @Manticore: Tu sembles confondre sticky et setuid...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #16
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut
    Effectivement j'inverse toujours le sticky bit et le suid

    Oui la vérification des droits avec le getuid permet de vérifier correctement les droits.

  17. #17
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 150
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 150
    Par défaut
    Citation Envoyé par manticore Voir le message
    Sinon étrange, de mon côté le système ne fait pas de contrôle (bon j'ai fais ça sur centOS ). Mais la je vois pas pourquoi tu as cette erreur.

    Quels droits as-tu mis sur des fichiers ?
    J'ai fait une copie de /etc/passwd (en root, cp -p), puis j'ai fait un lien leg_file.txt vers cette copie.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  18. #18
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut
    @gangsoleil

    Tu as bien le set les droits SUID ? Si tu as le SUID, il n'y a pas de raison que ton filesystem filtre le fopen.

  19. #19
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 481
    Par défaut
    La question est : pourquoi ton programme a-t-il les droits setuid ? C'est important pour deux raisons :

    La première est que si tu ne justifies pas ce point à l'avance, il sera difficile de faire le bilan de toutes les failles potentielles que cela introduit. Par exemple, une faille assez célèbre sur les anciens UNIX mais dont je n'arrive plus à retrouver le lien concernait un vieux logiciel de backup qui, à la fois, était setuidé root pour accéder aux bandes, avait une option en ligne de commande pour ajouter une ligne dans le log ET en avait une autre pour spécifier le nom du fichier de log. Pas la peine de dire ce que cela impliquait : ça te dispensait même de créer un lien symbolique. Il suffisait de choisir « /etc/passwd » comme fichier de log et d'ajouter une entrée permettant de se loguer avec l'UID 0 et l'identifiant de son choix pour obtenir le #.

    La seconde est que setuid comme setgid ne font pas systématiquement devenir root mais te font prendre de manière effective l'identité et/ou le groupe du propriétaire du fichier. Celui-ci peut tout-à-fait être un pseudo-user faisant fonctionner un dæmon ou un serveur en userland. C'est le cas de Postgresql, par exemple. C'est la méthode privilégiée à utiliser si ton programme doit être isolé des utilisateurs mais n'a pas spécialement besoin de privilèges spéciaux.

    Lorsque tu en as besoin, la solution consiste à effectuer les tâches nécessaires puis à abandonner ces droits en reprenant l'identité réelle de l'utilisateur. Ça réduit considérablement le périmètre application de ta race condition, sans la résoudre toutefois. Sous Linux enfin, il existe les capabilities qui te permettent de choisir les opérations privilégiées dont tu souhaites conserver le pouvoir avant de renoncer à tes privilèges.

    Dans les deux cas, les faiblesses de sécurité naîtront essentiellement de la politique adoptée au départ. En gros, le comportement d'un programme lorsqu'il est privilégié doit être si possible déterministe : si tu ne peux pas énumérer à l'avance tous les résultats possibles (ou au moins leur domaine de résultat) d'une opération en root, il ne faut pas la lancer. Évidemment, c'est un vœu pieux parce que c'est très difficile à établir, mais tu peux faire au moins une chose : lancer un thread root chargé de faire que ce qu'un processus ordinaire est réputé ne pas pouvoir faire et le laisser communiquer avec l'autre processus. Dans ton cas, ce n'est pas pour ouvrir le fichier que ton programme est setuidé root mais pour une autre tâche. Le fait de pouvoir ouvrir un fichier non autorisé est un effet de bord. Donc, tu laisses cette opération à la charge du processus non privilégié ;

    Donc, toujours remettre en question la légitimité des opérations à effectuer : par exemple, CAP_NET_BIND_SERVICE a l'air très intéressant de prime abord car elle te permet à un programme de se mettre à l'écoute d'un port inférieur à 1024 sans être root ni gagner un quelconque autre pouvoir, pas même celui de faire d'autres opérations d'administration réseau. C'est utile pour permettre à un dæmon de libérer le port tant qu'il est en sommeil et le reprendre éventuellement ensuite. Par contre, si on s'en sert pour permettre à un programme utilisateur d'utiliser ces ports, alors ça reste en soi une violation de la politique du système qui n'a pourtant pas été établie pour rien. La meilleure preuve étant qu'il te faudra quand même être setuidé root pour pouvoir acquérir cette capacité au départ et que ton administrateur système refusera (à raison) de le faire.

    Tout ceci pour dire que la sécurité d'un programme dépend essentiellement de sa conception initiale et très peu des choix techniques effectués quand on a commencé à l'écrire.

  20. #20
    Membre chevronné

    Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Novembre 2009
    Messages
    377
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Novembre 2009
    Messages : 377
    Par défaut
    @Obsidian
    Je suis parfaitement conscient de tout ça. Encore une fois c'était un pur exercice.

    Il existe certainement des cas ou cela est nécessaire et je m'intéressais uniquement à une solution au niveau du code C. Solution qui existe en testant le file descriptor ouvert et non pas le fichier à ouvrir.

    Je sais qu'il y a très peu de chance de trouver cette faille et encore moins de l'exploiter. Mais c'est une faille potentiel que je trouvais techniquement intéressante.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 11
    Dernier message: 07/12/2011, 07h11
  2. Vieille application, race condition sur seven
    Par b_lob dans le forum x86 32-bits / 64-bits
    Réponses: 2
    Dernier message: 24/01/2011, 19h38
  3. Réponses: 5
    Dernier message: 11/12/2002, 12h31
  4. Ouvrir (fopen) un fichier caché
    Par shef dans le forum C
    Réponses: 2
    Dernier message: 09/09/2002, 09h06
  5. Réponses: 2
    Dernier message: 06/07/2002, 12h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo