TP2-PROG-07 : Les mots de passe#

Internet est un monde ouvert où tout est accessible. Il est donc très important de protéger ses données sensibles (tout ce qui touche à votre vie privée).

Le mouvement hacktiviste Anonymous, se manifeste notamment sur Internet, agit de manière anonyme, généralement pour défendre la liberté d’expression.

Télécharger: dosser-a-cracker.zip

Objectif#

Comprendre l’importance d’un bon mot de passe.
Il sert à protéger nos données privées dans les réseaux sociaux, sur notre téléphone portable, etc.

Pourquoi ?

  • le nom d’utilisateur peut être public

  • le mot de passe DOIT être secret.

Un bon mot de passe#

Il doit être difficile à trouver pour un être humain, mais surtout pour un ordinateur. Un bon mot de passe doit :

  1. éviter les mots courants (nom, prénom, etc..)

  2. être long

  3. éviter des répétitions

  4. contenir des caractères variés (lettres, accents, chiffres, caractères spéciaux)

Malheureusement, beaucoup de personnes ont encore des mots de passe trop simple

Longueur de mot#

Avec la fonction len() nous pouvons tester la longuer d’un mot de passe.

mdp = input('Créez un mot de passe: ')
n = 6
while len(mdp) < n:
    print('Nombre minimum de caractères:', n)
    mdp = input('Créez un autre mot de passe: ')
print('OK:', mdp)
---------------------------------------------------------------------------
StdinNotImplementedError                  Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 mdp = input('Créez un mot de passe: ')
      2 n = 6
      3 while len(mdp) < n:

File ~/.local/lib/python3.9/site-packages/ipykernel/kernelbase.py:1174, in Kernel.raw_input(self, prompt)
   1167 """Forward raw_input to frontends
   1168 
   1169 Raises
   1170 ------
   1171 StdinNotImplementedError if active frontend doesn't support stdin.
   1172 """
   1173 if not self._allow_stdin:
-> 1174     raise StdinNotImplementedError(
   1175         "raw_input was called, but this frontend does not support input requests."
   1176     )
   1177 return self._input_request(
   1178     str(prompt),
   1179     self._parent_ident["shell"],
   1180     self.get_parent("shell"),
   1181     password=False,
   1182 )

StdinNotImplementedError: raw_input was called, but this frontend does not support input requests.

Exercice
Augmentez la longueur à 10 et refaites un test.

Caractères spéciaux#

Pour tester si un mot de passe contient un caractère spécial, nous définissons une chaîne qui contient tous les caractères spéciaux possibles.

special = '+"*ç%&/()=?,.-;:_$'

L’opérateur in permet de tester si un caractère est parmi les caractères spéciaux.

'$' in special
True

Pour tester si un mot contient des caractères spéciaux, nous devons tester chaque lettre dans une boucle.

for c in 'el$a':
    print(c, c in special)
e False
l False
$ True
a False

Une autre méthode est d’utiliser l’intersection des deux ensembles.

mdp = 'el$a.car+ier'
set(mdp).intersection(special)
{'$', '+', '.'}

Dans la boucle suivante, nous vérifions si le mot de passe contient au minimum un caractère spécial.

mdp = input('Créez un mot de passe: ')
special = '+"*ç%&/()=?,.-;:_$'

while len(set(mdp).intersection(special)) == 0:
    print('Ne contient pas de caractère spécial')
    mdp = input('Créez un autre mot de passe: ')
print('OK:', mdp)
Créez un mot de passe:  tina
Ne contient pas de caractère spécial
Créez un autre mot de passe:  tina$+
OK: tina$+

Exercice
Ajoutez les accolades [], les crochets {} et les chevrons <> aux caractères spéciaux et refaites un test.

Charger une liste#

Le fichier passwords.txt contient les 20’000 mots de passes les plus utilisés sur l’Internet francophone. Nous allons l’utiliser pour vérifier la qualité d’un mot de passe.

Déplaçons nous dans le dossier dossier-a-cracker:

cd dossier-a-cracker

L’instruction Python suivante permet de stocker dans la liste passwords les 20’000 mots de passes du fichier passwords.txt

passwords = [line.rstrip() for line in open('passwords.txt', "r")]

Exercice
Avec la fonction type derminez le type de la variable passwords et avec la fonction len sa longueur.

Accéder aux éléments d’une liste#

L’opérateur de tranche [m:n] permet d’accéder à des sous ensembles

  • [m:n] de m jusqu’à (n-1)

  • [:n] du début jusqu’à (n-1)

  • [m:] de m jusqu’à la fin

Un index negatif compte depuis la fin

Exercice
Avec les opérateurs de tranche affichez

  • les 5 premiers mots de passe

  • le 1000ème mot de passe

  • les mots de passes entre 10’000 et 10’005

  • l’avant-dernier mot de passe

Vérifier si un mot est dans la liste#

L’opérateur in permet de verifier si un mot est dans une liste.

Est-ce que le mot de passe 'iloveyou' est dans la liste passwords?

'iloveyou' in passwords
True

Est-ce que le mode de passe 'tiamo' est dans la liste passwords

'tiamo' in passwords
False

Exercice

  • Vérifiez que le mot de passe cristiano7 est dans la liste.

  • Et le mot de passe cristiano8 ?

Tester plusieurs mots de passes#

Avec une boucle, on peut tester n’importe quel mot de passe contre la liste passwords.

Testez vos mots de passe!
Pour quitter la boucle, appuyez tout simplement sur Retour

mot = input('Entrez un mot de passe')
while len(mot) > 0:
    print(mot in passwords)
    mot = input('Entrez un mot de passe:')
Entrez un mot de passe Vincent
True
Entrez un mot de passe: raphael
True
Entrez un mot de passe: Raphael
False
Entrez un mot de passe: 

ZIP protégé#

Le fichier confidentiel/mails_FBI.zip a été protégé par un mot de passe. Si vous tentez d’extraire l’archive, vous devez fournir un mot de passe.

Ces 4 lignes vont tester le mot de passe 'jetaime' sur l’archive. Cela va créer une erreur de type :

RuntimeError: Bad password for file 'original/mails_FBI.txt'
from zipfile import ZipFile
with ZipFile('confidentiel/mails_FBI.zip') as file:
   mdp = 'jetaime'
    
   file.extractall(pwd = bytes(mdp, 'utf-8'))

Attaquer en force brute#

A partir de maintenant, on dispose de tous les outils pour attaquer en force brute l’archive mails_FBI.zip.

La fonction check_ret(mdp, archive) va tester un mot de passe mdp sur l’archive protégée archive et retourner la valeur 0 si le mot de passe est le bon.

import subprocess
def check_ret(mdp, archive):
    rc = -1
    p1 = subprocess.Popen(['unzip', '-t','-q', '-P', mdp,archive])
    p1.wait()
    rc = p1.returncode
    p1.kill()
    return rc

Il est maintenant possible de tester tous les mots de passe de la liste sur une archive protégée par un mot de passe. Le fichier se trouve au chemin confidentiel/mails_FBI.zip

for mdp in passwords:
    ret = check_ret(mdp,'confidentiel/mails_FBI.zip')
    if ret == 0:
        print('Le mot de passe est :',mdp)
        break

L’algorithme est le suivant :

Pour tous les mots de passes mdp de la liste passwords :

  • Tester si le mot de passe est correct

  • si le mot de passe est correct

  • alors le mot de passe a été trouvé, sortir de la boucle

  • sinon aller au mot de passe suivant

Craquer le fichier#

A l’aide de la fonction vue plus haut, extrayez l’archive avec le mot de passe que vous avez trouvé. Dans le Finder, déplacez-vous dans le dossier /dossier-a-cracker/confidentiel et double-cliquez sur l’archive mails_FBI.zip

On peut aussi extraire l’archive avec une fonction Python.

Remplacez la valeur de la variable mdp = 'x' par le mot de passe que vous venez de trouver.

from zipfile import ZipFile
with ZipFile('confidentiel/mails_FBI.zip') as file:
   mdp = 'x' 
   file.extractall(pwd = bytes(mdp, 'utf-8'))

Catch the flag#

Dans le monde du hacking, il y a un jeu qui est souvent utilisé par les entreprises pour tester leur infrastructure. Ce jeu de guerre cybernétique, appelé catch the flag (capture du drapeau) dans lequel deux équipes s’affrontent: l’une pour protéger le drapeau, l’autre pour le capturer.

Un autre fichier archive ZIP a été caché dans le dossier dossier-a-cracker et protégé par un mot de passe.

Exercice
Retrouvez le fichier avec les commandes ls et cd et utilisez les fonctions décrites plus haut pour le décrypter

Ai-je été piraté ?#

Nous avons utilisé la force brute pour tester un seul mot de passe contre une liste définie. Les crackers du monde entier utilisent des dictionnaires bien plus grands contre des adresses mails, des comptes, etc.. que vous avez laissé ça et là au gré de vos interactions avec Internet. Ces listes sont ensuite vendues et utilisées à mauvais escient.

Il existe un site web qui vérifie si votre adresse mail a été piratée : Ai-je été piraté ?

Exercice
Testez vos adresses mails pour voir si elles ont été piratés.
Si elles le sont, changez votre mot de passe.