From: Ummon Date: Thu, 6 Nov 2014 18:08:19 +0000 (+0100) Subject: Code cleaning and report progress. X-Git-Url: http://git.euphorik.ch/index.cgi?a=commitdiff_plain;h=c484911fa250681026144ddb9e521daa2c2b4351;p=crypto_lab1.git Code cleaning and report progress. --- diff --git a/lab1_rust/src/main.rs b/lab1_rust/src/main.rs index de93150..9049ff6 100644 --- a/lab1_rust/src/main.rs +++ b/lab1_rust/src/main.rs @@ -17,10 +17,15 @@ const PORT: u16 = 4221; fn do_oracle_attack(address: &str, variant: packet::Variant) { // 16 bytes encrypted data from 'Packet::random_packet_data([4])'. - let cipher_block: [u8, ..16] = [254, 9, 228, 149, 60, 42, 165, 34, 233, 75, 112, 57, 37, 9, 116, 103]; // Known by the attacker. - let xor_operand: [u8, ..16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]; // This is the IV or the previous 16 bytes cipherblock. In our case we took the IV. + 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_clear_block: [u8, ..16] = [44, 92, 31, 98, 220, 84, 226, 53, 58, 94, 45, 25, 242, 6, 199, 1]; // 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]; + */ match oracle_machine::decipher(address, PORT, &xor_operand, &cipher_block, variant) { Some(ref deciphered) if deciphered.as_slice() == expected_clear_block => { @@ -35,6 +40,17 @@ fn do_oracle_attack(address: &str, variant: packet::Variant) { } } +fn print_usage() { + println!( + r"{} [genkey | tests | oracle-weak | oracle-fixed] + genkey: Generate a 256 bits key + tests: launch some tests between a client and a weak server + oracle-weak: launch a padding oracle attack against a weak server + oracle-fixed: launch a padding oracle attack against a fixed server", + os::args()[0] + ); +} + enum Mode { Help, ServerAlone, @@ -64,17 +80,6 @@ fn mode() -> Mode { } } -fn print_usage() { - println!( - r"{} [genkey | tests | oracle-weak | oracle-fixed] - genkey: Generate a 256 bits key - tests: launch some tests between a client and a weak server - oracle-weak: launch a padding oracle attack against a weak server - oracle-fixed: launch a padding oracle attack against a fixed server", - os::args()[0] - ); -} - fn main() { let mode = mode(); diff --git a/lab1_rust/src/oracle_machine.rs b/lab1_rust/src/oracle_machine.rs index 3d72ddf..316f06e 100644 --- a/lab1_rust/src/oracle_machine.rs +++ b/lab1_rust/src/oracle_machine.rs @@ -7,8 +7,8 @@ use packet::{ Packet, Error }; use end_point::EndPoint; /// Try to decipher a ciphered data block by using the previous XOR operand and an oracle on the provided address and port. -/// May print some message on stdout. -pub fn decipher(address: &str, port: u16, original_xor_operand: &[u8, ..16], cipherblock: &[u8, ..16], variant: packet::Variant) -> Option> { +/// May print some messages on stdout. +pub fn decipher(address: &str, port: u16, original_xor_operand: &[u8, ..16], cipher_block: &[u8, ..16], variant: packet::Variant) -> Option> { let mut end_point = EndPoint::new( match TcpStream::connect(address, port) { Ok(s) => s, @@ -23,10 +23,10 @@ pub fn decipher(address: &str, port: u16, original_xor_operand: &[u8, ..16], cip // See 'packet::Packet' documentation for a complete description about the binary packet structure. let mut final_packet = [0u8, ..2 + 1 + 8 + 32 + 10]; final_packet[1] = (final_packet.len() as u8) - 2; // Data length. - copy_memory(final_packet.slice_mut(2 + 1 + 8 + 16, 2 + 1 + 8 + 32), cipherblock); + copy_memory(final_packet.slice_mut(2 + 1 + 8 + 16, 2 + 1 + 8 + 32), cipher_block); let mut decipher_block = [0u8, ..16]; // The result. - let mut x_prime_block = [0u8, ..16]; // The cipher block ('cipherblock') after AES and before XOR. + let mut x_prime_block = [0u8, ..16]; // The cipher block ('cipher_block') after AES and before XOR. let mut current_timestamp = 0u64; let mut first_byte = 0u8; // Used to save the first byte for the first iteration. @@ -53,7 +53,8 @@ pub fn decipher(address: &str, port: u16, original_xor_operand: &[u8, ..16], cip Ok(Ok(p @ Packet { t: Error(packet::AuthError), .. })) => { println!("We received a MAC Error: {}", p); - // If we already got a MAC mismatch for the first byte then the second byte is incremented and the loop is replayed. + // If we already got a MAC mismatch for the first byte then + // the second byte is incremented and the main loop is replayed for the first byte. if byte == 15 && get_mac_mismatch_error { forged_xor_operand(&mut final_packet)[14] += 1; continue 'main_loop; diff --git a/lab1_rust/src/packet.rs b/lab1_rust/src/packet.rs index 95468a1..c81fe20 100644 --- a/lab1_rust/src/packet.rs +++ b/lab1_rust/src/packet.rs @@ -158,7 +158,7 @@ impl Packet { _ => () } - // Compute the MAC. It depends the choosen variant. + // Compute the MAC. It depends of the choosen variant. let mac = crypto::compute_mac(data.slice_to(match variant { Weak => data_size, _ => data.len() })); // Encrypt. diff --git a/rapport/main.bib b/rapport/main.bib index 1647767..8c58aea 100644 --- a/rapport/main.bib +++ b/rapport/main.bib @@ -1,3 +1,11 @@ +@article {authenticated-encryption-bellare-namprempre, + author = "M. Bellare and C. Namprempre", + title = "Authenticated Encryption: Relations among notions and analysis of the generic composition paradigm", + journal = "UC San-Diego", + year = "2007", + url = "\url{http://cseweb.ucsd.edu/~mihir/papers/oem.html}" +} + @misc {wiki-replay-attack, author = "Wikipedia", title = "Replay attack --- {W}ikipedia{,} The Free Encyclopedia", diff --git a/rapport/main.tex b/rapport/main.tex index 16b8e6c..2bfd029 100644 --- a/rapport/main.tex +++ b/rapport/main.tex @@ -31,10 +31,38 @@ Nous utiliseront \emph{AES-256} en mode \emph{CBC} pour chiffrer les données ai %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Simulation du protocole} -\subsection{Utilisation du code} +\subsection{Utilisation du programme} + +Le code est écrit en langage 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'installer la version \emph{nightly} disponible ici : \url{http://www.rust-lang.org/install.html}. + +Pour construire et lancer l'application il faut se trouver dans le dossier contenant le fichier \emph{Cargo.toml} et lancer la commande suivante. + +\begin{lstlisting} +$> cargo run -- +\end{lstlisting} + +Où \emph{} peut valoir : + +\begin{itemize} + \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}$ ; + \item \emph{tests} : effectue un certain nombre de tests pour vérifier le comportement du serveur vis-à-vis du protocole ; + \item \emph{oracle-weak} : effectue une attaque sur la première version du serveur ; + \item \emph{oracle-fixed} : effectue une attaque sur la version corrigé du serveur. +\end{itemize} + \subsection{Structure du code} +Le code est structuré 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{packet} : définit le format des paquets et permet leur sérialisation et dé-sérialisation ; + \item \emph{end\_point} : permet la création de serveurs et de clients et gère la communication sur \emph{TCP/IP} ; + \item \emph{oracle\_machine} : implémente l'attaque par padding-oracle. +\end{itemize} + + \subsection{Quelle est la stratégie recommandée en pratique parmi les trois listées ci après ?} \begin{itemize} @@ -43,6 +71,9 @@ Nous utiliseront \emph{AES-256} en mode \emph{CBC} pour chiffrer les données ai \item \emph{Encrypt-then-MAC} : $Enc(M)|MAC(Enc(M))$. \end{itemize} +D'après \cite{wiki-authentication-encryption} la stratégie \emph{Encrypt-then-MAC} est la plus sûre dans le cadre de chiffrage authentifié. L'article de \emph{M. Bellare and C. Namprempre} \cite{authenticated-encryption-bellare-namprempre} évalue ces trois stratégies. + + \subsubsection{Quelle stratégie est utilisée par \emph{TLS} ?} \emph{TSL} utilise la deuxième version (\emph{MAC-then-Encrypt}). À noté que le \emph{MAC} est optionnel. @@ -73,7 +104,7 @@ TODO \subsection{Remarques concernant la sécurité de notre protocole} -TODO +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}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -81,8 +112,11 @@ TODO \subsection{Historique de l'attaque par oracle à l'aide du remplissage} -TODO +L'attaque original a été publié en 2002 par \emph{Serge Vaudenay}. En 2010, cette attaque a été mise en pratique contre plusieurs frameworks web tel que \emph{JavaServer Faces}, \emph{Ruby on Rails} et \emph{ASP.NET}. En 2012, il a été montré qu'elle est efficace contre certain appareils hardware. + +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. +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} @@ -108,12 +142,18 @@ Dès qu'un paquet d'erreur \emph{AuthError} est reçu alors nous pouvons calcule Une subtilité existe pour la recherche du premier octet, il est possible que le paquet d'erreur \emph{AuthError} correspond, 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 paquet d'erreur \emph{AuthError} reçu. Si ce nombre est égal à 1 alors on peut passer à $b'$, sinon il faut recommencer en modifiant $F_{2} = (F_{2} + 1) mod 256$. +Le code correspondant à cette attaque peut être exécuté par la commande suivante : + +\begin{lstlisting} +$> cargo run --release -- oracle-weak +\end{lstlisting} + \subsection{Calcul de la complexité moyenne de l'attaque en terme de nombre de requête effectué auprès de l'oracle} 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 le cas présenté dans le code, le nombre de requête est de 1795. +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}. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% @@ -121,14 +161,24 @@ Dans le cas présenté dans le code, le nombre de requête est de 1795. \subsection{Description} +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 partis du protocole. + +Le code correspondant à ce correctif peut être exécuté par la commande suivante : + +\begin{lstlisting} +$> cargo run --release -- oracle-fixed +\end{lstlisting} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \section{Conclusion} +TODO + + + + -%http://crypto.stackexchange.com/a/205 -%https://en.wikipedia.org/wiki/Malleability_%28cryptography%29 \bibliographystyle{plain} \bibliography{main}