mirror of
https://github.com/MobSF/Mobile-Security-Framework-MobSF.git
synced 2026-10-11 22:50:09 +00:00
Bug Fixes + Improvements (#2307)
* Replace Android test APK * Added tests for Library analysis from binary (scan_library route) * iOS merge findings from swift and objective c rules with same rule identifier. Fixes #2287 * iOS Binary analysis, sort regex matches. Fixes #2252 * Framework dylibs with no extensions to skip PIE checks. Fixes #2307 * Select correct network_security config. Fixes #2049 * Android Manifest Analysis added support for detecting task hijacking (StrandHogg 1.0 and StrandHogg 2.0) . Fixes #2124 * Added new manifest analysis rule to warn on apps targeting older Android OS * Updated severity of findings * UI improvement for AppSec dashboard to show a loader * UI changes in Static Analysis to collapse large no of files in API and Code Analysis for better real estate * Improved certificate file analysis for android, jar, aar, and ios * MobSF version Bump
This commit is contained in:
+1
-1
@@ -10,7 +10,7 @@ from mobsf.install.windows.setup import windows_config_local
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
VERSION = '3.8.7'
|
||||
VERSION = '3.8.8'
|
||||
BANNER = """
|
||||
__ __ _ ____ _____ _____ ___
|
||||
| \/ | ___ | |__/ ___|| ___|_ _|___ / ( _ )
|
||||
|
||||
@@ -492,7 +492,8 @@ def update_local_db(db_name, url, local_file):
|
||||
else:
|
||||
logger.info('%s Database is up-to-date', db_name)
|
||||
return update
|
||||
except requests.exceptions.ReadTimeout:
|
||||
except (requests.exceptions.ReadTimeout,
|
||||
requests.exceptions.ConnectionError):
|
||||
logger.warning('Failed to download %s DB.', db_name)
|
||||
except Exception:
|
||||
logger.exception('[ERROR] %s DB Update', db_name)
|
||||
|
||||
@@ -164,7 +164,7 @@ class Upload(object):
|
||||
def api_docs(request):
|
||||
"""Api Docs Route."""
|
||||
context = {
|
||||
'title': 'REST API Docs',
|
||||
'title': 'API Docs',
|
||||
'api_key': api_key(),
|
||||
'version': settings.MOBSF_VER,
|
||||
}
|
||||
|
||||
Submodule mobsf/StaticAnalyzer/test_files updated: 5094ab786b...7d44d847af
@@ -71,7 +71,7 @@ def static_analysis_test():
|
||||
if platform.system() in ['Darwin', 'Linux']:
|
||||
pdfs = [
|
||||
'/pdf/02e7989c457ab67eb514a8328779f256/',
|
||||
'/pdf/3a552566097a8de588b8184b059b0158/',
|
||||
'/pdf/82ab8b2193b3cfb1c737e3a786be363a/',
|
||||
'/pdf/6c23c2970551be15f32bbab0b5db0c71/',
|
||||
'/pdf/52c50ae824e329ba8b5b7a0f523efffe/',
|
||||
'/pdf/57bb5be0ea44a755ada4a93885c3825e/',
|
||||
@@ -81,7 +81,7 @@ def static_analysis_test():
|
||||
else:
|
||||
pdfs = [
|
||||
'/pdf/02e7989c457ab67eb514a8328779f256/',
|
||||
'/pdf/3a552566097a8de588b8184b059b0158/',
|
||||
'/pdf/82ab8b2193b3cfb1c737e3a786be363a/',
|
||||
'/pdf/52c50ae824e329ba8b5b7a0f523efffe/',
|
||||
'/pdf/57bb5be0ea44a755ada4a93885c3825e/',
|
||||
'/pdf/8179b557433835827a70510584f3143e/',
|
||||
@@ -101,7 +101,7 @@ def static_analysis_test():
|
||||
|
||||
# Compare apps test
|
||||
logger.info('Running App Compare tests')
|
||||
first_app = '3a552566097a8de588b8184b059b0158'
|
||||
first_app = '82ab8b2193b3cfb1c737e3a786be363a'
|
||||
second_app = '52c50ae824e329ba8b5b7a0f523efffe'
|
||||
url = '/compare/{}/{}/'.format(first_app, second_app)
|
||||
resp = http_client.get(url, follow=True)
|
||||
@@ -113,10 +113,24 @@ def static_analysis_test():
|
||||
logger.info(resp.content)
|
||||
return True
|
||||
|
||||
# Scan shared object or dylib from binaries.
|
||||
logger.info('Running Library Analysis test')
|
||||
md5 = '82ab8b2193b3cfb1c737e3a786be363a'
|
||||
lib = 'apktool_out/lib/arm64-v8a/libdivajni.so'
|
||||
url = f'/scan_library/{md5}?library={lib}'
|
||||
resp = http_client.get(url, follow=True)
|
||||
assert (resp.status_code == 200)
|
||||
if resp.status_code == 200:
|
||||
logger.info('[OK] Library Analysis test passed successfully')
|
||||
else:
|
||||
logger.error('Library Analysis test failed')
|
||||
logger.info(resp.content)
|
||||
return True
|
||||
|
||||
# Search by MD5
|
||||
if platform.system() in ['Darwin', 'Linux']:
|
||||
scan_md5s = ['02e7989c457ab67eb514a8328779f256',
|
||||
'3a552566097a8de588b8184b059b0158',
|
||||
'82ab8b2193b3cfb1c737e3a786be363a',
|
||||
'6c23c2970551be15f32bbab0b5db0c71',
|
||||
'52c50ae824e329ba8b5b7a0f523efffe',
|
||||
'57bb5be0ea44a755ada4a93885c3825e',
|
||||
@@ -124,7 +138,7 @@ def static_analysis_test():
|
||||
'7b0a23bffc80bac05739ea1af898daad']
|
||||
else:
|
||||
scan_md5s = ['02e7989c457ab67eb514a8328779f256',
|
||||
'3a552566097a8de588b8184b059b0158',
|
||||
'82ab8b2193b3cfb1c737e3a786be363a',
|
||||
'52c50ae824e329ba8b5b7a0f523efffe',
|
||||
'57bb5be0ea44a755ada4a93885c3825e',
|
||||
'8179b557433835827a70510584f3143e',
|
||||
@@ -242,7 +256,7 @@ def api_test():
|
||||
if platform.system() in ['Darwin', 'Linux']:
|
||||
pdfs = [
|
||||
{'hash': '02e7989c457ab67eb514a8328779f256'},
|
||||
{'hash': '3a552566097a8de588b8184b059b0158'},
|
||||
{'hash': '82ab8b2193b3cfb1c737e3a786be363a'},
|
||||
{'hash': '6c23c2970551be15f32bbab0b5db0c71'},
|
||||
{'hash': '52c50ae824e329ba8b5b7a0f523efffe'},
|
||||
{'hash': '57bb5be0ea44a755ada4a93885c3825e'},
|
||||
@@ -252,7 +266,7 @@ def api_test():
|
||||
else:
|
||||
pdfs = [
|
||||
{'hash': '02e7989c457ab67eb514a8328779f256'},
|
||||
{'hash': '3a552566097a8de588b8184b059b0158'},
|
||||
{'hash': '82ab8b2193b3cfb1c737e3a786be363a'},
|
||||
{'hash': '52c50ae824e329ba8b5b7a0f523efffe'},
|
||||
{'hash': '57bb5be0ea44a755ada4a93885c3825e'},
|
||||
{'hash': '8179b557433835827a70510584f3143e'},
|
||||
@@ -314,9 +328,9 @@ def api_test():
|
||||
logger.info('[OK] Scorecard API test completed')
|
||||
logger.info('Running View Source API test')
|
||||
# View Source tests
|
||||
files = [{'file': 'opensecurity/helloworld/MainActivity.java',
|
||||
files = [{'file': 'jakhar/aseem/diva/MainActivity.java',
|
||||
'type': 'apk',
|
||||
'hash': '3a552566097a8de588b8184b059b0158'},
|
||||
'hash': '82ab8b2193b3cfb1c737e3a786be363a'},
|
||||
{'file': 'opensecurity/webviewignoressl/MainActivity.java',
|
||||
'type': 'studio',
|
||||
'hash': '52c50ae824e329ba8b5b7a0f523efffe'},
|
||||
@@ -351,7 +365,7 @@ def api_test():
|
||||
resp = http_client.post(
|
||||
'/api/v1/compare',
|
||||
{
|
||||
'hash1': '3a552566097a8de588b8184b059b0158',
|
||||
'hash1': '82ab8b2193b3cfb1c737e3a786be363a',
|
||||
'hash2': '52c50ae824e329ba8b5b7a0f523efffe',
|
||||
},
|
||||
HTTP_AUTHORIZATION=auth)
|
||||
@@ -359,7 +373,7 @@ def api_test():
|
||||
resp_custom = http_client.post(
|
||||
'/api/v1/compare',
|
||||
{
|
||||
'hash1': '3a552566097a8de588b8184b059b0158',
|
||||
'hash1': '82ab8b2193b3cfb1c737e3a786be363a',
|
||||
'hash2': '52c50ae824e329ba8b5b7a0f523efffe',
|
||||
},
|
||||
HTTP_X_MOBSF_API_KEY=auth)
|
||||
@@ -373,7 +387,7 @@ def api_test():
|
||||
logger.info('Running Delete Scan Results test')
|
||||
# Suppression tests
|
||||
# Android Manifest by rule
|
||||
and_hash = '3a552566097a8de588b8184b059b0158'
|
||||
and_hash = '82ab8b2193b3cfb1c737e3a786be363a'
|
||||
rule = 'app_is_debuggable'
|
||||
typ = 'manifest'
|
||||
logger.info('Running Suppression disable by rule for APK manifest')
|
||||
@@ -489,7 +503,7 @@ def api_test():
|
||||
# Deleting Scan Results
|
||||
if platform.system() in ['Darwin', 'Linux']:
|
||||
scan_md5s = ['02e7989c457ab67eb514a8328779f256',
|
||||
'3a552566097a8de588b8184b059b0158',
|
||||
'82ab8b2193b3cfb1c737e3a786be363a',
|
||||
'6c23c2970551be15f32bbab0b5db0c71',
|
||||
'52c50ae824e329ba8b5b7a0f523efffe',
|
||||
'57bb5be0ea44a755ada4a93885c3825e',
|
||||
@@ -498,7 +512,7 @@ def api_test():
|
||||
]
|
||||
else:
|
||||
scan_md5s = ['02e7989c457ab67eb514a8328779f256',
|
||||
'3a552566097a8de588b8184b059b0158',
|
||||
'82ab8b2193b3cfb1c737e3a786be363a',
|
||||
'52c50ae824e329ba8b5b7a0f523efffe',
|
||||
'57bb5be0ea44a755ada4a93885c3825e',
|
||||
'8179b557433835827a70510584f3143e',
|
||||
|
||||
@@ -42,15 +42,28 @@ MANIFEST_DESC = {
|
||||
'[android:networkSecurityConfig=%s]'),
|
||||
},
|
||||
'vulnerable_os_version': {
|
||||
'title': ('App can be installed on a vulnerable Android version'
|
||||
'<br>[minSdk=%s]'),
|
||||
'level': 'warning',
|
||||
'title': ('App can be installed on a vulnerable '
|
||||
'upatched Android version<br>Android %s, [minSdk=%s]'),
|
||||
'level': 'high',
|
||||
'description': ('This application can be installed on an older version'
|
||||
' of android that has multiple unfixed '
|
||||
'vulnerabilities. Support an Android version > 8, '
|
||||
'API 26 to receive reasonable security updates.'),
|
||||
'vulnerabilities. These devices won\'t receive '
|
||||
'reasonable security updates from Google. '
|
||||
'Support an Android version => 10, API 29 '
|
||||
'to receive reasonable security updates.'),
|
||||
'name': ('App can be installed on a vulnerable '
|
||||
'upatched Android version %s, [minSdk=%s]'),
|
||||
},
|
||||
'vulnerable_os_version2': {
|
||||
'title': ('App can be installed on a vulnerable Android version'
|
||||
'<br>Android %s, minSdk=%s]'),
|
||||
'level': 'warning',
|
||||
'description': ('This application can be installed on an older version'
|
||||
' of android that has multiple vulnerabilities. '
|
||||
'Support an Android version => 10, API 29 '
|
||||
'to receive reasonable security updates.'),
|
||||
'name': ('App can be installed on a vulnerable Android version'
|
||||
'[minSdk=%s]'),
|
||||
' %s, [minSdk=%s]'),
|
||||
},
|
||||
'app_is_debuggable': {
|
||||
'title': 'Debug Enabled For App<br>[android:debuggable=true]',
|
||||
@@ -104,7 +117,7 @@ MANIFEST_DESC = {
|
||||
},
|
||||
'non_standard_launchmode': {
|
||||
'title': 'Launch Mode of activity (%s) is not standard.',
|
||||
'level': 'high',
|
||||
'level': 'warning',
|
||||
'description': ('An Activity should not be having the launch mode'
|
||||
' attribute set to "singleTask/singleInstance" as '
|
||||
'it becomes root Activity and it is possible for'
|
||||
@@ -114,9 +127,45 @@ MANIFEST_DESC = {
|
||||
' information is included in an Intent.'),
|
||||
'name': 'Launch Mode of activity (%s) is not standard.',
|
||||
},
|
||||
'task_hijacking': {
|
||||
'title': ('Activity (%s) is vulnerable to Android '
|
||||
'Task Hijacking/StrandHogg.'),
|
||||
'level': 'high',
|
||||
'description': ('An Activity should not be having the launch mode '
|
||||
'attribute set to "singleTask". It is then '
|
||||
'possible for other applications to place a '
|
||||
'malicious activity on top of the activity stack '
|
||||
'resulting in Task Hijacking/StrandHogg 1.0'
|
||||
'vulnerability. This makes the application an easy '
|
||||
'target for phishing attacks. The vulnerability can '
|
||||
'be remediated by setting the launch mode attribute '
|
||||
'to "singleInstance" or by setting an empty '
|
||||
'taskAffinity (taskAffinity="") attribute. You can '
|
||||
'also update the target SDK version of the app to '
|
||||
'28 or higher to fix this issue at platform level.'),
|
||||
'name': ('Activity (%s) is vulnerable to Android '
|
||||
'Task Hijacking/StrandHogg.'),
|
||||
},
|
||||
'task_hijacking2': {
|
||||
'title': 'Activity (%s) is vulnerable to StrandHogg 2.0',
|
||||
'level': 'high',
|
||||
'description': ('Activity is found to be vulnerable to '
|
||||
'StrandHogg 2.0 task hijacking vulnerability. '
|
||||
'When vulnerable, it is possible for other '
|
||||
'applications to place a malicious activity '
|
||||
'on top of the activity stack of the vulnerable '
|
||||
'application. This makes the application an easy '
|
||||
'target for phishing attacks. The vulnerability can '
|
||||
'be remediated by setting the launch mode attribute '
|
||||
'to "singleInstance" and by setting an empty '
|
||||
'taskAffinity (taskAffinity=""). You can also update '
|
||||
'the target SDK version of the app to 29 or higher '
|
||||
'to fix this issue at platform level.'),
|
||||
'name': 'Activity (%s) is vulnerable to StrandHogg 2.0',
|
||||
},
|
||||
'improper_provider_permission': {
|
||||
'title': 'Improper Content Provider Permissions<br>[%s]',
|
||||
'level': 'high',
|
||||
'level': 'warning',
|
||||
'description': ('A content provider permission was set to allows'
|
||||
' access from any other app on the device. '
|
||||
'Content providers may contain sensitive '
|
||||
@@ -343,7 +392,7 @@ MANIFEST_DESC = {
|
||||
'explicitly_exported': {
|
||||
'title': ('<strong>%s</strong> (%s) is not Protected.'
|
||||
' <br>[android:exported=true]'),
|
||||
'level': 'high',
|
||||
'level': 'warning',
|
||||
'description': ('A%s %s is found to be shared with other apps on the'
|
||||
' device therefore leaving it accessible to any other'
|
||||
' application on the device.'),
|
||||
|
||||
@@ -50,10 +50,11 @@ def get_hardcoded_cert_keystore(files):
|
||||
for file_name in files:
|
||||
if '.' not in file_name:
|
||||
continue
|
||||
ext = file_name.split('.')[-1]
|
||||
if re.search('cer|pem|cert|crt|pub|key|pfx|p12|der', ext):
|
||||
ext = Path(file_name).suffix
|
||||
if ext in ('.cer', '.pem', '.cert', '.crt',
|
||||
'.pub', '.key', '.pfx', '.p12', '.der'):
|
||||
certz.append(escape(file_name))
|
||||
if re.search('jks|bks', ext):
|
||||
if ext in ('.jks', '.bks'):
|
||||
key_store.append(escape(file_name))
|
||||
if certz:
|
||||
desc = 'Certificate/Key files hardcoded inside the app.'
|
||||
|
||||
@@ -14,8 +14,42 @@ logger = logging.getLogger(__name__)
|
||||
ANDROID_4_2_LEVEL = 17
|
||||
ANDROID_5_0_LEVEL = 21
|
||||
ANDROID_8_0_LEVEL = 26
|
||||
ANDROID_9_0_LEVEL = 28
|
||||
ANDROID_10_0_LEVEL = 29
|
||||
ANDROID_MANIFEST_FILE = 'AndroidManifest.xml'
|
||||
|
||||
ANDROID_API_LEVEL_MAP = {
|
||||
'1': '1.0',
|
||||
'2': '1.1',
|
||||
'3': '1.5',
|
||||
'4': '1.6',
|
||||
'5': '2.0-2.1',
|
||||
'8': '2.2-2.2.3',
|
||||
'9': '2.3-2.3.2',
|
||||
'10': '2.3.3-2.3.7',
|
||||
'11': '3.0',
|
||||
'12': '3.1',
|
||||
'13': '3.2-3.2.6',
|
||||
'14': '4.0-4.0.2',
|
||||
'15': '4.0.3-4.0.4',
|
||||
'16': '4.1-4.1.2',
|
||||
'17': '4.2-4.2.2',
|
||||
'18': '4.3-4.3.1',
|
||||
'19': '4.4-4.4.4',
|
||||
'20': '4.4W-4.4W.2',
|
||||
'21': '5.0-5.0.2',
|
||||
'22': '5.1-5.1.1',
|
||||
'23': '6.0-6.0.1',
|
||||
'24': '7.0',
|
||||
'25': '7.1-7.1.2',
|
||||
'26': '8.0',
|
||||
'27': '8.1',
|
||||
'28': '9',
|
||||
'29': '10',
|
||||
'30': '11',
|
||||
'31': '12',
|
||||
'32': '12L',
|
||||
'33': '13',
|
||||
}
|
||||
|
||||
def get_browsable_activities(node, ns):
|
||||
"""Get Browsable Activities."""
|
||||
@@ -110,7 +144,12 @@ def manifest_analysis(mfxml, ns, man_data_dic, src_type, app_dir):
|
||||
# GENERAL
|
||||
if man_data_dic['min_sdk'] and int(man_data_dic['min_sdk']) < ANDROID_8_0_LEVEL:
|
||||
minsdk = man_data_dic.get('min_sdk')
|
||||
ret_list.append(('vulnerable_os_version', (minsdk,), ()))
|
||||
android_version = ANDROID_API_LEVEL_MAP.get(minsdk, 'XX')
|
||||
ret_list.append(('vulnerable_os_version', (android_version, minsdk,), ()))
|
||||
elif man_data_dic['min_sdk'] and int(man_data_dic['min_sdk']) < ANDROID_10_0_LEVEL:
|
||||
minsdk = man_data_dic.get('min_sdk')
|
||||
android_version = ANDROID_API_LEVEL_MAP.get(minsdk, 'XX')
|
||||
ret_list.append(('vulnerable_os_version2', (android_version, minsdk,), ()))
|
||||
# APPLICATIONS
|
||||
# Handle multiple application tags in AAR
|
||||
backupDisabled = False
|
||||
@@ -174,30 +213,44 @@ def manifest_analysis(mfxml, ns, man_data_dic, src_type, app_dir):
|
||||
else:
|
||||
itemname = 'NIL'
|
||||
item = ''
|
||||
if itemname in ['Activity', 'Activity-Alias']:
|
||||
# Task Affinity
|
||||
task_affinity = node.getAttribute(f'{ns}:taskAffinity')
|
||||
if (task_affinity):
|
||||
item = node.getAttribute(f'{ns}:name')
|
||||
ret_list.append(('task_affinity_set', (item,), ()))
|
||||
|
||||
# Task Affinity
|
||||
if (
|
||||
itemname in ['Activity', 'Activity-Alias'] and
|
||||
node.getAttribute(f'{ns}:taskAffinity')
|
||||
):
|
||||
# LaunchMode
|
||||
try:
|
||||
affected_sdk = int(
|
||||
man_data_dic['min_sdk']) < ANDROID_5_0_LEVEL
|
||||
except Exception:
|
||||
# in case min_sdk is not defined we assume vulnerability
|
||||
affected_sdk = True
|
||||
launchmode = node.getAttribute(f'{ns}:launchMode')
|
||||
item = node.getAttribute(f'{ns}:name')
|
||||
ret_list.append(('task_affinity_set', (item,), ()))
|
||||
modes = ('singleTask', 'singleInstance')
|
||||
if (affected_sdk
|
||||
and launchmode in modes):
|
||||
ret_list.append(('non_standard_launchmode', (item,), ()))
|
||||
|
||||
# LaunchMode
|
||||
try:
|
||||
affected_sdk = int(
|
||||
man_data_dic['min_sdk']) < ANDROID_5_0_LEVEL
|
||||
except Exception:
|
||||
# in case min_sdk is not defined we assume vulnerability
|
||||
affected_sdk = True
|
||||
# Android Task Hijacking or StrandHogg 1.0
|
||||
try:
|
||||
target_sdk = int(man_data_dic['target_sdk'])
|
||||
except Exception:
|
||||
target_sdk = ANDROID_8_0_LEVEL
|
||||
if (target_sdk < ANDROID_9_0_LEVEL
|
||||
and launchmode == 'singleTask'):
|
||||
ret_list.append(('task_hijacking', (item,), ()))
|
||||
|
||||
# Android StrandHogg 2.0
|
||||
exported_act = node.getAttribute(f'{ns}:exported')
|
||||
if (target_sdk < ANDROID_10_0_LEVEL
|
||||
and itemname in ['Activity', 'Activity-Alias']
|
||||
and exported_act == 'true'
|
||||
and (launchmode != 'singleInstance' or task_affinity != '')):
|
||||
ret_list.append(('task_hijacking2', (item,), ()))
|
||||
|
||||
if (
|
||||
affected_sdk and
|
||||
itemname in ['Activity', 'Activity-Alias'] and
|
||||
(node.getAttribute(f'{ns}:launchMode') == 'singleInstance'
|
||||
or node.getAttribute(f'{ns}:launchMode') == 'singleTask')):
|
||||
item = node.getAttribute(f'{ns}:name')
|
||||
ret_list.append(('non_standard_launchmode', (item,), ()))
|
||||
# Exported Check
|
||||
item = ''
|
||||
is_inf = False
|
||||
|
||||
@@ -4,6 +4,10 @@ import logging
|
||||
from xml.dom import minidom
|
||||
from pathlib import Path
|
||||
|
||||
from mobsf.MobSF.utils import (
|
||||
is_path_traversal,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
HIGH = 'high'
|
||||
WARNING = 'warning'
|
||||
@@ -13,7 +17,7 @@ SECURE = 'secure'
|
||||
|
||||
def read_netsec_config(app_dir, config, src_type):
|
||||
"""Read the manifest file."""
|
||||
msg = 'Reading Network Security Config'
|
||||
msg = 'Reading Network Security config'
|
||||
try:
|
||||
config_file = None
|
||||
config = config.replace('@xml/', '', 1)
|
||||
@@ -24,14 +28,20 @@ def read_netsec_config(app_dir, config, src_type):
|
||||
else:
|
||||
# APK
|
||||
xml_dir = base / 'apktool_out' / 'res' / 'xml'
|
||||
if not is_path_traversal(config):
|
||||
netsec_file = xml_dir / f'{config}.xml'
|
||||
if netsec_file.exists():
|
||||
logger.info('%s from %s.xml', msg, config)
|
||||
return netsec_file.read_text('utf8', 'ignore')
|
||||
# Couldn't find the file defined in manifest
|
||||
xmls = Path(xml_dir).glob('*.xml')
|
||||
for xml in xmls:
|
||||
if xml.stem in [config, 'network_security_config']:
|
||||
if 'network_security' in xml.stem:
|
||||
config_file = xml
|
||||
break
|
||||
if not config_file:
|
||||
return None
|
||||
logger.info(msg)
|
||||
logger.info('%s from %s', msg, config_file.name)
|
||||
return config_file.read_text('utf8', 'ignore')
|
||||
except Exception:
|
||||
logger.exception(msg)
|
||||
@@ -50,7 +60,7 @@ def analysis(app_dir, config, is_debuggable, src_type):
|
||||
netsec_conf = read_netsec_config(app_dir, config, src_type)
|
||||
if not netsec_conf:
|
||||
return netsec
|
||||
logger.info('Parsing Network Security Config')
|
||||
logger.info('Parsing Network Security config')
|
||||
parsed = minidom.parseString(netsec_conf)
|
||||
finds = []
|
||||
summary = {HIGH: 0, WARNING: 0, INFO: 0, SECURE: 0}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# coding=utf-8
|
||||
import shutil
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import lief
|
||||
|
||||
@@ -75,7 +76,12 @@ class MachOChecksec:
|
||||
'to execute reliably.')
|
||||
else:
|
||||
severity = 'high'
|
||||
if self.macho_name.endswith('.dylib'):
|
||||
ext = Path(self.macho_name).suffix
|
||||
# PIE check not applicable for static and dynamic libraries
|
||||
# https://github.com/MobSF/Mobile-Security-Framework-MobSF/
|
||||
# issues/2290#issuecomment-1837272113
|
||||
if (ext == '.dylib'
|
||||
or (not ext and '.framework' in self.macho_name)):
|
||||
severity = 'info'
|
||||
desc = (
|
||||
'The binary is built without Position '
|
||||
@@ -86,7 +92,7 @@ class MachOChecksec:
|
||||
'the address space positions of key data areas of a '
|
||||
'process, including the base of the executable and the '
|
||||
'positions of the stack,heap and libraries. Use compiler '
|
||||
'option -fPIC to enable Position Independent Code.'
|
||||
'option -fPIC to enable Position Independent Code. '
|
||||
'Not applicable for dylibs and static libraries.')
|
||||
macho_dict['pie'] = {
|
||||
'has_pie': has_pie,
|
||||
|
||||
@@ -13,7 +13,7 @@ logger = logging.getLogger(__name__)
|
||||
def get_desc(desc_str, match):
|
||||
"""Generate formatted detailed description with matches."""
|
||||
return desc_str.format(
|
||||
b', '.join(list(set(match))).decode('utf-8', 'ignore'))
|
||||
b', '.join(sorted(set(match))).decode('utf-8', 'ignore'))
|
||||
|
||||
|
||||
def _add_bfindings(findings, desc, detailed_desc, rule):
|
||||
|
||||
@@ -22,6 +22,19 @@ class _SourceType(Enum):
|
||||
nocode = 'No Code'
|
||||
|
||||
|
||||
def merge_findings(swift, objc):
|
||||
code_analysis = {}
|
||||
# Add all unique keys
|
||||
for k in swift:
|
||||
if k in objc:
|
||||
swift[k]['files'].update(objc[k]['files'])
|
||||
code_analysis[k] = swift[k]
|
||||
for k in objc:
|
||||
if k not in code_analysis:
|
||||
code_analysis[k] = objc[k]
|
||||
return code_analysis
|
||||
|
||||
|
||||
def ios_source_analysis(src):
|
||||
"""IOS Objective-C and Swift Code Analysis."""
|
||||
try:
|
||||
@@ -40,20 +53,22 @@ def ios_source_analysis(src):
|
||||
source_types = set()
|
||||
|
||||
# Code and API Analysis
|
||||
code_findings = scan(
|
||||
objc_findings = scan(
|
||||
objective_c_rules.as_posix(),
|
||||
{'.m'},
|
||||
[src],
|
||||
settings.SKIP_CLASS_PATH)
|
||||
if code_findings:
|
||||
if objc_findings:
|
||||
source_types.add(_SourceType.objc)
|
||||
code_findings.update(scan(
|
||||
swift_findings = scan(
|
||||
swift_rules.as_posix(),
|
||||
{'.swift'},
|
||||
[src],
|
||||
settings.SKIP_CLASS_PATH))
|
||||
if code_findings:
|
||||
settings.SKIP_CLASS_PATH)
|
||||
if swift_findings:
|
||||
source_types.add(_SourceType.swift)
|
||||
code_findings = merge_findings(swift_findings, objc_findings)
|
||||
# API Analysis
|
||||
api_findings = scan(
|
||||
api_rules.as_posix(),
|
||||
{'.m', '.swift'},
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
"""iOS File Analysis."""
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from django.utils.html import escape
|
||||
|
||||
@@ -39,15 +39,15 @@ def ios_list_files(src, md5_hash, binary_form, mode):
|
||||
fileparam = file_path.replace(src, '')
|
||||
filez.append(fileparam)
|
||||
full_paths.append(file_path)
|
||||
ext = jfile.split('.')[-1]
|
||||
if re.search(r'cer|pem|cert|crt|pub|key|pfx|p12|der', ext):
|
||||
ext = Path(jfile).suffix
|
||||
if ext in ('.cer', '.pem', '.cert', '.crt',
|
||||
'.pub', '.key', '.pfx', '.p12', '.der'):
|
||||
certz.append({
|
||||
'file_path': escape(file_path.replace(src, '')),
|
||||
'type': None,
|
||||
'hash': None,
|
||||
})
|
||||
|
||||
if re.search(r'^db$|^sqlitedb$|^sqlite$', ext):
|
||||
if ext in ('.db', '.sqlitedb', '.sqlite', '.sqlite3'):
|
||||
database.append({
|
||||
'file_path': escape(fileparam),
|
||||
'type': mode,
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
type: Regex
|
||||
metadata:
|
||||
cvss: 7.5
|
||||
cwe: CWE-532
|
||||
cwe: cwe-532
|
||||
masvs: storage-3
|
||||
owasp-mobile: ''
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x06i-Testing-Code-Quality-and-Build-Settings.md#finding-debugging-code-and-verbose-error-logging-mstg-code-4
|
||||
@@ -131,7 +131,7 @@
|
||||
type: RegexOr
|
||||
metadata:
|
||||
cvss: 5.9
|
||||
cwe: CWE-327
|
||||
cwe: cwe-327
|
||||
masvs: crypto-4
|
||||
owasp-mobile: m5
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x04g-Testing-Cryptography.md#identifying-insecure-andor-deprecated-cryptographic-algorithms-mstg-crypto-4
|
||||
@@ -144,7 +144,7 @@
|
||||
type: RegexOr
|
||||
metadata:
|
||||
cvss: 5.9
|
||||
cwe: CWE-327
|
||||
cwe: cwe-327
|
||||
masvs: crypto-4
|
||||
owasp-mobile: m5
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x04g-Testing-Cryptography.md#identifying-insecure-andor-deprecated-cryptographic-algorithms-mstg-crypto-4
|
||||
@@ -157,7 +157,7 @@
|
||||
type: RegexOr
|
||||
metadata:
|
||||
cvss: 5.9
|
||||
cwe: CWE-327
|
||||
cwe: cwe-327
|
||||
masvs: crypto-4
|
||||
owasp-mobile: m5
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x04g-Testing-Cryptography.md#identifying-insecure-andor-deprecated-cryptographic-algorithms-mstg-crypto-4
|
||||
@@ -171,7 +171,7 @@
|
||||
type: RegexOr
|
||||
metadata:
|
||||
cvss: 5.9
|
||||
cwe: CWE-327
|
||||
cwe: cwe-327
|
||||
masvs: crypto-4
|
||||
owasp-mobile: m5
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x04g-Testing-Cryptography.md#identifying-insecure-andor-deprecated-cryptographic-algorithms-mstg-crypto-4
|
||||
@@ -185,7 +185,7 @@
|
||||
type: RegexOr
|
||||
metadata:
|
||||
cvss: 5.9
|
||||
cwe: CWE-327
|
||||
cwe: cwe-327
|
||||
masvs: crypto-4
|
||||
owasp-mobile: m5
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x04g-Testing-Cryptography.md#identifying-insecure-andor-deprecated-cryptographic-algorithms-mstg-crypto-4
|
||||
@@ -344,7 +344,7 @@
|
||||
type: Regex
|
||||
metadata:
|
||||
cvss: 4.3
|
||||
cwe: CWE-311
|
||||
cwe: cwe-311
|
||||
masvs: storage-1
|
||||
owasp-mobile: m2
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x06d-Testing-Data-Storage.md#ios-data-storage
|
||||
@@ -410,7 +410,7 @@
|
||||
type: RegexOr
|
||||
metadata:
|
||||
cvss: 0
|
||||
cwe: CWE-295
|
||||
cwe: cwe-295
|
||||
masvs: network-4
|
||||
owasp-mobile: m3
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x05g-Testing-Network-Communication.md#testing-custom-certificate-stores-and-certificate-pinning-mstg-network-4
|
||||
@@ -422,7 +422,7 @@
|
||||
type: Regex
|
||||
metadata:
|
||||
cvss: 0
|
||||
cwe: CWE-311
|
||||
cwe: cwe-311
|
||||
masvs: storage-14
|
||||
owasp-mobile: m2
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x06d-Testing-Data-Storage.md#realm-databases
|
||||
@@ -436,7 +436,7 @@
|
||||
type: RegexAnd
|
||||
metadata:
|
||||
cvss: 0
|
||||
cwe: CWE-311
|
||||
cwe: cwe-311
|
||||
masvs: storage-14
|
||||
owasp-mobile: m2
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x06d-Testing-Data-Storage.md#coredata
|
||||
@@ -450,7 +450,7 @@
|
||||
type: RegexAnd
|
||||
metadata:
|
||||
cvss: 0
|
||||
cwe: CWE-311
|
||||
cwe: cwe-311
|
||||
masvs: storage-14
|
||||
owasp-mobile: m2
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x06d-Testing-Data-Storage.md#realm-databases
|
||||
@@ -475,7 +475,7 @@
|
||||
type: Regex
|
||||
metadata:
|
||||
cvss: 0
|
||||
cwe: CWE-939
|
||||
cwe: cwe-939
|
||||
masvs: platform-3
|
||||
owasp-mobile: m1
|
||||
- id: ios_sensitive_backup
|
||||
@@ -517,7 +517,7 @@
|
||||
type: RegexAndOr
|
||||
metadata:
|
||||
cvss: 7.5
|
||||
cwe: CWE-757
|
||||
cwe: cwe-757
|
||||
masvs: network-2
|
||||
owasp-mobile: m3
|
||||
ref: https://github.com/MobSF/owasp-mstg/blob/master/Document/0x04f-Testing-Network-Communication.md#verifying-data-encryption-on-the-network-mstg-network-1-and-mstg-network-2
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<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">REST API</a></li>
|
||||
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'api_docs' %}" class="nav-link">API</a></li>
|
||||
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'donate' %}" class="nav-link">DONATE ♥</a></li>
|
||||
<li class="nav-item d-none d-sm-inline-block"><a target="_blank" href="https://mobsf.github.io/docs/#/" class="nav-link">DOCS</a></li>
|
||||
<li class="nav-item d-none d-sm-inline-block"><a href="{% url 'about' %}" class="nav-link">ABOUT</a></li>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<h1>About Mobile Security Framework</h1>
|
||||
|
||||
<p class="lead">
|
||||
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. MobSF support mobile app binaries (APK, XAPK, IPA & APPX) along with zipped source code and provides REST APIs for seamless integration with your CI/CD or DevSecOps pipeline. The Dynamic Analyzer helps you to perform runtime security assessment and interactive instrumented testing.
|
||||
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. MobSF support mobile app binaries (APK, XAPK, IPA & APPX) along with zipped source code and provides APIs for seamless integration with your CI/CD or DevSecOps pipeline. The Dynamic Analyzer helps you to perform runtime security assessment and interactive instrumented testing.
|
||||
</p>
|
||||
<p> <strong>Author:</strong> <a href="//twitter.com/ajinabraham">Ajin Abraham</a> </p>
|
||||
<h2>Active Collaborators</h2>
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h1><strong>REST API Docs</strong></h1>
|
||||
<h1><strong>API Docs</strong></h1>
|
||||
<p class="lead">
|
||||
REST API Key: <strong><code>{{ api_key}}</code></strong>
|
||||
API Key: <strong><code>{{ api_key}}</code></strong>
|
||||
</p>
|
||||
|
||||
<!--API Docs -->
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
<a class="nav-link" href="{% url 'dynamic' %}">DYNAMIC ANALYZER</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'api_docs' %}">REST API</a>
|
||||
<a class="nav-link" href="{% url 'api_docs' %}">API</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav ml-auto">
|
||||
@@ -88,7 +88,7 @@
|
||||
|
||||
|
||||
<div class="inner">
|
||||
<h6> <a href="{% url 'recent' %}">RECENT SCANS</a> | <a href="{% url 'dynamic' %}">DYNAMIC ANALYZER</a> | <a href="{% url 'api_docs' %}">REST API</a> | <a href="{% url 'donate' %}">DONATE ♥</a> | <a target="_blank"
|
||||
<h6> <a href="{% url 'recent' %}">RECENT SCANS</a> | <a href="{% url 'dynamic' %}">DYNAMIC ANALYZER</a> | <a href="{% url 'api_docs' %}">API</a> | <a href="{% url 'donate' %}">DONATE ♥</a> | <a target="_blank"
|
||||
href="https://mobsf.github.io/docs/#/">DOCS</a> | <a href="{% url 'about' %}">ABOUT</a></h6>
|
||||
</br>
|
||||
<p>© {% now "Y" %} Mobile Security Framework - MobSF {{ version }}</p>
|
||||
|
||||
@@ -812,10 +812,17 @@
|
||||
{{ details.metadata.description }}
|
||||
</td>
|
||||
<td>
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines }}"> {{ file_path }}</a>
|
||||
<br/>
|
||||
{% endfor %}
|
||||
<a class="btn btn-primary btn-xs" data-toggle="collapse" href="#collapseapi{{forloop.counter}}" role="button" aria-expanded="false" aria-controls="collapseapi{{forloop.counter}}">
|
||||
Show Files
|
||||
</a>
|
||||
<div class="collapse" id="collapseapi{{forloop.counter}}">
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<small>
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines }}"> {{ file_path }}</a>
|
||||
</small>
|
||||
</br>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -1301,10 +1308,26 @@
|
||||
{% if details.metadata.masvs %}</br> <strong>OWASP MASVS: </strong>{{ details.metadata.masvs }}{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines}}"> {{ file_path }}</a>
|
||||
<br/>
|
||||
{% endfor %}
|
||||
{% if details.files|length < 4 %}
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<small>
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines}}"> {{ file_path }}</a>
|
||||
</small>
|
||||
</br>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<a class="btn btn-primary btn-xs" data-toggle="collapse" href="#collapsecode{{forloop.counter}}" role="button" aria-expanded="false" aria-controls="collapsecode{{forloop.counter}}">
|
||||
Show Files
|
||||
</a>
|
||||
<div class="collapse" id="collapsecode{{forloop.counter}}">
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<small>
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines}}"> {{ file_path }}</a>
|
||||
</small>
|
||||
</br>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
||||
@@ -628,10 +628,17 @@
|
||||
{{ details.metadata.description }}
|
||||
</td>
|
||||
<td>
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines }}"> {{ file_path }}</a>
|
||||
<br/>
|
||||
{% endfor %}
|
||||
<a class="btn btn-primary btn-xs" data-toggle="collapse" href="#collapseapi{{forloop.counter}}" role="button" aria-expanded="false" aria-controls="collapseapi{{forloop.counter}}">
|
||||
Show Files
|
||||
</a>
|
||||
<div class="collapse" id="collapseapi{{forloop.counter}}">
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<small>
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines }}"> {{ file_path }}</a>
|
||||
</small>
|
||||
</br>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -1038,10 +1045,27 @@
|
||||
{% if details.metadata.masvs %}</br> <strong>OWASP MASVS: </strong>{{ details.metadata.masvs }}{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines }}"> {{ file_path }}</a>
|
||||
<br/>
|
||||
{% endfor %}
|
||||
{% if details.files|length < 4 %}
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<small>
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines }}"> {{ file_path }}</a>
|
||||
</small>
|
||||
</br>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<a class="btn btn-primary btn-xs" data-toggle="collapse" href="#collapsecode{{forloop.counter}}" role="button" aria-expanded="false" aria-controls="collapsecode{{forloop.counter}}">
|
||||
Show Files
|
||||
</a>
|
||||
<div class="collapse" id="collapsecode{{forloop.counter}}">
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<small>
|
||||
<a href="{% url "view_source" %}?file={{ file_path }}&md5={{ md5 }}&type={{app_type}}&lines={{ lines }}"> {{ file_path }}</a>
|
||||
</small>
|
||||
</br>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ sidebar-collapse
|
||||
// @Version: 0.0.2 (2015-02-18)
|
||||
*/
|
||||
</style>
|
||||
<link rel="stylesheet" href="{% static "others/css/spinner.css" %}">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<!-- Content Wrapper. Contains page content -->
|
||||
@@ -490,13 +491,31 @@ sidebar-collapse
|
||||
<!-- /.content -->
|
||||
</div>
|
||||
<!-- /.content-wrapper -->
|
||||
<!--Loader-->
|
||||
<div class="hidden loading">
|
||||
<div class='uil-ring-css' style='transform:scale(0.79);'>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% block extra_scripts %}
|
||||
<script src="{% static "chartjs/Chart.bundle.js" %}"></script>
|
||||
<script src="{% static "chartjs/chartjs-gauge.js" %}"></script>
|
||||
<script src="{% static "jqueryknob/jquery.knob.min.js" %}"></script>
|
||||
<script>
|
||||
|
||||
function dynamic_loader(){
|
||||
var loadingOverlay = document.querySelector('.loading');
|
||||
loadingOverlay.classList.remove('hidden');
|
||||
}
|
||||
function stop_loader(){
|
||||
var loadingOverlay = document.querySelector('.loading');
|
||||
loadingOverlay.classList.add('hidden');
|
||||
}
|
||||
dynamic_loader();
|
||||
document.onreadystatechange = function(){
|
||||
if(document.readyState=='loaded' || document.readyState=='complete')
|
||||
stop_loader();
|
||||
}
|
||||
// Severity
|
||||
|
||||
const high = {{ high | length }};
|
||||
|
||||
@@ -521,10 +521,17 @@
|
||||
{{ details.metadata.description }}
|
||||
</td>
|
||||
<td>
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<a href="{% url 'view_file_ios' %}?file={{ file_path }}&md5={{ md5 }}&type=ios&lines={{ lines }}"> {{ file_path }}</a>
|
||||
</br>
|
||||
{% endfor %}
|
||||
<a class="btn btn-primary btn-xs" data-toggle="collapse" href="#collapseapi{{forloop.counter}}" role="button" aria-expanded="false" aria-controls="collapseapi{{forloop.counter}}">
|
||||
Show Files
|
||||
</a>
|
||||
<div class="collapse" id="collapseapi{{forloop.counter}}">
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<small>
|
||||
<a href="{% url 'view_file_ios' %}?file={{ file_path }}&md5={{ md5 }}&type=ios&lines={{ lines }}"> {{ file_path }}</a>
|
||||
</small>
|
||||
</br>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
@@ -745,10 +752,26 @@
|
||||
{% if details.metadata.masvs %}</br> <strong>OWASP MASVS: </strong>{{ details.metadata.masvs }}{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<a href="{% url 'view_file_ios' %}?file={{ file_path }}&md5={{ md5 }}&type=ios&lines={{ lines }}"> {{ file_path }}</a>
|
||||
</br>
|
||||
{% endfor %}
|
||||
{% if details.files|length < 4 %}
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<small>
|
||||
<a href="{% url 'view_file_ios' %}?file={{ file_path }}&md5={{ md5 }}&type=ios&lines={{ lines }}"> {{ file_path }}</a>
|
||||
</small>
|
||||
</br>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<a class="btn btn-primary btn-xs" data-toggle="collapse" href="#collapsecode{{forloop.counter}}" role="button" aria-expanded="false" aria-controls="collapsecode{{forloop.counter}}">
|
||||
Show Files
|
||||
</a>
|
||||
<div class="collapse" id="collapsecode{{forloop.counter}}">
|
||||
{% for file_path, lines in details.files.items %}
|
||||
<small>
|
||||
<a href="{% url 'view_file_ios' %}?file={{ file_path }}&md5={{ md5 }}&type=ios&lines={{ lines }}"> {{ file_path }}</a>
|
||||
</small>
|
||||
</br>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "mobsf"
|
||||
version = "3.8.7"
|
||||
version = "3.8.8"
|
||||
description = "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."
|
||||
keywords = ["mobsf", "mobile security framework", "mobile security", "security tool", "static analysis", "dynamic analysis", "malware analysis"]
|
||||
authors = ["Ajin Abraham <[email protected]>"]
|
||||
|
||||
@@ -73,7 +73,7 @@ if __name__ == '__main__':
|
||||
'of a running MobSF Server. '
|
||||
'(ex: 127.0.0.1:8000)')
|
||||
parser.add_argument(
|
||||
'-k', '--apikey', help='MobSF REST API Key')
|
||||
'-k', '--apikey', help='MobSF API Key')
|
||||
parser.add_argument(
|
||||
'-r', '--rescan', help='Run a fresh scan. '
|
||||
'Value can be 1 or 0 (Default: 0)')
|
||||
@@ -86,7 +86,7 @@ if __name__ == '__main__':
|
||||
apikey = args.apikey
|
||||
rescan = args.rescan
|
||||
if not is_server_up(server_url):
|
||||
print('MobSF REST API Server is not running at ' + server_url)
|
||||
print('MobSF API Server is not running at ' + server_url)
|
||||
print('Exiting!')
|
||||
exit(0)
|
||||
# MobSF is running, start scan
|
||||
|
||||
Reference in New Issue
Block a user