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

  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2017
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 25
    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 801
    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 801
    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 801
    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 801
    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

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 801
    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 801
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    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)"
    Ben déjà tu triches car la notion "string" n'existe pas en C donc tu ne pourras jamais voir nulle part printf(string) dans aucun bouquin valable de C. Mais sinon dans le K&R (premier lien de mon post précédent) en page 151 => int printf(char *format, arg1, ...). Ca signifie que le premier argument a tout a fait le droit d'être un char * (ce qui est l'équivalent C d'une string). Autre question ???

    Citation Envoyé par sambia39 Voir le message
    Bref, ce n’est pas le moment de parler de vulnérabilité, soit, je peux concevoir ;
    Alors pourquoi tu insistes ???

    Citation Envoyé par sambia39 Voir le message
    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.
    Pfff arrête avec tes lieux communs et tes phrases toutes faites qui ne s'appuient sur rien. Je ne parle pas d'honnêteté ou de malhonnêteté mais de moment. Quand tu construits une maison, est-ce que tu commences par faire l'étanchéïté des fenêtres ??? As-tu vu les ravages qu'ont fait la théorie des ensembles enseignée en 6° à des cerveaux tout juste sortis de la division ???

    Citation Envoyé par sambia39 Voir le message
    Sur ce qui suit, je vais te rembarrer avec ma fameuse science théorique.
    Ouais, vas-y, apprends-moi le C

    Citation Envoyé par sambia39 Voir le message
    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 :...
    Ouais bon t'as franchement rien compris de ce que je te dis (ou alors tu fais exprès). Je ne discute pas de la fiabilité de printf() mais du moment d'en parler à un débutant qui a autre chose à penser.

    Citation Envoyé par sambia39 Voir le message
    Même le compilateur émet un avertissement précisément sur la question.
    Euh non, pas le mien. Je veux bien toutefois admettre qu'il le pourrait si on lui donnait la bonne option mais je n'ai pas réussi avec celles que je connais.
    Pièce jointe 272626

    Accessoirement je viens de relire les premiers codes de Deezio et les premiers arguments de ses printf() sont tous issus de chaines en dur de son code donc ne sont pas contrôlables par l'utilisateur !!! Bref ses printf() sont tous fiables.
    Images attachées Images attachées  
    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]

  8. #8
    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,

    Citation Envoyé par Sve@r Voir le message
    Ben déjà tu triches car la notion "string" n'existe pas en C donc tu ne pourras jamais voir nulle part printf(string) dans aucun bouquin valable de C. Mais sinon dans le K&R (premier lien de mon post précédent) en page 151 => int printf(char *format, arg1, ...). Ca signifie que le premier argument a tout a fait le droit d'être un char * (ce qui est l'équivalent C d'une string). Autre question ???
    Non ça sera une réponse; Tout d'abord voici ce que Deezio a écrit:
    Citation Envoyé par Deezio Voir le message
    Bonjour, j'ai un problème, lorsque je lance mon programme, j'ai une erreur de segmentation. Je pense que cela vient de mon utilisation des pointeurs qui ne doit pas être encore au point. C'est pour cela que je viens vous demandé de l'aide, j'ai beau réfléchir je ne vois pas vraiment d'où ça peut venir.
    J'ai eu cette erreur dans deux programme : "my_revstr" et "my_strstr".
    Je vous laisse les codes ci-dessous :
    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);
    }
    .....
    Ce n’est pas à moi qu’il faut le dire ce n'est pas ce que j'ai écrit:
    Citation Envoyé par sambia39 Voir le message
    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)

    à bientôt
    Ensuite ceci:
    Citation Envoyé par sambia39 Voir le message
    Bonjour
    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
    Et ceci:
    Citation Envoyé par sambia39 Voir le message
    Bonsoir
    Je suis poli donc je commence par écrire bonsoir ou bonjour.

    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 également :
    Citation Envoyé par Sve@r Voir le message
    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..."
    C'est sûr tu as lu en diagonale. Je ne vois pas comment je peux tricher..... "printf(string)"

    Citation Envoyé par Sve@r Voir le message
    Alors pourquoi tu insistes ???
    Tout simplement parce que l’emploi de la fonction printf(string) est fausse et le programme devient exploitable. Donc, oui, je le dis. C’est un truc à ne pas faire. Et toi tu t’emballes et tu te lances dans une croisade... J’insiste également parce que tu admets pas que c’est une erreur.

    Citation Envoyé par Sve@r Voir le message
    Ouais bon t'as franchement rien compris de ce que je te dis (ou alors tu fais exprès). Je ne discute pas de la fiabilité de printf() mais du moment d'en parler à un débutant qui a autre chose à penser.
    Un étudiant curieux posera la question suivante: Pourquoi on ne doit pas écrire comme ça: et comme tes un bon pédagogue je te laisse le plaisir de le lui expliquer avec franchise pourquoi

    Ouais, vas-y, apprends-moi le C


    Ouais bon t'as franchement rien compris de ce que je te dis (ou alors tu fais exprès). Je ne discute pas de la fiabilité de printf() mais du moment d'en parler à un débutant qui a autre chose à penser.


    Euh non, pas le mien. Je veux bien toutefois admettre qu'il le pourrait si on lui donnait la bonne option mais je n'ai pas réussi avec celles que je connais.
    Pièce jointe 272626

    Accessoirement je viens de relire les premiers codes de Deezio et les premiers arguments de ses printf() sont tous issus de chaines en dur de son code donc ne sont pas contrôlables par l'utilisateur !!! Bref ses printf() sont tous fiables.
    As-tu essayé avec ceci -Wformat-security avec le code de Deezio et ensuite le mien ?
    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
    root@lab:~# uname -a      
    Linux lab 2.6.32-042stab123.1 #1 SMP Wed Mar 22 15:21:30 MSK 2017 x86_64 GNU/Linux
    root@lab:~# gcc --version 
    gcc (Debian 4.9.2-10) 4.9.2
    Copyright (C) 2014 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    
    root@lab:~# gcc -Wall -pedantic -ansi -Wformat-security source.c -o Deb 
    source.c: In function 'my_revstr':
    source.c:9:2: warning: implicit declaration of function 'strcpy' [-Wimplicit-function-declaration]
      strcpy(string, str);
      ^
    source.c:9:2: warning: incompatible implicit declaration of built-in function 'strcpy'
    source.c:10:2: warning: implicit declaration of function 'strlen' [-Wimplicit-function-declaration]
      len = strlen(string);
      ^
    source.c:10:8: warning: incompatible implicit declaration of built-in function 'strlen'
      len = strlen(string);
            ^
    source.c: In function 'main':
    source.c:21:2: warning: format not a string literal and no format arguments [-Wformat-security]
      printf(string);
      ^
    source.c:23:2: warning: format not a string literal and no format arguments [-Wformat-security]
      printf(string);
      ^
    source.c: In function 'my_revstr':
    source.c:16:1: warning: control reaches end of non-void function [-Wreturn-type]
     }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    root@lab:~# gcc -Wall -pedantic -ansi -Wformat-security source.c -o Deb 
    source.c: In function 'main':
    source.c:9:2: warning: format not a string literal and no format arguments [-Wformat-security]
      (void)printf(buffer);
      ^
    root@lab:~#
    Sur clang ça me donne également ce qui suit ci-dessous pour le cas de Deezio mais bon ce n’est qu’un détail:
    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
    source.c:19:2: warning: implicitly declaring library function 'strcpy' with type 'char *(char *, const char *)' [-Wimplicit-function-declaration]
            strcpy(string, str);
            ^
    source.c:19:2: note: include the header <string.h> or explicitly provide a declaration for 'strcpy'
    source.c:20:8: warning: implicitly declaring library function 'strlen' with type 'unsigned long (const char *)' [-Wimplicit-function-declaration]
            len = strlen(string);
                  ^
    source.c:20:8: note: include the header <string.h> or explicitly provide a declaration for 'strlen'
    source.c:26:1: warning: control reaches end of non-void function [-Wreturn-type]
    }
    ^
    source.c:31:9: warning: format string is not a string literal (potentially insecure) [-Wformat-security]
            printf(string);
                   ^~~~~~
    source.c:31:9: note: treat the string as an argument to avoid this
            printf(string);
                   ^
                   "%s", 
    source.c:33:9: warning: format string is not a string literal (potentially insecure) [-Wformat-security]
            printf(string);
                   ^~~~~~
    source.c:33:9: note: treat the string as an argument to avoid this
            printf(string);
                   ^
                   "%s", 
    5 warnings generated.
    C’est dommage que tu n’aies pas exécuté le programme ou fait plus de tests.
    Code C : 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
    #include <stdio.h>
    #include <stdlib.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()
    {
    	/*
    	*	Je modifie légèrement string
    	*	et j'ajoute un getchar()
    	*	pour une pause pour le test car juste aprés
    	*	il y'a une erreur de segmentation.
    	*/
    	char string[12] = "%p bizare...\0";
    	printf(string);
    	getchar();
    	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
    25
    26
    27
    28
     
    source.c:19:2: warning: implicitly declaring library function 'strcpy' with type 'char *(char *, const char *)' [-Wimplicit-function-declaration]
            strcpy(string, str);
            ^
    source.c:19:2: note: include the header <string.h> or explicitly provide a declaration for 'strcpy'
    source.c:20:8: warning: implicitly declaring library function 'strlen' with type 'unsigned long (const char *)' [-Wimplicit-function-declaration]
            len = strlen(string);
                  ^
    source.c:20:8: note: include the header <string.h> or explicitly provide a declaration for 'strlen'
    source.c:26:1: warning: control reaches end of non-void function [-Wreturn-type]
    }
    ^
    source.c:37:9: warning: format string is not a string literal (potentially insecure) [-Wformat-security]
            printf(string);
                   ^~~~~~
    source.c:37:9: note: treat the string as an argument to avoid this
            printf(string);
                   ^
                   "%s", 
    source.c:40:9: warning: format string is not a string literal (potentially insecure) [-Wformat-security]
            printf(string);
                   ^~~~~~
    source.c:40:9: note: treat the string as an argument to avoid this
            printf(string);
                   ^
                   "%s", 
    5 warnings generated.
    0x7fff5091e808 bizare...
    Pour conclure; Continue si tu le souhaites moi je m’arrête là.
    à bientôt.

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 801
    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 801
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    C'est sûr tu as lu en diagonale. Je ne vois pas comment je peux tricher..... "printf(string)"
    Non là c'est carrément de l'hypocrisie. Tu m'as demandé de te trouver printf(string), style "expression générique", dans un bouquin de C. Je te dis que l'expression générique "string" ne peut pas se trouver parce que la notion de "string" n'existe pas. Et là tu me dis "sisi il a écrit printf(string)". Ben oui, mais dans son code "string" est le nom de sa variable, ce n'est plus une notion !!!
    Et donc si demain il écrit char *toto="bonjour"; printf(toto) et que je te dis "c'est autorisé" tu viendras me dire "non ça ne l'est pas car on ne voit nulle part printf(toto) dans un bouquin" ??? Putain mais là ce n'est plus de l'incompréhension, c'est carrément de la mauvaise foi, !!!!!!!

    Citation Envoyé par sambia39 Voir le message
    Tout simplement parce que l’emploi de la fonction printf(string) est fausse et le programme devient exploitable. Donc, oui, je le dis. C’est un truc à ne pas faire. Et toi tu t’emballes et tu te lances dans une croisade... J’insiste également parce que tu admets pas que c’est une erreur.
    Bon, ok, nul n'est plus sourd que celui qui ne veut pas comprendre. Et dans ton cas, nul n'est plus crétin que celui qui ne veut pas réfléchir. Je te le redis que ce n'est pas de la fiabilité de printf() que je discute, mais du moment d'en parler !!! Et les erreurs de son code ne sont pas dues à printf() mais plutôt à sa boucle (et certainement à sa variable "len" qui décroit durant la boucle).

    Citation Envoyé par sambia39 Voir le message
    As-tu essayé avec ceci -Wformat-security avec le code de Deezio et ensuite le mien ?
    Ben non, je t'ai montré tout ce que j'avais essayé. Alors ok, avec -Wformat -Wformat-security ça me ressort des warnings mais bon, je te le redis (tout en sachant que tu feras exprès de ne pas le lire) que je ne discute pas de la vulnérabilité de printf() mais du bon moment d'en parler à un débutant qui a autre chose à réfléchir !!!

    Citation Envoyé par sambia39 Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    root@lab:~# gcc -Wall -pedantic -ansi -Wformat-security source.c -o Deb 
    source.c: In function 'main':
    source.c:9:2: warning: format not a string literal and no format arguments [-Wformat-security]
      (void)printf(buffer);
      ^
    root@lab:~#
    Putain le mec il fait la morale aux autres sur la sécurité et il bosse sous root !!! Tu sais que tu en deviens risible ???
    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]

  10. #10
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 492
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 492
    Billets dans le blog
    1
    Par défaut
    Dans le contexte de la discussion originale, je pense aussi le conseil anti printf() extrême. Celui de strcpy() un peu moins, mais quand même un peu. C'est un débutant, il a d'autres soucis à régler avant

    Reprenons cet obscur warning de gcc, que je n'avais jamais vu :
    -Wformat-security
    If -Wformat is specified, also warn about uses of format functions that represent possible security problems. At present, this warns about calls to printf and scanf functions where the format string is not a string literal and there are no format arguments, as in printf (foo);. This may be a security hole if the format string came from untrusted input and contains `%n'. (This is currently a subset of what -Wformat-nonliteral warns about, but in future warnings may be added to -Wformat-security that are not included in -Wformat-nonliteral.)
    Pour moi, cela confirme de l'extremité de parler de ça à un débutant. Surtout vu le code qui ne fait pas appel à une chaine venue d'une source inconnue.

    Je dis aussi merci car je suis un développeur averti et je n'étais pas (plus ?) au courant de ce risque.

  11. #11
    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
    Citation Envoyé par Sve@r Voir le message
    Putain le mec il fait la morale aux autres sur la sécurité et il bosse sous root !!! Tu sais que tu en deviens risible ???
    Oui et j'assume complètement. j’ai même préparé la suite au cas où tu voudrais voir ce qui se passerait que l’on soit sous root ou non et pour infos tous ces tests sont faites sous machine virtuelle. Je suis même prêt à mettre à ta disposition un VPS afin que tu puisses effectuer des tests de l'exploite de manière poussée pour que tu puisses voir à quels points ça pourrait être évident le mauvais emploi de la fonction printf(ma_variable);.

    à bientôt

  12. #12
    Responsable Systèmes


    Homme Profil pro
    Gestion de parcs informatique
    Inscrit en
    Août 2011
    Messages
    18 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Gestion de parcs informatique
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : Août 2011
    Messages : 18 160
    Par défaut
    Pour comprendre un peu mieux scanf :
    http://xrenault.developpez.com/tutoriels/c/scanf/
    Ma page sur developpez.com : http://chrtophe.developpez.com/ (avec mes articles)
    Mon article sur le P2V, mon article sur le cloud
    Consultez nos FAQ : Windows, Linux, Virtualisation

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