Frage

Ich schreibe einen Server, der eingehende TCP-Verbindungen akzeptiert. Nehmen wir an, der Server eine TCP-Verbindung angenommen hat, und hat bereits 16 empfangen (oder so) von der Client-Bytes. diese 16 Bytes zu wissen, wie kann der Server erkennt, ob der Client einen SSL-Handshake zu initiieren?

Ich habe ein Experiment gemacht, die das zu localhost Anschluss auf meinem Linux-System zeigte (entweder 127.0.0.1 oder AF_UNIX) über SSL der Client macht die folgenden Handshake (hexdump) senden, gefolgt von 16 scheinbar zufälligen Bytes:

8064010301004b0000001000003900003800003500001600001300000a07
00c000003300003200002f03008000000500000401008000001500001200
0009060040000014000011000008000006040080000003020080

Wie sollte der Server diese ersten paar Bytes Sonde, nur in der Lage sein, zu bestimmen, ob der Client einen SSL-Handshake sendet? Die Sonde muss return true für all gültiges SSL-Handshakes, und es muss mit hohen Wahrscheinlichkeit für eine Nachricht durch den Client gesendet, die kein SSL-Handshake return false ist. Es wird keine Bibliotheken (wie OpenSSL) für die Sonde benutzen. Die Sonde muss ein einfacher Code sein (wie ein paar Dutzend Zeilen in C oder Python).

War es hilfreich?

Lösung 2

Das konnte ich herausfinden, auf der Grundlage der Umsetzung des ClientHello.parse Verfahrens in http://tlslite.cvs.sourceforge.net /viewvc/tlslite/tlslite/tlslite/messages.py?view=markup

Ich gebe zwei Lösungen hier in Python. IsSSlClientHandshakeSimple ist ein einfaches regexp, die ganz leicht einige Fehlalarme ergeben können; IsSslClientHandshake ist komplizierter. es die Konsistenz der Längen überprüft, und die Reichweite von einigen anderen Zahlen

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

Andere Tipps

Der Client sendet immer so HelloClient Nachricht zuerst genannt. Es kann in SSL-2-Format oder SSL 3.0-Format (wie in TLS 1.0, 1.1 und 1.2 das gleichen Format) sein.

Und es gibt auch die Möglichkeit, dass SSL 3.0 / TLS 1.0 / 1.1 / 1.2-Clients HelloClient mit dem älteren Format (SSL 2), nur mit der höheren Versionsnummer in den Daten zu senden. So, Erkennung von SSL 2 HelloClient ist notwendig für neue Kunden auch. (Zum Beispiel Java SSL-Implementierung funktioniert so)

Lassen Sie uns sagen ‚b‘ ist Ihr Puffer. Ich habe versucht, das Nachrichtenformat, um Diagramm.

SSL 2

+-----------------+------+-------
| 2 byte header   | 0x01 | etc.
+-----------------|------+-------
  • b [0] & 0x80 == 0x80 (es bedeutet höchstwertigen Bits von b [0] ist '1')

  • ((b [0] & 0x7f) << 8 | b [1])> 9 (Es Menas die niedrigen 7 Bits von b [0] zusammen mit b [1] sind Datenlänge Sie. weniger in Ihrem Puffer kann, so dass Sie sie nicht überprüfen können. Aber von dem Nachrichtenformat wir wissen, gibt es 3 Feld von 2 Bytes (Länge Feldern), und mindestens ein Element in Chiffre-Listenfeld (Größe 3). so sollte es sein, mindestens 9 Bytes (Datenlänge> = 9).

  • b [2] muss 0x01 sein (Nachrichtentyp "Client")

SSL 3.0 oder TLS 1.0, 1.1 und 1.2

+-------+------------------+------------------+--------+------
| 0x16  | 2 bytes version  |  2 bytes length  |  0x01  |  etc.
+-------+------------------+------------------+--------+------
  • b [0] == 0x16 (Nachrichtentyp "SSL-Handshake")

  • b [1] sollte 0x03 (derzeit neueste Hauptversion, aber wer weiß, in Zukunft?) Sein

  • b [5] muss 0x01 sein (Handshake-Protokoll-Nachricht "HelloClient")

Als Referenz können Sie sehen http://www.mozilla.org/projects /security/pki/nss/ssl/draft02.html und http://tools.ietf.org/html/rfc4346

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top