Modificare la funzione in modo tale che non ci siano più canali laterali

3

Given è la funzione compareKey che è una parte di un crackme (un file binario). Quale attacco di canale laterale può essere utilizzato per trovare la password corretta (la password è composta da lettere grandi e piccole codificate ASCII da az e decimali) e come è possibile progettare questa funzione in modo tale che non ci siano canali laterali?

int compareKey() {
    unsigned int leng = strleng(keyInput);
    unsigned int correctLeng = strleng(correctKey);
    int i, randomTime, falseKey = 0;

    unsigned int seed = getpid() + keyInput[0];
    srand(seed);  // initialize the random seed

    if (leng != correctLeng)
        return 1;

    for (i = correctLeng-1; i >= 0; i--) {
        if (keyInput[i] != correctKey[i]) {
            usleep(500000);  // that delay will stop bruteforce attack

            falseKey = 1;
        }
    }
    randomTime = 500000 * (rand() % 3);
    usleep(randomTime); // take that
    // and this will prevent the attacker to perform a timed attack

    return falseKey;
}

Quindi ho già eseguito il crackme binario e inserito alcune password di diversa lunghezza. Mi sono reso conto che se la password ha lunghezza 7 , ha bisogno di più tempo per stampare Wrong (password errata ..). Se la password ha una lunghezza diversa da 7 , stampa immediatamente Wrong . Quindi la password è molto probabilmente di lunghezza 7 (lo è davvero!) E probabilmente abbiamo un attacco temporale qui perché vediamo dal codice precedente che le due stringhe keyInput e correctKey ) vengono confrontati carattere per carattere e disallineamento di allerta quando vedono una differenza tra i due caratteri attualmente confrontati.

Questa è una corretta obiezione?

Possiamo correggere questo canale laterale in questo modo:

def secureCompare(stringA, stringB) :
    if (sha256(A) == sha256(B))
        return True
    else
        return False
OR

def secureCompare(stringA, stringB) :
    if leng(A) != leng(B):
        return False

    result = 0
    for x, y in zip(A, B) :
        result |= x ^ y
    return result == 0

Va bene così non sono sicuro? : /

    
posta roblind 07.05.2018 - 19:49
fonte

2 risposte

3

Entrambe le implementazioni suggerite hanno problemi.

Il primo fallisce perché deve ancora preoccuparsi dei tempi durante il confronto degli hash e l'operatore == è quasi certamente non è un tempo costante.

Il secondo fallisce per due motivi, entrambi consentono a un utente malintenzionato di determinare facilmente la lunghezza del segreto:

  1. Hai un anticipo.
  2. Il zip di Python troneggia sulla lunghezza dell'iteratore più breve, quindi un attaccante può continuare ad aumentare la lunghezza del loro input fino a quando il tempo rimane lo stesso.
risposta data 07.05.2018 - 20:45
fonte
2

Prima dovevo copiare le password in un buffer di una dimensione statica, quindi riempire il resto del buffer con una stringa zero statica usando la stessa funzione di copia (altrimenti la copia perderà le informazioni sulla dimensione). Anche in questo caso è possibile che vengano rilevate informazioni di dimensioni poiché la copia potrebbe attraversare il limite di una pagina, ma in generale quel tipo di informazioni di memorizzazione nella cache viene divulgato solo se un attacco proviene dalla stessa macchina. Anche il calcolo delle dimensioni può far trapelare informazioni (giro e giro, non è divertente).

La stringa statica deve avere un valore specifico che non può essere parte dell'input, altrimenti le password che terminano con qualcosa nel buffer statico si confronteranno con lo stesso valore delle password più brevi (hiy | aa sarebbe identico a hiya | a) , dove | è una concatenazione.

Un'altra opzione è quella di copiare prima la lunghezza nell'array in modo da poter avere una stringa randomizzata (che ovviamente deve essere uguale per il valore da confrontare).

Diamo un nome alle dimensioni statiche xey come x 'e y' Quindi vorrei generare una chiave casuale e confrontare HMAC (K_r, x ') con HMAC (K_r, y'). Questo non perderà alcuna informazione sul valore di input perché l'HMAC al posto dell'ingresso è randomizzato per ogni confronto . Potresti anche usare H (K_r | x ') e H (K_r | y') per questo.

Se decidi di utilizzare un ritardo casuale, eseguilo prima dell'operazione . Ciò rende più difficile eseguire misurazioni di potenza durante le operazioni, nel caso in cui non sei solo preoccupato per gli attacchi basati sui tempi.

    
risposta data 11.05.2018 - 14:19
fonte