Autenticazione Challenge / Response per l'apriporta del garage

20

Sto costruendo un apriporta per garage radiofonico basato su Arduino, e per proteggerlo dagli attacchi di replay mi è venuta in mente questo algoritmo:

  1. mittente avvia la comunicazione
  2. Il ricevitore
  3. invia un numero casuale a 32 bit XORed con una chiave segreta
  4. il mittente inverte l'operazione XOR usando la stessa chiave segreta, risolve la sfida (es: challenge ^ 2 - 5), XORes e invia il risultato al ricevitore insieme al comando (gate up o gate down)
  5. Il ricevitore
  6. confronta la risposta con il proprio calcolo della sfida ed esegue il comando se corrispondono.

Sono curioso, i passaggi sopra descritti assicurano che la risposta sia impossibile da indovinare per un utente malintenzionato?

    
posta Denis Denisovici 21.04.2016 - 13:06
fonte

2 risposte

58

No.

Scriviamolo:

  • C è il messaggio di sfida
  • R è il messaggio di risposta
  • K è la chiave segreta
  • C = q ⊕ K dove q è un numero casuale.
  • R = ((C ⊕ K) 2 - 5) ⊕ K , oppure saltando il passo di decrittazione: R = (q 2 - 5) ⊕ K .

L'attaccante può vedere sia C sia R . Se l'utente malintenzionato esegue quindi il xors dei due valori:

C ⊕ R = (q 2 - 5) ⊕ K ⊕ q ⊕ K

Poiché eseguiamo il xoring con K due volte, possiamo semplicemente eliminare queste operazioni. Ciò fornisce all'attaccante quanto segue:

C ⊕ R = (q 2 - 5) ⊕ q

Ci sono solo alcuni valori per q per ogni dato valore di C ⊕ R nello spazio a 32 bit. In effetti, è un'operazione abbastanza semplice da fare solo forza bruta: prova tutti i valori q finché non trovi tutti i valori corrispondenti.

Questo ti dà qualche possibile valore di q , il numero casuale. Poiché C = q ⊕ K , basta calcolare C ⊕ q per ciascun candidato q per ottenere un piccolo numero di K valori. Ripeti questo processo per la seconda volta e vedi quale valore K candidato è apparso in entrambe le esecuzioni: questo ti dà K .

Ho persino scritto un PoC!

// our key!
int k = 0xBAD1DEA;

void Main()
{
    // output the key just so we can see it in the output
    Console.WriteLine("Key is: 0x{0:X8}", k);

    int challenge = GenerateChallenge();
    int response = GenerateResponse(challenge);

    Console.WriteLine();
    Console.WriteLine("Cracking the challenge and response...");

    // this is the attacker: they know only the challenge and respoonse!
    Crack(challenge, response);
}

int GenerateChallenge()
{
    Random rng = new Random();

    // I'm keeping the random number small-ish to avoid the c^2 operation from overflowing
    // this is just a limitation of the fact that .NET has sane integer types that don't wrap on multiplication overflows
    int q = rng.Next(0, 10000000);
    Console.WriteLine("I picked q={0}", q);

    int challenge = k ^ q;
    return challenge;
}

int GenerateResponse(int c)
{
    c ^= k;
    return ((c * c) - 5) ^ k;
}

void Crack(int c, int r)
{
    int c_r = c ^ r;

    // try all possible 'q' values.
    for (int q = 1; q < int.MaxValue; q++)
    {
        if ((((q * q) - 5) ^ q) == c_r)
        {
            // got a match, output it
            Console.WriteLine("q candidate: {0}", q);
            Console.WriteLine("k candidate: 0x{0:X8}", q ^ c);
        }
    }
}

Output di esempio:

Key is: 0x0BAD1DEA
I picked q=2847555

Cracking the challenge and response...
q candidate: 2847555
k candidate: 0x0BAD1DEA

Il processo di "cracking" ha richiesto meno di un secondo sul mio sistema.

EDIT: Dal momento che questo non è stato chiaro: non sei brutoforcing di nulla contro il sistema reale. Questo approccio non implica affatto l'invio di dati al destinatario. Ti siedi semplicemente con una radio definita dal software (SDR) e acquisisci i segnali prodotti quando il proprietario apre la porta del garage. Quindi estrai i valori di sfida e risposta da quei segnali: questi sono C e R . Dato C e R puoi usare il processo sopra riportato per calcolare alcuni possibili valori q per quella particolare coppia sfida / risposta. In alcuni casi ne riceverai solo uno, in alcuni casi potresti ottenere 2 o 3. Calcolare q ⊕ C per ciascun candidato q per ottenere una lista di candidati K valori. Se ne ottieni più di uno, attendi che aprano nuovamente il loro garage e catturi un'altra coppia C e R , riesegui il processo e vedi quale candidato I valori di K corrispondono per la prima volta - questo ti darà il vero valore K . Una volta ottenuto ciò, hai tutto ciò che ti serve per impersonare il vero dispositivo di apertura. Puoi rispondere correttamente ogni volta poiché conosci il valore di K .

    
risposta data 21.04.2016 - 13:44
fonte
1

Prima di tutto, hai bisogno di una funzione crittografica la cui relazione tra input e output non sia facilmente distinguibile. XOR non lo taglierà. Un modo lento ma efficace per crittografare i dati sarebbe quello di dividere il valore a 32 bit in due metà, H e L, e iterare il seguente alcune volte:

  • Pad H con abbastanza byte per creare un blocco crittografico per DES, AES o qualche altro schema decente (e una chiave segreta) e crittografarlo.
  • Imposta H sul vecchio valore di L e imposta L sul vecchio valore di H xor'ed a 16 bit dal blocco crittografato.

Se si utilizza l'approccio di cui sopra con un metodo di crittografia decente nel suo nucleo, il risultato sarà una mappatura sicura da 32 bit a 32 bit. La mappatura inversa può essere ottenuta scambiando H e L, seguendo la procedura sopra riportata e scambiandoli indietro.

Un payload a 32 bit è piuttosto piccolo, ma potrebbe fornire un ragionevole livello di sicurezza se le sfide non vengono mai ripetute. Ciò potrebbe essere ottenuto facendo in modo che il mittente mantenga un conteggio per tutta la durata del numero di sfide inviate e utilizzandolo come dati di prova da crittografare e convalidare.

    
risposta data 21.04.2016 - 18:29
fonte

Leggi altre domande sui tag