Compare commits
25 Commits
5052a60465
...
master
Author | SHA1 | Date | |
---|---|---|---|
5801eaa82a | |||
dfd38e4c25 | |||
cc8263a60b | |||
1bad2da1cb | |||
4e25261387 | |||
f23fddf8f2 | |||
3bfe23cb8d | |||
2c7c614619 | |||
2d92e9d552 | |||
dcc8573869 | |||
1a30284a72 | |||
e5c48fc2dc | |||
e3c146136c | |||
e141c2abed | |||
48cc1fadca | |||
e6fadc25ea | |||
84e269e3ca | |||
47307f155e | |||
18adbbfd91 | |||
5b8df75e08 | |||
e20c79d582 | |||
57a1bac0be | |||
03232cb192 | |||
0ac1aa7689 | |||
dabf5a27f7 |
18
README.md
18
README.md
@ -4,9 +4,9 @@ _François Lesueur ([francois.lesueur@univ-ubs.fr](mailto:francois.lesueur@univ-
|
||||
|
||||
Cette page recense les séances du module M3102 "Services réseaux". L'objectif est d'expliquer le fonctionnement d'Internet en tant que réseau de réseaux, Internet est donc notamment l'union des systèmes d'information de tous les acteurs. Séance après séance, vous allez créer un SI minimal (DNS, HTTP, Mail, etc.) interconnectable avec le reste du monde et ainsi constater qu'Internet est le résultat de chaque acteur/AS qui offre et consomme des services.
|
||||
|
||||
Ce module se situe entre M2102 (Couches OSI, de la modulation à IP, avec un peu de routage/adressage IP) et M4101C. Il dure 6 semaines, avec chaque semaine 1 séance de cours (1h30) et 2 séances de TD (2*1h30) (attention, pour des raisons d'edt, la séance de cours a en fait lieu à la fin de la semaine précédent les TD). Le contenu sera détaillé au fur et à mesure de la période.
|
||||
Ce module se situe entre M2102 (Couches OSI, de la modulation à IP, avec un peu de routage/adressage IP) et M4101C. Il dure 7 semaines, avec chaque semaine 1 séance de cours (1h30) et 2 séances de TD (2*1h30) (attention, pour des raisons d'edt, la séance de cours a en fait lieu à la fin de la semaine précédent les TD).
|
||||
|
||||
Une large part des séances pratiques sera réalisée sur la plateforme MI-LXC (https://github.com/flesueur/mi-lxc), pour laquelle il faudra télécharger une VM Virtualbox **avant** le TD1.1 "Découverte de MI-LXC" : [.ova à télécharger ici](https://filesender.renater.fr/?s=download&token=2f121a18-f94d-45d1-a079-f68229ebdfa9). Il faudra arriver en séance avec Virtualbox installé et le .ova de MI-LXC déjà téléchargé, l'installation et la découverte de la VM seront ensuite le programme de la séance TD1.1.
|
||||
Une large part des séances pratiques sera réalisée sur la plateforme MI-LXC (https://github.com/flesueur/mi-lxc), pour laquelle il faudra télécharger une VM Virtualbox **avant** le TD1 "Découverte de MI-LXC" : [.ova à télécharger ici](https://flesueur.irisa.fr/mi-lxc/images/milxc-debian-amd64-1.4.2pre3.ova), nous utiliserons la version 1.4.2pre3. Il faudra arriver en séance avec Virtualbox installé et le .ova de MI-LXC déjà téléchargé, l'installation et la découverte de la VM seront ensuite le programme de la séance TD1.
|
||||
|
||||
|
||||
## Programme
|
||||
@ -14,23 +14,23 @@ Une large part des séances pratiques sera réalisée sur la plateforme MI-LXC (
|
||||
* S19 :
|
||||
* [CM1](cm1.md) Introduction "C'est quoi internet ?" et panorama du cours
|
||||
* S20 :
|
||||
* [TD1](td1.1-milxc.md) Découverte MI-LXC
|
||||
* [TD1](td1-milxc.md) Découverte MI-LXC
|
||||
* [CM2](cm2-crypto.md) Cryptographie et sécurité des communications (complément en ligne : [Section "Bases de la crypto"](https://github.com/flesueur/csc/blob/master/cours.md#bases-de-la-crypto))
|
||||
<!-- * [TD1.2](td1.2-shell.md) Wargame shell -->
|
||||
* S21/S22 :
|
||||
* [TD2](td2.1-crypto.md) Cryptographie JdR
|
||||
* TD3 Mots de passe
|
||||
* [TD2](td2-crypto.md) Cryptographie JdR
|
||||
* [TD3](td3-passwords.md) Mots de passe
|
||||
* S22 :
|
||||
* [TD4](td2.2-apache.md) Apache/CMS/Tunnels
|
||||
* [TD4](td4-apache.md) Apache/CMS/Tunnels
|
||||
* [CM3](cm3-dns.md) DNS (complément en ligne : [S. Bortzmeyer](https://www.iletaitunefoisinternet.fr/post/1-dns-bortzmeyer/))
|
||||
* S23 :
|
||||
* [TD5](td3.1-dns.md) DNS
|
||||
* [TD5](td5-dns.md) DNS
|
||||
* [CM4](cm4-mail.md) Mail (complément en ligne : [B. Sonntag](https://www.iletaitunefoisinternet.fr/post/7-email-sonntag/))
|
||||
* S24 :
|
||||
* [TD6](td4.1-mail.md) SMTP, POP, IMAP
|
||||
* [TD6](td6-mail.md) SMTP, POP, IMAP
|
||||
* [CM5](cm5-archi.md) Architecture réseau et firewall (complément en ligne : [ANSSI](https://www.ssi.gouv.fr/administration/guide/definition-dune-architecture-de-passerelle-dinterconnexion-securisee/) (chapitre 2))
|
||||
* S25 :
|
||||
* [TD7](td5.1-archi.md) Segmentation réseau et IPTables
|
||||
* [TD7](td7-archi.md) Segmentation réseau et IPTables
|
||||
* [CM6](cm6-wrapup.md) Révisions, questions/réponses
|
||||
|
||||
<!-- * TD4.2 SPF, DKIM, Spam, webmail -->
|
||||
|
@ -1,4 +1,4 @@
|
||||
TD6.1 Tunnels et bonus (3 heures)
|
||||
TD bonus : Tunnels et bonus (3 heures)
|
||||
====================
|
||||
|
||||
_Compte-rendu à préparer et déposer en binôme_
|
6
cm1.md
6
cm1.md
@ -20,7 +20,7 @@ Comment est structuré internet ?
|
||||
|
||||
Un réseau de réseaux :
|
||||
|
||||
* Acentré (pas de chef, pas de décision unique sans consensus des acteurs indépendants, pas de point de défaillance unique (SPOF)). *Est-ce toujours aussi vrai ? De la panne Facebook aux clouds*
|
||||
* Acentré (**pas de chef, pas de décision unique sans consensus des acteurs indépendants, pas de point de défaillance unique (SPOF)**). *Est-ce toujours aussi vrai ? De la panne Facebook aux clouds*
|
||||
* Structuré autour de la notion d'AS (systèmes autonomes, environ 100 000) qui forment le découpage de premier niveau
|
||||
* Chaque AS (exemple : RENATER, Orange) est ensuite sous-divisé en interne
|
||||
* Les AS s'interconnectent entre eux et le protocole BGP assurent la glu entre ces AS
|
||||
@ -53,14 +53,12 @@ Panorama du cours
|
||||
* Un peu de sécurité des communications (crypto)
|
||||
* Du web (HTTP)
|
||||
* Du DNS
|
||||
* De l'autorité de certification
|
||||
* Du mail
|
||||
* Du firewall et de l'archi réseau
|
||||
* De la gestion centralisée ou à distance : DHCP, SSH, Ansible
|
||||
|
||||
|
||||
Les TODO
|
||||
========
|
||||
|
||||
* Venir en TD avec son laptop. Combien faut-il en prévoir en complément ?
|
||||
* Télécharger l'[ova de MI-LXC](https://filesender.renater.fr/?s=download&token=2ca6036b-49b8-4b4c-93bb-95c5de051400) et installer VirtualBox **avant le premier TD** !
|
||||
* Télécharger l'[ova de MI-LXC](https://filesender.renater.fr/?s=download&token=adb51140-dae2-4cc6-ba1c-15cd1f91c913) et installer VirtualBox ou VMWare **avant le premier TD** !
|
||||
|
@ -5,7 +5,7 @@ CM2 Cryptographie et sécurité des communications - Notes de cours
|
||||
À la rencontre d'Alice, Bob et Ernest
|
||||
=====================================
|
||||
|
||||
Comment permettre à Alice et Bob de communiquer de manière *sûre* sur un canal *non sûr* ?
|
||||
Comment permettre à Alice et Bob de communiquer de manière *sûre* sur un canal *non sûr* ? Notion centrale en sécurité/crypto : le **modèle d'attaque**.
|
||||
|
||||
* Alice et Bob veulent communiquer, Ernest écoute (attaque passive) ou altère (attaque active) les échanges
|
||||
* Le medium non sûr :
|
||||
@ -98,7 +98,7 @@ Exemple : le modèle HTTPS
|
||||
* nom = nom d'hôte DNS (par exemple www.univ-ubs.fr)
|
||||
* tiers = une autorité de certification (par exemple Let's Encrypt)
|
||||
* => On a bien une association entre un nom et une clé, ici certifiée par un tiers
|
||||
* Le client doit valider la signature de la CA :
|
||||
* Le client doit valider la signature de la CA, et ainsi vérifier l'association (clé publique, nom) :
|
||||
* Il lui faut donc vérifier avec la clé publique de la CA
|
||||
* Les clés publiques des CA reconnues par les clients sont pré-installées dans les navigateurs, pas de magie, il faut une *ancre de confiance* dans le logiciel
|
||||
|
||||
@ -106,5 +106,5 @@ Exemple : le modèle HTTPS
|
||||
Ce qu'on va faire en TD
|
||||
=======================
|
||||
|
||||
* TD2.1 : Crypto asymétrique
|
||||
* TD3.2 : CA
|
||||
* TD2 : Crypto asymétrique
|
||||
* TD3 : Stockage des mots de passe
|
||||
|
12
cm3-dns.md
12
cm3-dns.md
@ -40,7 +40,7 @@ Les acteurs
|
||||
Protocole
|
||||
---------
|
||||
|
||||
* UDP, écoute sur le port 53
|
||||
* Historiquement UDP, écoute sur le port 53. Progressivement TCP également.
|
||||
* Protocole binaire (et non texte comme HTTP, pas de netcat !)
|
||||
* Des outils de dialogue : dig, drill, nslookup
|
||||
|
||||
@ -140,6 +140,7 @@ Filtrage
|
||||
* Point de passage quasi-obligé, historiquement en clair et classiquement centralisé chez les FAI
|
||||
* Au niveau État pour la censure (application de blocage administratif de l'orient à l'occident)
|
||||
* Au niveau organisation pour limiter l'accès internet des employés
|
||||
* Attention, ce n'est pas une mesure de sécurité car facile à contourner...
|
||||
|
||||
Open resolvers
|
||||
--------------
|
||||
@ -159,5 +160,10 @@ DoT / DoH
|
||||
Ce qu'on va faire en TD
|
||||
=======================
|
||||
|
||||
* TD3.1 DNS
|
||||
* (TD3.2 CA ACME)
|
||||
* TD5 DNS
|
||||
|
||||
Bonus
|
||||
=====
|
||||
|
||||
https://jvns.ca/blog/2022/05/10/pages-that-didn-t-make-it-into--how-dns-works-/
|
||||
https://jvns.ca/blog/2022/02/01/a-dns-resolver-in-80-lines-of-go/
|
||||
|
@ -127,7 +127,7 @@ SPF
|
||||
---
|
||||
|
||||
* Un domaine possède son infrastructure, ses serveurs SMTP
|
||||
* Les mails se prétendant d'adresses "@CeDomaine.org" devraient logiquement venir de ces SMTP
|
||||
* Les mails se prétendant d'adresses "@CeDomaine.org" devraient logiquement venir de ses SMTP
|
||||
* => Annoncer dans la zone DNS "CeDomaine.org" un enregistrement SPF déclarant les serveurs autorisés à envoyer en son nom
|
||||
* Le MSA de "CeDomaine.org" doit authentifier ses utilisateurs, s'assurer qu'il n'autorise à envoyer pour ce domaine que les utilisateurs légitimes. On limite ainsi les usurpations et l'usage de notre nom pour des spams
|
||||
* Quand un MTA tiers reçoit un mail "@CeDomaine.org", il fait une requête DNS :
|
||||
@ -145,7 +145,7 @@ DKIM
|
||||
----
|
||||
|
||||
* Un domaine possède son infrastructure, ses serveurs SMTP
|
||||
* Les mails se prétendant d'adresses "@CeDomaine.org" devraient logiquement venir de ces SMTP
|
||||
* Les mails se prétendant d'adresses "@CeDomaine.org" devraient logiquement venir de ses SMTP
|
||||
* => Générer une paire de clés cryptographiques, signer avec la clé privée sur ces serveurs, annoncer dans la zone DNS "CeDomaine.org" un enregistrement DKIM déclarant la clé publique autorisée à signer
|
||||
* Le MSA de "CeDomaine.org" doit authentifier ses utilisateurs, s'assurer qu'il n'autorise à envoyer pour ce domaine que les utilisateurs légitimes. On limite ainsi les usurpations et l'usage de notre nom pour des spams
|
||||
* Quand un MTA tiers reçoit un mail "@CeDomaine.org", il fait une requête DNS :
|
||||
@ -194,7 +194,7 @@ Les acteurs
|
||||
Ce qu'on va faire en TD
|
||||
=======================
|
||||
|
||||
* TD4.1 Mail
|
||||
* TD6 Mail
|
||||
|
||||
|
||||
Biblio
|
||||
|
@ -14,7 +14,7 @@ Il était une fois les réseaux à plat
|
||||
|
||||
* Naturellement, comme on l'a fait dans les TD successifs : un subnet, tout le monde dedans !
|
||||
* Sauf que c'est en fait une mauvaise idée pour plein de raisons...
|
||||
* On va donc sub-diviser en sous-réseaux au niveau IP
|
||||
* On va donc sous-diviser en sous-réseaux au niveau IP
|
||||
|
||||
Raisons humaines
|
||||
----------------
|
||||
@ -23,7 +23,7 @@ Raisons humaines
|
||||
* Le cerveau humain a ses limites (sisi)
|
||||
* Besoin de cartographier, décomposer pour s'y repérer
|
||||
* Besoin d'une certaine autonomie/indépendance entre les parties pour maîtriser la gestion de chacune au quotidien
|
||||
* Subdivision en sous-réseaux logiques au niveau IP
|
||||
* Sous-division en sous-réseaux logiques au niveau IP
|
||||
* Par exemple géographiques (bâtiments, services, filiales, ...)
|
||||
|
||||
Exemple :
|
||||
@ -186,4 +186,4 @@ Pare-feu (_Firewall_)
|
||||
Ce qu'on va faire en TD
|
||||
=======================
|
||||
|
||||
* TD5.1 IPTables, SSH, segmentation
|
||||
* TD7 IPTables, segmentation
|
||||
|
@ -1,4 +1,4 @@
|
||||
CM6 Wrap-up + Questions/Réponses- Notes de cours
|
||||
CM6 Wrap-up + Questions/Réponses - Notes de cours
|
||||
================================================
|
||||
|
||||
Wrap-up
|
||||
@ -40,9 +40,3 @@ Questions/Réponses
|
||||
==================
|
||||
|
||||
(pour l'instant, je fais semblant de ne pas connaître les questions...)
|
||||
|
||||
|
||||
Retours
|
||||
=======
|
||||
|
||||
Questionnaire rapide et anonyme (3 questions : ce qui vous a plu, ce qui vous a déplu, suggestions d'améliorations) [ici](https://framaforms.org/retour-m3102-services-reseaux-1637759395). Clôture dimanche 12/12, merci !
|
||||
|
@ -1,7 +1,9 @@
|
||||
TD1.1 Découverte MI-LXC
|
||||
TD1 Découverte MI-LXC
|
||||
=======================
|
||||
|
||||
Ce TP sera réalisé dans la VM MI-LXC disponible [ici](https://filesender.renater.fr/?s=download&token=2f121a18-f94d-45d1-a079-f68229ebdfa9). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
Ce TP sera réalisé dans la VM MI-LXC disponible [ici](https://filesender.renater.fr/?s=download&token=adb51140-dae2-4cc6-ba1c-15cd1f91c913). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
|
||||
Pour vous connecter à la VM, utilisez le compte `root` avec le mot de passe `root`.
|
||||
|
||||
MI-LXC simule un internet minimaliste que nous utiliserons tout au long de la matière. Ce TD couvre la découverte de l'environnement existant et les premiers éléments qui seront nécessaires pour l'étendre par la suite. Dans la suite de la matière, vous installerez et configurerez un réseau et des services qui s'interconnecteront avec cet existant.
|
||||
|
||||
@ -9,8 +11,9 @@ MI-LXC simule un internet minimaliste que nous utiliserons tout au long de la ma
|
||||
|
||||
> La VM peut être affichée en plein écran. Si cela ne fonctionne pas, il faut parfois changer la taille de fenêtre manuellement, en tirant dans l'angle inférieur droit, pour que VirtualBox détecte que le redimensionnement automatique est disponible. Il y a une case adéquate (taille d'écran automatique) dans le menu écran qui doit être cochée. Si rien ne marche, c'est parfois en redémarrant la VM que cela peut se déclencher. Mais il *faut* la VM en grand écran.
|
||||
|
||||
> Si vous êtes sous Windows et que la VM ne fonctionne pas avec VirtualBox, vous pouvez utiliser à la place VMWare Player. Dans ce cas, il faudra cliquer sur "Retry" lors de l'import puis installer le paquet open-vm-tools-desktop dans la VM pour profiter du redimensionnement automatique du bureau (`apt install open-vm-tools-desktop` dans un shell).
|
||||
> Si vous êtes sous Windows et que la VM ne fonctionne pas avec VirtualBox, vous pouvez utiliser à la place VMWare Player. Dans ce cas, il faudra cliquer sur "Retry" lors de l'import.
|
||||
|
||||
> Le compte-rendu est à déposer en binôme sur Moodle avant mardi 24 mai soir.
|
||||
|
||||
Cheat sheet
|
||||
===========
|
||||
@ -60,7 +63,7 @@ Toutes les machines ont les deux comptes suivants : debian/debian et root/root (
|
||||
|
||||
> Question 3 : Depuis la machine isp-a-home, ouvrez un navigateur pour vous connecter au site web de l'UBS. Cela fonctionne-t-il ? Cette page est-elle hébergée dans l'infrastructure MI-LXC ?
|
||||
|
||||
> Question 4 : Ouvrez un shell sur la machine target-dmz (commande attach, donc). Installez le package nano grâce à l'outil `apt` et vérfifiez que vous pouvez maintenant éditer des fichiers avec nano.
|
||||
> Question 4 : Ouvrez un shell sur la machine target-dmz (commande attach, donc). Installez le package nano grâce à l'outil `apt` et vérifiez que vous pouvez maintenant éditer des fichiers avec nano.
|
||||
|
||||
> Dans la VM et sur les machines MI-LXC, vous pouvez donc installer des logiciels supplémentaires. Par défaut, vous avez mousepad pour éditer des fichiers de manière graphique.
|
||||
|
||||
@ -126,7 +129,9 @@ Une fois ceci défini, un `./mi-lxc.py print` pour vérifier la topologie, puis
|
||||
|
||||
On peut enfin faire un `./mi-lxc.py start` et vérifier le bon démarrage.
|
||||
|
||||
> Attention, pour des raisons de gestion des IP et des routes, étonnamment, il n'y a pas de façon simple pour que le routeur puisse lui-même initier des communications. C'est-à-dire que si tout fonctionne bien il sera démarré, aura de bonnes tables de routage, mais pour autant ne pourra pas ping en dehors du subnet du transitaire. C'est le comportement attendu et donc vérifier la connectivité du routeur ne peut pas se faire comme ça. On verra ensuite comment vérifier cela depuis un poste interne et nous utiliserons, sur le routeur ou ses voisins BGP, les commandes `birdc show route all` et `birdc show protocols` pour inspecter les tables de routage et vérifier l'établissement des sessions BGP.
|
||||
<!-- > Attention, pour des raisons de gestion des IP et des routes, étonnamment, il n'y a pas de façon simple pour que le routeur puisse lui-même initier des communications. C'est-à-dire que si tout fonctionne bien il sera démarré, aura de bonnes tables de routage, mais pour autant ne pourra pas ping en dehors du subnet du transitaire. C'est le comportement attendu et donc vérifier la connectivité du routeur ne peut pas se faire comme ça. On verra ensuite comment vérifier cela depuis un poste interne et nous utiliserons, sur le routeur ou ses voisins BGP, les commandes `birdc show route all` et `birdc show protocols` pour inspecter les tables de routage et vérifier l'établissement des sessions BGP. -->
|
||||
|
||||
> Sur le routeur ou ses voisins BGP, les commandes `birdc show route all` et `birdc show protocols` permettent d'inspecter les tables de routage et vérifier l'établissement des sessions BGP.
|
||||
|
||||
> Question 5 : Quels ajouts avez-vous fait dans `global.json` ?
|
||||
|
@ -1,4 +1,4 @@
|
||||
TD2.1 : Usage de la cryptographie asymétrique
|
||||
TD2 : Usage de la cryptographie asymétrique
|
||||
=============================================
|
||||
|
||||
_Pas de compte-rendu pour ce TD_
|
131
td3-code/skeleton.py
Executable file
131
td3-code/skeleton.py
Executable file
@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import time
|
||||
import sys
|
||||
from toolbox import *
|
||||
|
||||
# You should tweak these values during the work
|
||||
nblogins = 10 # would be larger in real-life
|
||||
nbpasswords = 1000000 # would be larger in real-life
|
||||
nbiterations = 10 # 10000 is currently recommended, should be adapted to the usecase and changed with time (improvement of computation power), like a key size
|
||||
|
||||
|
||||
############################################
|
||||
# Part of the script to edit #
|
||||
############################################
|
||||
|
||||
# Hint : you can call decrypt(key,data) to decrypt data using key
|
||||
def crackencrypted(database):
|
||||
key = readfile("enckey")[0]
|
||||
crackeddb = []
|
||||
for i in database:
|
||||
# i[0] is the login, i[1] is the encrypted password
|
||||
#...
|
||||
crackeddb.append((i[0],i[1])) # second argument should contain cleartext password
|
||||
return crackeddb
|
||||
|
||||
# Hint : - genshahashes(passwords) returns all the hashes of passwords dictionary
|
||||
# - getpassfromshahash(hashes, hash) returns the password which hashed as "hash" in hashes
|
||||
def cracksha(database):
|
||||
global nbpasswords
|
||||
passwords = getPassDict(nbpasswords) # passwords contains a dictionary of passwords
|
||||
#...
|
||||
crackeddb = []
|
||||
for i in database:
|
||||
# i[0] is the login, i[1] is the hashed password
|
||||
#...
|
||||
crackeddb.append((i[0],i[1])) # second argument should contain cleartext password
|
||||
return crackeddb
|
||||
|
||||
# Hint : salthash(password, salt) return the salted hash of password
|
||||
def cracksaltedsha(database):
|
||||
global nbpasswords
|
||||
passwords = getPassDict(nbpasswords)
|
||||
crackeddb = []
|
||||
for i in database:
|
||||
# i[0] is the login, i[1] is the hashed password, i[2] is the salt
|
||||
#...
|
||||
crackeddb.append((i[0],i[1])) # second argument should contain cleartext password
|
||||
return crackeddb
|
||||
|
||||
# Hint : pbkdf2(password, salt, nbiterations) returns the pbkdf2 of password using salt and nbiterations
|
||||
def crackpbkdf2(database):
|
||||
global nbpasswords
|
||||
passwords = getPassDict(nbpasswords)
|
||||
crackeddb = []
|
||||
for i in database:
|
||||
# i[0] is the login, i[1] is the hashed password, i[2] is the salt, i[3] is the iteration count
|
||||
#...
|
||||
crackeddb.append((i[0],i[1])) # second argument should contain cleartext password
|
||||
return crackeddb
|
||||
|
||||
|
||||
|
||||
############################################
|
||||
# Nothing to change after this line ! #
|
||||
############################################
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# When called with init
|
||||
if len(sys.argv) > 1 and sys.argv[1] == "init":
|
||||
initworkspace(nblogins,nbpasswords,nbiterations)
|
||||
print("Workspace initialized in files/ subdirectory")
|
||||
exit(0)
|
||||
|
||||
# Test whether init has been called before
|
||||
try :
|
||||
readfile("plain")
|
||||
except FileNotFoundError:
|
||||
initworkspace(nblogins,nbpasswords,nbiterations)
|
||||
print("Workspace initialized in files/ subdirectory")
|
||||
|
||||
# test plain DB
|
||||
print("\n============\nPlain storage:")
|
||||
plaindb = readfile("plain")
|
||||
print("Plain DB is : " + str(plaindb))
|
||||
print("Authenticating with plain DB : " + str(authplain(plaindb[0][0],plaindb[0][1],plaindb)))
|
||||
|
||||
#test encrypted db
|
||||
print("\n============\nEncrypted storage:")
|
||||
encdb = readfile("enc")
|
||||
print("Encrypted DB is " + str(encdb))
|
||||
print("Authenticating with encrypted DB : " + str(authencrypted(plaindb[1][0],plaindb[1][1],encdb)))
|
||||
start = time.time()
|
||||
crackedenc = crackencrypted(encdb)
|
||||
end = time.time()
|
||||
print("Time to crack encrypted DB : " + str(end-start) + " seconds")
|
||||
print("Cracked encrypted DB is " + str(crackedenc))
|
||||
|
||||
#test SHA db
|
||||
print("\n============\nSHA storage:")
|
||||
shadb = readfile("sha")
|
||||
print("SHA DB is " + str(shadb))
|
||||
print("Authenticating with SHA DB : " + str(authsha(plaindb[0][0],plaindb[0][1],shadb)))
|
||||
start = time.time()
|
||||
crackedsha = cracksha(shadb)
|
||||
end = time.time()
|
||||
print("Time to crack SHA DB : " + str(end-start) + " seconds")
|
||||
print("Cracked SHA DB is " + str(crackedsha))
|
||||
|
||||
#test Salted SHA db
|
||||
print("\n============\nSalted SHA storage:")
|
||||
saltedshadb = readfile("saltedsha")
|
||||
print("Salted SHA DB is " + str(saltedshadb))
|
||||
print("Authenticating with Salted SHA DB : " + str(authsaltedsha(plaindb[0][0],plaindb[0][1],saltedshadb)))
|
||||
start = time.time()
|
||||
crackedsaltedsha = cracksaltedsha(saltedshadb)
|
||||
end = time.time()
|
||||
print("Time to crack salted SHA DB : " + str(end-start) + " seconds")
|
||||
print("Cracked salted SHA DB is " + str(crackedsaltedsha))
|
||||
|
||||
# test PBKDF2 DB
|
||||
print("\n============\nPBKDF2 storage:")
|
||||
pbkdf2db = readfile("pbkdf2")
|
||||
print("PBKDF2 DB is " + str(pbkdf2db))
|
||||
print("Authenticating with PBKDF2 DB : " + str(authpbkdf2(plaindb[0][0],plaindb[0][1],pbkdf2db)))
|
||||
start = time.time()
|
||||
crackedpbkdf2 = crackpbkdf2(pbkdf2db)
|
||||
end = time.time()
|
||||
print("Time to crack PBKDF2 DB : " + str(end-start) + " seconds")
|
||||
print("Cracked PBKDF2 DB is " + str(crackedpbkdf2))
|
250
td3-code/toolbox.py
Executable file
250
td3-code/toolbox.py
Executable file
@ -0,0 +1,250 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Avoir une lib avec des briques prêtes
|
||||
# Avoir un script qui crée les fichiers de password SHA/PB/etc. pour pouvoir les manipuler en texte
|
||||
# TD : associer les briques pour évaluer les attaques sur un pass / une base
|
||||
# mettre un « except ImportError » et ressayer avec « Cryptodome » a la place de « Crypto »
|
||||
|
||||
import re
|
||||
import time
|
||||
import random
|
||||
import hashlib
|
||||
# tweak to (try to) handle different crypto lib naming across systems (Linux, Mac, Win)
|
||||
try:
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto import Random
|
||||
except ImportError:
|
||||
try:
|
||||
from crypto.Cipher import AES
|
||||
from crypto import Random
|
||||
except ImportError:
|
||||
from Cryptodome.Cipher import AES
|
||||
from Cryptodome import Random
|
||||
import base64
|
||||
import os
|
||||
import urllib.request
|
||||
import string
|
||||
|
||||
# returns an array of a dictionary of passwords
|
||||
def getPassDict(nbpasswords):
|
||||
try:
|
||||
f = open("files/passwords.txt")
|
||||
except FileNotFoundError:
|
||||
print("Downloading a passwords list...")
|
||||
urllib.request.urlretrieve("https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10-million-password-list-top-1000000.txt?raw=true", "files/passwords.txt")
|
||||
print("Done !")
|
||||
f = open("files/passwords.txt")
|
||||
passwords = []
|
||||
#nbpasswords = 10000
|
||||
passtogen = nbpasswords
|
||||
for password in f:
|
||||
passwords.append(password.strip())
|
||||
passtogen-=1
|
||||
if passtogen == 0:
|
||||
break
|
||||
return passwords
|
||||
|
||||
def genRandomPassword():
|
||||
length = 6
|
||||
chars = string.ascii_letters + string.digits
|
||||
return ''.join(random.choice(chars) for i in range(length))
|
||||
|
||||
# reads/writes shadow-style files
|
||||
def readfile(filename):
|
||||
f = open("files/"+filename)
|
||||
res = []
|
||||
for line in f:
|
||||
output = line.strip().split(":")
|
||||
res.append(output)
|
||||
return res
|
||||
|
||||
def writeFile(filename, array):
|
||||
f = open("files/"+filename,'w')
|
||||
for line in array:
|
||||
towrite = ""
|
||||
for item in line:
|
||||
towrite+=item + ":"
|
||||
towrite = towrite[:-1]
|
||||
f.write(towrite)
|
||||
f.write('\n')
|
||||
|
||||
|
||||
# Plain storage
|
||||
def genplain(nblogins,nbpasswords):
|
||||
passwords = getPassDict(nbpasswords)
|
||||
logins = []
|
||||
for i in range(0,nblogins):
|
||||
login = "user" + str(i)
|
||||
if (random.randint(0,10) < 4):
|
||||
logins.append((login,passwords[random.randint(0,len(passwords)-1)]))
|
||||
else:
|
||||
logins.append((login,genRandomPassword()))
|
||||
return logins
|
||||
|
||||
def authplain(login, passwd, database):
|
||||
for i in database:
|
||||
if i[0] == login:
|
||||
current = i[1]
|
||||
return (current == passwd)
|
||||
|
||||
# Encrypted storage
|
||||
def genencrypted(logins):
|
||||
encdb = []
|
||||
key = Random.new().read(16)
|
||||
iv = Random.new().read(AES.block_size)
|
||||
f = open("files/enckey",'wb')
|
||||
f.write((base64.b64encode(key)))
|
||||
f.write(b":")
|
||||
#f = open("files/enciv",'wb')
|
||||
f.write((base64.b64encode(iv)))
|
||||
for i in logins:
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv)
|
||||
enc = (base64.b64encode(cipher.encrypt(i[1].encode('utf-8')))).decode("utf-8")
|
||||
encdb.append((i[0],enc))
|
||||
#print(enc)
|
||||
return encdb
|
||||
|
||||
def authencrypted(login, passwd, database):
|
||||
for i in database:
|
||||
if i[0] == login:
|
||||
current = i[1]
|
||||
keyiv = readfile("enckey")[0]
|
||||
key = base64.b64decode(keyiv[0])
|
||||
iv = base64.b64decode(keyiv[1])
|
||||
#key = base64.b64decode(readfile("enckey")[0][0])
|
||||
#iv = base64.b64decode(readfile("enciv")[0][0])
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv)
|
||||
return (passwd == cipher.decrypt(base64.b64decode(current)).decode('utf-8'))
|
||||
|
||||
def decrypt(keyiv,data):
|
||||
key = base64.b64decode(keyiv[0])
|
||||
iv = base64.b64decode(keyiv[1])
|
||||
cipher = AES.new(key, AES.MODE_CFB, iv)
|
||||
return cipher.decrypt(base64.b64decode(data)).decode('utf-8')
|
||||
|
||||
|
||||
# SHA storage
|
||||
def gensha(logins):
|
||||
db = []
|
||||
for i in logins:
|
||||
csum = hashlib.sha256(i[1].encode('utf-8')).hexdigest()
|
||||
db.append((i[0],csum))
|
||||
return db
|
||||
|
||||
def authsha(login, passwd, database):
|
||||
for i in database:
|
||||
if i[0] == login:
|
||||
current = i[1]
|
||||
return (current == hashlib.sha256(passwd.encode('utf-8')).hexdigest())
|
||||
|
||||
def genshahashes(passwords):
|
||||
hashes = []
|
||||
for passwd in passwords:
|
||||
hashes.append([hashlib.sha256(passwd.encode('utf-8')).hexdigest(),passwd])
|
||||
return hashes
|
||||
|
||||
def getpassfromshahash(hashes, hash):
|
||||
for j in hashes:
|
||||
if j[0] == hash:
|
||||
return j[1]
|
||||
return None
|
||||
|
||||
# Salted SHA storage
|
||||
def gensaltedsha(logins):
|
||||
db = []
|
||||
for i in logins:
|
||||
salt = str(random.randint(0,65535))
|
||||
csum = hashlib.sha256((i[1]+salt).encode('utf-8')).hexdigest()
|
||||
db.append((i[0],csum,salt))
|
||||
return db
|
||||
|
||||
def authsaltedsha(login, passwd, database):
|
||||
for i in database:
|
||||
if i[0] == login:
|
||||
current = i[1]
|
||||
salt = i[2]
|
||||
return (current == hashlib.sha256((passwd+salt).encode('utf-8')).hexdigest())
|
||||
|
||||
def salthash(password,salt):
|
||||
return hashlib.sha256((password+str(salt)).encode('utf-8')).hexdigest()
|
||||
|
||||
# PBKDF2 storage
|
||||
def genpbkdf2(logins,nbiterations):
|
||||
db = []
|
||||
for i in logins:
|
||||
salt = str(random.randint(0,65535))
|
||||
csum = base64.b64encode(hashlib.pbkdf2_hmac('sha256',i[1].encode('utf-8'),str(salt).encode('utf-8'),nbiterations)).decode('utf-8')
|
||||
db.append((i[0],csum,salt,str(nbiterations)))
|
||||
return db
|
||||
|
||||
def authpbkdf2(login, passwd, database):
|
||||
for i in database:
|
||||
if i[0] == login:
|
||||
current = i[1]
|
||||
salt = i[2]
|
||||
nbiterations = int(i[3])
|
||||
return (base64.b64decode(current) == hashlib.pbkdf2_hmac('sha256',passwd.encode('utf-8'),str(salt).encode('utf-8'),nbiterations))
|
||||
|
||||
def pbkdf2(password,salt,nbiterations):
|
||||
nbiterations = int(nbiterations)
|
||||
return base64.b64encode(hashlib.pbkdf2_hmac('sha256',password.encode('utf-8'),str(salt).encode('utf-8'),nbiterations)).decode('utf-8')
|
||||
|
||||
|
||||
# Generate shadow-style files
|
||||
def initworkspace(nblogins,nbpasswords,nbiterations):
|
||||
print("Generating " + str(nblogins) + " logins and " + str(nbpasswords) + " passwords")
|
||||
try :
|
||||
os.mkdir("files")
|
||||
except FileExistsError:
|
||||
pass
|
||||
plaindb = genplain(nblogins,nbpasswords)
|
||||
writeFile("plain", plaindb)
|
||||
encdb = genencrypted(plaindb)
|
||||
writeFile("enc", encdb)
|
||||
shadb = gensha(plaindb)
|
||||
writeFile("sha", shadb)
|
||||
saltedshadb = gensaltedsha(plaindb)
|
||||
writeFile("saltedsha", saltedshadb)
|
||||
pbkdf2db = genpbkdf2(plaindb,nbiterations)
|
||||
writeFile("pbkdf2", pbkdf2db)
|
||||
|
||||
|
||||
|
||||
# Unit tests
|
||||
if __name__ == '__main__':
|
||||
# create shadow files
|
||||
initworkspace(10,100,1000)
|
||||
|
||||
print("======\nUnit tests of the toolbox, you must work in skeleton.py\n=========")
|
||||
|
||||
# test plain DB
|
||||
print("\n============\nPlain storage:")
|
||||
plaindb = readfile("plain")
|
||||
print("Plain DB is : " + str(plaindb))
|
||||
print("Authenticating with plain DB : " + str(authplain(plaindb[0][0],plaindb[0][1],plaindb)))
|
||||
|
||||
#test encrypted db
|
||||
print("\n============\nEncrypted storage:")
|
||||
encdb = readfile("enc")
|
||||
print("Encrypted DB is " + str(encdb))
|
||||
print("Authenticating with encrypted DB : " + str(authencrypted(plaindb[1][0],plaindb[1][1],encdb)))
|
||||
|
||||
#test SHA db
|
||||
print("\n============\nSHA storage:")
|
||||
shadb = readfile("sha")
|
||||
print("SHA DB is " + str(shadb))
|
||||
print("Authenticating with SHA DB : " + str(authsha(plaindb[0][0],plaindb[0][1],shadb)))
|
||||
|
||||
#test Salted SHA db
|
||||
print("\n============\nSalted SHA storage:")
|
||||
saltedshadb = readfile("saltedsha")
|
||||
print("Salted SHA DB is " + str(saltedshadb))
|
||||
print("Authenticating with Salted SHA DB : " + str(authsaltedsha(plaindb[0][0],plaindb[0][1],saltedshadb)))
|
||||
|
||||
# test PBKDF2 DB
|
||||
print("\n============\nPBKDF2 storage:")
|
||||
pbkdf2db = readfile("pbkdf2")
|
||||
print("PBKDF2 DB is " + str(pbkdf2db))
|
||||
print("Authenticating with PBKDF2 DB : " + str(authpbkdf2(plaindb[0][0],plaindb[0][1],pbkdf2db)))
|
||||
|
||||
print("\n======\nUnit tests of the toolbox, you must work in skeleton.py\n=========")
|
105
td3-passwords.md
Normal file
105
td3-passwords.md
Normal file
@ -0,0 +1,105 @@
|
||||
TD3 : Stockage et authentification par mot de passe
|
||||
=============================================
|
||||
|
||||
_Pas de compte-rendu pour ce TD_
|
||||
|
||||
Ce TD présente le stockage et l'authentification par mot de passe côté serveur. Il s'agit typiquement du problème rencontré par une application web qui souhaite authentifier ses utilisateurs, ou de ce qui est mis en œuvre dans une base de mots de passes système (/etc/shadow ou LDAP). Pour cela, l'application va stocker en base les comptes existants ainsi que le moyen de les authentifier. Comme il n'est évidemment pas souhaitable de stocker les mots de passe des utilisateurs en clair, nous allons analyser comment résoudre ce problème.
|
||||
|
||||
Contexte général
|
||||
================
|
||||
|
||||
Le scénario d'attaque est une exfiltration des fichiers de l'application (dont le fichier de la base de données ou le fichier `/etc/shadow` par exemple). Vous pouvez consulter une liste non exhaustive de bases ayant été dérobées sur le site [HaveIBeenPwned](https://haveibeenpwned.com/PwnedWebsites) pour vous rendre compte de l'étendue du problème. Dans ce cadre, nous posons les points suivants :
|
||||
|
||||
* Le serveur est déjà compromis, l'obtention d'un compte valide sur ce serveur n'a pas d'intérêt pour l'attaquant.
|
||||
* Les victimes potentielles sont les utilisateurs du site qui y ont enregistré un compte. En effet, un attaquant pourrait alors essayer de se connecter en leur nom sur des services tiers grâce aux informations récupérées.
|
||||
|
||||
Pour limiter ce risque, deux approches complémentaires doivent être mises en place :
|
||||
|
||||
1. Le serveur doit compliquer autant que possible la tâche de l'attaquant qui a volé la base en maximisant le temps nécessaire pour obtenir des informations valides à partir de la base (objet de ce TD).
|
||||
2. Les utilisateurs, n'ayant pas la possibilité de connaître les contre-mesures mises en place par le serveur, doivent limiter l'impact de cette compromission en utilisant des mots de passes différents, idéalement un pour chaque site (ce qui passe souvent par un gestionnaire de mots de passe, non abordé dans ce TD).
|
||||
|
||||
Ces deux mesures sont bien complémentaires car il est du devoir de chaque site de protéger les mots de passes des utilisateurs n'appliquant pas les meilleures pratiques et de chaque utilisateur de protéger au mieux de ses capacités ses mots de passes. Dans le cadre de ce TD, nous analysons la mesure (1), à appliquer côté serveur.
|
||||
|
||||
|
||||
Squelette de code fourni
|
||||
========================
|
||||
|
||||
Vous devez télécharger le squelette de code [ici](td3-code). Vous pouvez récupérer l'intégralité du dépôt en tapant `git clone https://git.kaz.bzh/francois.lesueur/LPCyber.git`, puis aller dans le dossier `td3-code`. Vous pourriez avoir besoin d'installer la bibliothèque python PyCryptodome (de préférence, et nécessaire avec Python 3.8) ou PyCrypto (dépréciée, mais a priori fonctionnelle jusque Python 3.7). Par exemple avec pip3 pour avoir PyCryptodome uniquement (les deux ne peuvent pas coexister sur le système) :
|
||||
|
||||
```
|
||||
pip3 uninstall PyCrypto
|
||||
pip3 install -U PyCryptodome
|
||||
```
|
||||
|
||||
* `toolbox.py` est la bibliothèque contenant la boîte à outils, il peut être intéressant d'aller la consulter mais elle n'est pas à modifier ;
|
||||
* `skeleton.py` contient le programme à écrire.
|
||||
|
||||
En début de TD, vous devez lancer `./skeleton.py init` pour créer votre espace de travail. Cette commande, que vous pourrez rappeler plus tard, génère les fichiers suivants (lisibles) dans le sous-dossier `files` :
|
||||
|
||||
* `plain` contient la base login/password en clair
|
||||
* `enc` contient la base chiffrée en AES (la clé, volée également car nécessairement accessible à proximité sauf cas particulier est dans `enckey`)
|
||||
* `sha` contient la base hashée avec SHA256
|
||||
* `saltedsha` contient la base hashée/salée avec SHA256
|
||||
* `pbkdf2` contient la base avec n itérations de hash salé (PBKDF2)
|
||||
|
||||
Vous pouvez visualiser tous ces fichiers dans un éditeur de texte classique et analyser les différents champs présents. Vous pouvez ensuite exécuter `./skeleton.py` (sans argument) qui affichera, pour chaque schéma de stockage :
|
||||
|
||||
* le contenu de la base stockée
|
||||
* le résultat d'un test unitaire d'authentification (doit toujours être vrai)
|
||||
* l'appel (chronométré) à une fonction pour casser la base (fonctions non implémentées dans le squelette fourni)
|
||||
|
||||
|
||||
Analyse des différents schémas
|
||||
==============================
|
||||
|
||||
Pour chaque schéma (clair `plain`, chiffré `enc`, hash `sha`, hash salé `saltedsha`, hash salé coûteux `pbkdf2`), vous devez :
|
||||
|
||||
* analyser le processus de l'ajout d'un compte et de la vérification d'un mot de passe
|
||||
* proposer la procédure de récupération pour un utilisateur qui a perdu son mot de passe
|
||||
* évaluer l'information révélée directement par la base de mots de passe
|
||||
* évaluer le coût de cassage d'un mot de passe isolé
|
||||
* évaluer le coût de cassage de la base entière
|
||||
* implémenter la fonction pour casser la base
|
||||
|
||||
|
||||
<!--
|
||||
Notations
|
||||
=========
|
||||
|
||||
* h(m) est le hash du message m
|
||||
* Si K<sub>A</sub> est une clé symétrique, {m}<sub>K<sub>A</sub></sub> est le chiffré de m avec la clé K<sub>A</sub>, m = { {m}<sub>K<sub>A</sub></sub>}<sub>K<sub>A</sub></sub>
|
||||
* Si Pub<sub>A</sub> et Priv<sub>A</sub> sont des clés asymétriques complémentaires publique/privée, {m}<sub>Pub<sub>A</sub></sub> est le chiffré de m avec la clé Pub<sub>A</sub> et m = { {m}<sub>Pub<sub>A</sub></sub>}<sub>Priv<sub>A</sub></sub>
|
||||
* m signé avec la clé Priv<sub>A</sub> est noté m.{h(m)}<sub>Priv<sub>A</sub></sub>
|
||||
-->
|
||||
|
||||
|
||||
|
||||
|
||||
<!--
|
||||
|
||||
Côté client
|
||||
===========
|
||||
|
||||
Un gestionnaire de mots de passe conserve une table liant un titre, un login et un mot de passe. Par exemple :
|
||||
|
||||
| Titre | Login | Password |
|
||||
| - | - | - |
|
||||
| CDiscount | Alice31 | hujk15tr |
|
||||
| laposte.net | AliceLefur@laposte.net | jku78!io |
|
||||
| CB | 4785 1547 4554 6657 | 7514 |
|
||||
|
||||
Considérons que l'utilisation de ce gestionnaire de mots de passe nécessite la saisie préalable d'un mot de passe maître, lors de l'ouverture.
|
||||
|
||||
Proposez la mise en œuvre d'un gestionnaire de mots de passe local puis d'un gestionnaire de mots de passe en ligne. Analysez les risques d'attaques par les différents acteurs (eux-mêmes ou suite à comprommission de leur infrastructure).
|
||||
|
||||
-->
|
||||
|
||||
Pour approfondir
|
||||
================
|
||||
|
||||
**Les schémas vus dans ce TD, de manière similaire à ce que nous avons vu côté RSA, sont simplifiés pour comprendre le principe (textbook)**. Pour référence plus précise, vous pouvez ensuite consulter (et garder) :
|
||||
|
||||
* [SOPHOS : Serious Security: How to store your users’ passwords safely](https://nakedsecurity.sophos.com/2013/11/20/serious-security-how-to-store-your-users-passwords-safely/)
|
||||
* [OWASP : Password Storage Cheat Sheet](https://www.owasp.org/index.php/Password_Storage_Cheat_Sheet)
|
||||
* [Micode : 30 000 MOTS DE PASSE CRACKÉS EN 5 MINUTES ! (vidéo)](https://youtu.be/_1ONcmFUOxE)
|
||||
* [Des exemples de dictionnaires](https://weakpass.com/wordlist)
|
@ -1,9 +1,11 @@
|
||||
TD2.2 Apache/CMS
|
||||
TD4 Apache/CMS/Tunnels
|
||||
================
|
||||
|
||||
_Compte-rendu à préparer et déposer en binôme_
|
||||
|
||||
Ce TD couvre la configuration et l'utilisation d'un serveur HTTP Apache ainsi qu'un CMS Wordpress.
|
||||
|
||||
Ce TD sera réalisé dans la VM MI-LXC disponible [ici](https://filesender.renater.fr/?s=download&token=2f121a18-f94d-45d1-a079-f68229ebdfa9). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
Ce TD sera réalisé dans la VM MI-LXC disponible [ici](https://filesender.renater.fr/?s=download&token=19a6f8f4-0cf8-47a4-bd05-db4b9ea2d4e4). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
|
||||
> Si vous êtes sous Windows et que la VM ne fonctionne pas avec VirtualBox, vous pouvez utiliser à la place VMWare Player. Dans ce cas, il faudra cliquer sur "Retry" lors de l'import puis installer le paquet open-vm-tools-desktop dans la VM pour profiter du redimensionnement automatique du bureau (`apt install open-vm-tools-desktop` dans un shell).
|
||||
|
||||
@ -70,11 +72,17 @@ Contrôle d'accès
|
||||
|
||||
Nous allons maintenant contrôler l'accès au sous-dossier créé (par login/mot de passe).
|
||||
|
||||
Vous devez tout d'abord créer un fichier `.htpasswd` qui va contenir les couples login/mot de passe autorisés. Vous pouvez le placer dans le sous-dossier à protéger ou ailleurs, par exemple dans un dossier (à créer) `/etc/apache2/htpasswd/`. Vous utiliserez pour cela la commande `htpasswd` en faisant attention à utiliser la fonction de hachage bcrypt (une option à htpasswd) au lieu du MD5 utilisé par défaut (Explication [ici](https://nakedsecurity.sophos.com/2013/11/20/serious-security-how-to-store-your-users-passwords-safely/), pas à lire en TD mais pour les curieux).
|
||||
Vous devez tout d'abord créer un fichier `.htpasswd` qui va contenir les couples login/mot de passe autorisés. Vous pouvez par exemple le placer dans un dossier (à créer) `/etc/apache2/htpasswd/` (pour des raisons de sécurité, on évitera de le placer dans un dossier servi par Apache comme `/var/www/html/...`). Vous utiliserez pour cela la commande `htpasswd` en faisant attention à utiliser la fonction de hachage bcrypt (une option à htpasswd) au lieu du MD5 utilisé par défaut (Explication [ici](https://nakedsecurity.sophos.com/2013/11/20/serious-security-how-to-store-your-users-passwords-safely/), pas à lire en TD mais pour les curieux).
|
||||
|
||||
> Question 4 : Quelles commandes avez-vous tapées ? Quel est votre fichier .htpasswd résultat ?
|
||||
|
||||
Vous devez ensuite spécifier quel dossier doit être protégé. Vous trouverez le nécessaire dans la [documentation officielle](https://httpd.apache.org/docs/2.4/fr/howto/auth.html), à parcourir jusqu'à la section "Autorisation d'accès à plusieurs personnes" (incluse). Lisez attentivement la partie sur les prérequis, votre fichier de configuration apache2 est `/etc/apache2/apache2.conf` (et non `httpd.conf` comme mentionné à certains endroits de cette documentation). Validez enfin le fonctionnement en vérifiant que l'authentification est bien demandée au client lors d'une connexion graphique avec Firefox.
|
||||
Vous devez ensuite spécifier quel dossier doit être protégé. Vous trouverez le nécessaire dans la [documentation officielle](https://httpd.apache.org/docs/2.4/fr/howto/auth.html), à parcourir jusqu'à la section "Autorisation d'accès à plusieurs personnes" (incluse). Lisez attentivement la partie sur les prérequis, votre fichier de configuration apache2 est `/etc/apache2/apache2.conf` (et non `httpd.conf` comme mentionné à certains endroits de cette documentation).
|
||||
|
||||
Vous devez réaliser ce contrôle de 2 façons distinctes :
|
||||
* D'abord en intégrant directement les directives `Auth*` dans une section `<Directory>...</Directory>`, par exemple en vous inspirant de la section concernant `/var/www/` dans le fichier de configuration `/etc/apache2/apache2.conf`. Attention à bien exécuter un `systemctl reload apache2` pour prendre en compte les changements dans les `.conf`
|
||||
* Ensuite en intégrant un `AllowOverride` dans la section concernant ce même répertoire puis en plaçant un fichier `.htaccess` dans le dossier `/var/www` (AllowOverride est décrit dans la partie "Les prérequis" de la page de documentation officielle)
|
||||
|
||||
Validez chaque fonctionnement en vérifiant que l'authentification est bien demandée au client lors d'une connexion graphique avec Firefox.
|
||||
|
||||
> Question 5 : Quelles modifications/ajouts avez-vous fait ?
|
||||
|
||||
@ -97,9 +105,9 @@ MariaDB
|
||||
|
||||
MariaDB est un fork de MySQL que nous allons utiliser ici, avec PHPMyAdmin pour aider l'administration (création de bases, d'utilisateurs, etc.).
|
||||
|
||||
Installez les paquets mariadb-server et phpmyadmin. Lors de l'installation de phpmyadmin, vous aurez à répondre à quelques questions : utilisez la fonctionnalité dbconfig, notez le mot de passe que vous choisirez pour l'utilisateur phpmyadmin et activez la configuration pour apache2.
|
||||
Installez d'abord mariadb-server. Pour finaliser l'installation, exécutez `mysql_secure_installation`, qui permettra de mieux configurer MariaDB et de spécifier un mot de passe root (par défaut vide et non autorisé).
|
||||
|
||||
Pour finaliser l'installation, exécutez `mysql_secure_installation`, qui permettra de mieux configurer MariaDB et de spécifier un mot de passe root (par défaut vide et non autorisé).
|
||||
Installez ensuite phpmyadmin (faîtes bien cela *après* avoir installé mariadb-server, dans un autre apt-get, sinon il y aura une erreur). Lors de l'installation de phpmyadmin, vous aurez à répondre à quelques questions : utilisez la fonctionnalité dbconfig, notez le mot de passe que vous choisirez pour l'utilisateur phpmyadmin et activez la configuration pour apache2.
|
||||
|
||||
> Question 8 : Faîtes une capture d'écran de PHPMyAdmin connecté en tant que root
|
||||
|
||||
@ -120,4 +128,63 @@ Enfin, installez un thème, un plugin et écrivez un premier billet
|
||||
|
||||
> Question 10 : Comme tout logiciel (que ce soit un binaire compilé depuis un code source C comme le serveur HTTPD Apache ou un code source PHP interprété à l'exécution), WordPress doit être tenu à jour afin d'installer les correctifs de sécurité. Pour chacune des méthodes d'installation, comment se passera ce mécanisme de mise à jour ? Pouvez-vous trouver des avantages et inconvénients à ces méthodes ?
|
||||
|
||||
**Votre compte-rendu doit être déposé sur Moodle en fin de journée au format PDF uniquement**
|
||||
|
||||
Tunnels
|
||||
=======
|
||||
|
||||
En utilisant des tunnels, vous allez voir comment cacher une connexion (par exemple HTTP) dans une autre connexion (par exemple SSH)
|
||||
|
||||
SSH
|
||||
---
|
||||
|
||||
L'outil ssh permet de réaliser des tunnels avec ses options -L (Local) et -R (Remote). Deux exemples :
|
||||
* `ssh -L 8080:192.168.1.2:80 192.168.2.4`:
|
||||
* La machine locale ouvre une connexion SSH vers la machine 192.168.2.4
|
||||
* La machine locale ouvre le port 8080 en écoute
|
||||
* Tout ce qui entre localement sur ce port 8080 emprunte le tunnel SSH jusqu'à 192.168.2.4 puis la machine 192.168.2.4 route ces paquets vers 192.168.1.2 sur le port 80
|
||||
* `ssh -R 8080:192.168.1.2:80 192.168.2.4` est symétrique :
|
||||
* La machine locale ouvre une connexion SSH vers la machine 192.168.2.4
|
||||
* La machine 192.168.2.4 ouvre le port 8080 en écoute
|
||||
* Tout ce qui entre sur 192.168.2.4 sur ce port 8080 emprunte le tunnel SSH jusqu'au client SSH puis ce client SSH route ces paquets vers 192.168.1.2 sur le port 80
|
||||
|
||||
Vous allez mettre en place deux tunnels SSH, chacun depuis target-dev vers isp-a-home :
|
||||
* Dans le premier, vous utiliserez -L pour qu'un `curl localhost:8080` exécuté sur target-dev récupère la page sur le serveur web (port 80) de 100.81.0.2 (un site externe dont on aurait souhaité interdire l'accès depuis target)
|
||||
* Dans le second, vous utiliserez -R pour qu'un `curl localhost:8080` exécuté sur isp-a-home récupère la page sur le serveur web (port 80) de 100.80.0.5 (l'intranet de target)
|
||||
|
||||
> Question 11 : Recopiez les commandes ssh exécutées.
|
||||
|
||||
> Question 12 : Utilisez Wireshark (avec le filtre ssh ou http) pour afficher les paquets SSH entre target-dev et isp-a-home et les paquets HTTP vers 100.81.0.2 et 100.80.0.5.
|
||||
|
||||
Netcat
|
||||
------
|
||||
|
||||
|
||||
Imaginez que vous êtes le développeur et que vous souhaitez fournir un accès au serveur web interne de prototypage "target-intranet" à un client externe, alors que celui-ci n'est normalement pas accessible de l'externe ! Vous allez créer un tunnel pour contourner la politique de sécurité. Vous disposez pour cela des machines "target-dev" (votre poste de travail interne) et "isp-a-home" (une machine extérieure, à votre domicile).
|
||||
|
||||
Nous allons utiliser l'outil `netcat` pour établir un tunnel très simple.
|
||||
|
||||
Connectez-vous sur la machine "isp-a-home". Nous allons commencer par éteindre le service _Apache_ en écoute pour libérer le port 80 qui nous sera utile puis nous allons écouter les connexions sur le port HTTP (TCP/80).
|
||||
```bash
|
||||
service apache2 stop
|
||||
while true; do nc -v -l -p 80 -c "nc -l -p 8080"; done
|
||||
```
|
||||
|
||||
Enfin, côté "target-dev", nous mettons en place la connexion sortante vers la machine distante:
|
||||
```bash
|
||||
while true; do nc -v 100.120.0.3 80 -c "nc 100.80.0.5 80"; sleep 2; done
|
||||
```
|
||||
|
||||
>Pour rappel :
|
||||
>* 100.120.0.3 = isp-a-home
|
||||
>* 100.80.0.5 = target-intranet
|
||||
|
||||
Testez avec la machine "isp-a-hacker" que vous pouvez bien accéder au serveur intranet depuis l'externe sans aucun contrôle via l'URL `http://100.120.0.3:8080`
|
||||
|
||||
> Question 13 : À l'aide d'un schéma, expliquez ce tunnel.
|
||||
|
||||
> Question 14 : Retrouvez-le dans Wireshark
|
||||
|
||||
Il est très difficile de bloquer ou même détecter les tunnels (tunnel chiffré par SSH, ou qui mime une apparence de HTTP, etc.)
|
||||
|
||||
|
||||
**Votre compte-rendu doit être déposé sur Moodle au format PDF uniquement**
|
@ -1,11 +1,11 @@
|
||||
TD3.1 DNS (3 heures)
|
||||
TD5 DNS (3 heures)
|
||||
====================
|
||||
|
||||
_Compte-rendu à préparer et déposer en binôme_
|
||||
|
||||
Ce TD couvre la configuration et l'utilisation du DNS, à la fois côté serveurs d'autorité et de résolution.
|
||||
|
||||
Ce TD sera réalisé dans la VM MI-LXC disponible [ici](https://filesender.renater.fr/?s=download&token=2f121a18-f94d-45d1-a079-f68229ebdfa9). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
Ce TD sera réalisé dans la VM MI-LXC disponible [ici](https://filesender.renater.fr/?s=download&token=19a6f8f4-0cf8-47a4-bd05-db4b9ea2d4e4). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
|
||||
> Si vous êtes sous Windows et que la VM ne fonctionne pas avec VirtualBox, vous pouvez utiliser à la place VMWare Player. Dans ce cas, il faudra cliquer sur "Retry" lors de l'import puis installer le paquet open-vm-tools-desktop dans la VM pour profiter du redimensionnement automatique du bureau (`apt install open-vm-tools-desktop` dans un shell).
|
||||
|
||||
@ -91,7 +91,7 @@ dig @80.67.169.12 www.univ-ubs.fr # Interroge le serveur (résolveur) 80.67
|
||||
|
||||
Le serveur racine alternatif O de MI-LXC est accessible à l'IP 100.100.0.10.
|
||||
|
||||
Nous allons faire la résolution manuellement depuis la machine `isp-a-home`. Commencez par démarrer wireshark sur cette machine (passage root avec su, écoute sur eth0 puis filtre "dns" pour ne voir que les paquets qui nous intéressent). En utilisant dig depuis la machine `isp-a-home` et en interrogeant successivement chaque nœud de l'arbre DNS depuis cette racine 100.100.0.10, résolvez le nom d'hôte `www.target.milxc`. À chaque étape, retrouvez les requêtes et les réponses dans Wireshark : dans la fenêtre d'analyse (zone du milieu), dépliez la partie DNS jusqu'à trouver le contenu décodé des questions et réponses DNS.
|
||||
Nous allons faire la résolution manuellement depuis la machine `isp-a-home`. Commencez par démarrer wireshark sur cette machine (écoute sur eth0 puis filtre "dns" pour ne voir que les paquets qui nous intéressent). En utilisant dig depuis la machine `isp-a-home` et en interrogeant successivement chaque nœud de l'arbre DNS depuis cette racine 100.100.0.10, résolvez le nom d'hôte `www.target.milxc`. À chaque étape, retrouvez les requêtes et les réponses dans Wireshark : dans la fenêtre d'analyse (zone du milieu), dépliez la partie DNS jusqu'à trouver le contenu décodé des questions et réponses DNS.
|
||||
|
||||
> Question 4 : Notez le chemin de résolution vers ce nom d'hôte, les questions posées et reçues par dig auprès des différents serveurs faisant autorité, jusqu'à obtenir l'IPv4 souhaitée.
|
||||
|
||||
@ -154,4 +154,4 @@ Relancez le serveur NSD et vérifiez l'absence d'erreurs dans les logs (`journal
|
||||
|
||||
> Question 9 (bonus) : Afin d'obtenir un système robuste et conforme aux recommandations standards, il faudrait ensuite dupliquer cette zone sur un serveur secondaire, indépendant, qui serait aussi annoncé dans la zone parente .milxc (par exemple sur target-infra). Explorez cela et rédigez ce que vous aurez compris ou réalisé.
|
||||
|
||||
**Votre compte-rendu doit être déposé sur Moodle en fin de journée au format PDF uniquement, un dépôt par binôme.**
|
||||
**Votre compte-rendu doit être déposé sur Moodle au format PDF uniquement, un dépôt par binôme.**
|
@ -1,4 +1,4 @@
|
||||
TD4.1 Mail (3 heures)
|
||||
TD6 Mail (3 heures)
|
||||
====================
|
||||
|
||||
_Compte-rendu à préparer et déposer en binôme_
|
||||
@ -7,7 +7,7 @@ _Compte-rendu à préparer et déposer en binôme_
|
||||
|
||||
Ce TD couvre la configuration et l'utilisation du mail, côté client et serveur. Les interactions sont complexes, l'objectif n'est pas d'avoir absolument un système mail entièrement fonctionnel, mais plutôt de bien appréhender la construction générale de ce type de système. Soyez méthodiques dans votre travail car vous allez manipuler de nombreuses perspectives différentes !
|
||||
|
||||
Ce TD sera réalisé dans la VM MI-LXC disponible [ici](https://filesender.renater.fr/?s=download&token=2f121a18-f94d-45d1-a079-f68229ebdfa9). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
Ce TD sera réalisé dans la VM MI-LXC disponible [ici](https://flesueur.irisa.fr/mi-lxc/images/milxc-debian-amd64-1.4.2pre3.ova). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
|
||||
> Si vous êtes sous Windows et que la VM ne fonctionne pas avec VirtualBox, vous pouvez utiliser à la place VMWare Player. Dans ce cas, il faudra cliquer sur "Retry" lors de l'import puis installer le paquet open-vm-tools-desktop dans la VM pour profiter du redimensionnement automatique du bureau (`apt install open-vm-tools-desktop` dans un shell).
|
||||
|
||||
@ -235,4 +235,4 @@ Roundcube est un webmail simple disponible dans les paquets Debian.
|
||||
|
||||
|
||||
|
||||
**Votre compte-rendu doit être déposé sur Moodle en fin de journée au format PDF uniquement, un dépôt par binôme.**
|
||||
**Votre compte-rendu doit être déposé sur Moodle au format PDF uniquement, un dépôt par binôme.**
|
@ -1,11 +1,11 @@
|
||||
TD5.1 Architecture réseau et firewall (3 heures)
|
||||
TD7 Architecture réseau et firewall (3 heures)
|
||||
====================
|
||||
|
||||
_Compte-rendu à préparer et déposer en binôme_
|
||||
|
||||
Ce TD couvre la segmentation réseau et l'utilisation du firewall IPTables.
|
||||
|
||||
Ce TD sera réalisé dans la VM MI-LXC disponible [ici](https://filesender.renater.fr/?s=download&token=2f121a18-f94d-45d1-a079-f68229ebdfa9). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
Ce TD sera réalisé dans la VM MI-LXC disponible [ici](https://flesueur.irisa.fr/mi-lxc/images/milxc-debian-amd64-1.4.2pre3.ova). Avant de lancer la VM, il peut être nécessaire de diminuer la RAM allouée. Par défaut, la VM a 3GO : si vous avez 4GO sur votre machine physique, il vaut mieux diminuer à 2GO, voire 1.5GO pour la VM (la VM devrait fonctionner de manière correcte toujours).
|
||||
|
||||
> Si vous êtes sous Windows et que la VM ne fonctionne pas avec VirtualBox, vous pouvez utiliser à la place VMWare Player. Dans ce cas, il faudra cliquer sur "Retry" lors de l'import puis installer le paquet open-vm-tools-desktop dans la VM pour profiter du redimensionnement automatique du bureau (`apt install open-vm-tools-desktop` dans un shell).
|
||||
|
||||
@ -196,7 +196,7 @@ Une fois que la politique réseau a été précédemment définie sur le papier
|
||||
|
||||
Implémentez votre matrice de flux sur la machine "target-router". Vous aurez besoin de procéder en deux étapes :
|
||||
|
||||
* Segmenter le réseau "target" (**Prenez le temps de regarder le [tuto vidéo](https://mi-lxc.citi-lab.fr/data/media/segmentation_milxc.mp4) !!!**) :
|
||||
* Segmenter le réseau "target" (**Prenez le temps de regarder le [tuto vidéo](https://flesueur.irisa.fr/mi-lxc/media/segmentation_milxc.mp4) !!!**) :
|
||||
* Éditer `global.json` (dans le dossier mi-lxc) pour spécifier les interfaces sur le routeur, dans la section "target". Il faut ajouter des bridges (dont le nom doit commencer par "target-") et découper l'espace 100.80.0.1/16. Enfin, il faut ajouter les interfaces eth2, eth3... ainsi créées à la liste des `asdev` definie juste au-dessus (avec des ';' de séparation entre interfaces)
|
||||
* Éditer `groups/target/local.json` pour modifier les adresses des interfaces et les bridges des machines internes (attention, pour un bridge nommé précédemment "target-dmz", il faut simplement écrire "dmz" ici, la partie "target-" est ajoutée automatiquement). Dans le même fichier vous devrez aussi mettre à jour les serveurs mentionnés dans les paramètres des templates "ldapclient", "sshfs" et "nodhcp", soit en remplaçant les noms de serveurs par leurs nouvelles adresses IP, soit en mettant à jour les enregistrements DNS correspondants (fichier `/etc/nsd/target.milxc.zone` sur "target-dmz")
|
||||
* Exécuter `./mi-lxc.py print` pour visualiser la topologie redéfinie
|
Reference in New Issue
Block a user