mirror of https://github.com/secdev/scapy.git
264 lines
5.9 KiB
Plaintext
264 lines
5.9 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"# TLS handshake overview\n",
|
|
"This is the standard, modern TLS 1.2 handshake:\n",
|
|
"\n",
|
|
"<img src=\"images/handshake_tls12.png\" alt=\"Handshake TLS 1.2\" width=\"400\"/>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# We're going to parse several successive records from the passive listening of a standard TLS handshake\n",
|
|
"from scapy.all import *"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## (C) ---> (S) ClientHello"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"record1 = TLS(open('raw_data/tls_session_protected/01_cli.raw').read())\n",
|
|
"record1.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"for extension in record1.msg[0].ext:\n",
|
|
" print ''\n",
|
|
" extension.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## (C) <--- (S) ServerHello"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"record2 = TLS(open('raw_data/tls_session_protected/02_srv.raw').read())\n",
|
|
"record2.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## (C) <--- (S) Certificate"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"record3 = TLS(open('raw_data/tls_session_protected/03_srv.raw').read())\n",
|
|
"record3.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# The Certificate message actually contains a *chain* of certificates\n",
|
|
"for cert in record3.msg[0].certs:\n",
|
|
" print type(cert[1])\n",
|
|
" cert[1].show()\n",
|
|
" print ''"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Let's recall the domain that the client wants to access\n",
|
|
"record1.msg[0].ext[0].show()\n",
|
|
"\n",
|
|
"# Indeed the certificate may be used with other domains than its CN 'www.github.com'\n",
|
|
"x509c = record3.msg[0].certs[0][1].x509Cert\n",
|
|
"print type(x509c)\n",
|
|
"x509c.tbsCertificate.extensions[2].show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## (C) <--- (S) CertificateStatus, ServerKeyExchange, ServerHelloDone"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Here the server sent three TLS records in the same TCP segment\n",
|
|
"record4 = TLS(open('raw_data/tls_session_protected/04_srv.raw').read())\n",
|
|
"record4.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Let's verify the signature in the ServerKeyExchange\n",
|
|
"# First, we need to assemble the whole data being signed\n",
|
|
"cli_random = pkcs_i2osp(record1.msg[0].gmt_unix_time, 4) + record1.msg[0].random_bytes\n",
|
|
"srv_random = pkcs_i2osp(record2.msg[0].gmt_unix_time, 4) + record2.msg[0].random_bytes\n",
|
|
"ecdh_params = str(record4[TLSServerKeyExchange].params)\n",
|
|
"\n",
|
|
"# Then we retrieve the server's Cert and verify the signature\n",
|
|
"cert_srv = record3.msg[0].certs[0][1]\n",
|
|
"cert_srv.verify(cli_random + srv_random + ecdh_params, record4[TLSServerKeyExchange].sig.sig_val, h='sha512')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"collapsed": true
|
|
},
|
|
"source": [
|
|
"## (C) ---> (S) ClientKeyExchange, ChangeCipherSpec, Finished"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"record5_str = open('raw_data/tls_session_protected/05_cli.raw').read()\n",
|
|
"record5 = TLS(record5_str)\n",
|
|
"record5.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Every record has a 'tls_session' context which may enhance the parsing of later records\n",
|
|
"record5 = TLS(record5_str, tls_session=record2.tls_session.mirror())\n",
|
|
"record5.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## (C) <--- (S) NewSessionTicket, ChangeCipherSpec, Finished"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"record6_str = open('raw_data/tls_session_protected/06_srv.raw').read()\n",
|
|
"record6 = TLS(record6_str, tls_session=record5.tls_session.mirror())\n",
|
|
"record6.show()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"## (C) ---> (S) ApplicationData"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"collapsed": false
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"record7_str = open('raw_data/tls_session_protected/07_cli.raw').read()\n",
|
|
"record7 = TLS(record7_str, tls_session=record6.tls_session.mirror())\n",
|
|
"record7.show()"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 2",
|
|
"language": "python",
|
|
"name": "python2"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 2
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython2",
|
|
"version": "2.7.13"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|