Programmation Web Sites dynamiques et bases de données Mathieu Lacroix I.U.T. de Villetaneuse Année 2015-2016 E-mail : mathieu.lacroix@iutv.univ-paris13.fr Page Web : http: // www-lipn. univ-paris13. fr/ ~lacroix/ Mathieu Lacroix Programmation Web 1 / 40
Plan 1 Programmation orientée objet en PHP 2 PHP et bases de données 3 Sécurité Mathieu Lacroix Programmation Web 2 / 40
Plan 1 Programmation orientée objet en PHP 2 PHP et bases de données 3 Sécurité Mathieu Lacroix Programmation Web 3 / 40
Syntaxe Proche du java : classes, héritage, interfaces. Définition d une classe class nomclass { //Attributs et méthodes } Visibilité : public, private ou protected. Noms des attributs : $attribut (lors de la déclaration). Constructeur : construct(). $this : référence à l objet sur lequel est appelée la méthode. Possibilité d attributs ou méthode statiques (static) Possibilité de constantes de classes (const) Mathieu Lacroix Programmation Web 4 / 40
Définition d une classe Exemple class Joueur { public $login; //attribut login (publique) private $score; //attribut score (privé) const NOM_JEU = "Tarot"; //Constante NOM_JEU de valeur Tarot public function construct($ch,$ent) { //Teste si la valeur $ent correspond à un entier if (((string) $ent) === ((string)(int) $ent)) $this->score = $ent; else $this->score = 0; } if (trim($ch)!= ) $this->login = $ch; else $this->login = anonymous ; Mathieu Lacroix Programmation Web 5 / 40
Définition d une classe Exemple public function score() { return $this->score; } public function gagne($score) { if (((string) $score) === ((string)(int) $score)) $this->score += $score; } } Mathieu Lacroix Programmation Web 6 / 40
Utilisation d une classe Exemple Instanciation : new suivi du nom de la classe Accès aux méthodes et attributs : $objet->attribut ou $objet->methode() Accès aux attributs ou méthodes statiques (ou constantes) : NOM_CLASSE::attribut ou NOM_CLASSE::methode() echo <p> Jeu :. Joueur::NOM_JEU. </p> ; $j1 = new Joueur( sky,33); $j2 = new Joueur( Dark,755); $j1->gagne(180); echo <p> Scores :. $j1->login. a. $j1->score(). points <br/>. $j2->login. a.$j2->score(). points</p> ; Jeu : Tarot Scores : sky a 213 points Dark a 755 points. Mathieu Lacroix Programmation Web 7 / 40
Plan 1 Programmation orientée objet en PHP 2 PHP et bases de données 3 Sécurité Mathieu Lacroix Programmation Web 8 / 40
Principe Principe 4 - Visualisation de la page 1 - Demande d'exécution du script PHP 2 - Génération de code HTML Visiteur Client 3 - Envoi du code HTML généré Serveur Requête(s) SQL Réponse(s) SQL Base de données Plusieurs requêtes possibles SQL dans un script PHP. Mathieu Lacroix Programmation Web 9 / 40
Rappels requêtes SQL Table Joueurs : IdJ, Nom, Prenom Table Scores : IdS, IdJ, NomJeu, Score Interrogation SELECT [DISTINCT] nomchamps/fonction FROM nomtable [WHERE condition] Exemples : SELECT DISTINCT nomjeu FROM Scores SELECT * FROM Scores WHERE IdJ=1 SELECT MAX(Score) FROM Scores WHERE IdJ=1 SELECT Nom, Prenom FROM Joueurs NATURAL JOIN (SELECT IdJ FROM Scores WHERE NomJeu = Tarot ) Mathieu Lacroix Programmation Web 10 / 40
Rappels requêtes SQL Suppressions (de lignes) DELETE FROM nomtable WHERE condition Exemples : DELETE FROM Scores WHERE IdJ = 1 DELETE FROM Scores Mise à jour UPDATE nomtable SET nomchamp = nouvellevaleur WHERE condition Exemple : UPDATE Scores SET score = 0 WHERE IdJ = 1 AND nomjeu = Tarot Mathieu Lacroix Programmation Web 11 / 40
Rappels requêtes SQL Ajout de lignes INSERT INTO nomtable (champ1, champ2,...) VALUES ( valeur1, valeur2,...) Exemples : INSERT INTO Joueurs ( Nom, Prenom ) VALUES ( Dupond, Jean ) INSERT INTO Scores ( IdJ, NomJeu,Score) VALUES (18, Tarot,750), (18, Poker,1200), (18, Belote, 90) Mathieu Lacroix Programmation Web 12 / 40
Librairie PDO Accès aux BD avec la librairie PHP Data Object (PDO). Intérêts de PDO Permet d accéder à n importe quel SGBD (Oracle, MySQL, PostgreSQL) Permet l utilisation de requêtes préparées Requêtes préparées 2 étapes : Préparation : analyse/optimisation de la requête par le SGBD Exécution : Interrogation de la BD et récupération des résultats Possibilité d utiliser des marqueurs de place (paramètres). Intérêts des requêtes préparées Meilleure sécurisation de la base de données Accélération si une requête est exécutée plusieurs fois Mathieu Lacroix Programmation Web 13 / 40
Connexion à la base de données Connexion lors de l instanciation d un objet de PDO 3 paramètres : DSN, login, mot de passe Data Source Name (DSN) SGDB:host=SERVEUR;dbname=NOM_BASE SGDB : mysql, pgsql,... SERVEUR : nom du serveur (localhost, aquanux,...) NOM_BASE : nom de la base de données Mathieu Lacroix Programmation Web 14 / 40
Connexion à la base de données Exemple try { $bd = new PDO( mysql:host=localhost;dbname=bdtest, mat, code ); //Php communique en utf-8 (pour les accents) $bd->query( SET NAMES utf8 ); //En cas d erreur, lever des exceptions $bd->setattribute(pdo::attr_errmode,pdo::errmode_exception); } catch(pdoexception $e) { //On termine le script die( <p> Erreur[.$e->getCode(). ] :.$e->getmessage(). </p> ); } Remarques : Une seule connexion dans un script PHP Mettre ce code dans un fichier séparé Mathieu Lacroix Programmation Web 15 / 40
Interrogation de la base de données Préparation d une requête Méthode prepare de la classe PDO. Prend en paramètre une requête SQL (string) Retourne un objet PDO_STATEMENT correspondant à la requête préparée Exception PDOException en cas d erreur Exécution de la requête Méthode execute de la classe PDO_STATEMENT Exception PDOException en cas d erreur Mathieu Lacroix Programmation Web 16 / 40
Interrogation de la base de données Récupération des résultats Méthode fetch de la classe PDO_STATEMENT Retourne la ligne (enregistrement) suivante sous forme de tableau ou d objet (selon la valeur du paramètre) Retourne false en cas d erreur Valeurs possibles pour le paramètre de fetch PDO::FETCH_ASSOC : retourne un tableau associatif (clés : noms des colonnes) PDO::FETCH_NUM : retourne un tableau associatif (clés : indices des colonnes) PDO::FETCH_BOTH : retourne un tableau associatif (clés : noms et indices des colonnes) PDO::FETCH_OBJ : retourne un objet (noms des attributs : noms des colonnes) Mathieu Lacroix Programmation Web 17 / 40
Interrogation de la base de données Table Personnes : Exemple Nom Grappe David Borne Toulouse Prenom Roland Julien Sylvie Sophie //Dans un bloc try/catch $req = $bd->prepare( SELECT Nom, Prenom FROM Personnes ); $req->execute(); $tab = $req->fetch(pdo::fetch_assoc); echo <p>. $tab[ Nom ].. $tab[ Prenom ]. </p> ; $tab = $req->fetch(pdo::fetch_num); echo <p>. $tab[0].. $tab[1]. </p> ; $tab = $req->fetch(pdo::fetch_both); echo <p>. $tab[0].. $tab[ Prenom ]. </p> ; $obj = $req->fetch(pdo::fetch_obj); echo <p>. $obj->nom.. $obj->prenom. </p> ; Mathieu Lacroix Programmation Web 18 / 40
Interrogation de la base de données Premier appel : fetch retourne Array ( [Nom] => Grappe [Prenom] => Roland ) Deuxième appel : fetch retourne Array ( [0] => David [1] => Julien ) Mathieu Lacroix Programmation Web 19 / 40
Interrogation de la base de données Troisième appel : fetch retourne Array ( [Nom] => Borne [0] => Borne [Prenom] => Sylvie [1] => Sylvie ) Quatrième appel : fetch retourne Objet contenant deux attributs : nom de l attribut : Nom, valeur : Toulouse nom de l attribut : Prenom, valeur : Sophie Si cinquième appel, fetch retourne false Mathieu Lacroix Programmation Web 20 / 40
Interrogation de la base de données Affichage produit <p> Grappe Roland </p> <p> David Julien </p> <p> Borne Sylvie </p> <p> Toulouse Sophie </p> Mathieu Lacroix Programmation Web 21 / 40
Interrogation de la base de données Parcours de tous les résultats //Préparation et exécution while($rep = $req->fetch(pdo::fetch_assoc)) { echo <p>. $rep[ Nom ].. $rep[ Prenom ]. </p> ; } La boucle s arrête quand fetch retourne false Mathieu Lacroix Programmation Web 22 / 40
Marqueurs de place Définition/Utilisation Intérêts Endroits dans la requête qui seront remplacés par des valeurs lors de l exécution Définis par ":" suivi du nom du marqueur dans la requête Valeur donnée grâce à la méthode bindvalue Exécution d une requête avec plusieurs valeurs différentes Sécurisation des requêtes contre les attaques par injection SQL Mathieu Lacroix Programmation Web 23 / 40
Marqueurs de place Exemple $couleur = rouge ; $req = $bd->prepare( SELECT nom, couleur, calories FROM fruit WHERE calories < :calories AND couleur = :couleur ); $req->bindvalue( :calories, 150); $req->bindvalue( :couleur, $couleur); $req->execute(); SELECT nom, couleur, calories FROM fruit WHERE calories < 150 AND couleur= rouge Mathieu Lacroix Programmation Web 24 / 40
Plan 1 Programmation orientée objet en PHP 2 PHP et bases de données 3 Sécurité Mathieu Lacroix Programmation Web 25 / 40
Attaques par injection SQL Définition Modification (non prévue par le développeur) d une requête SQL Résultats obtenus pouvant être très différents! Table Cmd : Id IdC NomP Qte 1 1 Canapé 1 2 1 Lit 2 3 2 Table 1 4 2 Voiture 1 Exemple if(isset($_get[ id ])) { $req=$bd->prepare( SELECT * FROM Cmd WHERE IdC =.$_GET[ id ]); $req->execute(); while($t = $req->fetch(pdo::fetch_assoc)) echo <p>. $t[ nomp ].. $t[ Qte ]. </p> ; } Mathieu Lacroix Programmation Web 26 / 40
Attaques par injection SQL http://serveur/script.php?id=1 SELECT * FROM Cmd WHERE IdC = 1 Affiche les deux premières lignes de la table http://serveur/script.php?id=1 OR 1=1 SELECT * FROM Cmd WHERE IdC = 1 OR 1=1 Affiche toutes les lignes! http://serveur/script.php?id=1;delete * FROM Cmd SELECT * FROM Cmd WHERE IdC = 1; DELETE * FROM Cmd Affiche les 2 premières lignes et supprime les données de la table! Mathieu Lacroix Programmation Web 27 / 40
Attaques par injection SQL Parades Mettre entre apostrophes les valeurs saisies par l utilisateur $req = $bd->prepare( SELECT * FROM Cmd WHERE IdC =. $bd->quote($_get[ id ])); Utiliser les marqueurs de place pour les valeurs saisies $req = $bd->prepare( SELECT * FROM Cmd WHERE IdC = :ident ); $req->bindvalue( :ident,$_get[ id ]); Meilleure solution : Marqueurs de place (plus rapide et plus simple) http://serveur/script.php?id=1;delete * FROM Cmd Affiche les lignes dont l IdC vaut : 1;DELETE * FROM Cmd Mathieu Lacroix Programmation Web 28 / 40
Faille XSS Définition Insertion de code javascript (langage client) interprété par le navigateur Table Personnes Nom Grappe David Malveillant Prenom Roland Julien <script>confirm("attaque") ;</script> Mathieu Lacroix Programmation Web 29 / 40
Faille XSS Script PHP $req = $bd->prepare( SELECT Nom, Prenom FROM Personnes ); $req->execute(); while($rep = $req->fetch(pdo::fetch_assoc)) { echo <p>. $rep[ Nom ].. $rep[ Prenom ]. </p> ; } Code HTML généré <p> Nom : Grappe et prénom : Roland </p> <p> Nom : David et prénom : Julien </p> <p> Nom : Malveillant et prénom : <script> confirm("attaque");</script> </p> Mathieu Lacroix Programmation Web 30 / 40
Faille XSS Résultat Toute personne accédant à cette page Web exécute un script sur son navigateur! Mathieu Lacroix Programmation Web 31 / 40
Faille XSS Conséquences possibles Redirection de l utilisateur (hameçonnage) Vol d informations (sessions et cookies) Actions sur le site, à l insu de la victime et sous son identité (envoi de messages, suppression de données...) Lecture d une page difficile (boucle infinie d alertes par exemple) Mathieu Lacroix Programmation Web 32 / 40
Faille XSS Parade Utilisation de htmlspecialchars Script PHP $req = $bd->prepare( SELECT Nom, Prenom FROM Personnes ); $req->execute(); while($rep = $req->fetch(pdo::fetch_assoc)) { echo <p>. htmlspecialchars($rep[ Nom ]).. htmlspecialchars($rep[ Prenom ]). </p> ; } Code HTML généré <p> Nom : Grappe et prénom : Roland </p> <p> Nom : David et prénom : Julien </p> <p> Nom : Malveillant et prénom : <script> confirm("attaque");</script> </p> Mathieu Lacroix Programmation Web 33 / 40
Faille XSS Résultat Aucun script n est exécuté! Utiliser htmlspecialchars lors de l affichage OU lors de l insertion dans la BD Mathieu Lacroix Programmation Web 34 / 40
Gestion des mots de passe Authentification par login/mot de passe. Table MotsDePasse login jim arn edge pass azerty php123 1maxABC Mathieu Lacroix Programmation Web 35 / 40
Gestion des mots de passe Script d authentification //On suppose que les login et mot de passe saisis sont //dans $_POST[ login ] et $_POST[ pass ] $req = $bd->prepare( SELECT pass FROM MotsDePasse WHERE login=:login ); $req->bindvalue( :login,$_post[ login ]); $req->execute(); $res = $req->fetch(pdo::fetch_assoc); if($res) //S il y a une correspondance { if($_post[ pass ]==$res[ pass ]) //Si mêmes mots de passe { echo <p> Connexion réussie </p> ; $_SESSION[ connecte ] = true; } } Mathieu Lacroix Programmation Web 36 / 40
Gestion des mots de passe Problème Toute personne accédant à la table connaît tous les mots de passe! Accès à la table MotsDePasse Faille dans le site Droits suffisants Utilisation frauduleuse Connexion avec n importe quel compte Connexion sur d autres sites avec mêmes login/mots de passe Mathieu Lacroix Programmation Web 37 / 40
Gestion des mots de passe Parade Stocker les mots de passe chiffrés! Chiffrement Différents algorithmes possibles (ex sha1) Chiffrement très facile Déchiffrement très difficile Utilisation en PHP sha1( azerty ) renvoie 9cf95dacd226dcf43da376cdb6cbba7035218921 Mathieu Lacroix Programmation Web 38 / 40
Gestion des mots de passe Table MotsDePasse login jim arn edge pass 9cf95dacd226dcf43da376cdb6cbba7035218921 83208025fbed57b01f8b54e14c36fab2b13cbc62 b670865400eabb1ef43b3ea2aec31d7e5bba389b Nouveau test dans le script PHP if(sha1($_post[ pass ])==$res[ pass ]) Mathieu Lacroix Programmation Web 39 / 40
Gestion des mots de passe Le chiffrement ne résoud pas tout! Attaque possible Génération de mots de passe et vérification de concordance Dictionnaire de mots de passe (en clair et chiffrés) Le mot de passe azerty très vite trouvé! Parade Utilisation d un grain de sel (ex : 1zetydEEcjel4ek3 ) Chiffrer la concaténation du mot de passe et du grain de sel if(sha1($_post[ pass ]. 1zetydEEcjel4ek3 ) ==$res[ pass ]) Mathieu Lacroix Programmation Web 40 / 40