Domanda

Sto scrivendo un server che accetta le connessioni TCP in ingresso. Supponiamo che il server ha accettato una connessione TCP, e ha già ricevuto 16 (o giù di lì) byte dal client. Conoscendo questi 16 byte come può il server di rilevare se il cliente vuole avviare un handshake SSL?

Ho fatto un esperimento, che ha dimostrato che sul mio sistema Linux connessione a localhost (127.0.0.1 sia o AF_UNIX) tramite SSL rende il client invia il seguente stretta di mano (esadecimale), seguito da 16 byte apparentemente casuali:

8064010301004b0000001000003900003800003500001600001300000a07
00c000003300003200002f03008000000500000401008000001500001200
0009060040000014000011000008000006040080000003020080

Come il server dovrebbe sondare questi primi byte, solo per essere in grado di determinare se il client invia un handshake SSL? La sonda deve restituire vero per tutte le strette di mano SSL validi, e deve restituire false con alta probabilità di un messaggio inviato dal cliente che non è un handshake SSL. Non è consentito di utilizzare tutte le librerie (come OpenSSL) per la sonda. La sonda deve essere un semplice codice (come un paio di dozzine di linee in C o Python).

È stato utile?

Soluzione 2

ho potuto capire questo fuori basato sulla realizzazione del metodo in ClientHello.parse http://tlslite.cvs.sourceforge.net /viewvc/tlslite/tlslite/tlslite/messages.py?view=markup

sto dando due soluzioni qui in Python. IsSSlClientHandshakeSimple è un regexp semplice, che può produrre risultati falsi positivi abbastanza facilmente; IsSslClientHandshake è più complicato:. controlla la coerenza di lunghezze, e la gamma di alcuni altri numeri

import re

def IsSslClientHandshakeSimple(buf):
  return bool(re.match(r'(?s)\A(?:\x80[\x0f-\xff]\x01[\x00-\x09][\x00-\x1f]'
                       r'[\x00-\x05].\x00.\x00.|'
                       r'\x16[\x2c-\xff]\x01\x00[\x00-\x05].'
                       r'[\x00-\x09][\x00-\x1f])', buf))

def IsSslClientHandshake(buf):
  if len(buf) < 2:  # Missing record header.
    return False
  if len(buf) < 2 + ord(buf[1]):  # Incomplete record body.
    return False
  # TODO(pts): Support two-byte lengths in buf[1].
  if ord(buf[0]) == 0x80:  # SSL v2.
    if ord(buf[1]) < 9:  # Message body too short.
      return False
    if ord(buf[2]) != 0x01:  # Not client_hello.
      return False
    if ord(buf[3]) > 9:  # Client major version too large. (Good: 0x03)
      return False
    if ord(buf[4]) > 31:  # Client minor version too large. (Good: 0x01)
      return False
    cipher_specs_size = ord(buf[5]) << 8 | ord(buf[6])
    session_id_size = ord(buf[7]) << 8 | ord(buf[8])
    random_size = ord(buf[9]) << 8 | ord(buf[10])
    if ord(buf[1]) < 9 + cipher_specs_size + session_id_size + random_size:
      return False
    if cipher_specs_size % 3 != 0:  # Cipher specs not a multiple of 3 bytes.
      return False
  elif ord(buf[0]) == 0x16:  # SSL v1.
    # TODO(pts): Test this.
    if ord(buf[1]) < 39:  # Message body too short.
      return False
    if ord(buf[2]) != 0x01:  # Not client_hello.
      return False
    head_size = ord(buf[3]) << 16 | ord(buf[4]) << 8 | ord(buf[5])
    if ord(buf[1]) < head_size + 4:  # Head doesn't fit in message body.
      return False
    if ord(buf[6]) > 9:  # Client major version too large. (Good: 0x03)
      return False
    if ord(buf[7]) > 31:  # Client minor version too large. (Good: 0x01)
      return False
    # random is at buf[8 : 40]
    session_id_size = ord(buf[40])
    i = 41 + session_id_size
    if ord(buf[1]) < i + 2:  # session_id + cipher_suites_size doesn't fit.
      return False
    cipher_specs_size = ord(buf[i]) << 8 | ord(buf[i + 1])
    if cipher_specs_size % 2 != 0:
      return False
    i += 2 + cipher_specs_size
    if ord(buf[1]) < i + 1: # cipher_specs + c..._methods_size doesn't fit.
      return False
    if ord(buf[1]) < i + 1 + ord(buf[i]): # compression_methods doesn't fit.
      return False
  else:  # Not SSL v1 or SSL v2.
    return False
return True

Altri suggerimenti

Il client invia sempre così chiamato messaggio HelloClient prima. Può essere in formato SSL 2 o in formato SSL 3.0 (lo stesso formato come in TLS 1.0, 1.1 e 1.2).

E c'è anche la possibilità che SSL 3.0 / TLS 1.0 / 1.1 / 1.2 client inviano HelloClient con il vecchio formato (SSL 2), solo con il numero di versione più alto nei dati. Così, l'individuazione di SSL 2 HelloClient è neccessary per i clienti più recenti anche. (Per esempio implementazione Java SSL fa)

del diciamo 'b' è il buffer. Ho cercato di diagramma il formato del messaggio.

SSL 2

+-----------------+------+-------
| 2 byte header   | 0x01 | etc.
+-----------------|------+-------
  • b [0] e 0x80 == 0x80 (significa bit più significativo di b [0] è '1')

  • ((b [0] & 0x7f) << 8 | b [1])> 9 (E Menas il basso 7 bit di b [0] con b [1] è la lunghezza dei dati È. può avere meno nel buffer, quindi non si può controllare la loro. Ma dal formato del messaggio sappiamo che ci sono 3 campo di 2 byte (campi di lunghezza), e almeno un elemento in campo dell'elenco cifra (di dimensioni 3). quindi ci deve essere almeno 9 byte (lunghezza dati> = 9).

  • b [2] deve essere 0x01 (tipo di messaggio "ClientHello")

SSL 3.0 o TLS 1.0, 1.1 e 1.2

+-------+------------------+------------------+--------+------
| 0x16  | 2 bytes version  |  2 bytes length  |  0x01  |  etc.
+-------+------------------+------------------+--------+------
  • b [0] == 0x16 (messaggio di tipo "handshake SSL")

  • b [1] dovrebbe essere 0x03 (attualmente più nuova versione principale, ma chissà in futuro?)

  • b [5] deve essere 0x01 (handshake messaggio di protocollo "HelloClient")

Per avere un riferimento, è possibile vedere http://www.mozilla.org/projects /security/pki/nss/ssl/draft02.html e http://tools.ietf.org/html/rfc4346

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top