In SSL / TLS , i messaggi vengono inviati come parte di record . Quello che ci si deve aspettare è che il client invii prima un messaggio ClientHello
che è contenuto in uno o più record.
Il formato del record è:
record type: 1 byte (0x16 for "records contains some handshake message data")
protocol version: 2 bytes (0x03 0x00 for SSL 3.0, 0x03 0x01 for TLS 1.0, and so on)
record length: 2 bytes (big endian)
then the record data...
Per il primo record (da client a server), il client invierà prima un messaggio ClientHello
che è un tipo di messaggio handshake, quindi incapsulato in un record come mostrato sopra (il primo byte del record sarà 0x16 ). In teoria , il client può inviare la suddivisione ClientHello
in più record e può iniziare con uno o più record vuoti, ma ciò non è molto probabile. Il messaggio ClientHello
inizia con la sua intestazione a quattro byte, con un byte per il tipo di messaggio (0x01 per ClientHello
), quindi la lunghezza del messaggio su tre byte (di nuovo big-endian).
Una volta che il client ha inviato il suo ClientHello
, allora si aspetta una risposta dal server, quindi ClientHello
sarà solo nel suo record.
Quindi potresti aspettarti un payload che inizi con i seguenti 9 byte:
0x16 0x03 X Y Z 0x01 A B C
con:
-
X sarà 0, 1, 2, 3 ... o più , a seconda della versione del protocollo utilizzata dal client per questo primo messaggio. Attualmente , le versioni SSL / TLS definite sono SSL 3.0 , TLS 1.0 , TLS 1.1 e TLS 1.2 . Altre versioni potrebbero essere definite in futuro. probabilmente useranno lo schema di numerazione 3. X , quindi puoi aspettarti che il secondo byte di intestazione rimanga un 0x03, ma non dovresti limitare arbitrariamente il terzo byte.
-
Y Z è la codifica della lunghezza del record; A B C è la codifica della lunghezza del messaggio ClientHello
. Poiché il messaggio ClientHello
inizia con un'intestazione di 4 byte (non compresa nella sua lunghezza) e si suppone che sia solo nel suo record, dovresti avere: A = 0 e 256 * X + Y = 256 * B + C + 4 .
Se vedi 9 di questi byte, che verificano queste condizioni, è probabile che si tratti di ClientHello
da un client SSL.
Alcuni client SSL non recenti possono supportare anche una versione precedente del protocollo, denominata SSL 2.0. Questi client emetteranno un ClientHello
che segue le regole SSL 2.0, dove messaggi e record sono in qualche modo uniti. Il messaggio diClientHello
di SSL 2.0% indicherà che il client conosce anche SSL 3.0 o più recente, ma non inizierà con la sequenza di 9 byte spiegata sopra.
La struttura diClientHello
di SSL 2.0% è spiegata in appendice E.2 o RFC 5246 . Anche se tali client sono rarefatti (esiste un RFC sul divieto del supporto di SSL 2.0 del tutto), ci sono ancora molti implementati là fuori.
Il tuo codice ha alcuni problemi:
- Non rileva un messaggio di
ClientHello
di SSL 2.0%.
- Verifica che il terzo byte di intestazione ( X nella mia descrizione sopra) sia uguale a 0, 1 o 2, che esclude TLS 1.2. Questo è troppo restrittivo.
- Presume che l'intero
ClientHello
sarà in un singolo record (che è un'ipotesi ragionevole) e che questo ClientHello
sarà codificato in un singolo pacchetto (che è un'ipotesi molto meno ragionevole).
- Non prova a guardare la lunghezza del messaggio di handshake e a confermarlo con la lunghezza del record.
Di conseguenza, l'evasione del rilevamento sarà facile (utilizzando unClientHello
di SSL 2.0%, utilizzando un record codificato con la versione TLS 1.2, creando un messaggio di ClientHello
che non rientra in un singolo pacchetto ... il il metodo è numeroso); e alcuni client esistenti non verranno rilevati: non solo uno può evitare il rilevamento di proposito , ma è anche possibile involontariamente .