Skip to content

Commit

Permalink
Merge pull request #10 from MobSF/master
Browse files Browse the repository at this point in the history
Update from the upstream
  • Loading branch information
pavelkrcma authored Jan 29, 2024
2 parents 09f9fb8 + 0a69464 commit f71e017
Show file tree
Hide file tree
Showing 10 changed files with 358 additions and 322 deletions.
10 changes: 7 additions & 3 deletions .github/SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ Please report all security issues [here](https://github.com/MobSF/Mobile-Securit

## Past Security Issues

* [Local file reading regression < 3.0.0](https://github.com/MobSF/Mobile-Security-Framework-MobSF/issues/1197)
* [Upload a malicious zip file can overwrite arbitary files >=v0.9.3.2 && <=0.9.4.1](https://github.com/MobSF/Mobile-Security-Framework-MobSF/issues/358)
* [Fix Local File Inclusion Vulnerability in ViewSource Function. Version <= v0.9.2](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/166)
| Vulnerability | Affected Versions |
| ------- | ------------------ |
| [Arbitrary Local file read in APK icon resource](https://github.com/MobSF/Mobile-Security-Framework-MobSF/commit/a58f8a8c0aa49e1581d97e19e8e2255ca96cd838) | `>=1.0.4, <=3.9.2` |
| [Remote Code Execution via arbitrary file overwrite vulnerability in apktool <2.9.2](https://github.com/MobSF/Mobile-Security-Framework-MobSF/commit/19c1b55c2c59596f2d43439926c9dc976cbeaec4), [[CVE-2024-21633]](https://github.com/0x33c0unt/CVE-2024-21633) | `<=3.9.1` |
| [Arbitrary Local file read regression](https://github.com/MobSF/Mobile-Security-Framework-MobSF/issues/1197) | `<3.0.0` |
| [Upload a malicious zip file can overwrite arbitary files](https://github.com/MobSF/Mobile-Security-Framework-MobSF/issues/358) | `>=0.9.3.2, <=0.9.4.1` |
| [Arbitrary Local file read](https://github.com/MobSF/Mobile-Security-Framework-MobSF/pull/166) | `<=0.9.2` |
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.9.1'
VERSION = '3.9.3'
BANNER = """
__ __ _ ____ _____ _____ ___
| \/ | ___ | |__/ ___|| ___|_ _|___ // _ \
Expand Down
Binary file not shown.
12 changes: 7 additions & 5 deletions mobsf/StaticAnalyzer/views/android/android_manifest_desc.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,15 @@
'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'
'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.'),
'also update the target SDK version (%s) of the '
'app to 28 or higher to fix this issue at '
'platform level.'),
'name': ('Activity (%s) is vulnerable to Android '
'Task Hijacking/StrandHogg.'),
},
Expand All @@ -180,8 +181,9 @@
'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.'),
'the target SDK version (%s) 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': {
Expand Down
6 changes: 3 additions & 3 deletions mobsf/StaticAnalyzer/views/android/cert_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ def get_pub_key_details(data):
elif isinstance(x509_public_key, dsa.DSAPublicKey):
alg = 'dsa'
dsa_parameters = x509_public_key.parameters()
p = dsa_parameters.p
q = dsa_parameters.q
g = dsa_parameters.g
p = dsa_parameters.parameter_numbers().p
q = dsa_parameters.parameter_numbers().q
g = dsa_parameters.parameter_numbers().g
y = x509_public_key.public_numbers().y
to_hash = f'{p}:{q}:{g}:{y}'
elif isinstance(x509_public_key, ec.EllipticCurvePublicKey):
Expand Down
6 changes: 6 additions & 0 deletions mobsf/StaticAnalyzer/views/android/icon_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from mobsf.MobSF.utils import (
find_java_binary,
is_file_exists,
is_path_traversal,
)


Expand Down Expand Up @@ -156,6 +157,8 @@ def get_icon_src(a, app_dic, res_dir):
icon_name = None
if a:
icon_name = a.get_app_icon(max_dpi=icon_resolution)
if is_path_traversal(icon_name):
icon_name = None
if not icon_name:
# androguard cannot find icon file.
icon_name = ''
Expand Down Expand Up @@ -196,6 +199,9 @@ def get_icon_src(a, app_dic, res_dir):
if icon_src.endswith('.xml'):
logger.warning('Cannot find icon file from xml')
icon_src = ''
elif not icon_src.endswith(('.png', '.svg', '.webp')):
logger.warning('Cannot find a valid icon file')
icon_src = ''
if not icon_name:
logger.warning('Cannot find icon file')
icon_src = ''
Expand Down
81 changes: 50 additions & 31 deletions mobsf/StaticAnalyzer/views/android/manifest_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging

import requests
from concurrent.futures import ThreadPoolExecutor

from mobsf.MobSF.utils import (
upstream_proxy,
Expand Down Expand Up @@ -53,39 +54,54 @@
'31': '12',
'32': '12L',
'33': '13',
'34': '14',
}


def assetlinks_check(act_name, well_knowns):
"""Well known assetlink check."""
findings = []
iden = 'sha256_cert_fingerprints'
try:
proxies, verify = upstream_proxy('https')
for host, w_url in well_knowns:

with ThreadPoolExecutor() as executor:
futures = []
for w_url, host in well_knowns.items():
logger.info(
'App Link Assetlinks Check - [%s] %s', act_name, host)
status = False
status_code = 0
try:
r = requests.get(w_url,
allow_redirects=True,
proxies=proxies,
verify=verify)
status_code = r.status_code
if (str(r.status_code).startswith('2')
and iden in str(r.json())):
status = True
except Exception:
pass
findings.append({
'url': w_url,
futures.append(
executor.submit(_check_url, host, w_url))
for future in futures:
findings.append(future.result())

return findings

def _check_url(host, w_url):
try:
iden = 'sha256_cert_fingerprints'
proxies, verify = upstream_proxy('https')
status = False
status_code = 0

r = requests.get(w_url,
allow_redirects=True,
proxies=proxies,
verify=verify,
timeout=5)

status_code = r.status_code
if (str(status_code).startswith('2') and iden in str(r.json())):
status = True

return {'url': w_url,
'host': host,
'status_code': status_code,
'status': status})
'status': status}

except Exception:
logger.exception('Well Known Assetlinks Check')
return findings
logger.error(f'Well Known Assetlinks Check for URL: {w_url}')
return {'url': w_url,
'host': host,
'status_code': None,
'status': False}


def get_browsable_activities(node, ns):
Expand All @@ -99,7 +115,7 @@ def get_browsable_activities(node, ns):
paths = []
path_prefixs = []
path_patterns = []
well_known = []
well_known = {}
well_known_path = '/.well-known/assetlinks.json'
catg = node.getElementsByTagName('category')
for cat in catg:
Expand Down Expand Up @@ -128,13 +144,17 @@ def get_browsable_activities(node, ns):
if path_pattern and path_pattern not in path_patterns:
path_patterns.append(path_pattern)
# Collect possible well-known paths
if scheme and scheme in ('http', 'https') and host:
if (scheme
and scheme in ('http', 'https')
and host
and host != '*'):
host = host.replace('*.', '')
shost = f'{scheme}://{host}'
if port:
c_url = f'{scheme}://{host}:{port}{well_known_path}'
c_url = f'{shost}:{port}{well_known_path}'
else:
c_url = f'{scheme}://{host}{well_known_path}'
if (host, c_url) not in well_known:
well_known.append((host, c_url))
c_url = f'{shost}{well_known_path}'
well_known[c_url] = shost
schemes = [scheme + '://' for scheme in schemes]
browse_dic['schemes'] = schemes
browse_dic['mime_types'] = mime_types
Expand Down Expand Up @@ -293,15 +313,14 @@ def manifest_analysis(mfxml, ns, man_data_dic, src_type, app_dir):
target_sdk = ANDROID_8_0_LEVEL
if (target_sdk < ANDROID_9_0_LEVEL
and launchmode == 'singleTask'):
ret_list.append(('task_hijacking', (item,), ()))
ret_list.append(('task_hijacking', (item,), (target_sdk,)))

# 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,), ()))
ret_list.append(('task_hijacking2', (item,), (target_sdk,)))

# Exported Check
item = ''
Expand Down
2 changes: 1 addition & 1 deletion mobsf/StaticAnalyzer/views/android/manifest_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def get_manifest_apk(app_path, app_dir, tools_dir):
and is_file_exists(settings.APKTOOL_BINARY)):
apktool_path = settings.APKTOOL_BINARY
else:
apktool_path = os.path.join(tools_dir, 'apktool_2.9.2.jar')
apktool_path = os.path.join(tools_dir, 'apktool_2.9.3.jar')
output_dir = os.path.join(app_dir, 'apktool_out')
args = [find_java_binary(),
'-jar',
Expand Down
Loading

0 comments on commit f71e017

Please sign in to comment.