Code cleaning and report progress.
authorUmmon <greg.burri@gmail.com>
Thu, 6 Nov 2014 18:08:19 +0000 (19:08 +0100)
committerUmmon <greg.burri@gmail.com>
Thu, 6 Nov 2014 18:08:19 +0000 (19:08 +0100)
lab1_rust/src/main.rs
lab1_rust/src/oracle_machine.rs
lab1_rust/src/packet.rs
rapport/main.bib
rapport/main.tex

index de93150..9049ff6 100644 (file)
@@ -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();
 
index 3d72ddf..316f06e 100644 (file)
@@ -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<Vec<u8>> {
+/// 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<Vec<u8>> {
    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;
index 95468a1..c81fe20 100644 (file)
@@ -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.
index 1647767..8c58aea 100644 (file)
@@ -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",
index 16b8e6c..2bfd029 100644 (file)
@@ -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 -- <args>
+\end{lstlisting}
+
+Où \emph{<args>} 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}