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 :

De la sécurité de printf()


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2017
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2017
    Messages : 15
    Par défaut De la sécurité de printf()
    [Cette discussion est dérivée de cette discussion : https://www.developpez.net/forums/d1...-segmentation/

    Elle vise à développer les problèmes de sécurité que la fonction printf() peut poser. Cette problématique est assez loin du problème original et une discussion dédiée est ouverte pour plus de clarté.

    Voici lecode incrimé :

    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
    #include <stdio.h>
    #include <string.h>
     
    char *my_revstr(char *str)
    {
    	char string[255];
    	int len, n;
     
    	strcpy(string, str);
    	len = strlen(string);
    	for(n = 0; n!=len; n++)
    	{
    		*(str+n) = string[len];
    		len--;
    	}
    }
     
    int main()
    {
    	char string[12] = "Hello World\0";
    	printf(string);
    	my_revstr(string);
    	printf(string);
    	return (0);
    }
    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
    #include <stdio.h>
    #include <string.h>
    char *my_strstr(char *str, char *to_find)
    {
    	char *string;
     
    	while (*str != *to_find)
    	{
    		str++;
    	}
     
    	strncpy(string, str, strlen(to_find));	
     
    	return (str);
    }
     
    int main()
    {
    	char string[12] = "Hello World\0";
    	char *str = my_strstr(string, "ello");
    	printf("%s\n", str);
     
    	return (0);
    }

  2. #2
    Membre très actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 548
    Par défaut
    Bonjour

    Votre programme comporte des instructions à ne pas faire car elles sont très dangereuses je parle de printf(string); et strcpy(string, str); car elles peuvent être exploitées. Je vous conseille donc de revoir le manuel du langage C et l'emploi des fonctions citées précédemment et leurs informations sur leur vulnérabilité.

    Deuxième point vous avez une variable pointeur sur char qui n'a pas été initialisée et qui pointe sur aucune zone mémoire allouée dynamiquement qui est utilisée (manque d'allocation dynamique de mémoire).

    Revoir aussi la réflexion et l'implémentation de votre algorithme car il faut savoir qu'un programme informatique fait toujours ce qui est écrit et pas forcément ce qu'on a souhaité qu'il fasse donc, il faut relire le code tel qu'il est écrit et non comme celui qu'on a voulu écrire... A ceci je pose une question si vous avez déjà effectue une copie à quoi ça sert d'effectuer une autre copie ?
    (utiliser également un débogueur)
    Citation Envoyé par Deezio Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    char *my_revstr(char *str)
    {
    	char string[255];
    	int len, n;
     
    	strcpy(string, str);
    	len = strlen(string);
    	for(n = 0; n!=len; n++)
    	{
    		*(str+n) = string[len];
    		len--;
    	}
    }
    à bientôt

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Deezio Voir le message
    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
    #include <stdio.h>
    #include <string.h>
    char *my_strstr(char *str, char *to_find)
    {
    	char *string;
    
    	while (*str != *to_find)
    	{
    		str++;
    	}
    	
    	strncpy(string, str, strlen(to_find));	
    	
    	return (str);
    }
    Bonjour

    j'ai lu en diagonale très rapidement et sans trop chercher mais j'ai de suite tiqué ici. Tu copies dans "string" et tu retournes "str". Il n'y aurait pas comme un souci ??? Sans parler du fait que tu copies dans un pointeur n'ayant aucune mémoire...

    Citation Envoyé par sambia39 Voir le message
    Votre programme comporte des instructions à ne pas faire car elles sont très dangereuses je parle de printf(string); et strcpy(string, str); car elles peuvent être exploitées. Je vous conseille donc de revoir le manuel du langage C et l'emploi des fonctions citées précédemment et leurs informations sur leur vulnérabilité.
    Non mais c'est bon quoi, faut arrêter de consommer les champignons magiques. Il ne fait pas un programme pour la NASA ou le MI5, il fait un exercice pour s'entrainer. Quand il saura marcher puis courir il aura alors le temps de s'intéresser aux vulnérabilités de son code...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Membre très actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 548
    Par défaut
    Bonjour

    Citation Envoyé par Sve@r Voir le message
    Bonjour
    Non mais c'est bon quoi, faut arrêter de fumer. Il ne fait pas un programme pour la NASA ou le MI5, il fait un exercice pour s'entrainer. Quand il saura marcher puis courir il aura alors le temps de s'intéresser aux vulnérabilités de son code...
    Je ne sais pas pour vous, mais pour moi un exercice est un ensemble de questions dans lequel on doit appliquer ce qui a été appris précédemment dans un cours ou un enseignement. Personnellement, je doute que l’enseignement donné ou ce qui est écrit dans les différents manuels du langage C apprenne à un débutant à utiliser et écrire des instructions de la sorte. Alors oui, je prends l’initiative de dire que la personne emploie très mal les fonctions. La preuve: un coup c’est "printf(string);" ou "printf("%s\n", str);". Vu d’ici, c'est un flou total ou un copié-collé abusif qui n’a pas d’intérêt ou pire, la personne ne sait pas comment utiliser la fonction. Alors oui, je préfère dire les choses telles quelles sont et renvoyer la personne vers son manuel d'apprentissage pour savoir comment les choses fonctionnent.
    à bientôt

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    Je ne sais pas pour vous, mais pour moi un exercice est un ensemble de questions dans lequel on doit appliquer ce qui a été appris précédemment dans un cours ou un enseignement.
    Jusque là, ça reste très trivial comme réflexion...

    Citation Envoyé par sambia39 Voir le message
    Personnellement, je doute que l’enseignement donné ou ce qui est écrit dans les différents manuels du langage C apprenne à un débutant à utiliser et écrire des instructions de la sorte.
    Ben au lieu de douter, t'as qu'à vérifier. Le K&R donne l'instruction printf() en page 6 => https://drive.google.com/file/d/0Byk...NCeFQ2TW8/view. Et les autres tutoriels que j'ai pu survoler y vont très rapidement y compris ceux qu'on trouve sur ce forum. Par exemple celui-ci (http://melem.developpez.com/tutoriel...ion-langage-c/) donne printf() en page 7. Cet autre (https://c.developpez.com/cours/20-heures) le donne en page 13. Et ce 3° (https://cpp.developpez.com/cours/cpp/) le donne en page 28. Tu veux que je continue??? D'autant plus que nulle part dans ces bouquins je n'ai vu d'information à propos des vulnérabilités de printf() (ce qui ne veut pas dire qu'il n'y en a pas, mais simplement que ce n'est pas le moment d'en parler).

    Citation Envoyé par sambia39 Voir le message
    La preuve: un coup c’est "printf(string);" ou "printf("%s\n", str);".
    Sur ce détail ci effectivement on peut s'arrêter (encore que si "string" contient une chaine ça n'est pas foncièrement incorrect). Mais cela n'a rien à voir avec la vulnérabilité de printf() mais simplement des bonnes conventions d'usage dans son utilisation.

    Citation Envoyé par sambia39 Voir le message
    Alors oui, je préfère dire les choses telles quelles sont et renvoyer la personne vers son manuel d'apprentissage pour savoir comment les choses fonctionnent.
    Bien entendu. Et donc s'il te venait l'envie d'enseigner l'astronomie tu shunterais direct toute l'observation du soleil qui semble tourner autour de la Terre pour passer direct aux équations de Newton. Ben non, que dis-je, ces équations sont incorrectes dans certains points de l'espace proches de grosses masses donc autant passer direct aux équations de la relativité générale car on n'a rien trouvé de mieux pour décrire comment les choses fonctionnent dans ce domaine !!!

    Tu ne sais donc pas que l'enseignement se fait étape par étape ; en enseignant au départ des notions peut-être incorrectes (ou plus exactement "incomplètes") mais plus simples d'appréhension tout en donnant quand-même une bonne idée de la façon dont les choses fonctionnent "en général".
    Puis ensuite, une fois ces notions assimilées, on les remet alors en question pour les détailler et donc forcément, quand on entre dans le détail, fatalement les notions "grossières" du départ se révèlent fausses mais remplacées par les nouvelles, plus précises certes mais aussi plus difficiles. Et ensuite ces notions sont encore remises en question au fur et à mesure qu'on entre en profondeur dans le domaine. Et etc etc etc. L'apprentissage ne peut se faire qu'étape par étape et vouloir aller direct au final conduit droit au mur.

    Et donc le C ne fait pas abstraction. Donc oui, au départ, on enseigne printf() et scanf() parce que c'est direct, accessible et relativement simple à apréhender. Ensuite, quand Deezio programmera le coeur du noyau du système de surveillance d'une centrale nucléaire ; peut-être alors qu'effectivement là il pourra s'inquiéter de la vulnérabilité des fonctions qu'il utilise.

    Citation Envoyé par sambia39 Voir le message
    Alors oui, je prends l’initiative de dire que la personne emploie très mal les fonctions
    Et moi je prends l'initiative de te rembarrer. Ce n'est pas le bon moment d'étaler ta science toute théorique.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre très actif
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    Mai 2010
    Messages
    548
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Mai 2010
    Messages : 548
    Par défaut
    Bonsoir

    Faut lire et comprendre, il ne suffit pas d’appliquer des principes du langage C bêtement. Je parle de ça "printf(string)". Alors dis-moi dans quels manuels on apprend à écrire ceci "printf(string)".

    Je cite ce qui est écrit dans le manuel que tu as fourni à travers ton lien qui me semble important : "Sous d’autres systèmes d’exploitation, il faut procéder différemment. Renseignez-vous auprès des spécialistes de votre système d’exploitation", mais aussi plus loin "Au passage, notez que printf ne fait pas partie du langage C. Le langage en soi ne définit pas l’instruction d’entrée sortie. printf est simplement une fonction utile extraite de la bibliothèque standard des fonctions accessibles au programme en C. Cependant, le comportement de printf est défini dans la norme ANSI si bien que ses propriétés sont censées être les mêmes avec n’importe quel compilateur muni d’une bibliothèque conforme à la norme."

    Et du langage, il est écrit :"The printf function is equivalent to fprintf with the argument stdout interposed before the arguments to printf.." et donc a la fonction "fprintf" : "The fprintf function writes output to the stream pointed to by stream, under control of the string pointed to by format that specifies how subsequent arguments are converted for output. If there are insufficient arguments for the format, the behavior is undefined."

    Tu as écrit:
    Citation Envoyé par Sve@r Voir le message
    Donc oui, au départ, on enseigne printf() et scanf() parce que c'est direct, accessible et relativement simple à apréhender. Ensuite, quand Deezio programmera le coeur du noyau du système de surveillance d'une centrale nucléaire ; peut-être alors qu'effectivement là il pourra s'inquiéter de la vulnérabilité des fonctions qu'il utilise.
    Tu l’écris toi-même, on enseigne printf d’abord, alors montre-moi dans ton manuel où tu vois qu’il faut employer ça "printf(string)"
    Bref, ce n’est pas le moment de parler de vulnérabilité, soit, je peux concevoir ; mais tolérer ça "printf(string)", non, donc désolé. Tu comprendras un jour peut-être que l'honnêteté est le premier devoir de celui qui transmet la connaissance. Sinon quelles que soient les connaissances aussi vastes soient-elles ne valent rien.

    Citation Envoyé par Sve@r Voir le message
    Et moi je prends l'initiative de te rembarrer. Ce n'est pas le bon moment d'étaler ta science toute théorique.
    Sur ce qui suit, je vais te rembarrer avec ma fameuse science théorique.
    La fonction printf est dite fonction d’impression formatée, cela veut dire que les données sont converties dans un format particulier et choisi (rappel du prototype de la fonction: printf("chaîne_de_contrôle", expression1, ..., expressionN)
    Pour faire simple, le premier argument de printf ne doit en aucun cas être contrôlable par l’utilisateur alors pourquoi? Parce que la fonction printf scanne la chaîne de caractères dans le but de trouver un ou des spécificateur(s) de formats, exemple: "%d %x, etc.", et lorsqu’un spécificateur de format est trouvé, l’argument correspondant à cette specificateur va être recherché. Une personne mal intentionnée peut alors très bien exploiter ce mauvais emploi de la fonction printf à travers le premier argument de printf et s’arranger de façon à ce que la fonction printf utilise cette variable comme un pointeur. Et de ce fait accéder en lecture et en écriture à l’ensemble de la mémoire du processus. Cela veut dire théoriquement, techniquement et simplement que l’attaquant peut alors contrôler la totalité du programme et si cela ne vous suffit pas, voici un exemple simple technique et non théorique de ce que j’avance :
    (Exemple de programme vulnérable.)
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <stdio.h>
    #include <stdlib.h> 
     
    int main( void ){
     
    	char buffer[BUFSIZ];
    	(void)scanf( "%s\n", buffer );
    	(void)printf( "(1)\t:%s\nAddr\t", buffer );
    	(void)printf(buffer);
    	(void)printf("\nFin de programme\n");	
    	return (EXIT_SUCCESS);
    }
    Même le compilateur émet un avertissement précisément sur la question.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    source.c:19:15: warning: format string is not a string literal (potentially insecure) [-Wformat-security]
            (void)printf(buffer);
                         ^~~~~~
    source.c:19:15: note: treat the string as an argument to avoid this
            (void)printf(buffer);
                         ^
                         "%s", 
    1 warning generated.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    %p blabla
    (1)	:%p
    Addr	0x54600
    Fin de programme
    Je pense que je vais m’arrêter là de toute façon , j’ai écrit ce que j’ai jugé pertinent avec des remarques autres que printf ou des fameuses questions de vulnérabilité dans mon tout premier message.
    à bientôt

Discussions similaires

  1. La Sécurité dans Access
    Par Maxence HUBICHE dans le forum Sondages et Débats
    Réponses: 81
    Dernier message: 24/06/2007, 01h07
  2. printf et LARGE_INTEGER
    Par KORTA dans le forum C
    Réponses: 10
    Dernier message: 05/09/2003, 15h20
  3. les accents et printf
    Par remi77 dans le forum C
    Réponses: 5
    Dernier message: 07/07/2003, 20h53
  4. Pb de sécurité
    Par xtrips dans le forum Débuter
    Réponses: 6
    Dernier message: 16/04/2003, 07h50
  5. fonction printf
    Par ydeleage dans le forum C
    Réponses: 7
    Dernier message: 30/05/2002, 11h24

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