• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1{
2 "cells": [
3  {
4   "cell_type": "markdown",
5   "metadata": {},
6   "source": [
7    "# TLS handshake overview\n",
8    "This is the standard, modern TLS 1.2 handshake:\n",
9    "\n",
10    "<img src=\"images/handshake_tls12.png\" alt=\"Handshake TLS 1.2\" width=\"400\"/>"
11   ]
12  },
13  {
14   "cell_type": "code",
15   "execution_count": null,
16   "metadata": {
17    "collapsed": true
18   },
19   "outputs": [],
20   "source": [
21    "# We're going to parse several successive records from the passive listening of a standard TLS handshake\n",
22    "from scapy.all import *"
23   ]
24  },
25  {
26   "cell_type": "markdown",
27   "metadata": {},
28   "source": [
29    "## (C) ---> (S) ClientHello"
30   ]
31  },
32  {
33   "cell_type": "code",
34   "execution_count": null,
35   "metadata": {
36    "collapsed": false
37   },
38   "outputs": [],
39   "source": [
40    "record1 = TLS(open('raw_data/tls_session_protected/01_cli.raw').read())\n",
41    "record1.show()"
42   ]
43  },
44  {
45   "cell_type": "code",
46   "execution_count": null,
47   "metadata": {
48    "collapsed": false
49   },
50   "outputs": [],
51   "source": [
52    "for extension in record1.msg[0].ext:\n",
53    "    print ''\n",
54    "    extension.show()"
55   ]
56  },
57  {
58   "cell_type": "markdown",
59   "metadata": {},
60   "source": [
61    "## (C) <--- (S) ServerHello"
62   ]
63  },
64  {
65   "cell_type": "code",
66   "execution_count": null,
67   "metadata": {
68    "collapsed": false
69   },
70   "outputs": [],
71   "source": [
72    "record2 = TLS(open('raw_data/tls_session_protected/02_srv.raw').read())\n",
73    "record2.show()"
74   ]
75  },
76  {
77   "cell_type": "markdown",
78   "metadata": {},
79   "source": [
80    "## (C) <--- (S) Certificate"
81   ]
82  },
83  {
84   "cell_type": "code",
85   "execution_count": null,
86   "metadata": {
87    "collapsed": false
88   },
89   "outputs": [],
90   "source": [
91    "record3 = TLS(open('raw_data/tls_session_protected/03_srv.raw').read())\n",
92    "record3.show()"
93   ]
94  },
95  {
96   "cell_type": "code",
97   "execution_count": null,
98   "metadata": {
99    "collapsed": false
100   },
101   "outputs": [],
102   "source": [
103    "# The Certificate message actually contains a *chain* of certificates\n",
104    "for cert in record3.msg[0].certs:\n",
105    "    print type(cert[1])\n",
106    "    cert[1].show()\n",
107    "    print ''"
108   ]
109  },
110  {
111   "cell_type": "code",
112   "execution_count": null,
113   "metadata": {
114    "collapsed": false
115   },
116   "outputs": [],
117   "source": [
118    "# Let's recall the domain that the client wants to access\n",
119    "record1.msg[0].ext[0].show()\n",
120    "\n",
121    "# Indeed the certificate may be used with other domains than its CN 'www.github.com'\n",
122    "x509c = record3.msg[0].certs[0][1].x509Cert\n",
123    "print type(x509c)\n",
124    "x509c.tbsCertificate.extensions[2].show()"
125   ]
126  },
127  {
128   "cell_type": "markdown",
129   "metadata": {},
130   "source": [
131    "## (C) <--- (S) CertificateStatus, ServerKeyExchange, ServerHelloDone"
132   ]
133  },
134  {
135   "cell_type": "code",
136   "execution_count": null,
137   "metadata": {
138    "collapsed": false
139   },
140   "outputs": [],
141   "source": [
142    "# Here the server sent three TLS records in the same TCP segment\n",
143    "record4 = TLS(open('raw_data/tls_session_protected/04_srv.raw').read())\n",
144    "record4.show()"
145   ]
146  },
147  {
148   "cell_type": "code",
149   "execution_count": null,
150   "metadata": {
151    "collapsed": false
152   },
153   "outputs": [],
154   "source": [
155    "# Let's verify the signature in the ServerKeyExchange\n",
156    "# First, we need to assemble the whole data being signed\n",
157    "cli_random = pkcs_i2osp(record1.msg[0].gmt_unix_time, 4) + record1.msg[0].random_bytes\n",
158    "srv_random = pkcs_i2osp(record2.msg[0].gmt_unix_time, 4) + record2.msg[0].random_bytes\n",
159    "ecdh_params = str(record4[TLSServerKeyExchange].params)\n",
160    "\n",
161    "# Then we retrieve the server's Cert and verify the signature\n",
162    "cert_srv = record3.msg[0].certs[0][1]\n",
163    "cert_srv.verify(cli_random + srv_random + ecdh_params, record4[TLSServerKeyExchange].sig.sig_val, h='sha512')"
164   ]
165  },
166  {
167   "cell_type": "markdown",
168   "metadata": {
169    "collapsed": true
170   },
171   "source": [
172    "## (C) ---> (S) ClientKeyExchange, ChangeCipherSpec, Finished"
173   ]
174  },
175  {
176   "cell_type": "code",
177   "execution_count": null,
178   "metadata": {
179    "collapsed": false
180   },
181   "outputs": [],
182   "source": [
183    "record5_str = open('raw_data/tls_session_protected/05_cli.raw').read()\n",
184    "record5 = TLS(record5_str)\n",
185    "record5.show()"
186   ]
187  },
188  {
189   "cell_type": "code",
190   "execution_count": null,
191   "metadata": {
192    "collapsed": false
193   },
194   "outputs": [],
195   "source": [
196    "# Every record has a 'tls_session' context which may enhance the parsing of later records\n",
197    "record5 = TLS(record5_str, tls_session=record2.tls_session.mirror())\n",
198    "record5.show()"
199   ]
200  },
201  {
202   "cell_type": "markdown",
203   "metadata": {},
204   "source": [
205    "## (C) <--- (S) NewSessionTicket, ChangeCipherSpec, Finished"
206   ]
207  },
208  {
209   "cell_type": "code",
210   "execution_count": null,
211   "metadata": {
212    "collapsed": false
213   },
214   "outputs": [],
215   "source": [
216    "record6_str = open('raw_data/tls_session_protected/06_srv.raw').read()\n",
217    "record6 = TLS(record6_str, tls_session=record5.tls_session.mirror())\n",
218    "record6.show()"
219   ]
220  },
221  {
222   "cell_type": "markdown",
223   "metadata": {},
224   "source": [
225    "## (C) ---> (S) ApplicationData"
226   ]
227  },
228  {
229   "cell_type": "code",
230   "execution_count": null,
231   "metadata": {
232    "collapsed": false
233   },
234   "outputs": [],
235   "source": [
236    "record7_str = open('raw_data/tls_session_protected/07_cli.raw').read()\n",
237    "record7 = TLS(record7_str, tls_session=record6.tls_session.mirror())\n",
238    "record7.show()"
239   ]
240  }
241 ],
242 "metadata": {
243  "kernelspec": {
244   "display_name": "Python 2",
245   "language": "python",
246   "name": "python2"
247  },
248  "language_info": {
249   "codemirror_mode": {
250    "name": "ipython",
251    "version": 2
252   },
253   "file_extension": ".py",
254   "mimetype": "text/x-python",
255   "name": "python",
256   "nbconvert_exporter": "python",
257   "pygments_lexer": "ipython2",
258   "version": "2.7.13"
259  }
260 },
261 "nbformat": 4,
262 "nbformat_minor": 2
263}
264