// 16 bytes encrypted data from 'Packet::random_packet_data([4])'.
let cipher_block = [191, 192, 149, 84, 202, 163, 109, 230, 173, 249, 170, 248, 83, 60, 228, 111]; // Known by the attacker.
let xor_operand = [213, 29, 217, 187, 93, 103, 76, 129, 233, 142, 98, 83, 69, 50, 97, 91]; // This is the IV or the previous 16 bytes cipherblock. In our case we took the previous block.
- let expected_clear_block = [242, 93, 12, 22, 8, 164, 4, 77, 200, 120, 189, 71, 75, 189, 2, 2]; // To be found by the attacker.
+ let expected_plain_block = [242, 93, 12, 22, 8, 164, 4, 77, 200, 120, 189, 71, 75, 189, 2, 2]; // To be found by the attacker.
/* Another sample with an IV instead of a previous block.
let cipher_block: [u8, ..16] = [254, 9, 228, 149, 60, 42, 165, 34, 233, 75, 112, 57, 37, 9, 116, 103];
let xor_operand: [u8, ..16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]; IV.
- let expected_clear_block: [u8, ..16] = [44, 92, 31, 98, 220, 84, 226, 53, 58, 94, 45, 25, 242, 6, 199, 1];
+ let expected_plain_block: [u8, ..16] = [44, 92, 31, 98, 220, 84, 226, 53, 58, 94, 45, 25, 242, 6, 199, 1];
*/
match oracle_machine::decipher(address, PORT, &xor_operand, &cipher_block, variant) {
- Some(ref deciphered) if deciphered.as_slice() == expected_clear_block => {
+ Some(ref deciphered) if deciphered.as_slice() == expected_plain_block => {
println!("The oracle machine has found the clear block!:");
- println!(" Expected block: {}", expected_clear_block.to_vec());
+ println!(" Expected block: {}", expected_plain_block.to_vec());
println!(" Decrypted block: {}", deciphered)
}
Some(ref other) =>
%!PS-Adobe-3.0 EPSF-3.0
%%Creator: cairo 1.13.1 (http://cairographics.org)
-%%CreationDate: Wed Nov 5 23:33:10 2014
+%%CreationDate: Thu Nov 6 23:55:58 2014
%%Pages: 1
%%DocumentData: Clean7Bit
%%LanguageLevel: 2
65.926 26.131 m 62.391 16.518 l 58.855 26.131 l 60.941 24.596 63.797 24.603
65.926 26.131 c h
65.926 26.131 m f*
-0.411765 g
+0.588235 g
BT
19.2 0 0 19.2 54.717017 -0.00000610352 Tm
/f-0-0 1 Tf
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4"
- inkscape:cx="232.21395"
- inkscape:cy="816.57431"
+ inkscape:cx="112.57109"
+ inkscape:cy="804.1497"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1366"
inkscape:window-height="725"
- inkscape:window-x="272"
- inkscape:window-y="1070"
+ inkscape:window-x="-5"
+ inkscape:window-y="-10"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
inkscape:connector-curvature="0" />
<text
xml:space="preserve"
- style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#000000;fill-opacity:0.58823532;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
+ style="font-size:40px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;text-anchor:middle;fill:#969696;fill-opacity:1;stroke:none;font-family:Serif;-inkscape-font-specification:Serif"
x="187.72357"
y="371.73889"
id="text4611"
id="tspan4613"
x="187.72357"
y="371.73889"
- style="font-size:24px;text-align:center;text-anchor:middle;fill:#000000;fill-opacity:0.58823532">D</tspan></text>
+ style="font-size:24px;text-align:center;text-anchor:middle;fill:#969696;fill-opacity:1">D</tspan></text>
<path
inkscape:connector-curvature="0"
id="path4619"
\subsection{Structure du code}
-Le code est structuré en quatre modules :
+Le code est découpé en quatre modules :
\begin{itemize}
\item \emph{crypto} : fournit les primitives de chiffrement, déchiffrement, calcul du MAC. Utilise un binding \emph{Rust} vers \emph{OpenSSL} ;
\item \emph{oracle\_machine} : implémente l'attaque par padding-oracle.
\end{itemize}
+\subsection{Tests du protocole}
+\begin{sloppypar}
+Un certain nombre de tests sont implémenté dans la fonction \texttt{end\_point::Client::start\_tests(..)}. Il est possible de les exécuter à l'aide de la commande suivante.
+\end{sloppypar}
+
+\begin{lstlisting}
+$> cargo run -- tests
+\end{lstlisting}
+
+La sortie de cette commande est la suivante.
+
+\begin{lstlisting}[breaklines, basicstyle=\small]
+$> cargo run -- tests
+ Compiling lab1_rust v0.0.1 (file:///home/gburri/Documents/Master/ICR/lab1/lab1_rust)
+ Running `target/lab1_rust tests`
+Starting server on [::1]:4221...
+Server started
+===== Test case #1:
+Sending a valid packet...
+[Client] time: 0. Sending: Command { id: 154, payload(29): "ba57cb4a9cc83c9b9027bca2cf9c46f25d0c1608a4044dc878bd474bbd" }
+[Server] time: 2. Valid command received: Packet { t: Command { id: 154, payload(29): "ba57cb4a9cc83c9b9027bca2cf9c46f25d0c1608a4044dc878bd474bbd" }, timestamp: 1 }
+[Server] time: 3. Answer sent: Answer { id: 125, payload(31): "a88ffbd4758e17d0130cd11c1749149bc33cc818c42edec5fb6edb29352f83" }
+[Client] time: 4. Command transmitted correctly, answer: Packet { t: Answer { id: 125, payload(31): "a88ffbd4758e17d0130cd11c1749149bc33cc818c42edec5fb6edb29352f83" }, timestamp: 3 }
+===== Test passed
+===== Test case #2:
+[Server] time: 3. Connection closed: EOF
+Sending a packet with an unknown type...
+[Server] time: 0. Error or invalid packet: Err(UnknownPacketTypeError)
+===== Test passed
+[Server] time: 0. Connection closed: EOF
+===== Test case #3:
+Sending a packet with an old timestamp...
+Error, timestamp mismatch, current timestamp: 0, packet received: Packet { t: Command { id: 154, payload(29): "ba57cb4a9cc83c9b9027bca2cf9c46f25d0c1608a4044dc878bd474bbd" }, timestamp: 0 }
+[Server] time: 0. Error or invalid packet: Err(InvalidTimestampError)
+===== Test passed
+[Server] time: 0. Connection closed: EOF
+===== Test case #4:
+Sending a packet with altered crypted data (do not alter the padding)...
+[Server] time: 2. Error or invalid packet: Err(MACMismatchError)
+===== Test passed
+[Server] time: 2. Connection closed: EOF
+===== Test case #5:
+Sending a packet with too small data...
+[Server] time: 0. Error or invalid packet: Err(UnconsistentDataSizeError)
+===== Test passed
+[Server] time: 0. Connection closed: EOF
+===== Test case #6:
+Sending a packet with too large data...
+[Server] time: 0. Error or invalid packet: Err(UnconsistentDataSizeError)
+===== Test passed
+[Server] time: 0. Connection closed: EOF
+===== Test case #7:
+Sending a packet with wrong padding (all 0)...
+[Server] time: 2. Error or invalid packet: Err(PaddingError)
+===== Test passed
+All tests passed
+[Server] time: 2. Connection closed: EOF
+\end{lstlisting}
+
\subsection{Quelle est la stratégie recommandée en pratique parmi les trois listées ci après ?}
\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é ?}
-TODO
+
\subsection{Remarques concernant la sécurité de notre protocole}
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.
+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.
+
Cette section est largement inspirée de l'article de \emph{Wikipedia} sur la \emph{padding-oracle attack} \cite{wiki-padding-oracle-attack}.
\subsection{Explication de l'attaque pour notre cas}
-Le but est de faire décoder tout ou une partie d'un message chiffré intercepté par un oracle. 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}.
+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}.
-Nous utilisons une attaque basé sur l'information renvoyé 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 déchiffrement 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 et renvoyé au client (\emph{CryptError}). Si le bourrage est correct alors celui ci est retiré et les données restantes sont authentifiée à l'aide de la \emph{MAC}, si l'authentification échoue alors un paquet d'erreur et renvoyé au client (\emph{AuthError}).
+Nous utilisons une attaque basé sur l'information renvoyé 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 et renvoyé au client (\emph{CryptError}). Si le bourrage est correct alors celui ci est retiré et les données restantes sont authentifiée à l'aide de la \emph{MAC}, si l'authentification échoue alors un paquet d'erreur et renvoyé au client (\emph{AuthError}).
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.
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.
-Dans l'exemple présenté dans le code, le nombre de requête est de 2099. La durée d'exécution est de ~0.180 ms, ça relative longueur est certainement dû à l'overhead des couches \emph{TCP/IP}.
+Dans l'exemple présenté dans le code, le nombre de requête est de 2099. La durée d'exécution est de ~180 ms, cette relative longue durée est certainement dû à un overhead engendré par les couches réseau \emph{TCP/IP}.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%