5

On a devices located between my local network and a router, (all the traffic pass through) I need to read the common name from Hello Server Certificate packet.

So I'm trying to figure out how to get the proper filter with tcpdump.

I found help from this paper : http://www.wains.be/pub/networking/tcpdump_advanced_filters.txt
It explain how to use advance filter on IP and TCP fields.

I tried this kind of filter :

$ tcpdump -i any \
  'tcp and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' \
   -A -s 0 -v | grep 'Host\|id-at-commonName='

As explained in the paper, "We are matching any packet that contains data."

It works for the Host field as for many other data, but I can't match the field id-at-commonName= which is in SSL field (so in the TCP Data field ?).

To be sure I captured a pcap file with the exact same filter (without the grep) and when I open it with Wireshark, I can get every Certificate Common name. I must use a tcpdump filter because I need to get the data "on the fly".

Can someone explain why I can't see this data through tcpdump?

slm
  • 7,615
  • 16
  • 56
  • 76
Kuruwan
  • 91
  • 2
  • 2
  • 8

3 Answers3

6

If you just want to get the SSL Handshake Hello packet to see the contained SNI, the following filter seems to work for both TLS1.0 and TLS1.2 :

tcpdump -i any -s 1500 (tcp[((tcp[12:1] & 0xf0) >> 2)+5:1] = 0x01) and (tcp[((tcp[12:1] & 0xf0) >> 2):1] = 0x16)

where 0x16 = Handshake (22) at the first byte field of the data

and 0x01 = Client Hello (1) at the 6th byte field of the data

Nathan Chan
  • 61
  • 1
  • 3
  • 3
    I had to adjust the statement `tcpdump -i any -s 1500 '(tcp[((tcp[12:1] & 0xf0) >> 2)+5:1] = 0x01) and (tcp[((tcp[12:1] & 0xf0) >> 2):1] = 0x16)'` – haschibaschi Jun 08 '17 at 06:35
  • It's worth noting the client is who initiated the conversation, and per the standard in "client hello" `0x01` the client tells the server its minimum supported version. The server eventually responds with a "server hello" `0x02` with the version it selected to use. – Ro Yo Mi Jul 08 '21 at 13:06
3

The id-at-commonName label is shown by Wireshark, the wire format does not contain the text, but raw bytes. The name id-at-commonName is 03 in bytes. Following that, there is a UTF8String (12 = 0x0c) with a length of 9 bytes (localhost).

Wireshark screenshot

If you are trying to match host names from a TCP stream, keep the following in mind:

  • Certificates may be valid for multiple subjects, you may find additional names in id-ce-subjectAltName (2.5.29.17)
  • The real host that you are trying to connect to may be advertised in ClientHello handshake message via the Server Name Indication (SNI) extension.
  • Multiple messages may be combined in a single record.

Finally, note that the SSL messages may be split over multiple TCP segments, making direct analysis even harder. Perhaps it is an option to capture to write a fixed count of packets to file with rotation enabled, manually parse with tshark afterwards, and finally remove the capture?

Lekensteyn
  • 6,241
  • 6
  • 39
  • 55
1

thanks @Nathan Chan, since I cannot comment due to no enough reputation, add parameters '-nnXSs0 -ttt' to make it readable.

tcpdump -i any -s 1500 '(tcp[((tcp[12:1] & 0xf0) >> 2)+5:1] = 0x01) and (tcp[((tcp[12:1] & 0xf0) >> 2):1] = 0x16)' -nnXSs0 -ttt
Howard.TH
  • 31
  • 1