Cambie la función para que no haya más canales laterales

3

Se da la función compareKey , que forma parte de un crackme (un archivo binario). ¿Qué ataque de canal lateral se puede usar para encontrar la contraseña correcta (la contraseña está formada por letras grandes y pequeñas codificadas en ASCII de az, y decimales) y cómo se puede diseñar esta función para que no haya ningún canal lateral? / p>

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;
}

Así que ya ejecuté el binario crackme e ingresé algunas contraseñas de diferente longitud. Me di cuenta de que si la contraseña tiene una longitud 7 , se necesita más tiempo para imprimir Wrong (contraseña incorrecta ..). Si la contraseña tiene una longitud diferente a 7 , se imprime inmediatamente Wrong . Por lo tanto, es más probable que la contraseña tenga una longitud 7 (¡de hecho lo es!) Y probablemente tengamos un ataque de tiempo aquí porque vemos en el código anterior que las dos cadenas keyInput y correctKey ) se comparan carácter por carácter y discrepancia de alerta cuando ven una diferencia entre los dos caracteres que se están comparando actualmente.

¿Esta es la respuesta correcta hasta ahora?

Podemos arreglar este canal lateral de esta manera:

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

¿Está bien así que realmente no estoy seguro? : /

    
pregunta roblind 07.05.2018 - 19:49
fuente

2 respuestas

3

Ambas implementaciones sugeridas tienen problemas.

El primero falla porque aún tiene que preocuparse por la sincronización al comparar hashes , y el operador == es casi con seguridad no es un tiempo constante.

El segundo falla por dos razones, las cuales le permiten al atacante determinar fácilmente la longitud del secreto:

  1. Tienes una salida temprana.
  2. zip de Python se trunca en la longitud del iterador más corto, por lo que un atacante puede seguir aumentando la duración de su entrada hasta que el tiempo permanezca igual.
respondido por el AndrolGenhald 07.05.2018 - 20:45
fuente
2

Primero copiaría las contraseñas en un búfer de un tamaño estático, luego llenaría el resto del búfer con una cadena de cero estática utilizando la misma función de copia (de lo contrario, la copia perderá la información del tamaño). Incluso entonces puede filtrar información de tamaño dado que la copia puede cruzar el límite de una página, pero en general ese tipo de información de almacenamiento en caché solo se filtra si un ataque se origina en la misma máquina. El cálculo del tamaño también puede filtrar información (vamos y venimos dando vueltas, no es tan divertido).

La cadena estática debe tener un valor específico que no puede ser parte de la entrada, de lo contrario, las contraseñas que terminen con algo en el búfer estático se compararán con el mismo valor que las contraseñas más cortas (hiy | aa sería idéntica a hiya | a) , donde | Es concatenación.

Otra opción es copiar primero la longitud en la matriz para que pueda tener una cadena aleatoria (que, por supuesto, debe ser la misma para que el valor se compare).

Nombremos x y y de tamaño estático como x 'e y' Luego generaría una clave aleatoria y compararía HMAC (K_r, x ') con HMAC (K_r, y'). Esto no filtrará ninguna información sobre el valor de entrada porque el HMAC en lugar de la entrada es aleatorio para cada comparación . Es posible que también puedas usar H (K_r | x ') y H (K_r | y') para esto.

Si decide utilizar un retardo aleatorio, entonces ejecútelo antes de la operación . Esto hace que sea más difícil realizar cualquier medición de potencia durante las operaciones, en caso de que no esté solo preocupado por los ataques basados en el tiempo.

    
respondido por el Maarten Bodewes 11.05.2018 - 14:19
fuente

Lea otras preguntas en las etiquetas