Improve the function 'from_elem(..)'.
[crypto_lab1.git] / rapport / main.tex
1 \documentclass[a4paper,10pt]{article}
2
3 \usepackage[francais]{babel}
4 \usepackage[utf8]{inputenc}
5 \usepackage[T1]{fontenc}
6 \usepackage{lmodern}
7
8 \usepackage{graphicx}
9 \usepackage{listings}
10 \usepackage{url}
11
12 \title{ICR - Labo \#1 : \textit{MAC-and-Encrypt and Padding Oracles}}
13 \author{G.Burri}
14
15 \begin{document}
16
17 \lstset{language=C}
18 \nocite{*}
19
20 \maketitle
21
22
23 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
24 \section{Introduction}
25
26 Le but de ce laboratoire est d'expérimenter le chiffrement symétrique \emph{AES} ainsi que la vérification de l'intégrité des données par \emph{MAC}, de mettre en évidence un problème de sécurité lié à un protocole choisi propre et de proposer une solution.
27
28 Nous utiliseront \emph{AES-256} en mode \emph{CBC} pour chiffrer les données ainsi que \emph{HMAC-SHA256} pour l'authentification.
29
30
31 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
32 \section{Simulation du protocole}
33
34 \subsection{Utilisation du programme}
35
36 Le code est écrit en langage \emph{Rust} \footnote{\url{http://www.rust-lang.org}} et utilise le système de build \emph{Cargo} qui est livré en standard. Il est conseillé d'utiliser la version \emph{nightly} disponible ici : \url{http://www.rust-lang.org/install.html}.
37
38 Pour construire et lancer l'application il faut se trouver dans le dossier contenant le fichier \emph{Cargo.toml} et lancer la commande suivante :
39
40 \begin{lstlisting}
41 $> cargo run -- <args>
42 \end{lstlisting}
43
44\emph{<args>} peut valoir :
45
46 \begin{itemize}
47 \item \emph{genkey} : génère une clef de 256 bits. Utilisé initialement pour définir la clef d'authentification $K_{a}$ et la clef de chiffrement $K_{c}$ ;
48 \item \emph{tests} : effectue un certain nombre de tests pour vérifier le comportement du serveur vis-à-vis du protocole ;
49 \item \emph{oracle-weak} : effectue une attaque sur la première version du serveur ;
50 \item \emph{oracle-fixed} : effectue une attaque sur la version corrigée du serveur.
51 \end{itemize}
52
53
54 \subsection{Structure du code}
55
56 Le code est découpé en quatre modules :
57
58 \begin{itemize}
59 \item \emph{crypto} : fournit les primitives de chiffrement, déchiffrement, calcul du MAC. Utilise un binding \emph{Rust} vers \emph{OpenSSL} ;
60 \item \emph{packet} : définit le format des paquets et permet leur sérialisation et dé-sérialisation ;
61 \item \emph{end\_point} : permet la création de serveurs et de clients et gère la communication sur \emph{TCP/IP} ;
62 \item \emph{oracle\_machine} : implémente l'attaque par padding-oracle.
63 \end{itemize}
64
65 \subsection{Tests du protocole}
66 \begin{sloppypar}
67 Un certain nombre de tests sont implémentés dans la fonction \texttt{end\_point::Client::start\_tests(..)}. Il est possible de les exécuter à l'aide de la commande suivante.
68 \end{sloppypar}
69
70 \begin{lstlisting}
71 $> cargo run -- tests
72 \end{lstlisting}
73
74 La sortie de cette commande est la suivante :
75
76 \begin{lstlisting}[breaklines, basicstyle=\small]
77 Compiling lab1_rust v0.0.1 (file:///home/gburri/Documents/Master/ICR/lab1/lab1_rust)
78 Running `target/lab1_rust tests`
79 Starting server on [::1]:4221...
80 Server started
81 ===== Test case #1:
82 Sending a valid packet...
83 [Client] time: 0. Sending: Command { id: 154, payload(29): "ba57cb4a9cc83c9b9027bca2cf9c46f25d0c1608a4044dc878bd474bbd" }
84 [Server] time: 2. Valid command received: Packet { t: Command { id: 154, payload(29): "ba57cb4a9cc83c9b9027bca2cf9c46f25d0c1608a4044dc878bd474bbd" }, timestamp: 1 }
85 [Server] time: 3. Answer sent: Answer { id: 125, payload(31): "a88ffbd4758e17d0130cd11c1749149bc33cc818c42edec5fb6edb29352f83" }
86 [Client] time: 4. Command transmitted correctly, answer: Packet { t: Answer { id: 125, payload(31): "a88ffbd4758e17d0130cd11c1749149bc33cc818c42edec5fb6edb29352f83" }, timestamp: 3 }
87 ===== Test passed
88 ===== Test case #2:
89 [Server] time: 3. Connection closed: EOF
90 Sending a packet with an unknown type...
91 [Server] time: 0. Error or invalid packet: Err(UnknownPacketTypeError)
92 ===== Test passed
93 [Server] time: 0. Connection closed: EOF
94 ===== Test case #3:
95 Sending a packet with an old timestamp...
96 Error, timestamp mismatch, current timestamp: 0, packet received: Packet { t: Command { id: 154, payload(29): "ba57cb4a9cc83c9b9027bca2cf9c46f25d0c1608a4044dc878bd474bbd" }, timestamp: 0 }
97 [Server] time: 0. Error or invalid packet: Err(InvalidTimestampError)
98 ===== Test passed
99 [Server] time: 0. Connection closed: EOF
100 ===== Test case #4:
101 Sending a packet with altered crypted data (do not alter the padding)...
102 [Server] time: 2. Error or invalid packet: Err(MACMismatchError)
103 ===== Test passed
104 [Server] time: 2. Connection closed: EOF
105 ===== Test case #5:
106 Sending a packet with too small data...
107 [Server] time: 0. Error or invalid packet: Err(UnconsistentDataSizeError)
108 ===== Test passed
109 [Server] time: 0. Connection closed: EOF
110 ===== Test case #6:
111 Sending a packet with too large data...
112 [Server] time: 0. Error or invalid packet: Err(UnconsistentDataSizeError)
113 ===== Test passed
114 [Server] time: 0. Connection closed: EOF
115 ===== Test case #7:
116 Sending a packet with wrong padding (all 0)...
117 [Server] time: 2. Error or invalid packet: Err(PaddingError)
118 ===== Test passed
119 All tests passed
120 [Server] time: 2. Connection closed: EOF
121 \end{lstlisting}
122
123
124 \subsection{Quelle est la stratégie recommandée en pratique parmi les trois listées ci-après ?}
125
126 \begin{itemize}
127 \item \emph{MAC-and-Encrypt} : $Enc(M)|MAC(M)$ ;
128 \item \emph{MAC-then-Encrypt} : $Enc(M|MAC(M))$ ;
129 \item \emph{Encrypt-then-MAC} : $Enc(M)|MAC(Enc(M))$.
130 \end{itemize}
131
132 D'après \cite{wiki-authentication-encryption}, la stratégie \emph{Encrypt-then-MAC} est la plus sûre dans le cadre du chiffrage authentifié. L'article de \emph{M. Bellare and C. Namprempre} \cite{authenticated-encryption-bellare-namprempre} évalue ces trois stratégies.
133
134
135 \subsubsection{Quelle stratégie est utilisée par \emph{TLS} ?}
136
137 \emph{TSL} utilise la deuxième version (\emph{MAC-then-Encrypt}). À noter que le \emph{MAC} est optionnel.
138
139 Une proposition \footnote{https://tools.ietf.org/html/draft-ietf-tls-encrypt-then-mac-02} existe afin d'utiliser du \textit{Encrypt-then-MAC} pour \emph{TSL}.
140
141
142 \subsubsection{Quelle stratégie est utilisée par \emph{SSH} ?}
143
144 \emph{SSH} utilise la même méthode que celle utilisée dans ce laboratoire, c'est-à-dire \emph{MAC-and-Encrypt}.
145
146 \subsection{Quel est le rôle du timestamp en terme de sécurité ?}
147
148 Il permet de minimiser certaines attaques comme l'attaque par rejeu (\emph{replay attack})\cite{wiki-replay-attack} où un attaquant réutilise tel-quel tout ou une partie d'un message intercepté au préalable.
149
150 Dans notre cas un attaquant ne pourra pas rejouer une commande telle quelle, car elle serait rejetée par le serveur ayant un \emph{timestamp} supérieur. Si l'attaquant essaie de renvoyer un paquet avec un timestamp modifié, alors les données décodées ne seront plus validées par le \emph{MAC} car le vecteur d'initialisation utilisé (\emph{IV}) lors du déchiffrement est composé en partie par le \emph{timestamp}.
151
152
153 \subsection{Y a-t-il un moyen d'effectuer une attaque de type \emph{denial-of-service} sur notre dispositif ?}
154
155 Via une \emph{replay attack} en modifiant le \emph{timestamp} pour qu'il soit valide, le dispositif va devoir déchiffrer les données puis calculer le \emph{MAC} avant de se rendre compte que le paquet est invalide et envoyer une réponse qui sera chiffrée et authentifiée. Dans ce cas on peut faire travailler énormément le dispositif en lui envoyant autant de paquets à déchiffrer que le permet le débit du moyen de communication utilisé. Cela peut amener le dispositif à être surchargé.
156
157
158 \subsection{À la place d'utiliser un \emph{IV} aléatoire, le mode \emph{CBC} implémente une approche basée sur un \emph{nonce}. Que peut-on dire de sa sécurité ?}
159
160 Cet article de \emph{P. Rogaway}\cite{modes-of-operation} suggère d'éviter de suivre le standard qui consiste à chiffrer le nonce avec la même clef utilisée pour les données.
161
162
163 \subsection{Remarques concernant la sécurité de notre protocole}
164
165 A priori nous n'avons pas choisi la stratégie la plus recommandée en terme de sécurité. Comme nous le verrons par la suite, ce protocole est vulnérable à une attaque de type \emph{padding-oracle}.
166
167
168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
169 \section{Utilisation du serveur comme d'un oracle de déchiffrement}
170
171 \subsection{Historique de l'attaque par oracle à l'aide du remplissage}
172
173 L'attaque originelle a été publiée en 2002 par \emph{Serge Vaudenay}. En 2010, cette attaque a été mise en pratique contre plusieurs frameworks web tels que \emph{JavaServer Faces}, \emph{Ruby on Rails} et \emph{ASP.NET}. En 2012, il a été montré qu'elle était efficace contre certain appareils hardware.
174
175 Il existe une nouvelle variante, publiée en 2013, nommée \emph{the Lucky Thirteen attack}, permettant d'attaquer des implémentations ayant été corrigées. En février 2013, les personnes en charge des implémentations de \emph{TLS} travaillaient à la réalisation d'un correctif à cette attaque.
176
177 L'attaque la plus récente utilisant un \emph{padding-oracle} est \emph{POODLE} \footnote{\url{http://en.wikipedia.org/wiki/POODLE}} qui a été dévoilée en septembre 2014.
178
179 Cette section est largement inspirée de l'article de \emph{Wikipedia} sur la \emph{padding-oracle attack} \cite{wiki-padding-oracle-attack}.
180
181 \subsection{Explication de l'attaque pour notre cas}
182
183 Le but est de faire décoder par un oracle tout ou une partie d'un message chiffré intercepté. Le décryptage se fait par bloc de 16 octets et nécessite le bloc chiffré le précédant ou l'\emph{IV} dans le cas du premier bloc. Pour notre test nous partons du principe que l'attaquant a intercepté un paquet chiffré, qu'il en a compris la structure et qu'il a deviné que l'\emph{IV} correspondait au \emph{timestamp}.
184
185 Nous utilisons une attaque basée sur l'information renvoyée par l'oracle concernant la présence d'un bourrage valide. D'après le protocole un \emph{MAC} est calculé à partir des données non-bourrées, puis le bourrage est ajouté pour obtenir une taille multiple de 16, et finalement les données et le bourrage sont chiffrés. Lors du traitement par l'oracle, les données sont d'abord déchiffrées puis le bourrage est contrôlé. S'il n'est pas valide un paquet d'erreur est renvoyé au client (\emph{CryptError}). Si le bourrage est correct, alors celui-ci est retiré et les données restantes sont authentifiées à l'aide du \emph{MAC}. Si l'authentification échoue alors un paquet d'erreur est renvoyé au client (\emph{AuthError}).
186
187 La valeur des octets du bourrage correspond à sa taille, par exemple un bourrage de longueur trois est représenté par \emph{[0x03, 0x03, 0x03]}. Si les données avant bourrage sont déjà multiple de 16, alors un bourrage de longueur 16 est ajouté de sorte qu'un bourrage soit toujours présent.
188
189 \begin{figure}
190 \begin{center}
191 \includegraphics[scale=0.6]{diagramme_AES-CBC.eps}
192 \caption{\label{diagramme_AES-CBC} \textit{Décryptage par un oracle, AES-CBC.}}
193
194 \end{center}
195 \end{figure}
196
197 La figure \ref{diagramme_AES-CBC} illustre la structure de l'attaque. \emph{IV} et \emph{D} n'ont pas d'importance dans notre cas. \emph{X} est le bloc à décrypter (\emph{ciphertext}), \emph{X'} est le bloc à décrypter après avoir été décodé par \emph{AES} mais avant d'avoir été \og xoré \fg{} par \emph{F}. \emph{F} correspond à un bloc qui sera forgé par nos soins durant le décryptage de \emph{X}. De plus \emph{C}, qui n'est pas illustré sur le schéma, correspond au bloc précédent \emph{X} ou à l'\emph{IV} si \emph{X} est le premier bloc et \emph{R} correspond au message décrypté (\emph{plaintext}).
198
199 Dans un premier temps nous allons chercher le premier octet $b$ de $F$ noté $F_{1}$ en itérant celui ci de 0 à 255. Pour chaque itération un paquet de commande est envoyé à l'oracle comprenant en guise de données chiffrées : $F + X$. Le paquet d'erreur renvoyé va nous indiquer si le bourrage est correct (\emph{AuthError}) ou s'il ne l'est pas (\emph{CryptError}). Pour le premier octet nous allons chercher le bourrage \emph{[0x01]}, pour le deuxième le bourrage \emph{[0x02, 0x02]} et ainsi de suite jusqu'à l'octet 16.
200
201 Dès qu'un paquet d'erreur \emph{AuthError} est reçu alors nous pouvons calculer $X'_{1} = F_{1} \oplus b$ puis le premier octet de notre message décrypté $R_{1} = X'_{1} \oplus C_{1}$. Avant de passer à l'octet suivant $b' = b + 1$ il faut s'assurer que les $b$ premiers octets de \emph{E} vaudront bien $b'$ lors du décryptage par l'oracle. Pour ce faire on met à jour \emph{F} comme ceci : $\forall i \in [1, \ldots, b], F_{i} = b' \oplus X_{i}$.
202
203 Une subtilité existe pour la recherche du premier octet : il est possible que le paquet d'erreur \emph{AuthError} corresponde, avec une faible probabilité, à un autre bourrage que \emph{[0x01]}. Pour prévenir ce cas il faut, pour ce premier octet, envoyer un paquet de commande pour toutes les valeurs de $F_{1}$ et compter le nombre de paquets d'erreur \emph{AuthError} reçus. Si ce nombre est égal à 1 alors on peut passer à $b'$, sinon il faut recommencer en modifiant $F_{2} = (F_{2} + 1)\, mod\, 256$.
204
205 Le code correspondant à cette attaque peut être exécuté par la commande suivante :
206
207 \begin{lstlisting}
208 $> cargo run --release -- oracle-weak
209 \end{lstlisting}
210
211 La sortie est la suivante :
212
213 \begin{lstlisting}[breaklines, basicstyle=\small]
214 The oracle machine has found the plain block!:
215 Expected block: [242, 93, 12, 22, 8, 164, 4, 77, 200, 120, 189, 71, 75, 189, 2, 2]
216 Decrypted block: [242, 93, 12, 22, 8, 164, 4, 77, 200, 120, 189, 71, 75, 189, 2, 2]
217 \end{lstlisting}
218
219
220 \subsection{Calcul de la complexité moyenne de l'attaque en terme de nombre de requêtes effectuées auprès de l'oracle}
221
222 Sans prendre en compte la particularité du premier octet illustré à la section précédente, la complexité moyenne pour le décryptage d'un bloc de 16 octets est de $16 * 256 / 2 = 2048$ requêtes.
223
224 Dans l'exemple présenté dans le code, le nombre de requêtes est de 2099. La durée d'exécution est de ~180 ms, cette relative longue durée est certainement due à un overhead engendré par les couches réseau \emph{TCP/IP}.
225
226
227 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
228 \section{Correction du protocole}
229
230 \subsection{Description}
231
232 Le correctif proposé consiste à authentifier également le bourrage et non plus que les données. Cela a pour conséquence de vérifier en premier l'authenticité du contenu avant de procéder à la validité du padding. Les deux messages d'erreur, \emph{CryptError} et \emph{AuthError}, font toujours parties du protocole.
233
234 Le code correspondant à ce correctif peut être exécuté par la commande suivante :
235
236 \begin{lstlisting}
237 $> cargo run --release -- oracle-fixed
238 \end{lstlisting}
239
240
241 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
242 \section{Conclusion}
243
244 Ce laboratoire a permis de mettre en évidence une attaque par \emph{padding-oracle} sur un protocole utilisant des normes de sécurité standards et éprouvées telles que \emph{AES} en mode \emph{CBC}, une authentification par \emph{HMAC-SHA256} et la stratégie \emph{MAC-and-Encrypt}. Une solution a ensuite été proposée et testée face à l'attaque précédemment citée.
245
246
247 \bibliographystyle{plain}
248 \bibliography{main}
249
250 \end{document}