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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  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
    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.

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 480
    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 480
    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).

  9. #9
    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

+ Répondre à la discussion
Cette discussion est résolue.

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