PHP et python peuvent être utilisés pour la programmation côté serveur. Dans les cas d’utilisation, on trouve par exemple le traitement de formulaires et enquêtes ou la gestion des mots de passe et de la base de données des utilisateurs. Dans la mesure où l’on va traiter sur le serveur des données entrées par l’utilisateur, il convient de prendre des précautions.

Stockage de mots de passe

Les mots de passe des utilisateurs sont stockés sur le serveur. La base de données des mots de passe peut être obtenue par des gens malveillants, il faut donc chiffrer les données. On utilise pour cela une “fonction à sens unique” nommée fonction de hashage, c’est-à-dire une fonction qui est facile à calculer mais difficile à inverser.

  1. Considérons la fonction md5. Sur un ordinateur raisonnable, on peut “hasher” 10000 chaînes par seconde. Supposons que les mots de passe sont des chaînes de 8 lettres minuscules. Étant donné le hash, combien de temps cela prendra-t-il de trouver mon mot de passe ?

    1. Dans un premier temps, on calculera combien de mots de passe existent.
    2. Puis on calculera le temps total pour calculer les hashes de tous les mots de passe.
    3. Écrire un algorithme qui étant donné le hashé d’un mot de passe calcule le mot de passe.
    4. On supposera négligeable le temps de comparaison entre deux hashes. On obtient donc un temps assurant que le mot de passe est trouvé.
  2. Supposons maintenant que les mots de passe sont constitués de majuscules, minuscules et de chiffres. Combien de temps pour déchiffrer le mot de passe à partir du hash ?

  3. Même question en supposant que les mots de passe sont constitués de 10 caractères (majuscules, minuscules, chiffres).

  4. Plutôt que trouver le mot de passe d’un utilisateur en particulier, je souhaite trouver un mot de passe quelconque parmi ceux des 1000 utilisateurs de mon site. Combien de temps cela prendra-t-il en moyenne de trouver un de ces mots de passe ?

  5. On considère maintenant la fonction de hashage sha256. Celle-ci est plus lente. Sur la même machine, on peut “hasher” 100 chaînes par seconde. Mêmes questions que précédemment.

  6. Une personne malveillante possède une base de données de hashes des 20% de mots de passe les plus fréquents. Il peut grace à cela rapidement trouver les mots de passe de 80% des utilisateurs du site. Pour parer à cela, on ajoute un “sel” propre au site à la chaîne avant de la hasher. Comment, sans connaître le sel a priori, la personne malveillante peut-elle tenter d’obtenir les mots de passe de certains utilisateurs ?

Données utilisateurs

Dans le cadre de formulaires, une application pourra lire des informations données par l’utilisateur et les afficher par la suite dans une page web.

Par exemple, si l’utilisateur entre dans le champ prenom le mot “Emmanuel”, le code python suivant

def hello(req):
	message = "Bonjour " + req.form["prenom"]
	return message

écrira Bonjour Emmanuel dans le code html transmis au navigateur.

  1. Que se passe-t-il si l’utilisateur met des balises dans son prénom ?
  2. L’utilisateur peut-il mettre du javascript qui sera exécuté dans ce champ ?
  3. Proposer une solution pour éviter que les balises html (et les scripts) ne soient interprétées. (penser aux cours de M1106)

Protocole d’échange de vélo

Alice veut prêter son vélo à Bob mais ils ne peuvent pas se rencontrer (Alice dort de 19h à 8h et Bob dort de 7h à 20h). Ils conviennent d’un lieu où déposer le vélo mais s’ils le laissent sans antivol, celui-ci sera volé !

  1. Pouvez-vous imaginer un protocole permettant de transmettre le vélo sans risque de vol en utilisant uniquement des antivols à clef ?
  2. Même question mais cette fois, Alice et Bob ne connaissent pas de personne de confiance à qui confier la clef de l’antivol.

Protocole d’échange de clef : NSPK

L’échange de clefs est indispensable pour établir une transmission chiffrée. On utilise pour cela le protocole d’échange de vélo mais en ajoutant des contraintes pour éviter les attaques MitM.

  • Alice (A), Bob (B) et Sophie (S, serveur de confiance) ont des couples clef publique/clef secrète notés K_P^A, K_S^A
  • S possède les clefs publiques de tout le monde, tout le monde possède la clef publique de S.
  • On notera \{M\}_{K_P^X} pour le message M chiffré avec la clef publique de X.
  • N_A et N_B sont des nonces, c’est-à-dire des nombres aléatoires à usage unique générés par Alice et Bob respectivement.

Le protocole Needham-Schroeder Public Key est un protocole d’échange de clef célèbre à la fin duquel, en théorie, Alice et Bob peuvent communiquer de façon sure (chacun a la clef publique de l’autre et sait que personne ne peut écouter la conversation).

NSPK
  1. Vérifier que le protocole est cohérent (quand quelqu’un utilise une clef, il la possède bien)
  2. Vérifier qu’à la fin, Alice et Bob ont bien la clef publique l’un de l’autre et peuvent donc échanger des messages chiffrés.
  3. Bob est-il sur que c’est bien Alice qui lui écrit et inversement ?

Structure d’une page web en python

Pour produire un page web en python, on doit écrire une fonction renvoyant une chaîne de caractères représentant le code de la page ’typiquement le code html). L’accès se fait ensuite via le chemin nomdufichier.py/nomdelafonction. Ainsi si dans le fichier foo.py, j’écris une fonction bar, pointer mon navigateur vers foo.py/bar va lui faire recevoir la page produite par cette fonction.

Exemple d’un fichier foo.py :

def index(req):
	return "Hello Python"

def full(req):
	ch = """<!DOCTYPE HTML>
<html>
<head><title>Une page web</title>
      <meta charset='utf-8'>
</head>
<body>
<h1>Test</h1>
"""
	for i in range(10):
		ch = ch + str(i)
	ch = ch + """</body>
</html>
"""
	return ch

Les pages seront foo.py/index qui contient seulement Hello Python, et foo.py/full qui contiendra :

<!DOCTYPE HTML>
<html> 
<head><title>Une page web</title>
      <meta charset='utf-8'>
</head>
<body>
<h1>Test</h1>
0123456789</body>
</html>
  1. Écrire un script python qui produit une page énumérant les carrés : pour chaque carré entre 1 et 100 apparaîtra un paragraphe de la forme <p>4 est un carré.</p>.
  2. Écrire un script python qui définit un annuaire téléphonique sous forme de tableau associatif et les affiche dans une table html (balises table, tr, td).
  3. Écrire une fonction python qui prend un nom comme entrée et renvoie le numéro de téléphone correspondant d’après l’annuaire défini à la question précédente.