Skip to content

Commit

Permalink
Added support task hijacking detection, improved manifest analysis, a…
Browse files Browse the repository at this point in the history
…dded new check for old version, ui changes, file analysis improvements
  • Loading branch information
ajinabraham committed Dec 17, 2023
1 parent 328dcef commit 823e2ff
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 65 deletions.
2 changes: 1 addition & 1 deletion mobsf/MobSF/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

logger = logging.getLogger(__name__)

VERSION = '3.8.7'
VERSION = '3.8.8'
BANNER = """
__ __ _ ____ _____ _____ ___
| \/ | ___ | |__/ ___|| ___|_ _|___ / ( _ )
Expand Down
65 changes: 57 additions & 8 deletions mobsf/StaticAnalyzer/views/android/android_manifest_desc.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,28 @@
'[android:networkSecurityConfig=%s]'),
},
'vulnerable_os_version': {
'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. 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>[minSdk=%s]'),
'<br>Android %s, minSdk=%s]'),
'level': 'warning',
'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.'),
' 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]',
Expand Down Expand Up @@ -104,7 +117,7 @@
},
'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'
Expand All @@ -114,9 +127,45 @@
' 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 '
Expand Down Expand Up @@ -343,7 +392,7 @@
'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.'),
Expand Down
7 changes: 4 additions & 3 deletions mobsf/StaticAnalyzer/views/android/cert_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.'
Expand Down
97 changes: 75 additions & 22 deletions mobsf/StaticAnalyzer/views/android/manifest_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,42 @@
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."""
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
10 changes: 5 additions & 5 deletions mobsf/StaticAnalyzer/views/ios/file_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand Down
39 changes: 31 additions & 8 deletions mobsf/templates/static_analysis/android_binary_analysis.html
Original file line number Diff line number Diff line change
Expand Up @@ -812,10 +812,17 @@ <h3>{{ providers | length }}</h3>
{{ details.metadata.description }}
</td>
<td>
{% for file_path, lines in details.files.items %}
<a href="{% url "view_source" %}?file={{ file_path }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;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 }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;lines={{ lines }}"> {{ file_path }}</a>
</small>
</br>
{% endfor %}
</div>
</td>
</tr>
{% endfor %}
Expand Down Expand Up @@ -1301,10 +1308,26 @@ <h5 class="description-header">{{ code_analysis.summary.suppressed }}</h5>
{% 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 }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;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 }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;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 }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;lines={{ lines}}"> {{ file_path }}</a>
</small>
</br>
{% endfor %}
</div>
{% endif %}
</td>
<td>

Expand Down
40 changes: 32 additions & 8 deletions mobsf/templates/static_analysis/android_source_analysis.html
Original file line number Diff line number Diff line change
Expand Up @@ -628,10 +628,17 @@ <h3>{{ providers | length }}</h3>
{{ details.metadata.description }}
</td>
<td>
{% for file_path, lines in details.files.items %}
<a href="{% url "view_source" %}?file={{ file_path }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;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 }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;lines={{ lines }}"> {{ file_path }}</a>
</small>
</br>
{% endfor %}
</div>
</td>
</tr>
{% endfor %}
Expand Down Expand Up @@ -1038,10 +1045,27 @@ <h5 class="description-header">{{ code_analysis.summary.suppressed }}</h5>
{% 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 }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;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 }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;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 }}&amp;md5={{ md5 }}&amp;type={{app_type}}&amp;lines={{ lines }}"> {{ file_path }}</a>
</small>
</br>
{% endfor %}
</div>
{% endif %}

</td>
<td>

Expand Down
Loading

0 comments on commit 823e2ff

Please sign in to comment.