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

  1. #1
    Membre à l'essai
    Homme Profil pro
    Invalidité
    Inscrit en
    mai 2019
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Invalidité

    Informations forums :
    Inscription : mai 2019
    Messages : 52
    Points : 15
    Points
    15

    Par défaut Entrer une chaîne de caractères de façon sécurisée

    Je connais la fonction fgets mais je me demandais s'il n'existait pas une fonction peut etre plus sécurisé pour rentrer une chaine de caractere .
    Si je demande d'entrer un prenom par exemple ,cette fonction comptabiliserai le nombre de caractere rentré au clavier et allouera dynamiquement juste ce qu'il faut d'emplacement memoire pour le stocker . Peut etre un truc de ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    define MAX 30
    int main(void){
     char nom[MAX];
     int nb;
     
     printf("Votre prenom?");
     scanf("%s",nom);
     nb=strlen(nom);
     malloc(sizeof(char)*nb;
     printf("Votre prenom est :%s\n",nom);
    return 0;}
    Merci de votre aide

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 359
    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 : 7 359
    Points : 20 966
    Points
    20 966
    Billets dans le blog
    1

    Par défaut

    Bonjour à toi aussi
    Citation Envoyé par chris7522 Voir le message
    Je connais la fonction fgets mais je me demandais s'il n'existait pas une fonction peut etre plus sécurisé pour rentrer une chaine de caractere .
    Tout dépend de ce que tu entends par "sécurisé"...

    Citation Envoyé par chris7522 Voir le message
    Si je demande d'entrer un prenom par exemple ,cette fonction comptabiliserai le nombre de caractere rentré au clavier et allouera dynamiquement juste ce qu'il faut d'emplacement memoire pour le stocker .
    Mouais. Enfin si on n'entre pas plus de 29 caractères et surtout si, en plus de corriger l'erreur de syntaxe avec la parenthèse manquante (je te rappelle qu'on attend des intervenants un code qui compile), tu récupères la zone allouée par malloc() !!!!!!!

    Et (cela va habituellement sans dire mais apparemment ici cela ira encore mieux en te le disant) si tu recopies dans la zone allouée ce qui a été saisi dans la zone temporaire....

    Perso si c'est pour le plaisir de programmer alors j'aurais plutôt vu un truc basé sur une lecture en boucle de stdin caractère par caractère et stockage avec allocation et réallocation au fur et à mesure.
    Et bien entendu, une allocation un petit peu optimisée c'est à dire de N et N (et non de 1 en 1 !!!)

    Maintenant si c'est pour de l'opérationnel, alors tu as getline() qui fait exactement ça...
    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

  3. #3
    Membre à l'essai
    Homme Profil pro
    Invalidité
    Inscrit en
    mai 2019
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Invalidité

    Informations forums :
    Inscription : mai 2019
    Messages : 52
    Points : 15
    Points
    15

    Par défaut

    C'est vrai que j'ai oublié l'essentiel , bonjour a toutes et a tous , surtout a toutes que malheureusement je n'entends jamais. Et merci a toi , de repondre a mes questions de debutant

  4. #4
    Membre expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    469
    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 : 469
    Points : 1 747
    Points
    1 747

    Par défaut

    Bonjour,
    En plus des remarques faites (fuite mémoire en cours d'exécution du programme, dû au fait que vous allouez de la mémoire dans le vide "si entre-temps vous avez ajouté la parenthèse fermante manquante"; sans oublier le # du define, mais également, la vulnérabilité que vous avez créée par l'utilisation du printf("Votre prenom?"); avec une chaîne de caractères non contenus dans une variable et qui peut tout à fait être remplacée/corriger par puts) et peut importer votre niveau débutant ou pas, vous êtes capable de lire et comprendre à votre niveau de débutant; pourquoi le compilateur ne compile pas ou ne génère pas le fichier exécutable souhaité à cause des messages d'erreur de ce genre "unknown type name 'define'.

    En ce qui concerne la sécurité des saisies, il va falloir attendre un peu et avoir des notions solides avant d'aborder le sujet ou comment l'on procède.
    À bientôt,
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  5. #5
    Membre à l'essai
    Homme Profil pro
    Invalidité
    Inscrit en
    mai 2019
    Messages
    52
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Invalidité

    Informations forums :
    Inscription : mai 2019
    Messages : 52
    Points : 15
    Points
    15

    Par défaut

    Merci beaucoup d'avoir prit le temps de me repondre

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    26 973
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 26 973
    Points : 40 001
    Points
    40 001

    Par défaut

    Euh, printf("Votre prenom?");, bien que pas forcément une bonne pratique, ne contient pas de vulnérabilité... (par contre, selon la plate-forme, il est possible qu'il s'affiche trop tard)
    Je n'en dirais pas autant du scanf("%s") qui le suit (vulnérabilité de saisie sans limite de taille). Pour ça il vaut mieux utiliser fgets() ou, sur une plate-forme compatible, getline().
    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 expérimenté
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    469
    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 : 469
    Points : 1 747
    Points
    1 747

    Par défaut

    Citation Envoyé par Médinoc Voir le message
    Euh, printf("Votre prenom?");, bien que pas forcément une bonne pratique, ne contient pas de vulnérabilité... (par contre, selon la plate-forme, il est possible qu'il s'affiche trop tard)
    @Médinoc: Effectivement vue sous cet angle, la chaîne littérale constante n’est pas à proprement parler une vulnérabilité. La raison pour laquelle j’ai avancé une vulnérabilité vient du fait que l’on peut aisément (qui dans le contexte actuel n’est pas à aborder ); modifier la chaîne constante écrite en dur dans le fichier exécutable par les séquences telles que %p %x %x %x %s ce qui aux finals donnes toujours une chaîne littérale constante convertie en pointeur sur le premier caractère, mais avec la particularité d’explorer la pile; pour les besoins d’illustration j’ai volontairement ajouté memset(nom,65,MAX) avants l’appel a la fonction printf ;
    labpent: Desktop user26$ gcc source.c -Wall -Werror -Wformat -o Deb
    labpent: Desktop user26$ r2 ./Deb
    -- We don't make mistakes... just happy little segfaults.
    [0x100000e80]> aaa
    [x] Analyze all flags starting with sym. and entry0 (aa)
    [x] Analyze function calls (aac)
    [x] Analyze len bytes of instructions for references (aar)
    [x] Check for objc references
    [x] Check for vtables
    [x] Type matching analysis for all functions (aaft)
    [x] Use -AA or aaaa to perform additional experimental analysis.
    [0x100000e80]> pdf @main
    ;-- main:
    ;-- section.0.__TEXT.__text:
    ;-- _main:
    ;-- func.100000e80:
    / (fcn) entry0 168
    | entry0 ();
    | ; var int32_t var_4ch @ rbp-0x4c
    | ; var char *var_48h @ rbp-0x48
    | ; var int32_t var_40h @ rbp-0x40
    | ; var int32_t var_3ch @ rbp-0x3c
    | ; var size_t var_38h @ rbp-0x38
    | ; var int32_t var_34h @ rbp-0x34
    | ; var char *s @ rbp-0x30
    | ; var int32_t var_8h @ rbp-0x8
    | 0x100000e80 55 push rbp ; [00] -r-x section size 170 named 0.__TEXT.__text
    | 0x100000e81 4889e5 mov rbp, rsp
    | 0x100000e84 4883ec50 sub rsp, 0x50 ; 'P'
    | 0x100000e88 b81e000000 mov eax, 0x1e ; 30
    | 0x100000e8d 89c2 mov edx, eax ; size_t n
    | 0x100000e8f 488d7dd0 lea rdi, [s] ; void *s
    | 0x100000e93 488b0d760100. mov rcx, qword [reloc.__stack_chk_guard] ; MOV rcx = [0x100001010] = 0x0 rflags
    | ; [0x100001010:8]=0
    | 0x100000e9a 488b09 mov rcx, qword [rcx]
    | 0x100000e9d 48894df8 mov qword [var_8h], rcx
    | 0x100000ea1 c745cc000000. mov dword [var_34h], 0
    | 0x100000ea8 be41000000 mov esi, 0x41 ; 'A' ; 65 ; int c
    | 0x100000ead e87e000000 call sym.imp.memset ; void *memset(void *s, int c, size_t n)
    | 0x100000eb2 488d3dd10000. lea rdi, str.Votre_prenom ; section.3.__TEXT.__cstring
    | ; 0x100000f8a ; "Votre prenom?" ; const char *format
    | 0x100000eb9 b000 mov al, 0
    | 0x100000ebb e876000000 call sym.imp.printf ; int printf(const char *format)
    | 0x100000ec0 488d75d0 lea rsi, [s]
    | 0x100000ec4 488d3dcd0000. lea rdi, [0x100000f98] ; "%s" ; const char *format
    | 0x100000ecb 8945c4 mov dword [var_3ch], eax
    | 0x100000ece b000 mov al, 0
    | 0x100000ed0 e867000000 call sym.imp.scanf ; int scanf(const char *format)
    | 0x100000ed5 488d4dd0 lea rcx, [s]
    | 0x100000ed9 4889cf mov rdi, rcx ; const char *s
    | 0x100000edc 8945c0 mov dword [var_40h], eax
    | 0x100000edf 48894db8 mov qword [var_48h], rcx
    | 0x100000ee3 e85a000000 call sym.imp.strlen ; size_t strlen(const char *s)
    | 0x100000ee8 4189c0 mov r8d, eax
    | 0x100000eeb 448945c8 mov dword [var_38h], r8d
    | 0x100000eef 488d3da50000. lea rdi, str.Votre_prenom_est_:_s ; 0x100000f9b ; "Votre prenom est :%s\n" ; const char *format
    | 0x100000ef6 488b75b8 mov rsi, qword [var_48h]
    | 0x100000efa b000 mov al, 0
    | 0x100000efc e835000000 call sym.imp.printf ; int printf(const char *format)
    | 0x100000f01 488b0d080100. mov rcx, qword [reloc.__stack_chk_guard] ; MOV rcx = [0x100001010] = 0x0 rflags
    | ; [0x100001010:8]=0
    | 0x100000f08 488b09 mov rcx, qword [rcx]
    | 0x100000f0b 488b55f8 mov rdx, qword [var_8h]
    | 0x100000f0f 4839d1 cmp rcx, rdx
    | 0x100000f12 8945b4 mov dword [var_4ch], eax
    | ,=< 0x100000f15 0f8508000000 jne 0x100000f23
    | | 0x100000f1b 31c0 xor eax, eax
    | | 0x100000f1d 4883c450 add rsp, 0x50 ; 'P'
    | | 0x100000f21 5d pop rbp
    | | 0x100000f22 c3 ret
    | | ; CODE XREF from entry0 (0x100000f15)
    \ `-> 0x100000f23 e802000000 call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
    [0x100000e80]> / Votre
    Searching 5 bytes in [0x100002000-0x100003000]
    hits: 0
    Searching 5 bytes in [0x100001000-0x100002000]
    hits: 0
    Searching 5 bytes in [0x100000000-0x100001000]
    hits: 2
    0x100000f8a hit0_0 .hAVotre prenom?%sVotr.
    0x100000f9b hit0_1 .otre prenom?%sVotre prenom est :%s.
    [0x100000e80]> s 0x100000f8a
    [0x100000f8a]> ps
    Votre prenom?
    [0x100000f8a]> oo++
    [0x100000f8a]> w %p %x %x %x %s
    [0x100000f8a]> q
    labpent: Desktop user26$ ./Deb
    0x4141414141414141 0 aade00e6 0 (null)?3?f?bonjour
    Votre prenom est :bonjour
    labpent: Desktop user26$


    Certes, ce n’est pas un vecteur à proprement parler qui est du type printf(ma variable), mais elle permet d’entrevoir et illustre une mauvaise pratique ; ce qu’il faut retenir ici: l’utilisation d'une chaîne de format non littéral est considérée comme une mauvaise pratique et l’utilisation une chaîne de format dont on n’a pas le contrôle est bien pire encore.
    à bientôt.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

Discussions similaires

  1. Réponses: 8
    Dernier message: 12/02/2013, 01h08
  2. Saisie et affichage d'une chaîne de caractères
    Par sali dans le forum Assembleur
    Réponses: 2
    Dernier message: 31/03/2004, 18h01
  3. [Debutant(e)] Analyse d'une chaîne de caractères
    Par maire106 dans le forum Langage
    Réponses: 6
    Dernier message: 22/03/2004, 15h04
  4. Inverser une chaîne de caractères
    Par DBBB dans le forum Assembleur
    Réponses: 2
    Dernier message: 30/03/2003, 11h09
  5. Réponses: 3
    Dernier message: 09/05/2002, 01h39

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