Vérification de formulaire avant envoi

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonsoir,

J'ai un formulaire avec plusieurs champs à vérifier ( texte, file, radio et select ).

J'ai un problème avec les champs select, j'ai essayé de mettre un FILTER_SANITIZE_STRING sur l'id des select, mais ça ne fonctionne pas.

Quelqu'un sait comment s'y prendre ?

Merci du coup de main :)

+0 -0
Auteur du sujet

Salut,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<div class="sejour">
                                <label for="sejour">Type de séjour : </label>
                                    <select name="sejour" id="sejour" required>
                                        <option value="" >Votre choix</option> 
                                        <option id="fam" value="famille">Famille</option>
                                        <option id="cp" value="couple">Couple</option>
                                        <option id="am" value="amis">Amis</option>
                                        <option id="so" value="solo">Voyage solo</option>
                                    </select>
                                <label for="herberg">Type d'hébergement : </label>
                                    <select name="heberg" id="heberg" required>
                                        <option value="">Votre choix</option>
                                        <option value="emplacement">Emplacement</option>
                                        <option value="mobile-home">Mobile Home</option>
                                        <option value="tente amenagee">Tente aménagée</option>
                                        <option value="maison/appartement">Maison-Appart</option>
                                    </select>

J'en ai 2 autres pour les mois et années.

Ce que je voudrai c'est savoir comment faire pour empêcher l'utilisateur de modifier les entrées ou pire envoyer des scripts via firebug par exemple.

Parce que j'ai testé avec une simple alert et ça passe sans problème …

Édité par clenake

+0 -0
Staff

Quelque chose comme ça devrait suffire je pense :

1
2
3
4
<?php
if(!in_array($_POST['sejour'], ['fam', 'cp', 'am', 'so'])){
    // Pas bon
}

Tu ne pourras jamais empêcher l'utilisateur d'entrer des valeurs erronées, mais tu peux gérer les cas où ça arrive.

Édité par viki53

Staff

Ce que je voudrai c'est savoir comment faire pour empêcher l'utilisateur de modifier les entrées ou pire envoyer des scripts via firebug par exemple.

C'est strictement impossible. La seule chose que tu peux faire c'est, côté serveur (donc PHP si j'ai bien compris dans ton cas) faire une vérification comme le propose viki.

+1 -0

Salut,

Tu ne pourras jamais empêcher quelqu'un d'envoyer n'importe quoi. Il faut que tu protéges les données reçus côté serveur. Toutes protections côté client est absolument inutile. Tu peux mettre des vérifications côté client, mais uniquement dans le but d'aide à l'utilisateur (le prévenir que tel champs est invalide, etc).

La protection dépendra du type de donnée attendu.

Pour un champs numérique, il faut tester que le champs soit bien un nombre, et le récupérer via intval:

1
2
if(is_numeric($_GET['num'])
    $value = intval($_GET['num'])

Si tu connais à l'avance le minimum et maximum qu'est censé prendre cette valeur, teste le.

Pour un champs de texte, il faut impérativement échapper les caractères spéciaux avec une fonction du type mysqli_real_escape_string (http://php.net/manual/fr/mysqli.real-escape-string.php). Et comme l'a montré viki53, si la valeur du champs n'est censé prendre que certaines valeurs, test le.

Pour l'uplaod d'un fichier, c'est plus complexe. Il faut vérifier l'extension (attention aux doubles extensions), le type mime, potentiellement d'autres choses suivant le type de fichier attendu.

Édité par harfang

+0 -0
Staff

Pour un champs numérique, il faut tester que le champs soit bien un nombre, et le récupérer via intval:

1
2
if(is_numeric($_GET['num'])
    $value = intval($_GET['num'])

harfang

Si le but est de récupérer un entier, autant utiliser ctype_digit, is_numeric autorisant les nombre décimaux.

Ou directement le filtre FILTER_VALIDATE_INT , histoire d'utiliser des trucs un peu plus modernes.

Édité par viki53

Auteur du sujet

Salut et merci de vos réponses.

Donc malgré toutes les vérif qu'on peut faire avant l'envoi, dans tous les cas il vaut mieux utiliser htmlspecialchars ou strip_tags à l'affichage.

Je vais finir et je posterai l'ensemble du traitement pour que vous puissiez me dire s'il y a des erreurs.

Edit: Au départ j'avais mis un strip_tags directement sur l'ensemble du formulaire. Est-ce que c'est une bonne méthode, ou mieux vaut éviter ?

Édité par clenake

+0 -0
Auteur du sujet

Bon finalement ça a été plus long que prévu parce que notepad a planté et j'ai perdu tout mon fichier traitement !

Du coup j'ai recommencé et je crois que c'est mieux :)

Voilà le code complet qui a l'air de fonctionner correctement

  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
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
<?php
$valid_formats = array("jpg", "png", "jpeg", "gif");
$max_file_size = 2000000; 
$max_file_uploads = 5;
$path = "photos/"; // Dossier de réception des fichiers
$count = 0;

//!empty vérifie que $_Files n'est pas vide 
if(!empty($_FILES['photos'])){
    // On fait une boucle de $_FILES pour executer et vérifier chaque fichier
    foreach ($_FILES['photos']['name'] as $f => $name) {     
        if ($_FILES['photos']['error'][$f] == 4) {
            continue; // Si les fichiers ne sont pas uploadés, on passe
        }          
        //S'il n'y a pas d'erreur
        if ($_FILES['photos']['error'][$f] == 0 AND $max_file_uploads <= 5) {
            if ($_FILES['photos']['size'][$f] > $max_file_size) {
                $message[] = "$name est trop gros!.";
                continue; // Si le fichier est trop gros, on le passe aussi + le message
            }

            //on vérifie maintenant l'extention
            elseif(! in_array(pathinfo(strtolower($name), PATHINFO_EXTENSION), $valid_formats)){
                $message[] = "$name n'est pas un format valide";
                continue; // Et si ce n'est pas bon, on passe le fichier avec la mauvaise extention + le message
            }

            else{ // S'il n'y a aucune erreur! On déplace les fichiers avec Move uploaded files 

                if(move_uploaded_file($_FILES['photos']['tmp_name'][$f], $path.$name)) {
                    $count++; // Compte le nombre de fichier correctement uploader
                }
            }
        }
    }   
}

// Récupère l'IP du visiteur

function get_ip() {
    // IP si internet partagé
    if (isset($_SERVER['HTTP_CLIENT_IP'])) {
        return $_SERVER['HTTP_CLIENT_IP'];
    }
    // IP derrière un proxy
    elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        return $_SERVER['HTTP_X_FORWARDED_FOR'];
    }
    // Sinon : IP normale
    else {
        return (isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '');
    }
}

// Déclaration des variables avant insertion en bdd

$profil = $_FILES['profil']['name'];
$name = $_POST['name'];
$sejour = $_POST['sejour'];
$heberg = $_POST['heberg'];
$mois = $_POST['mois'];
$annee = $_POST['annee'];
$acceuil = $_POST['acceuil'];
$hebergement = $_POST['hebergement'];
$proprete = $_POST['proprete'];
$services = $_POST['services'];
$loisirs = $_POST['loisirs'];
$animations = $_POST['animations'];
$prix = $_POST['prix'];
$IP = 
$avis = $_POST['avis'];
$dep_id = $_POST['dep_id'];
$campings_id = $_POST['campings_id'];

$album = $_FILES['photos']['name'];
$photos = serialize($album);

// round arrondit la moyenne et *2 / 2 permet d'aller au 0.5 le plus proche
$note = ($acceuil + $hebergement + $proprete + $services + $loisirs + $animations + $prix)/7;
$moyenne = round($note * 2) / 2;


// Insertion dans la base de donnée

$req = $bdd->prepare('INSERT INTO modale(profil, name, sejour, heberg, mois, annee, acceuil, hebergement, proprete, services, loisirs, animations, prix, moyenne, photos, avis, date_avis, IP, dep_id, campings_id) 
VALUES(:profil, :name, :sejour, :heberg, :mois, :annee, :acceuil, :hebergement, :proprete, :services, :loisirs, :animations, :prix, :moyenne, :photos, :avis, NOW(), :IP, :dep_id, :campings_id)');
$req->execute(array(
    'profil' => $profil,
    'name' => $name,
    'sejour' => $sejour,
    'heberg' => $heberg,
    'mois' => $mois,
    'annee' => $annee,
    'acceuil' => $acceuil,
    'hebergement' => $hebergement,
    'proprete' => $proprete,
    'services' => $services,
    'loisirs' => $loisirs,
    'animations' => $animations,
    'prix' => $prix,
    'moyenne' => $moyenne,
    'photos' => $photos,
    'avis' => $avis,
    'IP' => get_ip(),
    'dep_id' => $dep_id,
    'campings_id' => $campings_id
    ));


// Vérification de tous les champs du form (hors upload)    

if(!in_array($_POST['sejour'], ['famille', 'couple', 'amis', 'solo']) 
OR !in_array($_POST['heberg'], ['emplacement', 'mobile-home', 'tente amenagee', 'maison/appartement'])
OR !in_array($_POST['mois'], ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'])
){
    echo 'Choisissez parmi les propositions de la liste.';
}   
elseif(strlen($_POST['name']) <5){
    echo 'Votre pseudo est trop court.';
}
else{
$options = array(
    'name' => FILTER_SANITIZE_STRING, //Enlever les balises.
    'avis' => FILTER_SANITIZE_STRING,
    'acceuil' => array(
        'filter' => FILTER_VALIDATE_INT, //Valider l'entier.
        'options' => array(
            'min_range' => 1, //Minimum 1.
            'max_range' => 10
        )
    ),
    'hebergement' => array(
        'filter' => FILTER_VALIDATE_INT, //Valider l'entier.
        'options' => array(
            'min_range' => 1, //Minimum 1.
            'max_range' => 10
        )
    ),
    'proprete' => array(
        'filter' => FILTER_VALIDATE_INT, //Valider l'entier.
        'options' => array(
            'min_range' => 1, //Minimum 1.
            'max_range' => 10
        )
    ),
    'services' => array(
        'filter' => FILTER_VALIDATE_INT, //Valider l'entier.
        'options' => array(
            'min_range' => 1, //Minimum 1.
            'max_range' => 10
        )
    ),
    'loisirs' => array(
        'filter' => FILTER_VALIDATE_INT, //Valider l'entier.
        'options' => array(
            'min_range' => 1, //Minimum 1.
            'max_range' => 10
        )
    ),
    'animations' => array(
        'filter' => FILTER_VALIDATE_INT, //Valider l'entier.
        'options' => array(
            'min_range' => 1, //Minimum 1.
            'max_range' => 10
        )
    ),
    'prix' => array(
        'filter' => FILTER_VALIDATE_INT, //Valider l'entier.
        'options' => array(
            'min_range' => 1, //Minimum 1.
            'max_range' => 10
        )
    ),
    'annee' => array(
        'filter' => FILTER_VALIDATE_INT,
        'options' => array(
            'min_range' => 2010,
            'max_range' => 2025
        )
    )
);

$resultat = filter_input_array(INPUT_POST, $options);

if($resultat != null) { //Si le formulaire a bien été posté.
    //Enregistrer des messages d'erreur perso.
    $messageErreur = array(
        'name' => 'Votre pseudo est trop court.',
        'avis' => 'Veuillez écrire un commentaire.',
        'acceuil' => 'Choississez une note comprise entre 1 et 10 pour l\'acceuil !',
        'hebergement' => 'Choississez une note comprise entre 1 et 10 pour l\'hébergement !',
        'proprete' => 'Choississez une note comprise entre 1 et 10 pour la propreté !', 
        'services' => 'Choississez une note comprise entre 1 et 10 pour les services !',
        'loisirs' => 'Choississez une note comprise entre 1 et 10 pour les loisirs !',
        'animations' => 'Choississez une note comprise entre 1 et 10 pour les animations !',
        'prix' => 'Choississez une note comprise entre 1 et 10 pour le rapport qualité/prix !',
        'annee' => 'Choisissez une date de la liste'
    );

    $nbrErreurs = 0;

    foreach($options as $cle => $valeur) { //Parcourir tous les champs voulus.
        if(empty($_POST[$cle])) { //Si le champ est vide.
            echo 'Veuillez remplir le champ ' . $cle . '.<br/>';
            $nbrErreurs++;
        }
        elseif($resultat[$cle] === false) { //S'il n'est pas valide.
            echo $messageErreur[$cle] . '<br/>';
            $nbrErreurs++;
        }
    }

    if($nbrErreurs == 0) {
    header('Location:http://localhost/TEST avec JS/campings/Modale/affichage.php?dep_id='.$dep_id.'&campings_id='.$campings_id.'');
    }
}
else {
    echo 'Vous devez remplir le formulaire complet si vous voulez poster.';
}
}

Dites moi s'il y a des erreurs ou des trucs à ne pas faire.

Merci

Édité par Ymox

+0 -0

Salut,

Si deux utilisateurs upload une photo qui possède le même nom, l'une écrase l'autre.

Si un utilisateur upload une photo qui a pour nom par exemple : "../un-dossier-qui-existe/a.jpg" il pourra uploader son image dans n'importe quel dossier.

Bref, génère un nom unique pour l'upload ! :)

++

+0 -0
Staff

Si un utilisateur upload une photo qui a pour nom par exemple : "../un-dossier-qui-existe/a.jpg" il pourra uploader son image dans n'importe quel dossier.

jeremylevy

Comment tu veux uploader ce genre de nom, sachant qu'il contient des caractères interdits dans les noms de fichiers ? :euh:

Édité par viki53

Le nom du fichier est passé dans la requête HTTP :

Content-Disposition: form-data; name="img"; filename="a.png"

Il suffit de le modifier en faisant la requête avec CURL par exemple :)

http://www.acunetix.com/websitesecurity/php-security-4/

http://security.stackexchange.com/questions/43183/is-it-possible-for-a-hacker-to-bypass-upload-php-file

++

Édité par jeremylevy

+0 -0

@clenake : je me suis permis d'éditer ton message (même si c'était un peu "tardivement") pour mettre la coloration syntaxique sur ton code. Si jamais, pour que le PHP soit coloré sur Zeste de Savoir, il faut le <?php devant  ;)

Édité par Ymox

Evitez qu'on vous dise de les lire : FAQ PHP et Symfony 2Tutoriel WAMP • Cliquez 👍 pour dire merci • Marquez vos sujets résolus

+0 -0
Auteur du sujet

Désolée Ymox j'avais pas fait gaffe !

@viki53 : en gros il faut que je vérifie la présence de chacun de mes $_POST et autre avant. OK

@jeremylevy : J'ai essayé d'utiliser uniqid() pour changer le nom des photos up, mais je m'y prends comme un manche parce que ça fonctionne pas du tout !

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte