Standard API, Cert Analysis QA, URL Schemes, ATS Analysis QA, Removed Dupplicate Code

This commit is contained in:
Ajin Abraham
2019-12-08 20:47:38 -05:00
parent 49368fe812
commit dd2db1312e
39 changed files with 1577 additions and 1585 deletions
+2
View File
@@ -4,7 +4,9 @@
.dockerignore
.sonarcloud.properties
.travis.yml
.pyup.yml
tox.ini
db.sqlite3
Dockerfile
docker-compose.yml
setup.bat
+1 -1
View File
@@ -90,7 +90,7 @@ def get_screenshots(md5_hash, download_dir):
expact_imgs.append(img)
else:
imgs.append(img)
exported_act = python_list(sadb[0].EXPORTED_ACT)
exported_act = python_list(sadb[0].EXPORTED_ACTIVITIES)
act_desc = python_list(sadb[0].ACTIVITIES)
if act_imgs:
if len(act_imgs) == len(act_desc):
@@ -34,7 +34,7 @@ def dynamic_analysis(request):
"""Android Dynamic Analysis Entry point."""
try:
apks = StaticAnalyzerAndroid.objects.filter(
ZIPPED='apk').order_by('-id')
APP_TYPE='apk').order_by('-id')
try:
identifier = get_device()
except Exception:
+1 -1
View File
@@ -237,7 +237,7 @@ class Environment:
elif comp == 'libraries':
resp = python_list(anddb[0].LIBRARIES)
elif comp == 'exported_activities':
resp = python_list(anddb[0].EXPORTED_ACT)
resp = python_list(anddb[0].EXPORTED_ACTIVITIES)
return '\n'.join(resp)
def get_android_version(self):
@@ -50,7 +50,7 @@ def activity_tester(request):
if test == 'exported':
iden = 'Exported '
logger.info('Exported activity tester')
activities = python_list(static_android_db[0].EXPORTED_ACT)
activities = python_list(static_android_db[0].EXPORTED_ACTIVITIES)
else:
logger.info('Activity tester')
activities = python_list(static_android_db[0].ACTIVITIES)
+2 -1
View File
@@ -12,7 +12,7 @@ from MobSF.views import home
from MobSF.views.api import rest_api
from StaticAnalyzer import tests
from StaticAnalyzer.views import shared_func, windows
from StaticAnalyzer.views import shared_func
from StaticAnalyzer.views.android import (
find,
generate_downloads,
@@ -21,6 +21,7 @@ from StaticAnalyzer.views.android import (
smali,
view_source,
)
from StaticAnalyzer.views.windows import windows
from StaticAnalyzer.views.android import static_analyzer as android_sa
from StaticAnalyzer.views.ios import static_analyzer as ios_sa
from StaticAnalyzer.views.ios import view_source as io_view_source
+2 -2
View File
@@ -13,7 +13,7 @@ from StaticAnalyzer.views.android.static_analyzer import static_analyzer
from StaticAnalyzer.views.ios import view_source as ios_view_source
from StaticAnalyzer.views.ios.static_analyzer import static_analyzer_ios
from StaticAnalyzer.views.shared_func import pdf
from StaticAnalyzer.views.windows import staticanalyzer_windows
from StaticAnalyzer.views.windows import windows
BAD_REQUEST = 400
OK = 200
@@ -85,7 +85,7 @@ def api_scan(request):
response = make_api_response(resp, 200)
# APPX
elif scan_type == 'appx':
resp = staticanalyzer_windows(request, True)
resp = windows.staticanalyzer_windows(request, True)
if 'error' in resp:
response = make_api_response(resp, 500)
else:
+5 -5
View File
@@ -20,8 +20,9 @@ from MobSF.utils import (api_key, is_dir_exists, is_file_exists,
from MobSF.views.helpers import FileType
from MobSF.views.scanning import Scanning
from StaticAnalyzer.models import (RecentScansDB, StaticAnalyzerAndroid,
StaticAnalyzerIOSZIP, StaticAnalyzerIPA,
from StaticAnalyzer.models import (RecentScansDB,
StaticAnalyzerAndroid,
StaticAnalyzerIOS,
StaticAnalyzerWindows)
LINUX_PLATFORM = ['Darwin', 'Linux']
@@ -218,7 +219,7 @@ def recent_scans(request):
android = StaticAnalyzerAndroid.objects.all()
package_mapping = {}
for item in android:
package_mapping[item.MD5] = item.PACKAGENAME
package_mapping[item.MD5] = item.PACKAGE_NAME
for entry in db_obj:
if entry['MD5'] in package_mapping.keys():
entry['PACKAGE'] = package_mapping[entry['MD5']]
@@ -287,8 +288,7 @@ def delete_scan(request, api=False):
if scan.exists():
RecentScansDB.objects.filter(MD5=md5_hash).delete()
StaticAnalyzerAndroid.objects.filter(MD5=md5_hash).delete()
StaticAnalyzerIPA.objects.filter(MD5=md5_hash).delete()
StaticAnalyzerIOSZIP.objects.filter(MD5=md5_hash).delete()
StaticAnalyzerIOS.objects.filter(MD5=md5_hash).delete()
StaticAnalyzerWindows.objects.filter(MD5=md5_hash).delete()
# Delete Upload Dir Contents
app_upload_dir = os.path.join(settings.UPLD_DIR, md5_hash)
+56 -100
View File
@@ -10,136 +10,92 @@ class RecentScansDB(models.Model):
class StaticAnalyzerAndroid(models.Model):
TITLE = models.CharField(max_length=50)
APP_NAME = models.CharField(max_length=260)
REAL_NAME = models.CharField(max_length=255)
FILE_NAME = models.CharField(max_length=260)
APP_NAME = models.CharField(max_length=255)
APP_TYPE = models.TextField()
SIZE = models.CharField(max_length=50)
MD5 = models.CharField(max_length=32)
SHA1 = models.CharField(max_length=40)
SHA256 = models.CharField(max_length=64)
PACKAGENAME = models.CharField(max_length=40)
MAINACTIVITY = models.CharField(max_length=300)
TARGET_SDK = models.CharField(max_length=50)
MAX_SDK = models.CharField(max_length=50)
MIN_SDK = models.CharField(max_length=50)
ANDROVERNAME = models.CharField(max_length=100)
ANDROVER = models.CharField(max_length=50)
MANIFEST_ANAL = models.TextField()
PERMISSIONS = models.TextField()
BIN_ANALYSIS = models.TextField()
FILES = models.TextField()
CERTZ = models.TextField()
ICON_HIDDEN = models.BooleanField(default=False)
ICON_FOUND = models.BooleanField(default=False)
PACKAGE_NAME = models.CharField(max_length=40)
MAIN_ACTIVITY = models.CharField(max_length=300)
EXPORTED_ACTIVITIES = models.TextField()
BROWSABLE_ACTIVITIES = models.TextField()
ACTIVITIES = models.TextField()
RECEIVERS = models.TextField()
PROVIDERS = models.TextField()
SERVICES = models.TextField()
LIBRARIES = models.TextField()
BROWSABLE = models.TextField()
CNT_ACT = models.CharField(max_length=50)
CNT_PRO = models.CharField(max_length=50)
CNT_SER = models.CharField(max_length=50)
CNT_BRO = models.CharField(max_length=50)
CERT_INFO = models.TextField()
ISSUED = models.CharField(max_length=10)
SHA256DIGEST = models.BooleanField(default=False)
API = models.TextField()
DANG = models.TextField()
TARGET_SDK = models.CharField(max_length=50)
MAX_SDK = models.CharField(max_length=50)
MIN_SDK = models.CharField(max_length=50)
VERSION_NAME = models.CharField(max_length=100)
VERSION_CODE = models.CharField(max_length=50)
ICON_HIDDEN = models.BooleanField(default=False)
ICON_FOUND = models.BooleanField(default=False)
PERMISSIONS = models.TextField()
CERTIFICATE_ANALYSIS = models.TextField()
MANIFEST_ANALYSIS = models.TextField()
BINARY_ANALYSIS = models.TextField()
FILE_ANALYSIS = models.TextField()
ANDROID_API = models.TextField()
CODE_ANALYSIS = models.TextField()
URLS = models.TextField()
DOMAINS = models.TextField()
EMAILS = models.TextField()
STRINGS = models.TextField()
ZIPPED = models.TextField()
MANI = models.TextField()
EXPORTED_ACT = models.TextField()
E_ACT = models.CharField(max_length=50)
E_SER = models.CharField(max_length=50)
E_BRO = models.CharField(max_length=50)
E_CNT = models.CharField(max_length=50)
APK_ID = models.TextField()
PLAY_DETAILS = models.TextField(default={})
FIREBASE = models.TextField(default=[])
FIREBASE_URLS = models.TextField(default=[])
FILES = models.TextField()
EXPORTED_COUNT = models.TextField(default={})
APKID = models.TextField(default={})
TRACKERS = models.TextField(default={})
PLAYSTORE_DETAILS = models.TextField(default={})
class StaticAnalyzerIPA(models.Model):
TITLE = models.CharField(max_length=50)
class StaticAnalyzerIOS(models.Model):
FILE_NAME = models.CharField(max_length=255)
APP_NAME = models.CharField(max_length=255)
APP_TYPE = models.CharField(max_length=20, default='')
SIZE = models.CharField(max_length=50)
MD5 = models.CharField(max_length=32)
SHA1 = models.CharField(max_length=40)
SHA256 = models.CharField(max_length=64)
INFOPLIST = models.TextField()
MACHOINFO = models.TextField(default={})
# bundle_id
BINNAME = models.CharField(max_length=160)
IDF = models.TextField()
BUILD = models.TextField()
VERSION = models.CharField(max_length=100)
SDK = models.CharField(max_length=50)
PLTFM = models.CharField(max_length=50)
MINX = models.CharField(max_length=50)
BIN_ANAL = models.TextField()
LIBS = models.TextField()
FILES = models.TextField()
SFILESX = models.TextField()
STRINGS = models.TextField()
PERMISSIONS = models.TextField()
INSECCON = models.TextField()
BUNDLE_NAME = models.CharField(max_length=20)
BUNDLE_URL_TYPES = models.TextField()
APP_VERSION = models.CharField(max_length=100)
SDK_NAME = models.CharField(max_length=50)
PLATFORM = models.CharField(max_length=50)
MIN_OS_VERSION = models.CharField(max_length=50)
BUNDLE_ID = models.TextField()
BUNDLE_URL_TYPES = models.TextField(default=[])
BUNDLE_SUPPORTED_PLATFORMS = models.CharField(max_length=50)
BUNDLE_LOCALIZATIONS = models.TextField()
BINTYPE = models.CharField(max_length=20, default='')
INFO_PLIST = models.TextField()
MACHO_INFO = models.TextField(default={})
PERMISSIONS = models.TextField(default=[])
ATS_ANALYSIS = models.TextField(default=[])
BINARY_ANALYSIS = models.TextField(default=[])
IOS_API = models.TextField(default={})
CODE_ANALYSIS = models.TextField(default={})
FILE_ANALYSIS = models.TextField(default=[])
LIBRARIES = models.TextField(default=[])
FILES = models.TextField(default=[])
URLS = models.TextField(default=[])
DOMAINS = models.TextField(default={})
EMAILS = models.TextField(default=[])
STRINGS = models.TextField(default=[])
FIREBASE_URLS = models.TextField(default=[])
APPSTORE_DETAILS = models.TextField(default={})
class StaticAnalyzerIOSZIP(models.Model):
TITLE = models.CharField(max_length=50)
FILE_NAME = models.CharField(max_length=260)
SIZE = models.CharField(max_length=50)
MD5 = models.CharField(max_length=32)
SHA1 = models.CharField(max_length=40)
SHA256 = models.CharField(max_length=64)
INFOPLIST = models.TextField()
BINNAME = models.CharField(max_length=160)
IDF = models.TextField()
BUILD = models.TextField()
VERSION = models.CharField(max_length=100)
SDK = models.CharField(max_length=50)
PLTFM = models.CharField(max_length=50)
MINX = models.CharField(max_length=50)
BIN_ANAL = models.TextField()
LIBS = models.TextField()
FILES = models.TextField()
SFILESX = models.TextField()
API = models.TextField()
CODEANAL = models.TextField()
URLnFile = models.TextField()
DOMAINS = models.TextField()
EmailnFile = models.TextField()
PERMISSIONS = models.TextField()
INSECCON = models.TextField()
BUNDLE_NAME = models.CharField(max_length=20)
BUNDLE_URL_TYPES = models.TextField()
BUNDLE_SUPPORTED_PLATFORMS = models.CharField(max_length=50)
BUNDLE_LOCALIZATIONS = models.TextField()
APPSTORE_DETAILS = models.TextField(default={})
FIREBASE = models.TextField(default=[])
class StaticAnalyzerWindows(models.Model):
TITLE = models.CharField(max_length=260)
FILE_NAME = models.CharField(max_length=260)
APP_NAME = models.CharField(max_length=260)
PUB_NAME = models.TextField()
PUBLISHER_NAME = models.TextField()
SIZE = models.CharField(max_length=50)
MD5 = models.CharField(max_length=32)
SHA1 = models.CharField(max_length=40)
SHA256 = models.CharField(max_length=64)
BINNAME = models.CharField(max_length=260)
VERSION = models.TextField()
ARCH = models.TextField()
APP_VERSION = models.TextField()
ARCHITECTURE = models.TextField()
COMPILER_VERSION = models.TextField()
VISUAL_STUDIO_VERSION = models.TextField()
VISUAL_STUDIO_EDITION = models.TextField()
@@ -150,5 +106,5 @@ class StaticAnalyzerWindows(models.Model):
TARGET_RUN = models.TextField()
FILES = models.TextField()
STRINGS = models.TextField()
BIN_AN_RESULTS = models.TextField()
BIN_AN_WARNINGS = models.TextField()
BINARY_ANALYSIS = models.TextField()
BINARY_WARNINGS = models.TextField()
+25 -13
View File
@@ -47,8 +47,9 @@ def cert_info(app_dir, app_file):
"""Return certificate information."""
try:
logger.info('Reading Code Signing Certificate')
issued = ''
status = ''
manidat = ''
cert_info = ''
certlist = []
cert_path = os.path.join(app_dir, 'META-INF/')
@@ -103,25 +104,36 @@ def cert_info(app_dir, app_file):
certlist.append('Bit Size: {}'.format(x509_public_key.bit_size))
certlist.append('Fingerprint: {}'.format(
binascii.hexlify(x509_public_key.fingerprint).decode('utf-8')))
certlist = '\n'.join(certlist)
if a.is_signed():
issued = 'good'
else:
issued = 'missing'
if re.findall(r'CN=Android Debug', certlist):
issued = 'bad'
if re.findall(r'Hash Algorithm: sha1', certlist):
issued = 'bad hash'
cert_info = '\n'.join(certlist)
if 'MANIFEST.MF' in files:
manifestfile = os.path.join(cert_path, 'MANIFEST.MF')
if manifestfile:
with open(manifestfile, 'r', encoding='utf-8') as manifile:
manidat = manifile.read()
sha256_digest = bool(re.findall(r'SHA-256-Digest', manidat))
if a.is_signed():
status = 'good'
desc = 'Certificate looks good.'
else:
status = 'missing'
desc = 'Certificate is not found'
if re.findall(r'CN=Android Debug', cert_info):
status = 'bad'
desc = ('This is a debug certificate. Production application'
' must not be shipped with a debug certificate.')
if re.findall(r'Hash Algorithm: sha1', cert_info):
status = 'bad'
desc = ('The app is signed with SHA1withRSA. SHA1 hash algorithm'
' is known to have collision issues.')
if sha256_digest:
status = 'warning'
desc += ('The manifest indicates SHA256withRSA is in use. '
'Please verify this manually.')
cert_dic = {
'cert_info': certlist,
'issued': issued,
'sha256Digest': sha256_digest,
'certificate_info': cert_info,
'certificate_status': status,
'description': desc,
}
return cert_dic
except Exception:
+112 -203
View File
@@ -18,59 +18,51 @@ def get_context_from_db_entry(db_entry: QuerySet) -> dict:
"""Return the context for APK/ZIP from DB."""
try:
logger.info('Analysis is already Done. Fetching data from the DB...')
context = {
'version': settings.MOBSF_VER,
'title': db_entry[0].TITLE,
'name': db_entry[0].APP_NAME,
'real_name': db_entry[0].REAL_NAME,
'title': 'Static Analysis',
'file_name': db_entry[0].FILE_NAME,
'app_name': db_entry[0].APP_NAME,
'app_type': db_entry[0].APP_TYPE,
'size': db_entry[0].SIZE,
'md5': db_entry[0].MD5,
'sha1': db_entry[0].SHA1,
'sha256': db_entry[0].SHA256,
'packagename': db_entry[0].PACKAGENAME,
'mainactivity': db_entry[0].MAINACTIVITY,
'targetsdk': db_entry[0].TARGET_SDK,
'maxsdk': db_entry[0].MAX_SDK,
'minsdk': db_entry[0].MIN_SDK,
'androvername': db_entry[0].ANDROVERNAME,
'androver': db_entry[0].ANDROVER,
'manifest': python_list(db_entry[0].MANIFEST_ANAL),
'permissions': python_dict(db_entry[0].PERMISSIONS),
'binary_analysis': python_list(db_entry[0].BIN_ANALYSIS),
'files': python_list(db_entry[0].FILES),
'certz': python_list(db_entry[0].CERTZ),
'icon_hidden': db_entry[0].ICON_HIDDEN,
'icon_found': db_entry[0].ICON_FOUND,
'package_name': db_entry[0].PACKAGE_NAME,
'main_activity': db_entry[0].MAIN_ACTIVITY,
'exported_activities': db_entry[0].EXPORTED_ACTIVITIES,
'browsable_activities': python_dict(
db_entry[0].BROWSABLE_ACTIVITIES),
'activities': python_list(db_entry[0].ACTIVITIES),
'receivers': python_list(db_entry[0].RECEIVERS),
'providers': python_list(db_entry[0].PROVIDERS),
'services': python_list(db_entry[0].SERVICES),
'libraries': python_list(db_entry[0].LIBRARIES),
'browsable_activities': python_dict(db_entry[0].BROWSABLE),
'act_count': db_entry[0].CNT_ACT,
'prov_count': db_entry[0].CNT_PRO,
'serv_count': db_entry[0].CNT_SER,
'bro_count': db_entry[0].CNT_BRO,
'certinfo': db_entry[0].CERT_INFO,
'issued': db_entry[0].ISSUED,
'sha256Digest': db_entry[0].SHA256DIGEST,
'api': python_dict(db_entry[0].API),
'findings': python_dict(db_entry[0].DANG),
'target_sdk': db_entry[0].TARGET_SDK,
'max_sdk': db_entry[0].MAX_SDK,
'min_sdk': db_entry[0].MIN_SDK,
'version_name': db_entry[0].VERSION_NAME,
'version_code': db_entry[0].VERSION_CODE,
'icon_hidden': db_entry[0].ICON_HIDDEN,
'icon_found': db_entry[0].ICON_FOUND,
'permissions': python_dict(db_entry[0].PERMISSIONS),
'certificate_analysis': python_dict(
db_entry[0].CERTIFICATE_ANALYSIS),
'manifest_analysis': python_list(db_entry[0].MANIFEST_ANALYSIS),
'binary_analysis': python_list(db_entry[0].BINARY_ANALYSIS),
'file_analysis': python_list(db_entry[0].FILE_ANALYSIS),
'android_api': python_dict(db_entry[0].ANDROID_API),
'code_analysis': python_dict(db_entry[0].CODE_ANALYSIS),
'urls': python_list(db_entry[0].URLS),
'domains': python_dict(db_entry[0].DOMAINS),
'emails': python_list(db_entry[0].EMAILS),
'strings': python_list(db_entry[0].STRINGS),
'zipped': db_entry[0].ZIPPED,
'mani': db_entry[0].MANI,
'e_act': db_entry[0].E_ACT,
'e_ser': db_entry[0].E_SER,
'e_bro': db_entry[0].E_BRO,
'e_cnt': db_entry[0].E_CNT,
'apkid': python_dict(db_entry[0].APK_ID),
'play_details': python_dict(db_entry[0].PLAY_DETAILS),
'firebase': python_list(db_entry[0].FIREBASE),
'firebase_urls': python_list(db_entry[0].FIREBASE_URLS),
'files': python_list(db_entry[0].FILES),
'exported_count': python_dict(db_entry[0].EXPORTED_COUNT),
'apkid': python_dict(db_entry[0].APKID),
'trackers': python_dict(db_entry[0].TRACKERS),
'playstore_details': python_dict(db_entry[0].PLAYSTORE_DETAILS),
}
return context
except Exception:
@@ -88,194 +80,111 @@ def get_context_from_analysis(app_dic,
"""Get the context for APK/ZIP from analysis results."""
try:
context = {
'version': settings.MOBSF_VER,
'title': 'Static Analysis',
'name': app_dic['app_name'],
'real_name': app_dic['real_name'],
'version': settings.MOBSF_VER,
'file_name': app_dic['app_name'],
'app_name': app_dic['real_name'],
'app_type': app_dic['zipped'],
'size': app_dic['size'],
'md5': app_dic['md5'],
'sha1': app_dic['sha1'],
'sha256': app_dic['sha256'],
'packagename': man_data_dic['packagename'],
'mainactivity': man_data_dic['mainactivity'],
'targetsdk': man_data_dic['target_sdk'],
'maxsdk': man_data_dic['max_sdk'],
'minsdk': man_data_dic['min_sdk'],
'androvername': man_data_dic['androvername'],
'androver': man_data_dic['androver'],
'manifest': man_an_dic['manifest_anal'],
'permissions': man_an_dic['permissons'],
'binary_analysis': bin_anal,
'files': app_dic['files'],
'certz': app_dic['certz'],
'icon_hidden': app_dic['icon_hidden'],
'icon_found': app_dic['icon_found'],
'package_name': man_data_dic['packagename'],
'main_activity': man_data_dic['mainactivity'],
'exported_activities': man_an_dic['exported_act'],
'browsable_activities': man_an_dic['browsable_activities'],
'activities': man_data_dic['activities'],
'receivers': man_data_dic['receivers'],
'providers': man_data_dic['providers'],
'services': man_data_dic['services'],
'libraries': man_data_dic['libraries'],
'browsable_activities': man_an_dic['browsable_activities'],
'act_count': man_an_dic['cnt_act'],
'prov_count': man_an_dic['cnt_pro'],
'serv_count': man_an_dic['cnt_ser'],
'bro_count': man_an_dic['cnt_bro'],
'certinfo': cert_dic['cert_info'],
'issued': cert_dic['issued'],
'sha256Digest': cert_dic['sha256Digest'],
'api': code_an_dic['api'],
'findings': code_an_dic['findings'],
'target_sdk': man_data_dic['target_sdk'],
'max_sdk': man_data_dic['max_sdk'],
'min_sdk': man_data_dic['min_sdk'],
'version_name': man_data_dic['androvername'],
'version_code': man_data_dic['androver'],
'icon_hidden': app_dic['icon_hidden'],
'icon_found': app_dic['icon_found'],
'certificate_analysis': cert_dic,
'permissions': man_an_dic['permissons'],
'manifest_analysis': man_an_dic['manifest_anal'],
'binary_analysis': bin_anal,
'file_analysis': app_dic['certz'],
'android_api': code_an_dic['api'],
'code_analysis': code_an_dic['findings'],
'urls': code_an_dic['urls'],
'domains': code_an_dic['domains'],
'emails': code_an_dic['emails'],
'strings': app_dic['strings'],
'zipped': app_dic['zipped'],
'mani': app_dic['mani'],
'e_act': man_an_dic['exported_cnt']['act'],
'e_ser': man_an_dic['exported_cnt']['ser'],
'e_bro': man_an_dic['exported_cnt']['bro'],
'e_cnt': man_an_dic['exported_cnt']['cnt'],
'firebase_urls': code_an_dic['firebase'],
'files': app_dic['files'],
'exported_count': man_an_dic['exported_cnt'],
'apkid': apk_id,
'play_details': app_dic['playstore'],
'firebase': code_an_dic['firebase'],
'trackers': trackers,
'playstore_details': app_dic['playstore'],
}
return context
except Exception:
logger.exception('Rendering to Template')
def update_db_entry(app_dic,
man_data_dic,
man_an_dic,
code_an_dic,
cert_dic,
bin_anal,
apk_id,
trackers) -> None:
"""Update an APK/ZIP DB entry."""
def save_or_update(update_type,
app_dic,
man_data_dic,
man_an_dic,
code_an_dic,
cert_dic,
bin_anal,
apk_id,
trackers) -> None:
"""Save/Update an APK/ZIP DB entry."""
try:
# pylint: disable=E1101
StaticAnalyzerAndroid.objects.filter(MD5=app_dic['md5']).update(
TITLE='Static Analysis',
APP_NAME=app_dic['app_name'],
REAL_NAME=app_dic['real_name'],
SIZE=app_dic['size'],
MD5=app_dic['md5'],
SHA1=app_dic['sha1'],
SHA256=app_dic['sha256'],
PACKAGENAME=man_data_dic['packagename'],
MAINACTIVITY=man_data_dic['mainactivity'],
TARGET_SDK=man_data_dic['target_sdk'],
MAX_SDK=man_data_dic['max_sdk'],
MIN_SDK=man_data_dic['min_sdk'],
ANDROVERNAME=man_data_dic['androvername'],
ANDROVER=man_data_dic['androver'],
MANIFEST_ANAL=man_an_dic['manifest_anal'],
PERMISSIONS=man_an_dic['permissons'],
BIN_ANALYSIS=bin_anal,
FILES=app_dic['files'],
CERTZ=app_dic['certz'],
ICON_HIDDEN=app_dic['icon_hidden'],
ICON_FOUND=app_dic['icon_found'],
ACTIVITIES=man_data_dic['activities'],
RECEIVERS=man_data_dic['receivers'],
PROVIDERS=man_data_dic['providers'],
SERVICES=man_data_dic['services'],
LIBRARIES=man_data_dic['libraries'],
BROWSABLE=man_an_dic['browsable_activities'],
CNT_ACT=man_an_dic['cnt_act'],
CNT_PRO=man_an_dic['cnt_pro'],
CNT_SER=man_an_dic['cnt_ser'],
CNT_BRO=man_an_dic['cnt_bro'],
CERT_INFO=cert_dic['cert_info'],
ISSUED=cert_dic['issued'],
SHA256DIGEST=cert_dic['sha256Digest'],
API=code_an_dic['api'],
DANG=code_an_dic['findings'],
URLS=code_an_dic['urls'],
DOMAINS=code_an_dic['domains'],
EMAILS=code_an_dic['emails'],
STRINGS=app_dic['strings'],
ZIPPED=app_dic['zipped'],
MANI=app_dic['mani'],
EXPORTED_ACT=man_an_dic['exported_act'],
E_ACT=man_an_dic['exported_cnt']['act'],
E_SER=man_an_dic['exported_cnt']['ser'],
E_BRO=man_an_dic['exported_cnt']['bro'],
E_CNT=man_an_dic['exported_cnt']['cnt'],
APK_ID=apk_id,
PLAY_DETAILS=app_dic['playstore'],
FIREBASE=code_an_dic['firebase'],
TRACKERS=trackers,
)
values = {
'FILE_NAME': app_dic['app_name'],
'APP_NAME': app_dic['real_name'],
'APP_TYPE': app_dic['zipped'],
'SIZE': app_dic['size'],
'MD5': app_dic['md5'],
'SHA1': app_dic['sha1'],
'SHA256': app_dic['sha256'],
'PACKAGE_NAME': man_data_dic['packagename'],
'MAIN_ACTIVITY': man_data_dic['mainactivity'],
'EXPORTED_ACTIVITIES': man_an_dic['exported_act'],
'BROWSABLE_ACTIVITIES': man_an_dic['browsable_activities'],
'ACTIVITIES': man_data_dic['activities'],
'RECEIVERS': man_data_dic['receivers'],
'PROVIDERS': man_data_dic['providers'],
'SERVICES': man_data_dic['services'],
'LIBRARIES': man_data_dic['libraries'],
'TARGET_SDK': man_data_dic['target_sdk'],
'MAX_SDK': man_data_dic['max_sdk'],
'MIN_SDK': man_data_dic['min_sdk'],
'VERSION_NAME': man_data_dic['androvername'],
'VERSION_CODE': man_data_dic['androver'],
'ICON_HIDDEN': app_dic['icon_hidden'],
'ICON_FOUND': app_dic['icon_found'],
'CERTIFICATE_ANALYSIS': cert_dic,
'PERMISSIONS': man_an_dic['permissons'],
'MANIFEST_ANALYSIS': man_an_dic['manifest_anal'],
'BINARY_ANALYSIS': bin_anal,
'FILE_ANALYSIS': app_dic['certz'],
'ANDROID_API': code_an_dic['api'],
'CODE_ANALYSIS': code_an_dic['findings'],
'URLS': code_an_dic['urls'],
'DOMAINS': code_an_dic['domains'],
'EMAILS': code_an_dic['emails'],
'STRINGS': app_dic['strings'],
'FIREBASE_URLS': code_an_dic['firebase'],
'FILES': app_dic['files'],
'EXPORTED_COUNT': man_an_dic['exported_cnt'],
'APKID': apk_id,
'TRACKERS': trackers,
'PLAYSTORE_DETAILS': app_dic['playstore'],
}
if update_type == 'save':
StaticAnalyzerAndroid.objects.create(**values)
else:
StaticAnalyzerAndroid.objects.filter(
MD5=app_dic['md5']).update(**values)
except Exception:
logger.exception('Updating DB')
def create_db_entry(app_dic,
man_data_dic,
man_an_dic,
code_an_dic,
cert_dic,
bin_anal,
apk_id,
trackers) -> None:
"""Create a new DB-Entry for APK/ZIP."""
try:
static_db = StaticAnalyzerAndroid(
TITLE='Static Analysis',
APP_NAME=app_dic['app_name'],
REAL_NAME=app_dic['real_name'],
SIZE=app_dic['size'],
MD5=app_dic['md5'],
SHA1=app_dic['sha1'],
SHA256=app_dic['sha256'],
PACKAGENAME=man_data_dic['packagename'],
MAINACTIVITY=man_data_dic['mainactivity'],
TARGET_SDK=man_data_dic['target_sdk'],
MAX_SDK=man_data_dic['max_sdk'],
MIN_SDK=man_data_dic['min_sdk'],
ANDROVERNAME=man_data_dic['androvername'],
ANDROVER=man_data_dic['androver'],
MANIFEST_ANAL=man_an_dic['manifest_anal'],
PERMISSIONS=man_an_dic['permissons'],
BIN_ANALYSIS=bin_anal,
FILES=app_dic['files'],
CERTZ=app_dic['certz'],
ICON_HIDDEN=app_dic['icon_hidden'],
ICON_FOUND=app_dic['icon_found'],
ACTIVITIES=man_data_dic['activities'],
RECEIVERS=man_data_dic['receivers'],
PROVIDERS=man_data_dic['providers'],
SERVICES=man_data_dic['services'],
LIBRARIES=man_data_dic['libraries'],
BROWSABLE=man_an_dic['browsable_activities'],
CNT_ACT=man_an_dic['cnt_act'],
CNT_PRO=man_an_dic['cnt_pro'],
CNT_SER=man_an_dic['cnt_ser'],
CNT_BRO=man_an_dic['cnt_bro'],
CERT_INFO=cert_dic['cert_info'],
ISSUED=cert_dic['issued'],
SHA256DIGEST=cert_dic['sha256Digest'],
API=code_an_dic['api'],
DANG=code_an_dic['findings'],
URLS=code_an_dic['urls'],
DOMAINS=code_an_dic['domains'],
EMAILS=code_an_dic['emails'],
STRINGS=app_dic['strings'],
ZIPPED=app_dic['zipped'],
MANI=app_dic['mani'],
EXPORTED_ACT=man_an_dic['exported_act'],
E_ACT=man_an_dic['exported_cnt']['act'],
E_SER=man_an_dic['exported_cnt']['ser'],
E_BRO=man_an_dic['exported_cnt']['bro'],
E_CNT=man_an_dic['exported_cnt']['cnt'],
APK_ID=apk_id,
PLAY_DETAILS=app_dic['playstore'],
FIREBASE=code_an_dic['firebase'],
TRACKERS=trackers,
)
static_db.save()
except Exception:
logger.exception('Saving to DB')
@@ -796,16 +796,18 @@ def manifest_analysis(mfxml, man_data_dic):
'description': permisson[2],
})
# Prepare return dict
exported_comp = {
'exported_activities': exp_count['act'],
'exported_services': exp_count['ser'],
'exported_receivers': exp_count['bro'],
'exported_providers': exp_count['cnt'],
}
man_an_dic = {
'manifest_anal': ret_value,
'exported_act': exported,
'exported_cnt': exp_count,
'exported_cnt': exported_comp,
'browsable_activities': browsable_activities,
'permissons': permissons,
'cnt_act': len(man_data_dic['activities']),
'cnt_pro': len(man_data_dic['providers']),
'cnt_ser': len(man_data_dic['services']),
'cnt_bro': len(man_data_dic['receivers']),
'icon_hidden': icon_hidden,
}
return man_an_dic
+18 -14
View File
@@ -27,8 +27,7 @@ from StaticAnalyzer.views.android.cert_analysis import (
from StaticAnalyzer.views.android.code_analysis import code_analysis
from StaticAnalyzer.views.android.converter import (apk_2_java, dex_2_smali)
from StaticAnalyzer.views.android.db_interaction import (
create_db_entry, get_context_from_analysis, get_context_from_db_entry,
update_db_entry)
get_context_from_analysis, get_context_from_db_entry, save_or_update)
from StaticAnalyzer.views.android.icon_analysis import (find_icon_path_zip,
get_icon)
from StaticAnalyzer.views.android.manifest_analysis import (get_manifest,
@@ -228,7 +227,8 @@ def static_analyzer(request, api=False):
# SAVE TO DB
if rescan == '1':
logger.info('Updating Database...')
update_db_entry(
save_or_update(
'update',
app_dic,
man_data_dic,
man_an_dic,
@@ -241,7 +241,8 @@ def static_analyzer(request, api=False):
update_scan_timestamp(app_dic['md5'])
elif rescan == '0':
logger.info('Saving to Database')
create_db_entry(
save_or_update(
'save',
app_dic,
man_data_dic,
man_an_dic,
@@ -264,14 +265,14 @@ def static_analyzer(request, api=False):
tracker_res,
)
context['average_cvss'], context[
'security_score'] = score(context['findings'])
'security_score'] = score(context['code_analysis'])
context['dynamic_analysis_done'] = is_file_exists(
os.path.join(app_dic['app_dir'], 'logcat.txt'))
context['VT_RESULT'] = None
context['virus_total'] = None
if settings.VT_ENABLED:
vt = VirusTotal.VirusTotal()
context['VT_RESULT'] = vt.get_result(
context['virus_total'] = vt.get_result(
os.path.join(app_dic['app_dir'],
app_dic['md5']) + '.apk',
app_dic['md5'])
@@ -283,10 +284,11 @@ def static_analyzer(request, api=False):
elif typ == 'zip':
# Check if in DB
# pylint: disable=E1101
cert_dic = {}
cert_dic['cert_info'] = ''
cert_dic['issued'] = ''
cert_dic['sha256Digest'] = False
cert_dic = {
'certificate_info': '',
'certificate_status': '',
'description': '',
}
bin_an_buff = []
app_dic['strings'] = ''
app_dic['zipped'] = ''
@@ -404,7 +406,8 @@ def static_analyzer(request, api=False):
# SAVE TO DB
if rescan == '1':
logger.info('Updating Database...')
update_db_entry(
save_or_update(
'update',
app_dic,
man_data_dic,
man_an_dic,
@@ -417,7 +420,8 @@ def static_analyzer(request, api=False):
update_scan_timestamp(app_dic['md5'])
elif rescan == '0':
logger.info('Saving to Database')
create_db_entry(
save_or_update(
'save',
app_dic,
man_data_dic,
man_an_dic,
@@ -455,7 +459,7 @@ def static_analyzer(request, api=False):
template = 'general/zip.html'
return render(request, template, ctx)
context['average_cvss'], context[
'security_score'] = score(context['findings'])
'security_score'] = score(context['code_analysis'])
template = 'static_analysis/android_source_analysis.html'
if api:
return context
+15 -13
View File
@@ -10,6 +10,7 @@ from copy import deepcopy
from django.shortcuts import render
from django.conf import settings
from django.utils.html import escape
from MobSF.utils import print_n_send_error_response
@@ -78,14 +79,13 @@ def generic_compare(request,
'first_app': {},
'second_app': {},
'urls': {},
'api': {},
'android_api': {},
'permissions': {},
'apkid': {},
}
static_fields = ['md5', 'name', 'size', 'icon_found',
'icon_hidden', 'act_count', 'e_act', 'serv_count',
'e_ser', 'bro_count', 'e_bro', 'prov_count',
'e_cnt', 'apkid']
static_fields = ['md5', 'file_name', 'size', 'icon_found',
'icon_hidden', 'activities', 'services', 'providers',
'receivers', 'exported_count', 'apkid']
# For now - support only android
db_entry = StaticAnalyzerAndroid.objects.filter(MD5=first_hash)
@@ -94,10 +94,9 @@ def generic_compare(request,
if not (db_entry.exists() and db_entry2.exists()):
return print_n_send_error_response(
request,
'One of the Hashes is not found '
'in the Android scan database. Make '
'sure both of the apps finished '
'analysis and they are both Android.',
'Currently you can only diff android apps.'
'One of the app has not finished static analysis or'
'they are not both android APK/ZIP.',
False,
)
@@ -115,8 +114,8 @@ def generic_compare(request,
# format informative title
context[curr_app]['name_ver'] = '{0} - {1}'.format(
db_context['packagename'],
db_context['androvername'])
db_context['package_name'],
db_context['version_name'])
# Fill all the static information
for static_attr in static_fields:
@@ -124,7 +123,8 @@ def generic_compare(request,
# Get only the subject of the cert
subject_regex = re.compile(r'Subject: .*')
match = subject_regex.search(db_context['certinfo'])
match = subject_regex.search(
db_context['certificate_analysis']['certificate_info'])
if match:
context[curr_app]['cert_subject'] = match.group()
else:
@@ -137,6 +137,8 @@ def generic_compare(request,
for url in url_obj['urls']:
# urls can mess up the table because they can be really long,
# so let's cut them
# escape url
url = escape(url)
tmp_url = url[:70]
while len(url) > 70:
url = url[70:]
@@ -156,7 +158,7 @@ def generic_compare(request,
# Third, calculate some diffs
for section, is_tuples in [
('permissions', True),
('api', True),
('android_api', True),
('urls', False),
]:
if is_tuples:
@@ -0,0 +1,76 @@
import logging
logger = logging.getLogger(__name__)
def check_transport_security(p_list):
"""Check info.plist for insecure connection configurations."""
logger.info('Checking for Insecure Connections')
ats = []
if 'NSAppTransportSecurity' in p_list:
ats_dict = p_list['NSAppTransportSecurity']
if ats_dict.get('NSAllowsArbitraryLoads'):
ats.append({
'issue': 'App Transport Security is allowed',
'status': 'insecure',
'description': (
'App Transport Security restrictions are disabled'
' for all network connections. Disabling ATS means that '
'unsecured HTTP connections are allowed. HTTPS '
'connections are also allowed, and are still subject'
' to default server trust evaluation. However, '
'extended security checks like requiring a minimum '
'Transport Layer Security (TLS) protocol version—are'
' disabled. This setting is not applicable to domains '
'listed in NSExceptionDomains.'),
})
if ats_dict.get('NSAllowsArbitraryLoadsForMedia'):
ats.append({
'issue': 'Insecure media load is allowed',
'status': 'insecure',
'description': (
'App Transport Security restrictions are disabled for '
'media loaded using the AVFoundation framework, '
'without affecting your URLSession connections.'
' This setting is not applicable to domains '
'listed in NSExceptionDomains.'),
})
if ats_dict.get('NSAllowsArbitraryLoadsInWebContent'):
ats.append({
'issue': 'Insecure WebView load is allowed',
'status': 'insecure',
'description': (
'App Transport Security restrictions are disabled for'
' requests made from WebViews without affecting your'
' URLSession connections. This setting is not applicable'
' to domains listed in NSExceptionDomains.'),
})
exception_domain = ats_dict.get('NSExceptionDomains')
if exception_domain:
for domain, config in exception_domain.items():
if config.get('NSTemporaryExceptionAllowsInsecureHTTPLoads'):
findings = {
'issue': ('Insecure communication'
' to {} is allowed'.format(domain)),
'status': 'insecure',
'description': (
'This settings allow insecure HTTP loads for {},'
' or to be able to loosen the server trust '
'evaluation requirements for HTTPS '
'connections to the domain. '.format(domain)),
}
if config.get('NSIncludesSubdomains'):
findings['description'] += (
'This settings is applicable to the'
' subdomains as well. '
)
if config.get('NSExceptionMinimumTLSVersion'):
findings['description'] += (
'Minimum TLS '
'Version: {}'.format(
config.get(
'NSTemporaryExceptionMinimumTLSVersion'))
)
ats.append(findings)
return ats
+2 -4
View File
@@ -180,10 +180,10 @@ def otool_analysis(tools_dir, bin_name, bin_path, bin_dir):
baned_s = b', '.join(baned)
if len(baned_s) > 1:
banned_apis = {
'issue': 'Binary make use of banned API(s)',
'issue': 'Binary make use of insecure API(s)',
'level': IN_SECURE,
'description': ('The binary may contain'
' the following banned API(s) {}.').format(
' the following insecure API(s) {}.').format(
baned_s.decode('utf-8', 'ignore')),
'cvss': 6,
'cwe': 'CWE-676',
@@ -477,8 +477,6 @@ def strings_on_ipa(bin_path):
logger.info('Running strings against the Binary')
unique_str = []
unique_str = list(set(strings_util(bin_path))) # Make unique
unique_str = [escape(ip_str)
for ip_str in unique_str] # Escape evil strings
return unique_str
except Exception:
logger.exception('Running strings against the Binary')
+104 -299
View File
@@ -1,92 +1,53 @@
"""Module holding the functions for the db."""
import logging
from django.conf import settings
from MobSF.utils import python_dict, python_list
from StaticAnalyzer.models import StaticAnalyzerIOSZIP, StaticAnalyzerIPA
from StaticAnalyzer.models import StaticAnalyzerIOS
logger = logging.getLogger(__name__)
# IPA DB
def get_context_from_analysis_ipa(app_dict,
info_dict,
bin_dict,
files,
sfiles):
"""Get the context for IPA from analysis results."""
try:
context = {
'title': 'Static Analysis',
'file_name': app_dict['file_name'],
'size': app_dict['size'],
'md5': app_dict['md5_hash'],
'sha1': app_dict['sha1'],
'sha256': app_dict['sha256'],
'plist': info_dict['plist_xml'],
'bin_name': info_dict['bin_name'],
'id': info_dict['id'],
'build': info_dict['build'],
'bundle_version': info_dict['bundle_version_name'],
'sdk': info_dict['sdk'],
'pltfm': info_dict['pltfm'],
'min': info_dict['min'],
'bin_anal': bin_dict['bin_res'],
'libs': bin_dict['libs'],
'files': files,
'file_analysis': sfiles,
'strings': bin_dict['strings'],
'permissions': info_dict['permissions'],
'insecure_connections': info_dict['inseccon'],
'bundle_name': info_dict['bundle_name'],
'bundle_url_types': info_dict['bundle_url_types'],
'bundle_supported_platforms':
info_dict['bundle_supported_platforms'],
'bundle_localizations': info_dict['bundle_localizations'],
'binary_info': bin_dict['macho'],
'bin_type': bin_dict['bin_type'],
'appstore_details': app_dict['appstore'],
}
return context
except Exception:
logger.exception('Rendering to Template')
def get_context_from_db_entry_ipa(db_entry):
"""Return the context for IPA from DB."""
def get_context_from_db_entry(db_entry):
"""Return the context for IPA/ZIP from DB."""
try:
logger.info('Analysis is already Done. Fetching data from the DB...')
context = {
'title': db_entry[0].TITLE,
'version': settings.MOBSF_VER,
'title': 'Static Analysis',
'file_name': db_entry[0].FILE_NAME,
'app_name': db_entry[0].APP_NAME,
'app_type': db_entry[0].APP_TYPE,
'size': db_entry[0].SIZE,
'md5': db_entry[0].MD5,
'sha1': db_entry[0].SHA1,
'sha256': db_entry[0].SHA256,
'plist': db_entry[0].INFOPLIST,
'bin_name': db_entry[0].BINNAME,
'id': db_entry[0].IDF,
'build': db_entry[0].BUILD,
'bundle_version': db_entry[0].VERSION,
'sdk': db_entry[0].SDK,
'pltfm': db_entry[0].PLTFM,
'min': db_entry[0].MINX,
'bin_anal': python_list(db_entry[0].BIN_ANAL),
'libs': python_list(db_entry[0].LIBS),
'files': python_list(db_entry[0].FILES),
'file_analysis': python_list(db_entry[0].SFILESX),
'strings': python_list(db_entry[0].STRINGS),
'permissions': python_list(db_entry[0].PERMISSIONS),
'insecure_connections': python_list(db_entry[0].INSECCON),
'bundle_name': db_entry[0].BUNDLE_NAME,
'app_version': db_entry[0].APP_VERSION,
'sdk_name': db_entry[0].SDK_NAME,
'platform': db_entry[0].PLATFORM,
'min_os_version': db_entry[0].MIN_OS_VERSION,
'bundle_id': db_entry[0].BUNDLE_ID,
'bundle_url_types': python_list(db_entry[0].BUNDLE_URL_TYPES),
'bundle_supported_platforms':
python_list(db_entry[0].BUNDLE_SUPPORTED_PLATFORMS),
'bundle_localizations':
python_list(db_entry[0].BUNDLE_LOCALIZATIONS),
'binary_info': python_dict(db_entry[0].MACHOINFO),
'bin_type': db_entry[0].BINTYPE,
'info_plist': db_entry[0].INFO_PLIST,
'binary_info': python_dict(db_entry[0].MACHO_INFO),
'permissions': python_list(db_entry[0].PERMISSIONS),
'ats_analysis': python_list(db_entry[0].ATS_ANALYSIS),
'binary_analysis': python_list(db_entry[0].BINARY_ANALYSIS),
'ios_api': python_dict(db_entry[0].IOS_API),
'code_analysis': python_dict(db_entry[0].CODE_ANALYSIS),
'file_analysis': python_list(db_entry[0].FILE_ANALYSIS),
'libraries': python_list(db_entry[0].LIBRARIES),
'files': python_list(db_entry[0].FILES),
'urls': python_list(db_entry[0].URLS),
'domains': python_dict(db_entry[0].DOMAINS),
'emails': python_list(db_entry[0].EMAILS),
'strings': python_list(db_entry[0].STRINGS),
'firebase_urls': python_list(db_entry[0].FIREBASE_URLS),
'appstore_details': python_dict(db_entry[0].APPSTORE_DETAILS),
}
@@ -95,258 +56,102 @@ def get_context_from_db_entry_ipa(db_entry):
logger.exception('Fetching from DB')
def update_db_entry_ipa(app_dict,
info_dict,
bin_dict,
files,
sfiles):
"""Update an IPA DB entry."""
try:
# pylint: disable=E1101
StaticAnalyzerIPA.objects.filter(MD5=app_dict['md5_hash']).update(
TITLE='Static Analysis',
FILE_NAME=app_dict['file_name'],
SIZE=app_dict['size'],
MD5=app_dict['md5_hash'],
SHA1=app_dict['sha1'],
SHA256=app_dict['sha256'],
INFOPLIST=info_dict['plist_xml'],
BINNAME=info_dict['bin_name'],
IDF=info_dict['id'],
BUILD=info_dict['build'],
VERSION=info_dict['bundle_version_name'],
SDK=info_dict['sdk'],
PLTFM=info_dict['pltfm'],
MINX=info_dict['min'],
BIN_ANAL=bin_dict['bin_res'],
LIBS=bin_dict['libs'],
FILES=files,
SFILESX=sfiles,
STRINGS=bin_dict['strings'],
PERMISSIONS=info_dict['permissions'],
INSECCON=info_dict['inseccon'],
BUNDLE_NAME=info_dict['bundle_name'],
BUNDLE_URL_TYPES=info_dict['bundle_url_types'],
BUNDLE_SUPPORTED_PLATFORMS=info_dict['bundle_supported_platforms'],
BUNDLE_LOCALIZATIONS=info_dict['bundle_localizations'],
MACHOINFO=bin_dict['macho'],
BINTYPE=bin_dict['bin_type'],
APPSTORE_DETAILS=app_dict['appstore'],
)
except Exception:
logger.exception('Updating DB')
def create_db_entry_ipa(app_dict,
info_dict,
bin_dict,
files,
sfiles):
"""Save an IOS IPA DB entry."""
try:
static_db = StaticAnalyzerIPA(
TITLE='Static Analysis',
FILE_NAME=app_dict['file_name'],
SIZE=app_dict['size'],
MD5=app_dict['md5_hash'],
SHA1=app_dict['sha1'],
SHA256=app_dict['sha256'],
INFOPLIST=info_dict['plist_xml'],
BINNAME=info_dict['bin_name'],
IDF=info_dict['id'],
BUILD=info_dict['build'],
VERSION=info_dict['bundle_version_name'],
SDK=info_dict['sdk'],
PLTFM=info_dict['pltfm'],
MINX=info_dict['min'],
BIN_ANAL=bin_dict['bin_res'],
LIBS=bin_dict['libs'],
FILES=files,
SFILESX=sfiles,
STRINGS=bin_dict['strings'],
PERMISSIONS=info_dict['permissions'],
INSECCON=info_dict['inseccon'],
BUNDLE_NAME=info_dict['bundle_name'],
BUNDLE_URL_TYPES=info_dict['bundle_url_types'],
BUNDLE_SUPPORTED_PLATFORMS=info_dict['bundle_supported_platforms'],
BUNDLE_LOCALIZATIONS=info_dict['bundle_localizations'],
MACHOINFO=bin_dict['macho'],
BINTYPE=bin_dict['bin_type'],
APPSTORE_DETAILS=app_dict['appstore'],
)
static_db.save()
except Exception:
logger.exception('Saving to DB')
# IOS ZIP DB ENTRY
def get_context_from_analysis_ios(app_dict,
info_dict,
code_dict,
files,
sfiles):
"""Get the context for IOS ZIP from analysis results."""
def get_context_from_analysis(app_dict,
info_dict,
code_dict,
bin_dict,
files,
sfiles):
"""Get the context for IPA/ZIP from analysis results."""
try:
context = {
'version': settings.MOBSF_VER,
'title': 'Static Analysis',
'file_name': app_dict['file_name'],
'app_name': info_dict['bin_name'],
'app_type': bin_dict['bin_type'],
'size': app_dict['size'],
'md5': app_dict['md5_hash'],
'sha1': app_dict['sha1'],
'sha256': app_dict['sha256'],
'plist': info_dict['plist_xml'],
'bin_name': info_dict['bin_name'],
'id': info_dict['id'],
'build': info_dict['build'],
'bundle_version': info_dict['bundle_version_name'],
'sdk': info_dict['sdk'],
'pltfm': info_dict['pltfm'],
'min': info_dict['min'],
'files': files,
'app_version': info_dict['bundle_version_name'],
'sdk_name': info_dict['sdk'],
'platform': info_dict['pltfm'],
'min_os_version': info_dict['min'],
'bundle_id': info_dict['id'],
'bundle_url_types': info_dict['bundle_url_types'],
'bundle_supported_platforms':
info_dict['bundle_supported_platforms'],
'info_plist': info_dict['plist_xml'],
'binary_info': bin_dict['macho'],
'permissions': info_dict['permissions'],
'ats_analysis': info_dict['inseccon'],
'binary_analysis': bin_dict['bin_res'],
'ios_api': code_dict['api'],
'code_analysis': code_dict['code_anal'],
'file_analysis': sfiles,
'api': code_dict['api'],
'insecure': code_dict['code_anal'],
'libraries': bin_dict['libs'],
'files': files,
'urls': code_dict['urlnfile'],
'domains': code_dict['domains'],
'emails': code_dict['emailnfile'],
'permissions': info_dict['permissions'],
'insecure_connections': info_dict['inseccon'],
'bundle_name': info_dict['bundle_name'],
'bundle_url_types': info_dict['bundle_url_types'],
'bundle_supported_platforms':
info_dict['bundle_supported_platforms'],
'bundle_localizations': info_dict['bundle_localizations'],
'strings': bin_dict['strings'],
'firebase_urls': code_dict['firebase'],
'appstore_details': app_dict['appstore'],
'firebase': code_dict['firebase'],
}
return context
except Exception:
logger.exception('Rendering to Template')
def get_context_from_db_entry_ios(db_entry):
"""Return the context for IOS ZIP from DB."""
def save_or_update(update_type,
app_dict,
info_dict,
code_dict,
bin_dict,
files,
sfiles) -> None:
"""Save/Update an IPA/ZIP DB entry."""
try:
logger.info('Analysis is already Done. Fetching data from the DB...')
context = {
'title': db_entry[0].TITLE,
'file_name': db_entry[0].FILE_NAME,
'size': db_entry[0].SIZE,
'md5': db_entry[0].MD5,
'sha1': db_entry[0].SHA1,
'sha256': db_entry[0].SHA256,
'plist': db_entry[0].INFOPLIST,
'bin_name': db_entry[0].BINNAME,
'id': db_entry[0].IDF,
'build': db_entry[0].BUILD,
'bundle_version': db_entry[0].VERSION,
'sdk': db_entry[0].SDK,
'pltfm': db_entry[0].PLTFM,
'min': db_entry[0].MINX,
'files': python_list(db_entry[0].FILES),
'file_analysis': python_list(db_entry[0].SFILESX),
'api': python_dict(db_entry[0].API),
'insecure': python_dict(db_entry[0].CODEANAL),
'urls': python_list(db_entry[0].URLnFile),
'domains': python_dict(db_entry[0].DOMAINS),
'emails': python_list(db_entry[0].EmailnFile),
'permissions': python_list(db_entry[0].PERMISSIONS),
'insecure_connections': python_list(db_entry[0].INSECCON),
'bundle_name': db_entry[0].BUNDLE_NAME,
'bundle_url_types': python_list(db_entry[0].BUNDLE_URL_TYPES),
'bundle_supported_platforms':
python_list(db_entry[0].BUNDLE_SUPPORTED_PLATFORMS),
'bundle_localizations':
python_list(db_entry[0].BUNDLE_LOCALIZATIONS),
'appstore_details': python_dict(db_entry[0].APPSTORE_DETAILS),
'firebase': python_list(db_entry[0].FIREBASE),
values = {
'FILE_NAME': app_dict['file_name'],
'APP_NAME': info_dict['bin_name'],
'APP_TYPE': bin_dict['bin_type'],
'SIZE': app_dict['size'],
'MD5': app_dict['md5_hash'],
'SHA1': app_dict['sha1'],
'SHA256': app_dict['sha256'],
'BUILD': info_dict['build'],
'APP_VERSION': info_dict['bundle_version_name'],
'SDK_NAME': info_dict['sdk'],
'PLATFORM': info_dict['pltfm'],
'MIN_OS_VERSION': info_dict['min'],
'BUNDLE_ID': info_dict['id'],
'BUNDLE_URL_TYPES': info_dict['bundle_url_types'],
'BUNDLE_SUPPORTED_PLATFORMS':
info_dict['bundle_supported_platforms'],
'INFO_PLIST': info_dict['plist_xml'],
'MACHO_INFO': bin_dict['macho'],
'PERMISSIONS': info_dict['permissions'],
'ATS_ANALYSIS': info_dict['inseccon'],
'BINARY_ANALYSIS': bin_dict['bin_res'],
'IOS_API': code_dict['api'],
'CODE_ANALYSIS': code_dict['code_anal'],
'FILE_ANALYSIS': sfiles,
'LIBRARIES': bin_dict['libs'],
'FILES': files,
'URLS': code_dict['urlnfile'],
'DOMAINS': code_dict['domains'],
'EMAILS': code_dict['emailnfile'],
'STRINGS': bin_dict['strings'],
'FIREBASE_URLS': code_dict['firebase'],
'APPSTORE_DETAILS': app_dict['appstore'],
}
return context
except Exception:
logger.exception('Fetching from DB')
def update_db_entry_ios(app_dict,
info_dict,
code_dict,
files,
sfiles):
"""Update an IOS ZIP DB entry."""
try:
# pylint: disable=E1101
StaticAnalyzerIOSZIP.objects.filter(MD5=app_dict['md5_hash']).update(
TITLE='Static Analysis',
FILE_NAME=app_dict['file_name'],
SIZE=app_dict['size'],
MD5=app_dict['md5_hash'],
SHA1=app_dict['sha1'],
SHA256=app_dict['sha256'],
INFOPLIST=info_dict['plist_xml'],
BINNAME=info_dict['bin_name'],
IDF=info_dict['id'],
BUILD=info_dict['build'],
VERSION=info_dict['bundle_version_name'],
SDK=info_dict['sdk'],
PLTFM=info_dict['pltfm'],
MINX=info_dict['min'],
FILES=files,
SFILESX=sfiles,
API=code_dict['api'],
CODEANAL=code_dict['code_anal'],
URLnFile=code_dict['urlnfile'],
DOMAINS=code_dict['domains'],
EmailnFile=code_dict['emailnfile'],
PERMISSIONS=info_dict['permissions'],
INSECCON=info_dict['inseccon'],
BUNDLE_NAME=info_dict['bundle_name'],
BUNDLE_URL_TYPES=info_dict['bundle_url_types'],
BUNDLE_SUPPORTED_PLATFORMS=info_dict['bundle_supported_platforms'],
BUNDLE_LOCALIZATIONS=info_dict['bundle_localizations'],
APPSTORE_DETAILS=app_dict['appstore'],
FIREBASE=code_dict['firebase'],
)
if update_type == 'save':
StaticAnalyzerIOS.objects.create(**values)
else:
StaticAnalyzerIOS.objects.filter(
MD5=app_dict['md5_hash']).update(**values)
except Exception:
logger.exception('Updating DB')
def create_db_entry_ios(app_dict, info_dict, code_dict, files, sfiles):
"""Save an IOS ZIP DB entry."""
try:
# pylint: disable=E1101
static_db = StaticAnalyzerIOSZIP(
TITLE='Static Analysis',
FILE_NAME=app_dict['file_name'],
SIZE=app_dict['size'],
MD5=app_dict['md5_hash'],
SHA1=app_dict['sha1'],
SHA256=app_dict['sha256'],
INFOPLIST=info_dict['plist_xml'],
BINNAME=info_dict['bin_name'],
IDF=info_dict['id'],
BUILD=info_dict['build'],
VERSION=info_dict['bundle_version_name'],
SDK=info_dict['sdk'],
PLTFM=info_dict['pltfm'],
MINX=info_dict['min'],
FILES=files,
SFILESX=sfiles,
API=code_dict['api'],
CODEANAL=code_dict['code_anal'],
URLnFile=code_dict['urlnfile'],
DOMAINS=code_dict['domains'],
EmailnFile=code_dict['emailnfile'],
PERMISSIONS=info_dict['permissions'],
INSECCON=info_dict['inseccon'],
BUNDLE_NAME=info_dict['bundle_name'],
BUNDLE_URL_TYPES=info_dict['bundle_url_types'],
BUNDLE_SUPPORTED_PLATFORMS=info_dict['bundle_supported_platforms'],
BUNDLE_LOCALIZATIONS=info_dict['bundle_localizations'],
APPSTORE_DETAILS=app_dict['appstore'],
FIREBASE=code_dict['firebase'],
)
static_db.save()
except Exception:
logger.exception('Saving DB')
+52
View File
@@ -157,6 +157,58 @@ CODE_RULES = [
'cwe': 'CWE-22',
'owasp': 'M10: Extraneous Functionality',
},
{
'desc': ('File is stored in an encrypted format on '
'disk and cannot be read from or written to '
'while the device is locked or booting.'),
'type': 'string',
'string1': 'NSFileProtectionComplete',
'level': 'good',
'match': 'single_string',
'input_case': 'exact',
'cvss': 0,
'cwe': '',
'owasp': '',
},
{
'desc': ('File is stored in an encrypted format '
'on disk after it is closed.'),
'type': 'string',
'string1': 'NSFileProtectionCompleteUnlessOpen',
'level': 'good',
'match': 'single_string',
'input_case': 'exact',
'cvss': 0,
'cwe': '',
'owasp': '',
},
{
'desc': ('File is stored in an encrypted format '
'on disk and cannot be accessed until after '
'the device has booted.'),
'type': 'string',
'string1': (
'NSFileProtectionComplete'
'UntilFirstUserAuthentication'),
'level': 'good',
'match': 'single_string',
'input_case': 'exact',
'cvss': 0,
'cwe': '',
'owasp': '',
},
{
'desc': ('The file has no special protections '
'associated with it.'),
'type': 'string',
'string1': 'NSFileProtectionNone',
'level': 'warning',
'match': 'single_string',
'input_case': 'exact',
'cvss': 4.3,
'cwe': 'CWE-311',
'owasp': 'M1: Improper Platform Usage',
},
{
'desc': ('User input in "loadHTMLString" '
'will result in JavaScript Injection.'),
@@ -0,0 +1,112 @@
import logging
logger = logging.getLogger(__name__)
def check_permissions(p_list):
"""Check the permissions the app requests."""
# List taken from
# https://developer.apple.com/library/content/
# documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html
logger.info('Checking Permissions')
permissions = []
if 'NSAppleMusicUsageDescription' in p_list:
permissions.append({
'name': 'NSAppleMusicUsageDescription',
'description': 'Access Apple Media Library.',
'reason': p_list['NSAppleMusicUsageDescription'],
})
if 'NSBluetoothPeripheralUsageDescription' in p_list:
permissions.append({
'name': 'NSBluetoothPeripheralUsageDescription',
'description': 'Access Bluetooth Interface.',
'reason': p_list['NSBluetoothPeripheralUsageDescription'],
})
if 'NSCalendarsUsageDescription' in p_list:
permissions.append({
'name': 'NSCalendarsUsageDescription',
'description': 'Access Calendars.',
'reason': p_list['NSCalendarsUsageDescription'],
})
if 'NSCameraUsageDescription' in p_list:
permissions.append({
'name': 'NSCameraUsageDescription',
'description': 'Access the Camera.',
'reason': p_list['NSCameraUsageDescription'],
})
if 'NSContactsUsageDescription' in p_list:
permissions.append({
'name': 'NSContactsUsageDescription',
'description': 'Access Contacts.',
'reason': p_list['NSContactsUsageDescription'],
})
if 'NSHealthShareUsageDescription' in p_list:
permissions.append({
'name': 'NSHealthShareUsageDescription',
'description': 'Read Health Data.',
'reason': p_list['NSHealthShareUsageDescription'],
})
if 'NSHealthUpdateUsageDescription' in p_list:
permissions.append({
'name': 'NSHealthUpdateUsageDescription',
'description': 'Write Health Data.',
'reason': p_list['NSHealthUpdateUsageDescription'],
})
if 'NSHomeKitUsageDescription' in p_list:
permissions.append({
'name': 'NSHomeKitUsageDescription',
'description': 'Access HomeKit configuration data.',
'reason': p_list['NSHomeKitUsageDescription'],
})
if 'NSLocationAlwaysUsageDescription' in p_list:
permissions.append({
'name': 'NSLocationAlwaysUsageDescription',
'description': 'Access location information at all times.',
'reason': p_list['NSLocationAlwaysUsageDescription'],
})
if 'NSLocationUsageDescription' in p_list:
permissions.append({
'name': 'NSLocationUsageDescription',
'description': ('Access location information'
' at all times (< iOS 8).'),
'reason': p_list['NSLocationUsageDescription'],
})
if 'NSLocationWhenInUseUsageDescription' in p_list:
permissions.append({
'name': 'NSLocationWhenInUseUsageDescription',
'description': ('Access location information when'
' app is in the foreground.'),
'reason': p_list['NSLocationWhenInUseUsageDescription'],
})
if 'NSMicrophoneUsageDescription' in p_list:
permissions.append({
'name': 'NSMicrophoneUsageDescription',
'description': 'Access microphone.',
'reason': p_list['NSMicrophoneUsageDescription'],
})
if 'NSMotionUsageDescription' in p_list:
permissions.append({
'name': 'NSMotionUsageDescription',
'description': 'Access the device’s accelerometer.',
'reason': p_list['NSMotionUsageDescription'],
})
if 'NSPhotoLibraryUsageDescription' in p_list:
permissions.append({
'name': 'NSPhotoLibraryUsageDescription',
'description': 'Access the user’s photo library.',
'reason': p_list['NSPhotoLibraryUsageDescription'],
})
if 'NSRemindersUsageDescription' in p_list:
permissions.append({
'name': 'NSRemindersUsageDescription',
'description': 'Access the user’s reminders.',
'reason': p_list['NSRemindersUsageDescription'],
})
if 'NSVideoSubscriberAccountUsageDescription' in p_list:
permissions.append({
'name': 'NSVideoSubscriberAccountUsageDescription',
'description': 'Access the user’s TV provider account.',
'reason': p_list['NSVideoSubscriberAccountUsageDescription'],
})
return permissions
+20 -154
View File
@@ -10,6 +10,10 @@ from biplist import readPlist, writePlistToString
from MobSF.utils import is_file_exists
from StaticAnalyzer.views.ios.permission_analysis import check_permissions
from StaticAnalyzer.views.ios.app_transport_security import (
check_transport_security)
logger = logging.getLogger(__name__)
@@ -23,131 +27,6 @@ def convert_bin_xml(bin_xml_file):
logger.warning('Failed to convert plist')
def check_permissions(p_list):
"""Check the permissions the app requests."""
# List taken from
# https://developer.apple.com/library/content/
# documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html
logger.info('Checking Permissions')
permissions = []
if 'NSAppleMusicUsageDescription' in p_list:
permissions.append({
'name': 'NSAppleMusicUsageDescription',
'description': 'Access Apple Media Library.',
'reason': p_list['NSAppleMusicUsageDescription'],
})
if 'NSBluetoothPeripheralUsageDescription' in p_list:
permissions.append({
'name': 'NSBluetoothPeripheralUsageDescription',
'description': 'Access Bluetooth Interface.',
'reason': p_list['NSBluetoothPeripheralUsageDescription'],
})
if 'NSCalendarsUsageDescription' in p_list:
permissions.append({
'name': 'NSCalendarsUsageDescription',
'description': 'Access Calendars.',
'reason': p_list['NSCalendarsUsageDescription'],
})
if 'NSCameraUsageDescription' in p_list:
permissions.append({
'name': 'NSCameraUsageDescription',
'description': 'Access the Camera.',
'reason': p_list['NSCameraUsageDescription'],
})
if 'NSContactsUsageDescription' in p_list:
permissions.append({
'name': 'NSContactsUsageDescription',
'description': 'Access Contacts.',
'reason': p_list['NSContactsUsageDescription'],
})
if 'NSHealthShareUsageDescription' in p_list:
permissions.append({
'name': 'NSHealthShareUsageDescription',
'description': 'Read Health Data.',
'reason': p_list['NSHealthShareUsageDescription'],
})
if 'NSHealthUpdateUsageDescription' in p_list:
permissions.append({
'name': 'NSHealthUpdateUsageDescription',
'description': 'Write Health Data.',
'reason': p_list['NSHealthUpdateUsageDescription'],
})
if 'NSHomeKitUsageDescription' in p_list:
permissions.append({
'name': 'NSHomeKitUsageDescription',
'description': 'Access HomeKit configuration data.',
'reason': p_list['NSHomeKitUsageDescription'],
})
if 'NSLocationAlwaysUsageDescription' in p_list:
permissions.append({
'name': 'NSLocationAlwaysUsageDescription',
'description': 'Access location information at all times.',
'reason': p_list['NSLocationAlwaysUsageDescription'],
})
if 'NSLocationUsageDescription' in p_list:
permissions.append({
'name': 'NSLocationUsageDescription',
'description': ('Access location information'
' at all times (< iOS 8).'),
'reason': p_list['NSLocationUsageDescription'],
})
if 'NSLocationWhenInUseUsageDescription' in p_list:
permissions.append({
'name': 'NSLocationWhenInUseUsageDescription',
'description': ('Access location information when'
' app is in the foreground.'),
'reason': p_list['NSLocationWhenInUseUsageDescription'],
})
if 'NSMicrophoneUsageDescription' in p_list:
permissions.append({
'name': 'NSMicrophoneUsageDescription',
'description': 'Access microphone.',
'reason': p_list['NSMicrophoneUsageDescription'],
})
if 'NSMotionUsageDescription' in p_list:
permissions.append({
'name': 'NSMotionUsageDescription',
'description': 'Access the device’s accelerometer.',
'reason': p_list['NSMotionUsageDescription'],
})
if 'NSPhotoLibraryUsageDescription' in p_list:
permissions.append({
'name': 'NSPhotoLibraryUsageDescription',
'description': 'Access the user’s photo library.',
'reason': p_list['NSPhotoLibraryUsageDescription'],
})
if 'NSRemindersUsageDescription' in p_list:
permissions.append({
'name': 'NSRemindersUsageDescription',
'description': 'Access the user’s reminders.',
'reason': p_list['NSRemindersUsageDescription'],
})
if 'NSVideoSubscriberAccountUsageDescription' in p_list:
permissions.append({
'name': 'NSVideoSubscriberAccountUsageDescription',
'description': 'Access the user’s TV provider account.',
'reason': p_list['NSVideoSubscriberAccountUsageDescription'],
})
return permissions
def check_insecure_connections(p_list):
"""Check info.plist for insecure connection configurations."""
logger.info('Checking for Insecure Connections')
insecure_connections = []
if 'NSAppTransportSecurity' in p_list:
ns_app_trans_dic = p_list['NSAppTransportSecurity']
if 'NSExceptionDomains' in ns_app_trans_dic:
for key in ns_app_trans_dic['NSExceptionDomains']:
insecure_connections.append(key)
if 'NSAllowsArbitraryLoads' in ns_app_trans_dic:
if ns_app_trans_dic['NSAllowsArbitraryLoads'] is True:
insecure_connections.append(p_list['NSAppTransportSecurity'])
return insecure_connections
def plist_analysis(src, is_source):
"""Plist Analysis."""
try:
@@ -168,15 +47,14 @@ def plist_analysis(src, is_source):
'build_version_name': '',
'bundle_url_types': [],
'bundle_supported_platforms': [],
'bundle_localizations': [],
}
plist_file = None
if is_source:
logger.info('Finding Info.plist in iOS Source')
app_plist_file = 'Info.plist'
for dirpath, _dirnames, files in os.walk(src):
for name in files:
if '__MACOSX' not in dirpath and name == app_plist_file:
if (not any(x in dirpath for x in ['__MACOSX', 'Pods'])
and name == 'Info.plist'):
plist_file = os.path.join(dirpath, name)
break
else:
@@ -197,27 +75,17 @@ def plist_analysis(src, is_source):
plist_obj = plistlib.readPlist(plist_file)
plist_info['plist_xml'] = plistlib.writePlistToBytes(
plist_obj).decode('utf-8', 'ignore')
if 'CFBundleDisplayName' in plist_obj:
plist_info['bin_name'] = plist_obj['CFBundleDisplayName']
else:
if not is_source:
# For iOS IPA
plist_info['bin_name'] = dot_app_dir.replace('.app', '')
if 'CFBundleExecutable' in plist_obj:
plist_info['bin'] = plist_obj['CFBundleExecutable']
if 'CFBundleIdentifier' in plist_obj:
plist_info['id'] = plist_obj['CFBundleIdentifier']
# build
if 'CFBundleVersion' in plist_obj:
plist_info['build'] = plist_obj['CFBundleVersion']
if 'DTSDKName' in plist_obj:
plist_info['sdk'] = plist_obj['DTSDKName']
if 'DTPlatformVersion' in plist_obj:
plist_info['pltfm'] = plist_obj['DTPlatformVersion']
if 'MinimumOSVersion' in plist_obj:
plist_info['min'] = plist_obj['MinimumOSVersion']
plist_info['bin_name'] = (plist_obj.get('CFBundleDisplayName', '')
or plist_obj.get('CFBundleName', ''))
if not plist_info['bin_name'] and not is_source:
# For iOS IPA
plist_info['bin_name'] = dot_app_dir.replace('.app', '')
plist_info['bin'] = plist_obj.get('CFBundleExecutable', '')
plist_info['id'] = plist_obj.get('CFBundleIdentifier', '')
plist_info['build'] = plist_obj.get('CFBundleVersion', '')
plist_info['sdk'] = plist_obj.get('DTSDKName', '')
plist_info['pltfm'] = plist_obj.get('DTPlatformVersion', '')
plist_info['min'] = plist_obj.get('MinimumOSVersion', '')
plist_info['bundle_name'] = plist_obj.get('CFBundleName', '')
plist_info['bundle_version_name'] = plist_obj.get(
'CFBundleShortVersionString', '')
@@ -225,12 +93,10 @@ def plist_analysis(src, is_source):
'CFBundleURLTypes', [])
plist_info['bundle_supported_platforms'] = plist_obj.get(
'CFBundleSupportedPlatforms', [])
plist_info['bundle_localizations'] = plist_obj.get(
'CFBundleLocalizations', [])
# Check possible app-permissions
# Check for app-permissions
plist_info['permissions'] = check_permissions(plist_obj)
plist_info['inseccon'] = check_insecure_connections(plist_obj)
# Check for ats misconfigurations
plist_info['inseccon'] = check_transport_security(plist_obj)
return plist_info
except Exception:
logger.exception('Reading from Info.plist')
+43 -20
View File
@@ -11,14 +11,14 @@ from django.shortcuts import render
from MobSF.utils import print_n_send_error_response
from StaticAnalyzer.models import StaticAnalyzerIOSZIP, StaticAnalyzerIPA
from StaticAnalyzer.models import StaticAnalyzerIOS
from StaticAnalyzer.views.ios.appstore import app_search
from StaticAnalyzer.views.ios.binary_analysis import binary_analysis
from StaticAnalyzer.views.ios.code_analysis import ios_source_analysis
from StaticAnalyzer.views.ios.db_interaction import (
create_db_entry_ios, create_db_entry_ipa, get_context_from_analysis_ios,
get_context_from_analysis_ipa, get_context_from_db_entry_ios,
get_context_from_db_entry_ipa, update_db_entry_ios, update_db_entry_ipa)
get_context_from_analysis,
get_context_from_db_entry,
save_or_update)
from StaticAnalyzer.views.ios.file_analysis import ios_list_files
from StaticAnalyzer.views.ios.plist_analysis import plist_analysis
from StaticAnalyzer.views.shared_func import (file_size, firebase_analysis,
@@ -62,10 +62,10 @@ def static_analyzer_ios(request, api=False):
app_dict['directory'], 'StaticAnalyzer/tools/mac/')
if file_type == 'ipa':
# DB
ipa_db = StaticAnalyzerIPA.objects.filter(
ipa_db = StaticAnalyzerIOS.objects.filter(
MD5=app_dict['md5_hash'])
if ipa_db.exists() and rescan == '0':
context = get_context_from_db_entry_ipa(ipa_db)
context = get_context_from_db_entry(ipa_db)
else:
logger.info('iOS Binary (IPA) Analysis Started')
app_dict['app_file'] = app_dict[
@@ -92,51 +92,63 @@ def static_analyzer_ios(request, api=False):
tools_dir,
app_dict['app_dir'],
infoplist_dict.get('bin'))
fake_code_dict = {
'api': {},
'code_anal': {},
'urlnfile': [],
'domains': {},
'emailnfile': [],
'firebase': [],
}
# Saving to DB
logger.info('Connecting to DB')
if rescan == '1':
logger.info('Updating Database...')
update_db_entry_ipa(
save_or_update(
'update',
app_dict,
infoplist_dict,
fake_code_dict,
bin_analysis_dict,
files,
sfiles)
update_scan_timestamp(app_dict['md5_hash'])
elif rescan == '0':
logger.info('Saving to Database')
create_db_entry_ipa(
save_or_update(
'save',
app_dict,
infoplist_dict,
fake_code_dict,
bin_analysis_dict,
files,
sfiles)
context = get_context_from_analysis_ipa(
context = get_context_from_analysis(
app_dict,
infoplist_dict,
fake_code_dict,
bin_analysis_dict,
files,
sfiles)
context['VT_RESULT'] = None
context['virus_total'] = None
if settings.VT_ENABLED:
vt = VirusTotal.VirusTotal()
context['VT_RESULT'] = vt.get_result(
context['virus_total'] = vt.get_result(
os.path.join(app_dict['app_dir'], app_dict[
'md5_hash']) + '.ipa',
app_dict['md5_hash'])
context['version'] = settings.MOBSF_VER
context['average_cvss'], context[
'security_score'] = score(context['bin_anal'])
'security_score'] = score(context['binary_analysis'])
template = 'static_analysis/ios_binary_analysis.html'
if api:
return context
else:
return render(request, template, context)
elif file_type == 'ios':
ios_zip_db = StaticAnalyzerIOSZIP.objects.filter(
ios_zip_db = StaticAnalyzerIOS.objects.filter(
MD5=app_dict['md5_hash'])
if ios_zip_db.exists() and rescan == '0':
context = get_context_from_db_entry_ios(ios_zip_db)
context = get_context_from_db_entry(ios_zip_db)
else:
logger.info('iOS Source Code Analysis Started')
app_dict['app_file'] = app_dict[
@@ -161,34 +173,45 @@ def static_analyzer_ios(request, api=False):
# Firebase DB Check
code_analysis_dic['firebase'] = firebase_analysis(
list(set(code_analysis_dic['urls_list'])))
fake_bin_dict = {
'bin_type': '',
'macho': {},
'bin_res': [],
'libs': [],
'strings': [],
}
# Saving to DB
logger.info('Connecting to DB')
if rescan == '1':
logger.info('Updating Database...')
update_db_entry_ios(
save_or_update(
'update',
app_dict,
infoplist_dict,
code_analysis_dic,
fake_bin_dict,
files,
sfiles)
update_scan_timestamp(app_dict['md5_hash'])
elif rescan == '0':
logger.info('Saving to Database')
create_db_entry_ios(
save_or_update(
'save',
app_dict,
infoplist_dict,
code_analysis_dic,
fake_bin_dict,
files,
sfiles)
context = get_context_from_analysis_ios(
context = get_context_from_analysis(
app_dict,
infoplist_dict,
code_analysis_dic,
fake_bin_dict,
files,
sfiles)
context['version'] = settings.MOBSF_VER
context['average_cvss'], context[
'security_score'] = score(context['insecure'])
'security_score'] = score(context['code_analysis'])
template = 'static_analysis/ios_source_analysis.html'
if api:
return context
+21 -46
View File
@@ -27,17 +27,19 @@ from django.utils.html import escape
from MobSF import settings
from MobSF.utils import (print_n_send_error_response,
python_list,
upstream_proxy)
from StaticAnalyzer.models import (RecentScansDB, StaticAnalyzerAndroid,
StaticAnalyzerIOSZIP, StaticAnalyzerIPA,
from StaticAnalyzer.models import (RecentScansDB,
StaticAnalyzerAndroid,
StaticAnalyzerIOS,
StaticAnalyzerWindows)
from StaticAnalyzer.views.android.db_interaction import (
get_context_from_db_entry)
from StaticAnalyzer.views.comparer import generic_compare
from StaticAnalyzer.views.android.db_interaction import (
get_context_from_db_entry as adb)
from StaticAnalyzer.views.ios.db_interaction import (
get_context_from_db_entry_ios, get_context_from_db_entry_ipa)
get_context_from_db_entry as idb)
from StaticAnalyzer.views.windows.db_interaction import (
get_context_from_db_entry as wdb)
logger = logging.getLogger(__name__)
try:
@@ -122,9 +124,9 @@ def pdf(request, api=False, jsonres=False):
logger.info(
'Fetching data from DB for '
'PDF Report Generation (Android)')
context = get_context_from_db_entry(static_db)
context = adb(static_db)
context['average_cvss'], context[
'security_score'] = score(context['findings'])
'security_score'] = score(context['code_analysis'])
if scan_type.lower() == 'apk':
template = get_template(
'pdf/android_binary_analysis.pdf.html')
@@ -141,14 +143,15 @@ def pdf(request, api=False, jsonres=False):
status=500)
elif scan_type.lower() in ['ipa', 'ioszip']:
if scan_type.lower() == 'ipa':
static_db = StaticAnalyzerIPA.objects.filter(MD5=checksum)
static_db = StaticAnalyzerIOS.objects.filter(MD5=checksum)
if static_db.exists():
logger.info(
'Fetching data from DB for '
'PDF Report Generation (IOS IPA)')
context = get_context_from_db_entry_ipa(static_db)
context = idb(static_db)
context['average_cvss'], context[
'security_score'] = score(context['bin_anal'])
'security_score'] = score(
context['binary_analysis'])
template = get_template(
'pdf/ios_binary_analysis_pdf.html')
else:
@@ -160,15 +163,15 @@ def pdf(request, api=False, jsonres=False):
content_type='application/json; charset=utf-8',
status=500)
elif scan_type.lower() == 'ioszip':
static_db = StaticAnalyzerIOSZIP.objects.filter(
static_db = StaticAnalyzerIOS.objects.filter(
MD5=checksum)
if static_db.exists():
logger.info(
'Fetching data from DB for '
'PDF Report Generation (IOS ZIP)')
context = get_context_from_db_entry_ios(static_db)
context = idb(static_db)
context['average_cvss'], context[
'security_score'] = score(context['insecure'])
'security_score'] = score(context['code_analysis'])
template = get_template(
'pdf/ios_source_analysis_pdf.html')
else:
@@ -188,35 +191,7 @@ def pdf(request, api=False, jsonres=False):
logger.info(
'Fetching data from DB for '
'PDF Report Generation (APPX)')
context = {
'title': db_entry[0].TITLE,
'name': db_entry[0].APP_NAME,
'pub_name': db_entry[0].PUB_NAME,
'size': db_entry[0].SIZE,
'md5': db_entry[0].MD5,
'sha1': db_entry[0].SHA1,
'sha256': db_entry[0].SHA256,
'bin_name': db_entry[0].BINNAME,
'app_version': db_entry[0].VERSION,
'arch': db_entry[0].ARCH,
'compiler_version': db_entry[0].COMPILER_VERSION,
'visual_studio_version':
db_entry[0].VISUAL_STUDIO_VERSION,
'visual_studio_edition':
db_entry[0].VISUAL_STUDIO_EDITION,
'target_os': db_entry[0].TARGET_OS,
'appx_dll_version': db_entry[0].APPX_DLL_VERSION,
'proj_guid': db_entry[0].PROJ_GUID,
'opti_tool': db_entry[0].OPTI_TOOL,
'target_run': db_entry[0].TARGET_RUN,
'files': python_list(db_entry[0].FILES),
'strings': python_list(db_entry[0].STRINGS),
'bin_an_results':
python_list(db_entry[0].BIN_AN_RESULTS),
'bin_an_warnings':
python_list(db_entry[0].BIN_AN_WARNINGS),
}
context = wdb(db_entry)
template = get_template(
'pdf/windows_binary_analysis_pdf.html')
else:
@@ -228,14 +203,14 @@ def pdf(request, api=False, jsonres=False):
content_type='application/json; charset=utf-8',
status=500)
context['VT_RESULT'] = None
context['virus_total'] = None
if settings.VT_ENABLED:
app_dir = os.path.join(settings.UPLD_DIR, checksum + '/')
vt = VirusTotal.VirusTotal()
if 'zip' in scan_type.lower():
context['VT_RESULT'] = None
context['virus_total'] = None
else:
context['VT_RESULT'] = vt.get_result(
context['virus_total'] = vt.get_result(
os.path.join(app_dir, checksum)
+ '.' + scan_type.lower(),
checksum)
@@ -0,0 +1,117 @@
"""Module holding the functions for the db."""
import logging
from django.conf import settings
from MobSF.utils import python_list
from StaticAnalyzer.models import StaticAnalyzerWindows
logger = logging.getLogger(__name__)
def get_context_from_db_entry(db_entry):
"""Return the context for APPX from DB."""
try:
logger.info('Analysis is already Done. Fetching data from the DB...')
context = {
'title': 'Static Analysis',
'version': settings.MOBSF_VER,
'file_name': db_entry[0].FILE_NAME,
'app_name': db_entry[0].APP_NAME,
'publisher_name': db_entry[0].PUBLISHER_NAME,
'size': db_entry[0].SIZE,
'md5': db_entry[0].MD5,
'sha1': db_entry[0].SHA1,
'sha256': db_entry[0].SHA256,
'app_version': db_entry[0].APP_VERSION,
'architecture': db_entry[0].ARCHITECTURE,
'compiler_version': db_entry[0].COMPILER_VERSION,
'visual_studio_version': db_entry[0].VISUAL_STUDIO_VERSION,
'visual_studio_edition': db_entry[0].VISUAL_STUDIO_EDITION,
'target_os': db_entry[0].TARGET_OS,
'appx_dll_version': db_entry[0].APPX_DLL_VERSION,
'proj_guid': db_entry[0].PROJ_GUID,
'opti_tool': db_entry[0].OPTI_TOOL,
'target_run': db_entry[0].TARGET_RUN,
'files': python_list(db_entry[0].FILES),
'strings': python_list(db_entry[0].STRINGS),
'binary_analysis': python_list(db_entry[0].BINARY_ANALYSIS),
'binary_warnings': python_list(db_entry[0].BINARY_WARNINGS),
}
return context
except Exception:
logger.exception('Fetching from DB')
def get_context_from_analysis(app_dic,
xml_dic,
bin_an_dic):
"""Get the context for APPX from analysis results."""
try:
context = {
'title': 'Static Analysis',
'version': settings.MOBSF_VER,
'file_name': app_dic['app_name'],
'app_name': bin_an_dic['bin_name'],
'publisher_name': xml_dic['pub_name'],
'size': app_dic['size'],
'md5': app_dic['md5'],
'sha1': app_dic['sha1'],
'sha256': app_dic['sha256'],
'app_version': xml_dic['version'],
'architecture': xml_dic['arch'],
'compiler_version': xml_dic['compiler_version'],
'visual_studio_version': xml_dic['visual_studio_version'],
'visual_studio_edition': xml_dic['visual_studio_edition'],
'target_os': xml_dic['target_os'],
'appx_dll_version': xml_dic['appx_dll_version'],
'proj_guid': xml_dic['proj_guid'],
'opti_tool': xml_dic['opti_tool'],
'target_run': xml_dic['target_run'],
'files': app_dic['files'],
'strings': bin_an_dic['strings'],
'binary_analysis': bin_an_dic['results'],
'binary_warnings': bin_an_dic['warnings'],
}
return context
except Exception:
logger.exception('Rendering to Template')
def save_or_update(update_type,
app_dic,
xml_dic,
bin_an_dic) -> None:
"""Save/Update an APPX DB entry."""
try:
values = {
'FILE_NAME': app_dic['app_name'],
'APP_NAME': bin_an_dic['bin_name'],
'PUBLISHER_NAME': xml_dic['pub_name'],
'SIZE': app_dic['size'],
'MD5': app_dic['md5'],
'SHA1': app_dic['sha1'],
'SHA256': app_dic['sha256'],
'APP_VERSION': xml_dic['version'],
'ARCHITECTURE': xml_dic['arch'],
'COMPILER_VERSION': xml_dic['compiler_version'],
'VISUAL_STUDIO_VERSION': xml_dic['visual_studio_version'],
'VISUAL_STUDIO_EDITION': xml_dic['visual_studio_edition'],
'TARGET_OS': xml_dic['target_os'],
'APPX_DLL_VERSION': xml_dic['appx_dll_version'],
'PROJ_GUID': xml_dic['proj_guid'],
'OPTI_TOOL': xml_dic['opti_tool'],
'TARGET_RUN': xml_dic['target_run'],
'FILES': app_dic['files'],
'STRINGS': bin_an_dic['strings'],
'BINARY_ANALYSIS': bin_an_dic['results'],
'BINARY_WARNINGS': bin_an_dic['warnings'],
}
if update_type == 'save':
StaticAnalyzerWindows.objects.create(**values)
else:
StaticAnalyzerWindows.objects.filter(
MD5=app_dic['md5']).update(**values)
except Exception:
logger.exception('Updating DB')
@@ -21,12 +21,19 @@ from django.conf import settings
from django.shortcuts import render
from django.utils.html import escape
from MobSF.utils import print_n_send_error_response, python_list
from MobSF.utils import print_n_send_error_response
from StaticAnalyzer.models import StaticAnalyzerWindows
from StaticAnalyzer.tools.strings import strings_util
from StaticAnalyzer.views.shared_func import (file_size, hash_gen, unzip,
update_scan_timestamp)
from StaticAnalyzer.views.shared_func import (
file_size,
hash_gen,
unzip,
update_scan_timestamp)
from StaticAnalyzer.views.windows.db_interaction import (
get_context_from_analysis,
get_context_from_db_entry,
save_or_update)
logger = logging.getLogger(__name__)
@@ -74,35 +81,7 @@ def staticanalyzer_windows(request, api=False):
logger.info(
'Analysis is already Done.'
' Fetching data from the DB...')
context = {
'title': db_entry[0].TITLE,
'name': db_entry[0].APP_NAME,
'pub_name': db_entry[0].PUB_NAME,
'size': db_entry[0].SIZE,
'md5': db_entry[0].MD5,
'sha1': db_entry[0].SHA1,
'sha256': db_entry[0].SHA256,
'bin_name': db_entry[0].BINNAME,
'app_version': db_entry[0].VERSION,
'arch': db_entry[0].ARCH,
'compiler_version': db_entry[0].COMPILER_VERSION,
'visual_studio_version':
db_entry[0].VISUAL_STUDIO_VERSION,
'visual_studio_edition':
db_entry[0].VISUAL_STUDIO_EDITION,
'target_os': db_entry[0].TARGET_OS,
'appx_dll_version': db_entry[0].APPX_DLL_VERSION,
'proj_guid': db_entry[0].PROJ_GUID,
'opti_tool': db_entry[0].OPTI_TOOL,
'target_run': db_entry[0].TARGET_RUN,
'files': python_list(db_entry[0].FILES),
'strings': python_list(db_entry[0].STRINGS),
'bin_an_results':
python_list(db_entry[0].BIN_AN_RESULTS),
'bin_an_warnings':
python_list(db_entry[0].BIN_AN_WARNINGS),
'version': settings.MOBSF_VER,
}
context = get_context_from_db_entry(db_entry)
else:
logger.info('Windows Binary Analysis Started')
app_dic['app_path'] = os.path.join(
@@ -123,91 +102,20 @@ def staticanalyzer_windows(request, api=False):
logger.info('Connecting to DB')
if rescan == '1':
logger.info('Updating Database...')
StaticAnalyzerWindows.objects.filter(
MD5=app_dic['md5'],
).update(
TITLE='Static Analysis',
APP_NAME=app_dic['app_name'],
PUB_NAME=xml_dic['pub_name'],
SIZE=app_dic['size'],
MD5=app_dic['md5'],
SHA1=app_dic['sha1'],
SHA256=app_dic['sha256'],
BINNAME=bin_an_dic['bin_name'],
VERSION=xml_dic['version'],
ARCH=xml_dic['arch'],
COMPILER_VERSION=xml_dic['compiler_version'],
VISUAL_STUDIO_VERSION=xml_dic[
'visual_studio_version'],
VISUAL_STUDIO_EDITION=xml_dic[
'visual_studio_edition'],
TARGET_OS=xml_dic['target_os'],
APPX_DLL_VERSION=xml_dic['appx_dll_version'],
PROJ_GUID=xml_dic['proj_guid'],
OPTI_TOOL=xml_dic['opti_tool'],
TARGET_RUN=xml_dic['target_run'],
FILES=app_dic['files'],
STRINGS=bin_an_dic['strings'],
BIN_AN_RESULTS=bin_an_dic['results'],
BIN_AN_WARNINGS=bin_an_dic['warnings'],
)
save_or_update('update',
app_dic,
xml_dic,
bin_an_dic)
update_scan_timestamp(app_dic['md5'])
elif rescan == '0':
logger.info('Saving to Database')
db_item = StaticAnalyzerWindows(
TITLE='Static Analysis',
APP_NAME=app_dic['app_name'],
PUB_NAME=xml_dic['pub_name'],
SIZE=app_dic['size'],
MD5=app_dic['md5'],
SHA1=app_dic['sha1'],
SHA256=app_dic['sha256'],
BINNAME=bin_an_dic['bin_name'],
VERSION=xml_dic['version'],
ARCH=xml_dic['arch'],
COMPILER_VERSION=xml_dic['compiler_version'],
VISUAL_STUDIO_VERSION=xml_dic[
'visual_studio_version'],
VISUAL_STUDIO_EDITION=xml_dic[
'visual_studio_edition'],
TARGET_OS=xml_dic['target_os'],
APPX_DLL_VERSION=xml_dic['appx_dll_version'],
PROJ_GUID=xml_dic['proj_guid'],
OPTI_TOOL=xml_dic['opti_tool'],
TARGET_RUN=xml_dic['target_run'],
FILES=app_dic['files'],
STRINGS=bin_an_dic['strings'],
BIN_AN_RESULTS=bin_an_dic['results'],
BIN_AN_WARNINGS=bin_an_dic['warnings'],
)
db_item.save()
context = {
'title': 'Static Analysis',
'name': app_dic['app_name'],
'pub_name': xml_dic['pub_name'],
'size': app_dic['size'],
'md5': app_dic['md5'],
'sha1': app_dic['sha1'],
'sha256': app_dic['sha256'],
'bin_name': bin_an_dic['bin_name'],
'app_version': xml_dic['version'],
'arch': xml_dic['arch'],
'compiler_version': xml_dic['compiler_version'],
'visual_studio_version':
xml_dic['visual_studio_version'],
'visual_studio_edition':
xml_dic['visual_studio_edition'],
'target_os': xml_dic['target_os'],
'appx_dll_version': xml_dic['appx_dll_version'],
'proj_guid': xml_dic['proj_guid'],
'opti_tool': xml_dic['opti_tool'],
'target_run': xml_dic['target_run'],
'files': app_dic['files'],
'strings': bin_an_dic['strings'],
'bin_an_results': bin_an_dic['results'],
'bin_an_warnings': bin_an_dic['warnings'],
'version': settings.MOBSF_VER,
}
save_or_update('save',
app_dic,
xml_dic,
bin_an_dic)
context = get_context_from_analysis(app_dic,
xml_dic,
bin_an_dic)
template = 'static_analysis/windows_binary_analysis.html'
if api:
return context
+56
View File
@@ -211,7 +211,63 @@ div#textnode {
vertical-align: middle;
transition: font-size 175ms;
}
/* TOP NAV */
/* Add a black background color to the top navigation */
.topnav {
overflow: hidden;
background-color: #312f2f;
position: fixed;
top: 0;
width: 100%;
}
/* Style the links inside the navigation bar */
.topnav a {
float: left;
color: #a7a6a6;
text-align: center;
padding: 14px 16px;
text-decoration: none;
font-size: 20px;
}
/* Change the color of links on hover */
.topnav a:hover {
color: #fff;
}
/* Centered section inside the top navigation */
.topnav-centered a {
float: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.topnav-centered a:hover {
background-color: #312f2f;
}
/* Right-aligned section inside the top navigation */
.topnav-right {
float: right;
}
/* Responsive navigation menu - display links on top of each other instead of next to each other (for mobile devices) */
@media screen and (max-width: 600px) {
.topnav a, .topnav-right {
float: none;
display: block;
}
.topnav-centered a {
position: relative;
top: 0;
left: 0;
transform: none;
}
}
/* PROGRESS BAR */
progress {
+5 -5
View File
@@ -38,11 +38,11 @@
</ul>
<!-- Right navbar links -->
<ul class="navbar-nav ml-auto">
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'recent' %}" class="nav-link">Recent Scans</a></li>
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'home' %}" class="nav-link">Static Analysis</a></li>
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'dynamic' %}" class="nav-link">Dynamic Analysis</a></li>
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'api_docs' %}" class="nav-link">API Docs</a></li>
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'about' %}" class="nav-link">About</a></li>
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'recent' %}" class="nav-link">RECENT SCANS</a></li>
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'home' %}" class="nav-link">STATIC ANALYZER</a></li>
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'dynamic' %}" class="nav-link">DYNAMIC ANALYZER</a></li>
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'api_docs' %}" class="nav-link">API DOCS</a></li>
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'about' %}" class="nav-link">ABOUT</a></li>
</ul>
<!-- SEARCH FORM -->
@@ -295,21 +295,20 @@ div.loading{
{% if apks %}
{% for e in apks %}
<tr>
<td>
<img id="app_icon" src="{% if e.ICON_FOUND %}/download/{{ e.MD5 }}-icon.png{% else %}{% static 'img/no_icon.png' %}{% endif %}"/><br/><strong>{{ e.REAL_NAME }}</strong>
<td align="center">
<img id="app_icon" src="{% if e.ICON_FOUND %}/download/{{ e.MD5 }}-icon.png{% else %}{% static 'img/no_icon.png' %}{% endif %}"/>
<br/><strong>{{ e.APP_NAME }}</strong>
</td>
<td>
{{ e.APP_NAME }}<br/><br/>Hash: {{e.MD5}}
{{ e.FILE_NAME }}
</td>
<td>
{{ e.PACKAGENAME }}
{{ e.PACKAGE_NAME }}
</td>
<td>
<p align="center">
<a class="btn btn-success" onclick="dynamic_loader()" href="../android_dynamic/?hash={{e.MD5}}&amp;package={{e.PACKAGENAME}}"><i class="fab fa-android"></i> Start Dynamic Analysis</a>
<td align="center">
<a class="btn btn-success" onclick="dynamic_loader()" href="../android_dynamic/?hash={{e.MD5}}&amp;package={{e.PACKAGE_NAME}}"><i class="fab fa-android"></i> Start Dynamic Analysis</a>
<br/> <br/>
<a class="btn btn-info" href="../dynamic_report/?hash={{ e.MD5 }}&amp;package={{ e.PACKAGENAME }}"><i class="fa fa-mobile"></i> View Report </a>
</p>
<a class="btn btn-info" href="../dynamic_report/?hash={{ e.MD5 }}&amp;package={{ e.PACKAGE_NAME }}"><i class="fa fa-mobile"></i> View Report </a>
</td>
</tr>
{% endfor %}
+9 -9
View File
@@ -95,7 +95,7 @@ pre {
</li>
<li>
<p><strong>Sample Call:</strong></p>
<pre><code>curl -F 'file=@/Users/ajin/Desktop/diva-beta.apk' http://localhost:8000/api/v1/upload -H &quot;Authorization:563d64fc5054d3b239ac0419f1d6b2378465f5c80e1778c283eb1e3265bdd7ae&quot;
<pre><code>curl -F 'file=@/Users/ajin/Desktop/diva-beta.apk' http://localhost:8000/api/v1/upload -H &quot;Authorization:{{ api_key}}&quot;
</code></pre>
</li>
</ul>
@@ -182,7 +182,7 @@ pre {
</li>
<li>
<p><strong>Sample Call:</strong></p>
<pre><code>curl -X POST --url http://localhost:8000/api/v1/scan --data &quot;scan_type=apk&amp;file_name=diva-beta.apk&amp;hash=82ab8b2193b3cfb1c737e3a786be363a&quot; -H &quot;Authorization:563d64fc5054d3b239ac0419f1d6b2378465f5c80e1778c283eb1e3265bdd7ae&quot;
<pre><code>curl -X POST --url http://localhost:8000/api/v1/scan --data &quot;scan_type=apk&amp;file_name=diva-beta.apk&amp;hash=82ab8b2193b3cfb1c737e3a786be363a&quot; -H &quot;Authorization:{{ api_key}}&quot;
</code></pre>
</li>
</ul>
@@ -245,7 +245,7 @@ pre {
</li>
<li>
<p><strong>Sample Call:</strong></p>
<pre><code>curl -X POST --url http://localhost:8000/api/v1/delete_scan --data &quot;hash=82ab8b2193b3cfb1c737e3a786be363a&quot; -H &quot;Authorization:563d64fc5054d3b239ac0419f1d6b2378465f5c80e1778c283eb1e3265bdd7ae&quot;
<pre><code>curl -X POST --url http://localhost:8000/api/v1/delete_scan --data &quot;hash=82ab8b2193b3cfb1c737e3a786be363a&quot; -H &quot;Authorization:{{ api_key}}&quot;
</code></pre>
</li>
</ul>
@@ -313,7 +313,7 @@ pre {
</li>
<li>
<p><strong>Sample Call:</strong></p>
<pre><code>curl -X POST --url http://localhost:8000/api/v1/download_pdf --data &quot;hash=82ab8b2193b3cfb1c737e3a786be363a&amp;scan_type=apk&quot; -H &quot;Authorization:563d64fc5054d3b239ac0419f1d6b2378465f5c80e1778c283eb1e3265bdd7ae&quot;
<pre><code>curl -X POST --url http://localhost:8000/api/v1/download_pdf --data &quot;hash=82ab8b2193b3cfb1c737e3a786be363a&amp;scan_type=apk&quot; -H &quot;Authorization:{{ api_key}}&quot;
</code></pre>
</li>
</ul>
@@ -382,7 +382,7 @@ pre {
</li>
<li>
<p><strong>Sample Call:</strong></p>
<pre><code>curl -X POST --url http://localhost:8000/api/v1/report_json --data &quot;hash=82ab8b2193b3cfb1c737e3a786be363a&amp;scan_type=apk&quot; -H &quot;Authorization:563d64fc5054d3b239ac0419f1d6b2378465f5c80e1778c283eb1e3265bdd7ae&quot;
<pre><code>curl -X POST --url http://localhost:8000/api/v1/report_json --data &quot;hash=82ab8b2193b3cfb1c737e3a786be363a&amp;scan_type=apk&quot; -H &quot;Authorization:{{ api_key}}&quot;
</code></pre>
</li>
</ul>
@@ -456,9 +456,9 @@ pre {
</li>
<li>
<p><strong>Sample Call:</strong></p>
<pre><code>curl -X POST --url http://localhost:8000/api/v1/view_source --data "hash=18e244926da1e49c5b8ffc1c30de8abc&amp;type=apk&amp;file=b/a/a/a/a/a.java" -H "Authorization:7e2ddf418b291d2e070496524d1b8599c31637f84055c5db632f49f1a613f5f5"
<pre><code>curl -X POST --url http://localhost:8000/api/v1/view_source --data "hash=18e244926da1e49c5b8ffc1c30de8abc&amp;type=apk&amp;file=b/a/a/a/a/a.java" -H "Authorization:{{ api_key}}"
</code></pre>
<pre><code>curl -X POST --url http://localhost:8000/api/v1/view_source --data "hash=6c23c2970551be15f32bbab0b5db0c71&amp;type=ipa&amp;file=classdump.txt" -H "Authorization:87e2ddf418b291d2e070496524d1b8599c31637f84055c5db632f49f1a613f5f5"
<pre><code>curl -X POST --url http://localhost:8000/api/v1/view_source --data "hash=6c23c2970551be15f32bbab0b5db0c71&amp;type=ipa&amp;file=classdump.txt" -H "Authorization:{{ api_key}}"
</code></pre>
</li>
</ul>
@@ -541,9 +541,9 @@ pre {
</li>
<li>
<p><strong>Sample Call:</strong></p>
<pre><code>curl --url "http://localhost:8000/api/v1/scans" -H "Authorization:87e2ddf418b291d2e070496524d1b8599c31637f84055c5db632f49f1a613f5f5"
<pre><code>curl --url "http://localhost:8000/api/v1/scans" -H "Authorization:{{ api_key}}"
</code></pre>
<pre><code>curl --url "http://localhost:8000/api/v1/scans?page=1&page_size=10" -H "Authorization:87e2ddf418b291d2e070496524d1b8599c31637f84055c5db632f49f1a613f5f5"
<pre><code>curl --url "http://localhost:8000/api/v1/scans?page=1&page_size=10" -H "Authorization:{{ api_key}}"
</code></pre>
</li>
</ul>
+21 -3
View File
@@ -7,7 +7,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="Mobile Security Framework (MobSF) is an automated, all-in-one mobile application (Android/iOS/Windows) pen-testing, malware analysis and security assessment framework capable of performing static and dynamic analysis.">
<meta name="author" content="Ajin Abraham">
<link rel="icon" href="{% static "favicon.ico" %}">
<link rel="icon" href="{% static "img/favicon.ico" %}">
<title>Mobile Security Framework - MobSF</title>
<link rel="stylesheet" href="{% static "adminlte/dashboard/css/adminlte.min.css" %}">
<link rel="stylesheet" href="{% static "adminlte/plugins/fontawesome-free/css/all.min.css" %}">
@@ -16,12 +16,30 @@
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700" rel="stylesheet">
</head>
<body>
<div class="topnav">
<!-- Centered link -->
<div class="topnav-centered">
<a>
<img src="{% static "img/mobsf_logo.png" %}" width="20%" height="20%"/>
</a>
</div>
<!-- Left-aligned links (default) -->
<a href="{% url 'recent' %}">RECENT SCANS</a>
<a href="{% url 'dynamic' %}">DYNAMIC ANALYZER</a>
<!-- Right-aligned links -->
<div class="topnav-right">
<a href="{% url 'api_docs' %}">API DOCS</a>
<a href="{% url 'about' %}">ABOUT</a>
</div>
</div>
<div class="site-wrapper">
<div class="site-wrapper-inner">
<div class="cover-container">
<div class="masthead clearfix">
<div align="center" class="inner">
<h3 class="masthead-brand"><img src="{% static "img/mobsf_logo.png" %}" width="45%" height="45%"></h3>
</div>
</div>
<div class="inner cover">
@@ -47,7 +65,7 @@
<input name="md5" type="text" class="form-control" placeholder="Search MD5">
</form>
<div class="inner">
<h5><strong> <a href="{% url 'recent' %}">RECENT SCANS</a> | <a href="{% url 'dynamic' %}">DYNAMIC ANALYSIS</a> | <a href="{% url 'api_docs' %}">API DOCS</a> | <a href="{% url 'about' %}">ABOUT</a></strong></h5>
<h6> <a href="{% url 'recent' %}">RECENT SCANS</a> | <a href="{% url 'dynamic' %}">DYNAMIC ANALYZER</a> | <a href="{% url 'api_docs' %}">API DOCS</a> | <a href="{% url 'about' %}">ABOUT</a></h6>
</br>
<p>&copy; {% now "Y" %} Mobile Security Framework - MobSF {{ version }}</p>
</div>
+60 -102
View File
@@ -6,7 +6,7 @@ body {
}
</style>
<h1 align="center" class="page-header">Static Analysis - {{name}} </h1>
<h1 align="center" class="page-header">Static Analysis - {{file_name}} </h1>
<hr>
<div class="col-lg-2">
<div class="panel panel-default">
@@ -21,9 +21,9 @@ body {
<p>
<span class="label label-primary"><b>App Security Score: </b>{{ security_score }}/100</span>
</p>
{% if VT_RESULT and VT_RESULT.total %}
{% if virus_total and virus_total.total %}
<p>
<span class="label label-primary"><b>VirusTotal Detection: </b>{{ VT_RESULT.positives }}/{{ VT_RESULT.total }}</span>
<span class="label label-primary"><b>VirusTotal Detection: </b>{{ virus_total.positives }}/{{ virus_total.total }}</span>
</p>
{% endif %}
{% if trackers %}
@@ -45,8 +45,8 @@ body {
<div class="panel-body">
<div class="list-group">
<p>
<span class="label label-primary"><b>Name: </b></span>
{{ name }}
<span class="label label-primary"><b>File Name: </b></span>
{{ file_name }}
</p>
<p>
<span class="label label-primary"><b>Size:</b></span>
@@ -76,32 +76,32 @@ body {
<div class="panel-body">
<div class="list-group">
<p>
<span class="label label-primary"><b>Name: </b></span>
{{ real_name }}
<span class="label label-primary"><b>App Name: </b></span>
{{ app_name }}
</p>
<p>
<span class="label label-primary"><b>Package Name: </b></span>
{{ packagename }}
{{ package_name }}
</p>
<p>
<span class="label label-primary"><b>Main Activity: </b></span>
{{ mainactivity }}
{{ main_activity }}
</p><p>
<span class="label label-primary"><b>Target SDK: </b></span>
{{ targetsdk }}
{{ target_sdk }}
</p><p>
<span class="label label-primary"><b>Min SDK: </b></span>
{{ minsdk }}
{{ min_sdk }}
</p><p>
<span class="label label-primary"><b>Max SDK: </b></span>
{{ maxsdk }}
{{ max_sdk }}
</p><p>
<span class="label label-primary"><b>Android Version Name: </b></span>
{{ androvername }}
{{ version_name }}
</p><p>
<span class="label label-primary"><b>Android Version Code: </b></span>
{{ androver }}
{{ version_code }}
</p>
</div>
@@ -118,50 +118,50 @@ body {
<div class="panel-body">
<div class="list-group">
{% if not play_details.error %}
{% if not playstore_details.error %}
<p>
<span class="label label-info"><b>Title: </b></span>
{{ play_details.title }}
{{ playstore_details.title }}
</p>
<p>
<span class="label label-info"><b>Score: </b></span>
{{ play_details.score}}
{{ playstore_details.score}}
<span class="label label-info"><b>Installs: </b></span>
{{ play_details.installs }}
{{ playstore_details.installs }}
<span class="label label-info"><b>Price: </b></span>
{{ play_details.price }}
{{ playstore_details.price }}
<span class="label label-info"><b>Android Version Support: </b></span>
{{ play_details.androidVersionText }}
{{ playstore_details.androidVersionText }}
<span class="label label-info"><b>Category: </b></span>
{{ play_details.genre }}
{{ playstore_details.genre }}
<span class="label label-info"><b>Play Store URL: </b></span>
<a target="_blank" href="{{ play_details.url }}"> {{ packagename }} </a>
<a target="_blank" href="{{ playstore_details.url }}"> {{ packagename }} </a>
</p>
<p>
<span class="label label-info"><b>Developer Details: </b></span>
{{play_details.developer}},
{{play_details.developerId}},
{{play_details.developerAddress }},
{{play_details.developerWebsite}},
{{play_details.developerEmail}},
{{playstore_details.developer}},
{{playstore_details.developerId}},
{{playstore_details.developerAddress }},
{{playstore_details.developerWebsite}},
{{playstore_details.developerEmail}},
</p>
<p>
<span class="label label-info"><b>Release Date: </b></span>
{{ play_details.released }}
{{ playstore_details.released }}
<span class="label label-info"><b>Privacy Policy: </b></span>
<a target="_blank" href="{{ play_details.privacyPolicy }}">Privacy link</a>
<a target="_blank" href="{{ playstore_details.privacyPolicy }}">Privacy link</a>
</p>
<p>
<span class="label label-info"><b>Description: </b></span>
<pre>{{ play_details.description }}</pre>
<pre>{{ playstore_details.description }}</pre>
</p>
{% endif %}
{% endif %}
</div>
</div>
@@ -174,29 +174,25 @@ body {
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i> <span class="glyphicon glyphicon-eye-close"></span> CERTIFICATE</h3><hr>
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i> <span class="glyphicon glyphicon-eye-close"></span> SIGNER CERTIFICATE</h3><hr>
</div>
<div class="panel-body">
<pre>
{{ certinfo | safe}}
{% if issued == "good" %}
<strong>Certificate Status: </strong><span class="label label-success">Good</span>
{% elif issued == "bad" %}
<strong>Certificate Status: </strong><span class="label label-danger">Bad</span>
<strong>Description:</strong>App Signed by 'Android Debug' Certificate.
Production ready applications should not be signed with 'Android Debug' Certificate.
{% elif issued == "missing" %}
<strong>Certificate Status: </strong><span class="label label-warning">Certificate not found</span>
{% elif issued == "bad hash" and sha256Digest is True %}
<strong>Certificate Status: </strong><span class="label label-warning">Warning</span>
<strong>Description:</strong>The app is signed with `SHA1withRSA`. SHA1 hash algorithm is known to have collision issues.
<strong>Note:</strong>The manifest indicates `SHA256withRSA` is in use. Be sure to manually confirm this issue.
{% elif issued == "bad hash" %}
<strong>Certificate Status: </strong><span class="label label-danger">Bad</span>
<strong>Description:</strong>The app is signed with `SHA1withRSA`. SHA1 hash algorithm is known to have collision issues.
{% endif %}
</pre>
<pre><code>{{ certificate_analysis.certificate_info }}</code></pre>
<!--Cert status-->
{% if certificate_analysis.certificate_status == "good" %}
<strong>Certificate Status: </strong><span class="badge bg-success">Good</span><br />
<strong>Description: </strong>{{ certificate_analysis.description }}<br />
{% elif certificate_analysis.certificate_status == "bad" %}
<strong>Certificate Status: </strong><span class="badge bg-danger">Bad</span><br />
<strong>Description:</strong>{{ certificate_analysis.description }}<br />
{% elif certificate_analysis.certificate_status == "missing" %}
<strong>Certificate Status: </strong><span class="badge bg-warning">Certificate missing</span><br />
<strong>Description:</strong>{{ certificate_analysis.description }}<br />
{% elif certificate_analysis.certificate_status == "warning" %}
<strong>Certificate Status: </strong><span class="badge bg-warning">Warning</span><br />
<strong>Description:</strong>{{ certificate_analysis.description }}<br />
{% endif %}
</div>
</div>
</div>
@@ -296,15 +292,15 @@ Production ready applications should not be signed with 'Android Debug' Certific
<hr>
<!-- ============================================================= -->
{% if VT_RESULT %}
{% if virus_total %}
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-bug"></i>VirusTotal Report</h3><hr>
</div>
<div class="panel-body">
<p> {{ VT_RESULT.positives }} / {{ VT_RESULT.total }}&nbsp; AVs found this file Malicious! </p>
{% if VT_RESULT.positives %}
<p> {{ virus_total.positives }} / {{ virus_total.total }}&nbsp; AVs found this file Malicious! </p>
{% if virus_total.positives %}
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
@@ -314,7 +310,7 @@ Production ready applications should not be signed with 'Android Debug' Certific
</tr>
</thead>
<tbody>
{% for av_name,av_result in VT_RESULT.scans.items %}
{% for av_name,av_result in virus_total.scans.items %}
{% if av_result.detected == True %}
<tr>
<td>
@@ -507,7 +503,7 @@ Production ready applications should not be signed with 'Android Debug' Certific
</tr>
</thead>
<tbody>
{% for item in manifest %}
{% for item in manifest_analysis %}
<tr>
<td>
{{item|key:"title" | safe}}
@@ -560,7 +556,7 @@ Production ready applications should not be signed with 'Android Debug' Certific
</tr>
</thead>
<tbody>
{% for issue, details in findings.items %}
{% for issue, details in code_analysis.items %}
<tr>
<td>
{{ issue }}
@@ -612,7 +608,7 @@ Production ready applications should not be signed with 'Android Debug' Certific
</tr>
</thead>
<tbody>
{% for desc, details in api.items %}
{% for desc, details in android_api.items %}
<tr>
<td>
{{ desc }}
@@ -681,7 +677,7 @@ Production ready applications should not be signed with 'Android Debug' Certific
<div class="panel-body">
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
{% if firebase %}
{% if firebase_urls %}
<thead>
<tr>
<th>URL</th>
@@ -692,7 +688,7 @@ Production ready applications should not be signed with 'Android Debug' Certific
<tbody>
{% for item in firebase %}
{% for item in firebase_urls %}
<tr>
<td>
{{ item.url }}
@@ -847,7 +843,7 @@ Production ready applications should not be signed with 'Android Debug' Certific
</div>
<div class="panel-body">
<div class="table-responsive">
{% if certz %}
{% if file_analysis %}
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
@@ -856,7 +852,7 @@ Production ready applications should not be signed with 'Android Debug' Certific
</tr>
</thead>
<tbody>
{% for item in certz %}
{% for item in file_analysis %}
<tr>
<td>
{{ item|key:"finding" }}
@@ -875,28 +871,7 @@ Production ready applications should not be signed with 'Android Debug' Certific
</div>
</div>
</div>
<hr><div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span> STRINGS</h3><hr>
</div>
<div class="panel-body">
<div class="list-group">
<p>
{% for val in strings %}
{{ val }}<br>
{% endfor %}
</p>
</div>
</div>
</div>
</div>
<hr>
<div class="col-lg-5">
<div class="panel panel-default">
@@ -985,23 +960,6 @@ Production ready applications should not be signed with 'Android Debug' Certific
</p>
</div>
</div>
</div>
</div><hr> <div class="col-lg-7">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="glyphicon glyphicon-folder-open"></span> FILES</h3><hr>
</div>
<div class="panel-body">
<div class="list-group">
<p>
{% for file in files %}
{{ file}} <br>
{% endfor %}
</p>
</div>
</div>
</div>
</div>
+39 -57
View File
@@ -6,7 +6,7 @@ body {
}
</style>
<h1 align="center" class="page-header">Static Analysis - {{name}} </h1>
<h1 align="center" class="page-header">Static Analysis - {{file_name}} </h1>
<hr>
<div class="col-lg-2">
<div class="panel panel-default">
@@ -36,8 +36,8 @@ body {
<div class="panel-body">
<div class="list-group">
<p>
<span class="label label-primary"><b>Name: </b></span>
{{ name }}
<span class="label label-primary"><b>File Name: </b></span>
{{ file_name }}
</p>
<p>
<span class="label label-primary"><b>Size: </b></span>
@@ -67,31 +67,31 @@ body {
<div class="panel-body">
<div class="list-group">
<p>
<span class="label label-primary">Name</span>
{{ real_name }}
<span class="label label-primary">App Name</span>
{{ app_name }}
</p>
<p>
<span class="label label-primary"><b>Package Name: </b></span>
{{ packagename }}
{{ package_name }}
</p>
<p>
<span class="label label-primary"><b>Main Activity: </b></span>
{{ mainactivity }}
{{ main_activity }}
</p><p>
<span class="label label-primary"><b>Target SDK: </b></span>
{{ targetsdk }}
{{ target_sdk }}
</p><p>
<span class="label label-primary"><b>Min SDK: </b></span>
{{ minsdk }}
{{ min_sdk }}
</p><p>
<span class="label label-primary"><b>Max SDK: </b></span>
{{ maxsdk }}
{{ max_sdk }}
</p><p>
<span class="label label-primary"><b>Android Version Name: </b></span>
{{ androvername }}
{{ version_name }}
</p><p>
<span class="label label-primary"><b>Android Version Code: </b></span>
{{ androver }}
{{ version_code }}
</p>
</div>
@@ -108,48 +108,47 @@ body {
<div class="panel-body">
<div class="list-group">
{% if not play_details.error %}
{% if not playstore_details.error %}
<p>
<span class="label label-info"><b>Title: </b></span>
{{ play_details.title }}
{{ playstore_details.title }}
</p>
<p>
<span class="label label-info"><b>Score: </b></span>
{{ play_details.score}}
{{ playstore_details.score}}
<span class="label label-info"><b>Installs: </b></span>
{{ play_details.installs }}
{{ playstore_details.installs }}
<span class="label label-info"><b>Price: </b></span>
{{ play_details.price }}
{{ playstore_details.price }}
<span class="label label-info"><b>Android Version Support: </b></span>
{{ play_details.required_android_version }}
{{ playstore_details.required_android_version }}
<span class="label label-info"><b>Category: </b></span>
{{ play_details.genre }
{{ playstore_details.genre }}
<span class="label label-info"><b>Play Store URL: </b></span>
<a target="_blank" href="{{ play_details.url }}"> {{ packagename }} </a>
<a target="_blank" href="{{ playstore_details.url }}"> {{ packagename }} </a>
</p>
<p>
<span class="label label-info"><b>Developer Details: </b></span>
{{play_details.developer}},
{{play_details.developerId}},
{{play_details.developerAddress }},
{{play_details.developerWebsite}},
{{play_details.developerEmail}},
{{playstore_details.developer}},
{{playstore_details.developerId}},
{{playstore_details.developerAddress }},
{{playstore_details.developerWebsite}},
{{playstore_details.developerEmail}},
</p>
<p>
<span class="label label-info"><b>Release Date: </b></<span>
{{ play_details.released }}
<span class="label label-info"><b>Release Date: </b> </<span>
{{ playstore_details.released }}
<span class="label label-info"><b>Privacy Policy: </b></span>
<a target="_blank" href="{{ play_details.privacyPolicy }}">Privacy link</a>
<a target="_blank" href="{{ playstore_details.privacyPolicy }}">Privacy link</a>
</p>
<p>
<span class="label label-info"><b>Description: </b></span>
<pre>{{ play_details.description }}</pre>
<pre>{{ playstore_details.description }}</pre>
</p>
{% endif %}
</div>
@@ -282,7 +281,7 @@ body {
</tr>
</thead>
<tbody>
{% for item in manifest %}
{% for item in manifest_analysis %}
<tr>
<td>
{{item|key:"title" | safe}}
@@ -332,7 +331,7 @@ body {
</tr>
</thead>
<tbody>
{% for issue, details in findings.items %}
{% for issue, details in code_analysis.items %}
<tr>
<td>
{{ issue }}
@@ -353,7 +352,7 @@ body {
<td><b>{{ details|key:"owasp" }}</b></td>
<td>
{% for path in details|key:"path" %}
<a href="../ViewSource/?file={{ path }}&md5={{ md5 }}&type={{zipped}}"> {{ path }}</a>
<a href="../ViewSource/?file={{ path }}&md5={{ md5 }}&type={{app_type}}"> {{ path }}</a>
</br>
{% endfor %}
</td>
@@ -384,14 +383,14 @@ body {
</tr>
</thead>
<tbody>
{% for desc, details in api.items %}
{% for desc, details in android_api.items %}
<tr>
<td>
{{ desc }}
</td>
<td>
{% for path in details|key:"path" %}
<a href="../ViewSource/?file={{ path }}&md5={{ md5 }}&type={{zipped}}"> {{ path }}</a>
<a href="../ViewSource/?file={{ path }}&md5={{ md5 }}&type={{app_type}}"> {{ path }}</a>
</br>
{% endfor %}
</td>
@@ -431,7 +430,7 @@ body {
</td>
<td>
<a href="../ViewSource/?file={{urldict|key:"path"}}&md5={{ md5}}&type={{zipped}}">{{urldict|key:"path"}}</a>
<a href="../ViewSource/?file={{urldict|key:"path"}}&md5={{ md5}}&type={{app_type}}">{{urldict|key:"path"}}</a>
</td>
</tr>
@@ -454,7 +453,7 @@ body {
<div class="panel-body">
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
{% if firebase %}
{% if firebase_urls %}
<thead>
<tr>
<th>URL</th>
@@ -465,7 +464,7 @@ body {
<tbody>
{% for item in firebase %}
{% for item in firebase_urls %}
<tr>
<td>
{{ item.url }}
@@ -589,7 +588,7 @@ body {
</tr>
</thead>
<tbody>
{% for item in certz %}
{% for item in file_analysis %}
<tr>
<td>
{{ item|key:"finding" }}
@@ -700,24 +699,7 @@ body {
</div>
</div>
</div>
<hr> <div class="col-lg-7">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="glyphicon glyphicon-folder-open"></span> FILES</h3><hr>
</div>
<div class="panel-body">
<div class="list-group">
<p>
{% for file in files %}
{{ file}} <br>
{% endfor %}
</p>
</div>
</div>
</div>
</div>
<hr><hr>
<h3 align="center"> Report Generated by - MobSF | http://opensecurity.in</h3>
+107 -92
View File
@@ -20,9 +20,9 @@ body {
<p>
<span class="label label-primary"><b>App Security Score: </b>{{ security_score }}/100</span>
</p>
{% if VT_RESULT and VT_RESULT.total %}
{% if virus_total and virus_total.total %}
<p>
<span class="label label-primary"><b>VirusTotal Detection: </b>{{ VT_RESULT.positives }}/{{ VT_RESULT.total }}</span>
<span class="label label-primary"><b>VirusTotal Detection: </b>{{ virus_total.positives }}/{{ virus_total.total }}</span>
</p>
{% endif %}
@@ -46,7 +46,7 @@ body {
</p>
<p>
<span class="label label-primary"><b>App Type:</b></span>
{{ bin_type }}
{{ app_type }}
</p>
<p>
<span class="label label-primary"><b>Size: </b></span>
@@ -95,26 +95,32 @@ body {
<div class="list-group">
<p>
<span class="label label-primary"><b>App Name: </b></span>
{{ bin_name }}
{{ app_name }}
</p>
<p>
<span class="label label-primary"><b>Identifier: </b></span>
{{ id }}</p>
{{ bundle_id }}</p>
<p>
<span class="label label-primary"><b>Version: </b></span>
{{ bundle_version }}
{{ app_version }}
</p>
<p>
<span class="label label-primary"><b>Build: </b></span>
{{ build }}
{{ build }}
</p>
<p>
<span class="label label-primary"><b>SDK Name: </b></span>
{{ sdk }}</p><p>
{{ sdk_name }}</p><p>
<span class="label label-primary"><b>Platform Version: </b></span>
{{ pltfm }}</p><p>
{{ platform }}</p><p>
<span class="label label-primary"><b>Min OS Version: </b></span>
{{ min }}
{{ min_os_version }}
</p>
<p>
<span class="badge bg-primary">Supported Platforms</span>
{% for pl in bundle_supported_platforms %}
{{pl}},
{% endfor %}
</p>
</div>
</div>
@@ -185,7 +191,53 @@ body {
</div>
</div>
<hr>
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="fa fa-mobile"></span> URL SCHEMES</h3><hr>
</div>
<div class="panel-body">
{% if bundle_url_types|length > 0 %}
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>URL NAME</th>
<th>SCHEMES</th>
</tr>
</thead>
<tbody>
{% for scheme in bundle_url_types %}
<tr>
<td>
{{scheme | key:"CFBundleURLName" }}
{% if scheme|key:"CFBundleTypeRole" %}
<br>
{{scheme | key:"CFBundleTypeRole" }}
{% endif %}
</td>
<td>
{% for ul in scheme.CFBundleURLSchemes %}
{{ul}} <br/>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p>
No URL Schemes found.
</p>
{% endif %}
</div>
</div>
</div>
<hr>
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
@@ -203,7 +255,7 @@ body {
</tr>
</thead>
<tbody>
{%for perm in permissions%}
{% for perm in permissions %}
<tr>
<td>
{{ perm.name }}
@@ -240,42 +292,43 @@ body {
<div class="panel-body">
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>ISSUE</th>
<th>STATUS</th>
<th>DESCRIPTION</th>
</tr>
</thead>
<tbody>
{% if insecure_connections|length > 0 %}
{%for con in insecure_connections%}
<tr>
<td>
Exception in NSAppTransportSecurity found.
<td>
Insecure
</td>
<td>
App Transport Security (ATS) is disabled on the domain '{{ con }}'. Disabling ATS can allow insecure communication with particular servers or allow insecure loads for web views or for media, while maintaining ATS protections elsewhere in your app.
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>
None
<td>
Secure
</td>
<td>
No insecure connections configured. App Transport Security (ATS) is enabled.
</td>
</tr>
{% endif %}
</tbody>
</table>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>ISSUE</th>
<th>STATUS</th>
<th>DESCRIPTION</th>
</tr>
</thead>
<tbody>
{% if ats_analysis|length > 0 %}
{% for findings in ats_analysis %}
<tr>
<td>
{{findings.issue}}
<td>
<span class="badge bg-danger"> {{findings.status}}</span>
</td>
<td>
{{findings.description}}
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>
No ATS exceptions found.
<td>
<span class="badge bg-success">secure</span>
</td>
<td>
No insecure connections configured. App Transport Security (ATS) is enabled.
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<!-- /.box-body -->
</div>
@@ -283,15 +336,15 @@ body {
</div><hr>
<!-- ============================================================= -->
{% if VT_RESULT %}
{% if virus_total %}
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-bug"></i>VirusTotal Report</h3><hr>
</div>
<div class="panel-body">
<p> {{ VT_RESULT.positives }} / {{ VT_RESULT.total }}&nbsp; AVs found this file Malicious! </p>
{% if VT_RESULT.positives %}
<p> {{ virus_total.positives }} / {{ virus_total.total }}&nbsp; AVs found this file Malicious! </p>
{% if virus_total.positives %}
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
@@ -301,7 +354,7 @@ body {
</tr>
</thead>
<tbody>
{% for av_name,av_result in VT_RESULT.scans.items %}
{% for av_name,av_result in virus_total.scans.items %}
{% if av_result.detected == True %}
<tr>
<td>
@@ -342,7 +395,7 @@ body {
</tr>
</thead>
<tbody>
{%for bin in bin_anal%}
{% for bin in binary_analysis %}
<tr>
<td>
{{ bin.issue }}
@@ -393,7 +446,7 @@ body {
</thead>
<tbody>
{%for item in file_analysis %}
{% for item in file_analysis %}
<tr>
<td>
{{ item.issue }}
@@ -423,7 +476,7 @@ body {
<div class="panel-body">
<div class="list-group">
<p>
{% for lib in libs %}
{% for lib in libraries %}
{{ lib }}
</br>
{% endfor %}
@@ -433,44 +486,6 @@ body {
</div>
</div>
</div>
<hr>
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span> STRINGS</h3><hr>
</div>
<div class="panel-body">
<div class="list-group">
<p>
{% for string in strings %}
{{string | safe}} </br>
{% endfor %}
</p>
</div>
</div>
</div>
</div>
<hr>
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="glyphicon glyphicon-folder-open"></span> FILES</h3><hr>
</div>
<div class="panel-body">
<div class="list-group">
<p>
{% for file in files %}
{{ file}} <br>
{% endfor %}
</p>
</div>
</div>
</div>
</div>
<hr><hr>
<h3 align="center"> Report Generated by - MobSF | http://opensecurity.in</h3>
+123 -89
View File
@@ -70,14 +70,14 @@ body {
<div class="list-group">
<p>
<span class="label label-primary"><b>App Name: </b></span>
{{ bin_name }}
{{ app_name }}
</p>
<p>
<span class="label label-primary"><b>Identifier: </b></span>
{{ id }}
{{ bundle_id }}
</p><p>
<span class="label label-primary"><b>Version: </b></span>
{{ bundle_version }}
{{ app_version }}
</p>
<p>
@@ -86,13 +86,18 @@ body {
</p>
<p>
<span class="label label-primary"><b>SDK Name: </b></span>
{{ sdk }}</p><p>
{{ sdk_name }}</p><p>
<span class="label label-primary"><b>Platform Version: </b></span>
{{ pltfm }}
{{ platform }}
</p><p>
<span class="label label-primary"><b>Min OS Version: </b></span>
{{ min }}
{{ min_os_version }}
</p> <p>
<span class="badge bg-primary">Supported Platforms</span>
{% for pl in bundle_supported_platforms %}
{{pl}},
{% endfor %}
</p>
</div>
@@ -163,6 +168,51 @@ body {
</div>
</div>
<hr>
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="fa fa-mobile"></span> URL SCHEMES</h3><hr>
</div>
<div class="panel-body">
{% if bundle_url_types|length > 0 %}
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>URL NAME</th>
<th>SCHEMES</th>
</tr>
</thead>
<tbody>
{% for scheme in bundle_url_types %}
<tr>
<td>
{{scheme | key:"CFBundleURLName" }}
{% if scheme|key:"CFBundleTypeRole" %}
<br>
{{scheme | key:"CFBundleTypeRole" }}
{% endif %}
</td>
<td>
{% for ul in scheme.CFBundleURLSchemes %}
{{ul}} <br/>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p>
No URL Schemes found.
</p>
{% endif %}
</div>
</div>
</div> <hr>
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
@@ -171,30 +221,32 @@ body {
<div class="panel-body">
{% if permissions|length > 0 %}
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>Permissions</th>
<th>Description</th>
<th>Reason in Manifest</th>
</tr>
</thead>
<tbody>
{%for perm in permissions%}
<tr>
<td>
{{ perm.0 | safe }}
</td>
<td>
{{ perm.1 | safe }}
</td>
<td>
{{ perm.2 | safe }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>PERMISSIONS</th>
<th>DESCRIPTION</th>
<th>REASON IN MANIFEST</th>
</tr>
</thead>
<tbody>
{% for perm in permissions %}
<tr>
<td>
{{ perm.name }}
</td>
<td>
{{ perm.description}}
</td>
<td>
{{ perm.reason }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<div class="list-group">
@@ -217,41 +269,42 @@ body {
<div class="panel-body">
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>ISSUE</th>
<th>STATUS</th>
<th>DESCRIPTION</th>
</tr>
</thead>
<tbody>
{% if insecure_connections|length > 0 %}
{%for con in insecure_connections%}
<tr>
<td>
Exception in NSAppTransportSecurity found.
<td>
Insecure
</td>
<td>
App Transport Security (ATS) is disabled on the domain '{{ con }}'. Disabling ATS can allow insecure communication with particular servers or allow insecure loads for web views or for media, while maintaining ATS protections elsewhere in your app.
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>
None
<td>
Secure
</td>
<td>
No insecure connections configured. App Transport Security (ATS) is enabled.
</td>
</tr>
{% endif %}
</tbody>
</table>
<thead>
<tr>
<th>ISSUE</th>
<th>STATUS</th>
<th>DESCRIPTION</th>
</tr>
</thead>
<tbody>
{% if ats_analysis|length > 0 %}
{% for findings in ats_analysis %}
<tr>
<td>
{{findings.issue}}
<td>
<span class="badge bg-danger"> {{findings.status}}</span>
</td>
<td>
{{findings.description}}
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>
No ATS exceptions found.
<td>
<span class="badge bg-success">secure</span>
</td>
<td>
No insecure connections configured. App Transport Security (ATS) is enabled.
</td>
</tr>
{% endif %}
</tbody>
</table>
</div>
<!-- /.box-body -->
</div>
@@ -280,7 +333,7 @@ body {
</tr>
</thead>
<tbody>
{% for issue, details in insecure.items %}
{% for issue, details in code_analysis.items %}
<tr>
<td>
{{ issue }}
@@ -333,7 +386,7 @@ body {
</tr>
</thead>
<tbody>
{% for desc, details in api.items %}
{% for desc, details in ios_api.items %}
<tr>
<td>
{{ desc }}
@@ -403,7 +456,7 @@ body {
<div class="panel-body">
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
{% if firebase %}
{% if firebase_urls %}
<thead>
<tr>
<th>URL</th>
@@ -414,7 +467,7 @@ body {
<tbody>
{% for item in firebase %}
{% for item in firebase_urls %}
<tr>
<td>
{{ item.url }}
@@ -538,7 +591,7 @@ body {
</tr>
</thead>
<tbody>
{%for item in file_analysis %}
{% for item in file_analysis %}
<tr>
<td>
{{ item.issue }}
@@ -559,25 +612,6 @@ body {
</div>
</div>
</div>
<hr>
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="glyphicon glyphicon-folder-open"></span> FILES</h3><hr>
</div>
<div class="panel-body">
<div class="list-group">
<p>
{% for file in files %}
{{ file}} <br>
{% endfor %}
</p>
</div>
</div>
</div>
</div>
<hr><hr>
<h3 align="center"> Report Generated by - MobSF | http://opensecurity.in</h3>
+11 -42
View File
@@ -6,7 +6,7 @@ body {
}
</style>
<h1 align="center" class="page-header">Static Analysis - {{name}} </h1>
<h1 align="center" class="page-header">Static Analysis - {{file_name}} </h1>
<hr>
<div class="col-lg-7">
<div class="panel panel-default">
@@ -18,7 +18,7 @@ body {
<div class="list-group">
<p>
<span class="label label-primary"><b>File Name: </b></span>
{{ name }}
{{ file_name }}
</p>
<p>
<span class="label label-primary"><b>Size: </b></span>
@@ -49,11 +49,11 @@ body {
<div class="list-group">
<p>
<span class="label label-primary"><b>App Name: </b></span>
{{ bin_name }}
{{ app_name }}
</p>
<p>
<span class="label label-primary"><b>Publisher: </b></span>
{{ pub_name }}
<span class="label label-primary"><b>Publisher: </b></span>
{{ publisher_name }}
</p>
<p>
<span class="label label-primary"><b>Version: </b></span>
@@ -61,7 +61,7 @@ body {
</p>
<p>
<span class="label label-primary"><b>Arch: </b></span>
{{ arch }}
{{ architecture }}
</p>
</div>
</div>
@@ -133,7 +133,7 @@ body {
</tr>
</thead>
<tbody>
{% for result in bin_an_results %}
{% for result in binary_analysis %}
<tr>
<td>{{ result.rule_id }}</td>
<td>
@@ -152,7 +152,7 @@ body {
<td>{{ result.desc }}</td>
</tr>
{% endfor %}
{% for warn in bin_an_warnings %}
{% for warn in binary_warnings %}
<tr>
<td>{{ warn.rule_id }}</td>
<td>
@@ -170,39 +170,8 @@ body {
</div>
</div>
</div>
<hr>
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="glyphicon glyphicon-sort-by-alphabet-alt"></span> STRINGS</h3><hr>
</div>
<div class="panel-body">
<div class="list-group">
<p>
{% for string in strings %}
{{string | safe}} </br>
{% endfor %}
</p>
</div>
<hr><hr>
<h3 align="center"> Report Generated by - MobSF | http://opensecurity.in</h3>
</div>
</div>
</div>
<hr>
<div class="col-lg-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-clock-o fa-fw"></i><span class="glyphicon glyphicon-folder-open"></span> FILES</h3><hr>
</div>
<div class="panel-body">
<div class="list-group">
<p>
{% for file in files %}
{{ file}} <br>
{% endfor %}
</p>
</div>
</div>
</div>
</div>
{% endblock %}
@@ -145,7 +145,7 @@
<p>APKiD Analysis</p>
</a>
</li>
{% if VT_RESULT %}
{% if virus_total %}
<li class="nav-item">
<a href="#virus_total" class="nav-link">
<i class="fas fa-spider nav-icon"></i>
@@ -267,7 +267,7 @@
</li>
{% if dynamic_analysis_done %}
<li class="nav-item">
<a href="../dynamic_report/?hash={{ md5 }}&amp;package={{ packagename }}" class="nav-link">
<a href="../dynamic_report/?hash={{ md5 }}&amp;package={{ package_name }}" class="nav-link">
<i class="nav-icon fas fa-file-alt"></i>
<p>
Dynamic Analysis Report
@@ -276,7 +276,7 @@
</li>
{% else %}
<li class="nav-item">
<a href="../android_dynamic/?hash={{md5}}&amp;package={{packagename}}" class="nav-link">
<a href="../android_dynamic/?hash={{md5}}&amp;package={{package_name}}" class="nav-link">
<i class="nav-icon fa fa-play-circle"></i>
<p>
Start Dynamic Analysis
@@ -331,18 +331,18 @@
{% else %}
<span class="badge bg-success">Trackers Detection</span> <strong>{{ trackers.detected_trackers }}/{{ trackers.total_trackers }}</strong><br/>
{% endif %}
{% if VT_RESULT %}
{% if VT_RESULT.positives > 0 %}
<span class="badge bg-danger">VirusTotal Detection</span> <strong>{{ VT_RESULT.positives }}/{{ VT_RESULT.total }}</strong><br/>
{% if virus_total %}
{% if virus_total.positives > 0 %}
<span class="badge bg-danger">VirusTotal Detection</span> <strong>{{ virus_total.positives }}/{{ virus_total.total }}</strong><br/>
{% else %}
<span class="badge bg-success">VirusTotal Detection</span> <strong>{{ VT_RESULT.positives }}/{{ VT_RESULT.total }}</strong><br/>
<span class="badge bg-success">VirusTotal Detection</span> <strong>{{ virus_total.positives }}/{{ virus_total.total }}</strong><br/>
{% endif %}
{% endif %}
</div>
<div class="col-6">
<p><strong><i class="fas fa-box-open"></i> FILE INFORMATION </strong></p>
<span class="badge bg-primary">File Name</span>
{{ name }}<br/>
{{ file_name }}<br/>
<span class="badge bg-primary">Size</span>
{{ size }}<br/>
<span class="badge bg-primary">MD5</span>
@@ -355,21 +355,21 @@
<div class="col-4">
<p><strong><i class="fas fa-info"></i> APP INFORMATION </strong></p>
<span class="badge bg-primary">App Name</span>
{{ real_name }}<br/>
{{ app_name }}<br/>
<span class="badge bg-primary">Package Name</span>
{{ packagename }}<br/>
{{ package_name }}<br/>
<span class="badge bg-primary">Main Activity</span>
{{ mainactivity }}<br/>
{{ main_activity }}<br/>
<span class="badge bg-primary">Target SDK</span>
{{ targetsdk }}
{{ target_sdk }}
<span class="badge bg-primary">Min SDK</span>
{{ minsdk }}
{{ min_sdk }}
<span class="badge bg-primary">Max SDK</span>
{{ maxsdk }}<br/>
{{ max_sdk }}<br/>
<span class="badge bg-primary">Android Version Name</span>
{{ androvername }}
{{ version_name }}
<span class="badge bg-primary">Android Version Code</span>
{{ androver }}
{{ version_code }}
</div>
</div>
@@ -377,7 +377,7 @@
</div>
</div>
<!-- Play Store -->
{% if not play_details.error %}
{% if not playstore_details.error %}
<div class="col-lg-12">
<div class="card">
<div class="card-body">
@@ -385,38 +385,38 @@
<strong><i class="fab fa-google-play"></i> PLAYSTORE INFORMATION</strong>
</p>
<span class="badge bg-info">Title</span>
{{ play_details.title }} <br/>
{{ playstore_details.title }} <br/>
<span class="badge bg-info">Score</span>
{{ play_details.score}}
{{ playstore_details.score}}
<span class="badge bg-info">Installs</span>
{{ play_details.installs }}
{{ playstore_details.installs }}
<span class="badge bg-info">Price</span>
{{ play_details.price }}
{{ playstore_details.price }}
<span class="badge bg-info">Android Version Support</span>
{{ play_details.androidVersionText }}
{{ playstore_details.androidVersionText }}
<span class="badge bg-info">Category</span>
{{ play_details.genre }}
{{ playstore_details.genre }}
<span class="badge bg-info">Play Store URL</span>
<a target="_blank" href="{{ play_details.url }}"> {{ packagename }} </a>
<a target="_blank" href="{{ playstore_details.url }}"> {{ package_name }} </a>
<br/>
<span class="badge bg-info">Developer</span>
{{play_details.developer}},
{{playstore_details.developer}},
<span class="badge bg-info">Developer ID</span>
{{play_details.developerId}} <br/>
{{playstore_details.developerId}} <br/>
<span class="badge bg-info">Developer Address</span>
{{play_details.developerAddress}} <br/>
{{playstore_details.developerAddress}} <br/>
<span class="badge bg-info">Developer Website</span>
{{play_details.developerWebsite}} <br/>
{{playstore_details.developerWebsite}} <br/>
<span class="badge bg-info">Developer Email</span>
{{play_details.developerEmail}}
{{playstore_details.developerEmail}}
<br/>
<span class="badge bg-info">Release Date</span>
{{ play_details.released }}
{{ playstore_details.released }}
<span class="badge bg-info">Privacy Policy</span>
<a target="_blank" href="{{ play_details.privacyPolicy }}">Privacy link</a>
<a target="_blank" href="{{ playstore_details.privacyPolicy }}">Privacy link</a>
<br/>
<span class="badge bg-info">Description</span>
<pre id="pre-wrap">{{ play_details.description }}</pre>
<pre id="pre-wrap">{{ playstore_details.description }}</pre>
</div>
</div><!-- /.card -->
</div>
@@ -440,7 +440,7 @@
<!-- small box -->
<div class="small-box bg-info">
<div class="inner">
<h3>{{ act_count }}</h3>
<h3>{{ activities | length }}</h3>
<p>ACTIVITIES</p>
</div>
@@ -455,7 +455,7 @@
<!-- small box -->
<div class="small-box bg-success">
<div class="inner">
<h3>{{ serv_count }}</h3>
<h3>{{ services | length }}</h3>
<p>SERVICES</p>
</div>
@@ -470,7 +470,7 @@
<!-- small box -->
<div class="small-box bg-warning">
<div class="inner">
<h3>{{ bro_count }}</h3>
<h3>{{ receivers | length }}</h3>
<p>RECEIVERS</p>
</div>
@@ -485,7 +485,7 @@
<!-- small box -->
<div class="small-box bg-danger">
<div class="inner">
<h3>{{ prov_count }}</h3>
<h3>{{ providers | length }}</h3>
<p>PROVIDERS</p>
</div>
@@ -503,7 +503,7 @@
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Activities</span>
<span class="info-box-number">
{{ e_act }}
{{ exported_count.exported_activities }}
</span>
</div>
<!-- /.info-box-content -->
@@ -517,7 +517,7 @@
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Services</span>
<span class="info-box-number">{{ e_ser }}</span>
<span class="info-box-number">{{ exported_count.exported_services }}</span>
</div>
<!-- /.info-box-content -->
</div>
@@ -534,7 +534,7 @@
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Receivers</span>
<span class="info-box-number">{{e_bro}}</span>
<span class="info-box-number">{{ exported_count.exported_receivers }}</span>
</div>
<!-- /.info-box-content -->
</div>
@@ -547,7 +547,7 @@
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Providers</span>
<span class="info-box-number">{{e_cnt}}</span>
<span class="info-box-number">{{exported_count.exported_providers}}</span>
</div>
<!-- /.info-box-content -->
</div>
@@ -575,9 +575,9 @@
<p>
<strong><i class="fas fa-cog"></i> SCAN OPTIONS</strong>
</p>
<p> <a href="../StaticAnalyzer/?checksum={{ md5 }}&amp;name={{ name }}&amp;type=apk&amp;rescan=1" class="btn btn-info" role="button"><i class="fa fa-sync"></i> Rescan</a></p>
<p> <a href="../StaticAnalyzer/?checksum={{ md5 }}&amp;name={{ file_name }}&amp;type=apk&amp;rescan=1" class="btn btn-info" role="button"><i class="fa fa-sync"></i> Rescan</a></p>
<p>
<a href="../android_dynamic/?hash={{md5}}&amp;package={{packagename}}" class="btn btn-success" role="button"><i class="fa fa-play-circle"></i> Start Dynamic Analysis</a>
<a href="../android_dynamic/?hash={{md5}}&amp;package={{package_name}}" class="btn btn-success" role="button"><i class="fa fa-play-circle"></i> Start Dynamic Analysis</a>
</p>
</div>
</div><!-- /.card -->
@@ -589,8 +589,8 @@
<strong><i class="fas fa-file-code"></i> DECOMPILED CODE</strong>
</p>
<p>
<a target="_blank" href="{{mani}}" role="button" class="btn btn-primary"><i class="fa fa-eye"></i> View AndroidManifest.xml</a>
<a href="../Java/?md5={{ md5 }}&amp;type={{ zipped }}" class="btn btn-info" role="button"><i class="fa fa-code"></i> View Java</a>
<a target="_blank" href="../ManifestView/?md5={{ md5 }}&amp;type={{ app_type }}&amp;bin=1" role="button" class="btn btn-primary"><i class="fa fa-eye"></i> View AndroidManifest.xml</a>
<a href="../Java/?md5={{ md5 }}&amp;type={{ app_type }}" class="btn btn-info" role="button"><i class="fa fa-code"></i> View Java</a>
<a href="../Smali/?md5={{ md5 }}" class="btn btn-info" role="button"><i class="fa fa-code"></i> View Smali</a>
</p>
<p>
@@ -617,23 +617,20 @@
<p>
<strong><i class="fa fa-certificate"></i> SIGNER CERTIFICATE</strong>
</p>
<pre><code>{{ certinfo }}</code></pre>
<pre><code>{{ certificate_analysis.certificate_info }}</code></pre>
<!--Cert status-->
{% if issued == "good" %}
{% if certificate_analysis.certificate_status == "good" %}
<strong>Certificate Status: </strong><span class="badge bg-success">Good</span><br />
{% elif issued == "bad" %}
<strong>Description: </strong>{{ certificate_analysis.description }}<br />
{% elif certificate_analysis.certificate_status == "bad" %}
<strong>Certificate Status: </strong><span class="badge bg-danger">Bad</span><br />
<strong>Description:</strong>App Signed by <code>Android Debug</code> Certificate.
Production ready applications should not be signed with <code>Android Debug</code> Certificate.<br />
{% elif issued == "missing" %}
<strong>Certificate Status: </strong><span class="badge bg-warning">Certificate not found</span><br />
{% elif issued == "bad hash" and sha256Digest is True %}
<strong>Description:</strong>{{ certificate_analysis.description }}<br />
{% elif certificate_analysis.certificate_status == "missing" %}
<strong>Certificate Status: </strong><span class="badge bg-warning">Certificate missing</span><br />
<strong>Description:</strong>{{ certificate_analysis.description }}<br />
{% elif certificate_analysis.certificate_status == "warning" %}
<strong>Certificate Status: </strong><span class="badge bg-warning">Warning</span><br />
<strong>Description:</strong>The app is signed with <code>SHA1withRSA</code>. SHA1 hash algorithm is known to have collision issues.<br />
<strong>Note:</strong>The manifest indicates <code>SHA256withRSA</code> is in use. Be sure to manually confirm this issue.<br />
{% elif issued == "bad hash" %}
<strong>Certificate Status: </strong><span class="badge bg-danger">Bad</span> <br />
<strong>Description:</strong>The app is signed with <code>SHA1withRSA</code>. SHA1 hash algorithm is known to have collision issues.
<strong>Description:</strong>{{ certificate_analysis.description }}<br />
{% endif %}
</div>
@@ -790,14 +787,14 @@
</tr>
</thead>
<tbody>
{% for desc, details in api.items %}
{% for desc, details in android_api.items %}
<tr>
<td>
{{ desc }}
</td>
<td>
{% for path in details|key:"path" %}
<a href="../ViewSource/?file={{ path }}&amp;md5={{ md5 }}&amp;type={{zipped}}"> {{ path }}</a>
<a href="../ViewSource/?file={{ path }}&amp;md5={{ md5 }}&amp;type={{app_type}}"> {{ path }}</a>
<br/>
{% endfor %}
</td>
@@ -915,7 +912,7 @@
</thead>
<tbody>
{% for item in manifest %}
{% for item in manifest_analysis %}
<tr>
<td>
{{item|key:"title" | safe}}
@@ -971,7 +968,7 @@
</tr>
</thead>
<tbody>
{% for issue, details in findings.items %}
{% for issue, details in code_analysis.items %}
<tr>
<td>
{{ issue }}
@@ -992,7 +989,7 @@
<td><strong>{{ details|key:"owasp" }}</strong></td>
<td>
{% for path in details|key:"path" %}
<a href="../ViewSource/?file={{ path }}&amp;md5={{ md5 }}&amp;type={{zipped}}"> {{ path }}</a>
<a href="../ViewSource/?file={{ path }}&amp;md5={{ md5 }}&amp;type={{app_type}}"> {{ path }}</a>
<br/>
{% endfor %}
</td>
@@ -1028,7 +1025,7 @@
</tr>
</thead>
<tbody>
{% for item in certz %}
{% for item in file_analysis %}
<tr>
<td>
{{ item|key:"finding" }}
@@ -1136,7 +1133,7 @@
</div>
</section>
<!-- ===========================end apkid analysis ================================== -->
{% if VT_RESULT %}
{% if virus_total %}
<a id="virus_total" class="anchor"></a>
<section class="content">
<div class="container-fluid">
@@ -1148,11 +1145,11 @@
<strong><i class="fas fa-spider"></i> VIRUSTOTAL SCAN</strong>
</p>
<div class="table-responsive">
{% if VT_RESULT.items|length < 9 %} {% comment %} Basic check to determine if the response is a msg or a result {% endcomment %}
<p align="left">&nbsp;&nbsp;<strong>{{ VT_RESULT.verbose_msg }}</strong></p>
{% if virus_total.items|length < 9 %} {% comment %} Basic check to determine if the response is a msg or a result {% endcomment %}
<p align="left">&nbsp;&nbsp;<strong>{{ virus_total.verbose_msg }}</strong></p>
{% else %}
<p align="left">&nbsp;&nbsp;<strong> {{ VT_RESULT.positives }} / {{ VT_RESULT.total }}&nbsp; AVs found this file Malicious! </strong> &nbsp;&nbsp;<a href="{{ VT_RESULT.permalink }}" target="_blank" rel="noopener"><i class="fas fa-th-list"></i> Full Report</a></p>
{% if VT_RESULT.positives > 0 %}
<p align="left">&nbsp;&nbsp;<strong> {{ virus_total.positives }} / {{ virus_total.total }}&nbsp; AVs found this file Malicious! </strong> &nbsp;&nbsp;<a href="{{ virus_total.permalink }}" target="_blank" rel="noopener"><i class="fas fa-th-list"></i> Full Report</a></p>
{% if virus_total.positives > 0 %}
<table id="table_vt" class="table table-bordered table-hover table-striped">
<thead>
<tr>
@@ -1161,7 +1158,7 @@
</tr>
</thead>
<tbody>
{% for av_name,av_result in VT_RESULT.scans.items %}
{% for av_name,av_result in virus_total.scans.items %}
{% if av_result.detected == True %}
<tr>
<td>
@@ -1263,7 +1260,7 @@
</td>
<td>
<a href="../ViewSource/?file={{urldict|key:"path"}}&amp;md5={{ md5}}&amp;type={{zipped}}">{{urldict|key:"path"}}</a>
<a href="../ViewSource/?file={{urldict|key:"path"}}&amp;md5={{ md5}}&amp;type={{app_type}}">{{urldict|key:"path"}}</a>
</td>
</tr>
{% endfor %}
@@ -1290,7 +1287,7 @@
<strong><i class="fas fa-database"></i> FIREBASE DATABASE</strong>
</p>
<div class="table-responsive">
{% if firebase %}
{% if firebase_urls %}
<table id="table_firebase" class="table table-bordered table-hover table-striped">
<thead>
<tr>
@@ -1300,7 +1297,7 @@
</thead>
<tbody>
{% for item in firebase %}
{% for item in firebase_urls %}
<tr>
<td>
{{ item.url }}
@@ -1354,7 +1351,7 @@
{% endfor %}
</td>
<td>
<a href="../ViewSource/?file={{email_dict|key:"path"}}&amp;md5={{ md5}}&amp;type={{zipped}}">{{email_dict|key:"path"}}</a>
<a href="../ViewSource/?file={{email_dict|key:"path"}}&amp;md5={{ md5}}&amp;type={{app_type}}">{{email_dict|key:"path"}}</a>
</td>
</tr>
{% endfor %}
@@ -267,7 +267,7 @@
<div class="col-6">
<p><strong><i class="fas fa-box-open"></i> FILE INFORMATION </strong></p>
<span class="badge bg-primary">File Name</span>
{{ name }}<br/>
{{ file_name }}<br/>
<span class="badge bg-primary">Size</span>
{{ size }}<br/>
<span class="badge bg-primary">MD5</span>
@@ -280,21 +280,21 @@
<div class="col-4">
<p><strong><i class="fas fa-info"></i> APP INFORMATION </strong></p>
<span class="badge bg-primary">App Name</span>
{{ real_name }}<br/>
{{ app_name }}<br/>
<span class="badge bg-primary">Package Name</span>
{{ packagename }}<br/>
{{ package_name }}<br/>
<span class="badge bg-primary">Main Activity</span>
{{ mainactivity }}<br/>
{{ main_activity }}<br/>
<span class="badge bg-primary">Target SDK</span>
{{ targetsdk }}
{{ target_sdk }}
<span class="badge bg-primary">Min SDK</span>
{{ minsdk }}
{{ min_sdk }}
<span class="badge bg-primary">Max SDK</span>
{{ maxsdk }}<br/>
{{ max_sdk }}<br/>
<span class="badge bg-primary">Android Version Name</span>
{{ androvername }}
{{ version_name }}
<span class="badge bg-primary">Android Version Code</span>
{{ androver }}
{{ version_code }}
</div>
</div>
@@ -302,7 +302,7 @@
</div>
</div>
<!-- Play Store -->
{% if not play_details.error %}
{% if not playstore_details.error %}
<div class="col-lg-12">
<div class="card">
<div class="card-body">
@@ -310,34 +310,34 @@
<strong><i class="fab fa-google-play"></i> PLAYSTORE INFORMATION</strong>
</p>
<span class="badge bg-info">Title</span>
{{ play_details.title }} <br/>
{{ playstore_details.title }} <br/>
<span class="badge bg-info">Score</span>
{{ play_details.score}}
{{ playstore_details.score}}
<span class="badge bg-info">Installs</span>
{{ play_details.installs }}
{{ playstore_details.installs }}
<span class="badge bg-info">Price</span>
{{ play_details.price }}
{{ playstore_details.price }}
<span class="badge bg-info">Android Version Support</span>
{{ play_details.androidVersionText }}
{{ playstore_details.androidVersionText }}
<span class="badge bg-info">Category</span>
{{ play_details.genre }}
{{ playstore_details.genre }}
<span class="badge bg-info">Play Store URL</span>
<a target="_blank" href="{{ play_details.url }}"> {{ packagename }} </a>
<a target="_blank" href="{{ playstore_details.url }}"> {{ package_name }} </a>
<br/>
<span class="badge bg-info">Developer Details</span>
{{play_details.developer}},
{{play_details.developerId}},
{{play_details.developerAddress}},
{{play_details.developerWebsite}},
{{play_details.developerEmail}},
{{playstore_details.developer}},
{{playstore_details.developerId}},
{{playstore_details.developerAddress}},
{{playstore_details.developerWebsite}},
{{playstore_details.developerEmail}},
<br/>
<span class="badge bg-info">Release Date</span>
{{ play_details.released }}
{{ playstore_details.released }}
<span class="badge bg-info">Privacy Policy</span>
<a target="_blank" href="{{ play_details.privacyPolicy }}">Privacy link</a>
<a target="_blank" href="{{ playstore_details.privacyPolicy }}">Privacy link</a>
<br/>
<span class="badge bg-info">Description</span>
<pre id="pre-wrap">{{ play_details.description }}</pre>
<pre id="pre-wrap">{{ playstore_details.description }}</pre>
</div>
</div><!-- /.card -->
</div>
@@ -361,7 +361,7 @@
<!-- small box -->
<div class="small-box bg-info">
<div class="inner">
<h3>{{ act_count }}</h3>
<h3>{{ activities | length }}</h3>
<p>ACTIVITIES</p>
</div>
@@ -376,7 +376,7 @@
<!-- small box -->
<div class="small-box bg-success">
<div class="inner">
<h3>{{ serv_count }}</h3>
<h3>{{ services | length }}</h3>
<p>SERVICES</p>
</div>
@@ -391,7 +391,7 @@
<!-- small box -->
<div class="small-box bg-warning">
<div class="inner">
<h3>{{ bro_count }}</h3>
<h3>{{ receivers | length }}</h3>
<p>RECEIVERS</p>
</div>
@@ -406,7 +406,7 @@
<!-- small box -->
<div class="small-box bg-danger">
<div class="inner">
<h3>{{ prov_count }}</h3>
<h3>{{ providers | length }}</h3>
<p>PROVIDERS</p>
</div>
@@ -424,7 +424,7 @@
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Activities</span>
<span class="info-box-number">
{{ e_act }}
{{ exported_count.exported_activities }}
</span>
</div>
<!-- /.info-box-content -->
@@ -438,7 +438,7 @@
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Services</span>
<span class="info-box-number">{{ e_ser }}</span>
<span class="info-box-number">{{ exported_count.exported_services }}</span>
</div>
<!-- /.info-box-content -->
</div>
@@ -455,7 +455,7 @@
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Receivers</span>
<span class="info-box-number">{{e_bro}}</span>
<span class="info-box-number">{{ exported_count.exported_receivers}}</span>
</div>
<!-- /.info-box-content -->
</div>
@@ -468,7 +468,7 @@
<div class="info-box-content">
<span class="info-box-text">Exported <br/>Providers</span>
<span class="info-box-number">{{e_cnt}}</span>
<span class="info-box-number">{{ exported_count.exported_providers }}</span>
</div>
<!-- /.info-box-content -->
</div>
@@ -496,8 +496,8 @@
<strong><i class="fas fa-cog"></i> SCAN OPTIONS</strong>
</p>
<p align="center">
<a href="../StaticAnalyzer/?checksum={{ md5 }}&amp;name={{ name }}&amp;type=zip&amp;rescan=1" class="btn btn-info" role="button"><i class="fa fa-sync"></i> Rescan</a>
<a target="_blank" href="{{mani}}" role="button" class="btn btn-primary"><i class="fa fa-eye"></i> View AndroidManifest.xml</a>
<a href="../StaticAnalyzer/?checksum={{ md5 }}&amp;name={{ file_name }}&amp;type=zip&amp;rescan=1" class="btn btn-info" role="button"><i class="fa fa-sync"></i> Rescan</a>
<a target="_blank" href="../ManifestView/?md5={{ md5 }}&amp;type={{ app_type }}&amp;bin=0" role="button" class="btn btn-primary"><i class="fa fa-eye"></i> View AndroidManifest.xml</a>
</p>
</div>
</div><!-- /.card -->
@@ -578,14 +578,14 @@
</tr>
</thead>
<tbody>
{% for desc, details in api.items %}
{% for desc, details in android_api.items %}
<tr>
<td>
{{ desc }}
</td>
<td>
{% for path in details|key:"path" %}
<a href="../ViewSource/?file={{ path }}&amp;md5={{ md5 }}&amp;type={{zipped}}"> {{ path }}</a>
<a href="../ViewSource/?file={{ path }}&amp;md5={{ md5 }}&amp;type={{app_type}}"> {{ path }}</a>
<br/>
{% endfor %}
</td>
@@ -703,7 +703,7 @@
</thead>
<tbody>
{% for item in manifest %}
{% for item in manifest_analysis %}
<tr>
<td>
{{item|key:"title" | safe}}
@@ -759,7 +759,7 @@
</tr>
</thead>
<tbody>
{% for issue, details in findings.items %}
{% for issue, details in code_analysis.items %}
<tr>
<td>
{{ issue }}
@@ -780,7 +780,7 @@
<td><b>{{ details|key:"owasp" }}</b></td>
<td>
{% for path in details|key:"path" %}
<a href="../ViewSource/?file={{ path }}&amp;md5={{ md5 }}&amp;type={{zipped}}"> {{ path }}</a>
<a href="../ViewSource/?file={{ path }}&amp;md5={{ md5 }}&amp;type={{app_type}}"> {{ path }}</a>
<br/>
{% endfor %}
</td>
@@ -816,10 +816,10 @@
</tr>
</thead>
<tbody>
{% for item in certz %}
{% for item in file_analysis %}
<tr>
<td>
{{ item|key:"finding" }}
{{ item|key:"findings" }}
</td>
<td>
{% for cert_f in item|key:"files" %}
@@ -915,7 +915,7 @@
</td>
<td>
<a href="../ViewSource/?file={{urldict|key:"path"}}&amp;md5={{ md5}}&amp;type={{zipped}}">{{urldict|key:"path"}}</a>
<a href="../ViewSource/?file={{urldict|key:"path"}}&amp;md5={{ md5}}&amp;type={{app_type}}">{{urldict|key:"path"}}</a>
</td>
</tr>
{% endfor %}
@@ -942,7 +942,7 @@
<strong><i class="fas fa-database"></i> FIREBASE DATABASE</strong>
</p>
<div class="table-responsive">
{% if firebase %}
{% if firebase_urls %}
<table id="table_firebase" class="table table-bordered table-hover table-striped">
<thead>
<tr>
@@ -952,7 +952,7 @@
</thead>
<tbody>
{% for item in firebase %}
{% for item in firebase_urls %}
<tr>
<td>
{{ item.url }}
@@ -1006,7 +1006,7 @@
{% endfor %}
</td>
<td>
<a href="../ViewSource/?file={{email_dict|key:"path"}}&amp;md5={{ md5}}&amp;type={{zipped}}">{{email_dict|key:"path"}}</a>
<a href="../ViewSource/?file={{email_dict|key:"path"}}&amp;md5={{ md5}}&amp;type={{app_type}}">{{email_dict|key:"path"}}</a>
</td>
</tr>
{% endfor %}
@@ -58,6 +58,14 @@
Scan Options
</p>
</a>
</li>
<li class="nav-item">
<a href="#url_schemes" class="nav-link">
<i class="nav-icon fas fa-hashtag"></i>
<p>
URL Schemes
</p>
</a>
</li>
<li class="nav-item">
<a href="#permissions" class="nav-link">
@@ -67,7 +75,16 @@
</p>
</a>
</li>
<li class="nav-item">
<li class="nav-item has-treeview">
<a href="#" class="nav-link">
<i class="nav-icon fas fa-shield-alt"></i>
<p>
Security Analysis
<i class="fas fa-angle-left right"></i>
</p>
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="#transport_security" class="nav-link">
<i class="nav-icon fas fa-lock"></i>
<p>
@@ -90,8 +107,10 @@
File Analysis
</p>
</a>
</li>
</ul>
</li>
{% if VT_RESULT %}
{% if virus_total %}
<li class="nav-item">
<a href="#virus_total" class="nav-link">
<i class="nav-icon fas fa-spider"></i>
@@ -170,11 +189,11 @@
<br/>
<span class="badge bg-info">Average CVSS</span> <strong>{{ average_cvss }} </strong><br/>
<span class="badge bg-{% if security_score < 50 %}danger{% elif security_score == 100 %}success{% else %}warning{% endif %}">Security Score</span> <strong>{{ security_score }}/100 </strong><br/>
{% if VT_RESULT %}
{% if VT_RESULT.positives > 0 %}
<span class="badge bg-danger">VirusTotal Detection</span> <strong>{{ VT_RESULT.positives }}/{{ VT_RESULT.total }}</strong><br/>
{% if virus_total %}
{% if virus_total.positives > 0 %}
<span class="badge bg-danger">VirusTotal Detection</span> <strong>{{ virus_total.positives }}/{{ virus_total.total }}</strong><br/>
{% else %}
<span class="badge bg-success">VirusTotal Detection</span> <strong>{{ VT_RESULT.positives }}/{{ VT_RESULT.total }}</strong><br/>
<span class="badge bg-success">VirusTotal Detection</span> <strong>{{ virus_total.positives }}/{{ virus_total.total }}</strong><br/>
{% endif %}
{% endif %}
</div>
@@ -194,21 +213,25 @@
<div class="col-3">
<p><strong><i class="fas fa-info"></i> APP INFORMATION </strong></p>
<span class="badge bg-primary">App Name</span>
{{ bin_name }}<br/>
{{ app_name }}<br/>
<span class="badge bg-primary">App Type</span>
{{ bin_type }}<br/>
{{ app_type }}<br/>
<span class="badge bg-primary">Identifier</span>
{{ id }}<br/>
{{ bundle_id }}<br/>
<span class="badge bg-primary">SDK Name</span>
{{ sdk }}<br/>
{{ sdk_name }}<br/>
<span class="badge bg-primary">Version</span>
{{ bundle_version }}
{{ app_version }}
<span class="badge bg-primary">Build</span>
{{ build }}
<span class="badge bg-primary">Platform Version</span>
{{ pltfm }}
{{ platform }}
<span class="badge bg-primary">Min OS Version</span>
{{ min }}
{{ min_os_version }} <br/>
<span class="badge bg-primary">Supported Platforms</span>
{% for pl in bundle_supported_platforms %}
{{pl}},
{% endfor %}
</div>
<div class="col-3">
<p><strong><i class="fas fa-ad"></i> BINARY INFORMATION </strong></p>
@@ -305,6 +328,61 @@
</div>
</section>
<!-- ===========================end scan options================================== -->
<a id="url_schemes" class="anchor"></a>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<p>
<strong><i class="fas fa-hashtag"></i> CUSTOM URL SCHEMES</strong>
<p>
{% if bundle_url_types|length > 0 %}
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>URL NAME</th>
<th>SCHEMES</th>
</tr>
</thead>
<tbody>
{% for scheme in bundle_url_types %}
<tr>
<td>
{{scheme | key:"CFBundleURLName" }}
{% if scheme|key:"CFBundleTypeRole" %}
<br>
{{scheme | key:"CFBundleTypeRole" }}
{% endif %}
</td>
<td>
{% for ul in scheme.CFBundleURLSchemes %}
{{ul}} <br/>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p>
No URL Schemes found.
</p>
{% endif %}
</div>
</div><!-- /.card -->
</div>
<!-- end row -->
</div>
</div>
</section>
<!-- ===========================end url schemes ================================== -->
<a id="permissions" class="anchor"></a>
<section class="content">
<div class="container-fluid">
@@ -328,7 +406,7 @@
</thead>
<tbody>
{%for perm in permissions%}
{% for perm in permissions %}
<tr>
<td>
{{ perm.name }}
@@ -346,7 +424,7 @@
</div>
{% else %}
<p>
No permissions required.
No Permissions required.
</p>
{% endif %}
</div>
@@ -378,23 +456,23 @@
</tr>
</thead>
<tbody>
{% if insecure_connections|length > 0 %}
{%for con in insecure_connections%}
{% if ats_analysis|length > 0 %}
{% for findings in ats_analysis %}
<tr>
<td>
Exception in NSAppTransportSecurity found.
{{findings.issue}}
<td>
<span class="badge bg-danger">insecure</span>
<span class="badge bg-danger"> {{findings.status}}</span>
</td>
<td>
App Transport Security (ATS) is disabled on the domain <strong>{{ con }}</strong>. Disabling ATS can allow insecure communication with particular servers or allow insecure loads for web views or for media, while maintaining ATS protections elsewhere in your app.
{{findings.description}}
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>
None
No ATS exceptions found.
<td>
<span class="badge bg-success">secure</span>
</td>
@@ -440,7 +518,7 @@
</tr>
</thead>
<tbody>
{% for bin in bin_anal %}
{% for bin in binary_analysis %}
<tr>
<td>
{{ bin.issue }}
@@ -460,7 +538,7 @@
<td><strong>{{bin.cwe}}</strong></td>
<td><strong>{{bin.owasp}}</strong></td>
<td>
{{ bin.description | safe}}
{{ bin.description}}
</td>
</tr>
{% endfor %}
@@ -524,7 +602,7 @@
</div>
</section>
<!-- ===========================end file analysis ================================== -->
{% if VT_RESULT %}
{% if virus_total %}
<a id="virus_total" class="anchor"></a>
<section class="content">
<div class="container-fluid">
@@ -536,11 +614,11 @@
<strong><i class="fas fa-spider"></i> VIRUSTOTAL SCAN</strong>
</p>
<div class="table-responsive">
{% if VT_RESULT.items|length < 9 %} {% comment %} Basic check to determine if the response is a msg or a result {% endcomment %}
<p align="left">&nbsp;&nbsp;<strong>{{ VT_RESULT.verbose_msg }}</strong></p>
{% if virus_total.items|length < 9 %} {% comment %} Basic check to determine if the response is a msg or a result {% endcomment %}
<p align="left">&nbsp;&nbsp;<strong>{{ virus_total.verbose_msg }}</strong></p>
{% else %}
<p align="left">&nbsp;&nbsp;<strong> {{ VT_RESULT.positives }} / {{ VT_RESULT.total }}&nbsp; AVs found this file Malicious! </strong> &nbsp;&nbsp;<a href="{{ VT_RESULT.permalink }}" target="_blank" rel="noopener"><i class="fas fa-th-list"></i> Full Report</a></p>
{% if VT_RESULT.positives > 0 %}
<p align="left">&nbsp;&nbsp;<strong> {{ virus_total.positives }} / {{ virus_total.total }}&nbsp; AVs found this file Malicious! </strong> &nbsp;&nbsp;<a href="{{ virus_total.permalink }}" target="_blank" rel="noopener"><i class="fas fa-th-list"></i> Full Report</a></p>
{% if virus_total.positives > 0 %}
<table id="table_vt" class="table table-bordered table-hover table-striped">
<thead>
<tr>
@@ -549,7 +627,7 @@
</tr>
</thead>
<tbody>
{% for av_name,av_result in VT_RESULT.scans.items %}
{% for av_name,av_result in virus_total.scans.items %}
{% if av_result.detected == True %}
<tr>
<td>
@@ -587,7 +665,7 @@
</p>
<div class="list-group">
<p>
{% for lib in libs %}
{% for lib in libraries %}
{{ lib }}
<br/>
{% endfor %}
@@ -642,7 +720,7 @@
</div>
<div class="modal-body">
<pre><code>
{{ plist }}
{{ info_plist }}
</code></pre>
</div>
</div>
@@ -663,7 +741,7 @@
<div class="modal-body">
<pre><code>
{% for string in strings %}
{{string | safe}}
{{string}}
{% endfor %}
</code></pre>
</div>
@@ -58,6 +58,14 @@
Scan Options
</p>
</a>
</li>
<li class="nav-item">
<a href="#url_schemes" class="nav-link">
<i class="nav-icon fas fa-hashtag"></i>
<p>
URL Schemes
</p>
</a>
</li>
<li class="nav-item">
<a href="#permissions" class="nav-link">
@@ -232,19 +240,23 @@
<div class="col-5">
<p><strong><i class="fas fa-info"></i> APP INFORMATION </strong></p>
<span class="badge bg-primary">App Name</span>
{{ bin_name }}<br/>
{{ app_name }}<br/>
<span class="badge bg-primary">Identifier</span>
{{ id }}<br/>
{{ bundle_id }}<br/>
<span class="badge bg-primary">SDK Name</span>
{{ sdk }}<br/>
{{ sdk_name }}<br/>
<span class="badge bg-primary">Version</span>
{{ bundle_version }}
{{ app_version }}
<span class="badge bg-primary">Build</span>
{{ build }}
<span class="badge bg-primary">Platform Version</span>
{{ pltfm }}
{{ platform }}
<span class="badge bg-primary">Min OS Version</span>
{{ min }}
{{ min_os_version }} <br/>
<span class="badge bg-primary">Supported Platforms</span>
{% for pl in bundle_supported_platforms %}
{{pl}},
{% endfor %}
</div>
@@ -328,6 +340,60 @@
</div>
</section>
<!-- ===========================end scan options================================== -->
<a id="url_schemes" class="anchor"></a>
<section class="content">
<div class="container-fluid">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-body">
<p>
<strong><i class="fas fa-hashtag"></i> CUSTOM URL SCHEMES</strong>
<p>
{% if bundle_url_types|length > 0 %}
<div class="table-responsive">
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>URL NAME</th>
<th>SCHEMES</th>
</tr>
</thead>
<tbody>
{% for scheme in bundle_url_types %}
<tr>
<td>
{{scheme | key:"CFBundleURLName" }}
{% if scheme|key:"CFBundleTypeRole" %}
<br>
{{scheme | key:"CFBundleTypeRole" }}
{% endif %}
</td>
<td>
{% for ul in scheme.CFBundleURLSchemes %}
{{ul}} <br/>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% else %}
<p>
No URL Schemes found.
</p>
{% endif %}
</div>
</div><!-- /.card -->
</div>
<!-- end row -->
</div>
</div>
</section>
<!-- ===========================end url schemes ================================== -->
<a id="permissions" class="anchor"></a>
<section class="content">
<div class="container-fluid">
@@ -351,7 +417,7 @@
</thead>
<tbody>
{%for perm in permissions%}
{% for perm in permissions %}
<tr>
<td>
{{ perm.name }}
@@ -369,7 +435,7 @@
</div>
{% else %}
<p>
No permissions required.
No Permissions required.
</p>
{% endif %}
</div>
@@ -400,7 +466,7 @@
</tr>
</thead>
<tbody>
{% for desc, details in api.items %}
{% for desc, details in ios_api.items %}
<tr>
<td>
{{ desc }}
@@ -425,7 +491,7 @@
</div>
</section>
<!-- ===========================end ios api analysis ================================== -->
<a id="transport_security" class="anchor"></a>
<a id="transport_security" class="anchor"></a>
<section class="content">
<div class="container-fluid">
<div class="row">
@@ -446,23 +512,23 @@
</tr>
</thead>
<tbody>
{% if insecure_connections|length > 0 %}
{% for con in insecure_connections %}
{% if ats_analysis|length > 0 %}
{% for findings in ats_analysis %}
<tr>
<td>
Exception in NSAppTransportSecurity found.
{{findings.issue}}
<td>
<span class="badge bg-danger">insecure</span>
<span class="badge bg-danger"> {{findings.status}}</span>
</td>
<td>
App Transport Security (ATS) is disabled on the domain <strong>{{ con }}</strong>. Disabling ATS can allow insecure communication with particular servers or allow insecure loads for web views or for media, while maintaining ATS protections elsewhere in your app.
{{findings.description}}
</td>
</tr>
{% endfor %}
{% else %}
<tr>
<td>
None
No ATS exceptions found.
<td>
<span class="badge bg-success">secure</span>
</td>
@@ -508,7 +574,7 @@
</tr>
</thead>
<tbody>
{% for issue, details in insecure.items %}
{% for issue, details in code_analysis.items %}
<tr>
<td>
{{ issue }}
@@ -697,7 +763,7 @@
<strong><i class="fas fa-database"></i> FIREBASE DATABASE</strong>
</p>
<div class="table-responsive">
{% if firebase %}
{% if firebase_urls %}
<table id="table_firebase" class="table table-bordered table-hover table-striped">
<thead>
<tr>
@@ -707,7 +773,7 @@
</thead>
<tbody>
{% for item in firebase %}
{% for item in firebase_urls %}
<tr>
<td>
{{ item.url }}
@@ -818,7 +884,7 @@
</div>
<div class="modal-body">
<pre><code>
{{ plist }}
{{ info_plist }}
</code></pre>
</div>
</div>
@@ -120,18 +120,18 @@
<div class="col-2">
<p><strong><i class="fas fa-info"></i> APP INFORMATION </strong></p>
<span class="badge bg-primary">App Name</span>
{{ bin_name }} <br/>
{{ app_name }} <br/>
<span class="badge bg-primary">Publisher</span>
{{ pub_name }} <br/>
{{ publisher_name }} <br/>
<span class="badge bg-primary">Version</span>
{{ app_version }} <br/>
<span class="badge bg-primary">Arch</span>
{{ arch }}
{{ architecture }}
</div>
<div class="col-5">
<p><strong><i class="fas fa-box-open"></i> FILE INFORMATION </strong></p>
<span class="badge bg-primary">Name</span>
{{ name }} <br/>
<span class="badge bg-primary">File Name</span>
{{ file_name }} <br/>
<span class="badge bg-primary">Size</span>
{{ size }} <br/>
<span class="badge bg-primary">MD5</span>
@@ -139,7 +139,7 @@
<span class="badge bg-primary">SHA1</span>
{{ sha1 }} <br/>
<span class="badge bg-primary">SHA256</span>
{{ sha256 }}
{{ sha256 }}
</p>
</div>
<div class="col-5">
@@ -188,7 +188,7 @@
<strong><i class="fas fa-cog"></i> SCAN OPTIONS</strong>
</p>
<p align="center">
<a href="../StaticAnalyzer_Windows/?checksum={{ md5 }}&amp;name={{ name }}&amp;type=appx&amp;rescan=1" class="btn btn-info" role="button"><i class="fa fa-sync"></i> Rescan</a>
<a href="../StaticAnalyzer_Windows/?checksum={{ md5 }}&amp;name={{ file_name }}&amp;type=appx&amp;rescan=1" class="btn btn-info" role="button"><i class="fa fa-sync"></i> Rescan</a>
<a href="#" data-target="#mstrings" role="button" class="btn btn-primary" data-toggle="modal"><i class="fa fa-list"></i> View Strings</a>
</p>
</div>
@@ -220,7 +220,7 @@
</tr>
</thead>
<tbody>
{% for result in bin_an_results %}
{% for result in binary_analysis %}
<tr>
<td>{{ result.rule_id }}</td>
<td>
@@ -240,7 +240,7 @@
<td>{{ result.info }}</td>
</tr>
{% endfor %}
{% for warn in bin_an_warnings %}
{% for warn in binary_warnings %}
<tr>
<td>{{ warn.rule_id }}</td>
<td>