Files
Mobile-Security-Framework-M…/mobsf/MalwareAnalyzer/views/MalwareDomainCheck.py
T
Ajin Abraham cf59941081 HOTFIX: setup.py and directory refactoring
Python setup.py #1585
directory refactoring
2021-01-17 01:47:49 -05:00

228 lines
7.4 KiB
Python

# -*- coding: utf_8 -*-
# Module for Malware Analysis
import io
import logging
import re
from pathlib import Path
from socket import (
gaierror,
gethostbyname,
)
from urllib.parse import urlparse
from django.conf import settings
import IP2Location
from mobsf.MobSF.utils import (
is_internet_available,
update_local_db,
)
logger = logging.getLogger(__name__)
IP2Loc = IP2Location.IP2Location()
class MalwareDomainCheck:
def __init__(self):
self.sig_dir = Path(settings.SIGNATURE_DIR)
self.malwaredomainlist = self.sig_dir / 'malwaredomainlist'
self.maltrail = self.sig_dir / 'maltrail-malware-domains.txt'
self.iplocbin = self.sig_dir / 'IP2LOCATION-LITE-DB5.IPV6.BIN'
self.result = {}
self.domainlist = None
def update_malware_db(self):
"""Check for update in malware DB."""
try:
mal_db = self.malwaredomainlist
resp = update_local_db('Malware', settings.MALWARE_DB_URL, mal_db)
if not resp:
return
# DB needs update
# Check2: DB Syntax Changed
line = resp.decode('utf-8', 'ignore').split('\n')[0]
lst = line.split('",')
if len(lst) == 10:
# DB Format is not changed. Let's update DB
logger.info('Updating Malware Database')
with open(mal_db, 'wb') as wfp:
wfp.write(resp)
else:
logger.warning('Unable to Update Malware DB')
except Exception:
logger.exception('[ERROR] Malware DB Update')
def update_maltrail_db(self):
"""Check for update in maltrail DB."""
try:
mal_db = self.maltrail
resp = update_local_db(
'Maltrail',
settings.MALTRAIL_DB_URL, mal_db)
if not resp:
return
# DB needs update
# Check2: DB Syntax Changed
lines = resp.decode('utf-8', 'ignore').splitlines()
if len(lines) > 100:
logger.info('Updating Maltrail Database')
with open(mal_db, 'wb') as wfp:
wfp.write(resp)
else:
logger.warning('Unable to Update Maltrail DB')
except Exception:
logger.exception('[ERROR] Maltrail DB Update')
def gelocation(self):
"""Perform Geolocation."""
try:
IP2Loc.open(self.iplocbin)
for domain in self.domainlist:
# Tag Good Domains
if domain not in self.result:
tmp_d = {}
tmp_d['bad'] = 'no'
self.result[domain] = tmp_d
# GeoIP
ip = None
try:
ip = gethostbyname(domain)
except (gaierror, UnicodeError):
pass
if ip:
rec = IP2Loc.get_all(ip)
self.result[domain]['geolocation'] = rec.__dict__
else:
self.result[domain]['geolocation'] = None
except Exception:
logger.exception('Failed to Perform Geolocation')
finally:
if IP2Loc:
IP2Loc.close()
def malware_check(self):
try:
mal_db = self.malwaredomainlist
with io.open(mal_db,
mode='r',
encoding='utf8',
errors='ignore') as flip:
entry_list = flip.readlines()
for entry in entry_list:
enlist = entry.split('","')
if len(enlist) > 5:
details_dict = {}
details_dict['domain_or_url'] = enlist[1]
details_dict['ip'] = enlist[2]
details_dict['desc'] = enlist[4]
details_dict['bad'] = 'yes'
dmn_url = details_dict['domain_or_url']
for domain in self.domainlist:
dmn_neturl = get_netloc(dmn_url)
if (((dmn_neturl == domain or dmn_neturl == domain[4:])
and (len(dmn_url) > 1))
or details_dict['ip'].startswith(domain)):
self.result[domain] = details_dict
except Exception:
logger.exception('[ERROR] Performing Malware Check')
def maltrail_check(self):
try:
mal_db = self.maltrail
with io.open(mal_db,
mode='r',
encoding='utf8',
errors='ignore') as flip:
entry_list = flip.read().splitlines()
for domain in self.domainlist:
if domain in entry_list:
self.result[domain] = {
'domain_or_url': domain,
'ip': 'N/A',
'desc': 'Malicious Domain tagged by Maltrail',
'bad': 'yes',
}
except Exception:
logger.exception('[ERROR] Performing Maltrail Check')
def update(self):
if is_internet_available():
self.update_malware_db()
self.update_maltrail_db()
else:
logger.warning('Internet not available. '
'Skipping Malware Database Update.')
def scan(self, urls):
if not settings.DOMAIN_MALWARE_SCAN:
logger.info('Domain Malware Check disabled in settings')
return self.result
self.domainlist = get_domains(urls)
if self.domainlist:
self.update()
self.malware_check()
self.maltrail_check()
self.gelocation()
return self.result
# Helper Functions
def verify_domain(checkeddom):
try:
if (len(checkeddom) > 2
and '.' in checkeddom
and (checkeddom.endswith('.') is False
and re.search('[a-zA-Z0-9]', checkeddom))):
return True
else:
return False
except Exception:
logger.exception('[ERROR] Verifying Domain')
def get_netloc(url):
"""Get Domain."""
try:
domain = ''
parse_uri = urlparse(url)
if not parse_uri.scheme:
url = '//' + url
parse_uri = urlparse(url)
domain = '{uri.netloc}'.format(uri=parse_uri)
if verify_domain(domain):
return domain
except Exception:
logger.exception('[ERROR] Extracting Domain form URL')
def sanitize_domain(domain):
"""Sanitize domain to be RFC1034 compliant."""
domain = domain.split('_')[0]
domain = re.sub(r'[^\w^\.^\-]', '', domain)
if domain.startswith('-'):
domain = sanitize_domain(domain[1:])
elif domain.endswith('-'):
domain = sanitize_domain(domain[:-1])
return domain
def get_domains(urls):
"""Get Domains."""
try:
domains = set()
for url in urls:
parse_uri = urlparse(url)
if not parse_uri.scheme:
url = '//' + url
parse_uri = urlparse(url)
domain = sanitize_domain(
'{uri.hostname}'.format(uri=parse_uri))
if verify_domain(domain):
domains.add(domain)
return domains
except Exception:
logger.exception('[ERROR] Extracting Domain form URL')