From faf20f2d540c60a01065ea2f0196dfe099a4fa0b Mon Sep 17 00:00:00 2001 From: Ajin Abraham Date: Tue, 22 Sep 2020 09:22:31 -0400 Subject: [PATCH] Fix #1542 (#1543) Fix #1542 IPA can have Payload or payload directory. Speed up getting scan results of already scanned iOS ZIP source. Dockerfile optimisation for quick code change and build * sppedup ios zip, test fix --- Dockerfile | 14 +++++-- MobSF/settings.py | 2 +- .../views/android/static_analyzer.py | 23 ++++++++--- StaticAnalyzer/views/ios/static_analyzer.py | 39 ++++++++++++------- StaticAnalyzer/views/ios/view_source.py | 17 ++++++-- 5 files changed, 67 insertions(+), 28 deletions(-) diff --git a/Dockerfile b/Dockerfile index 29898ffa..ea85d0de 100644 --- a/Dockerfile +++ b/Dockerfile @@ -58,8 +58,9 @@ ENV PATH="$JAVA_HOME/bin:$PATH" WORKDIR /root/Mobile-Security-Framework-MobSF -# Copy source code -COPY . . +# Copy static +COPY requirements.txt . +COPY scripts/wheels/*.whl scripts/wheels/ # Install Requirements RUN pip3 install --no-index --find-links=scripts/wheels/ yara-python && \ @@ -77,8 +78,13 @@ RUN \ apt clean && \ apt autoclean && \ apt autoremove -y && \ - rm -rf /var/lib/apt/lists/* /tmp/* > /dev/null 2>&1 && \ - rm -rf /root/Mobile-Security-Framework-MobSF/scripts/wheels > /dev/null 2>&1 + rm -rf /var/lib/apt/lists/* /tmp/* > /dev/null 2>&1 + +# Copy source code +COPY . . + +# Remove Wheels +RUN rm -rf /root/Mobile-Security-Framework-MobSF/scripts/wheels > /dev/null 2>&1 # Enable Use Home Directory and set adb path RUN sed -i 's/USE_HOME = False/USE_HOME = True/g' MobSF/settings.py && \ diff --git a/MobSF/settings.py b/MobSF/settings.py index 510afd38..54204891 100644 --- a/MobSF/settings.py +++ b/MobSF/settings.py @@ -21,7 +21,7 @@ logger = logging.getLogger(__name__) # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -MOBSF_VER = 'v3.1.5 Beta' +MOBSF_VER = 'v3.1.6 Beta' BANNER = """ __ __ _ ____ _____ _____ _ diff --git a/StaticAnalyzer/views/android/static_analyzer.py b/StaticAnalyzer/views/android/static_analyzer.py index d3381f70..02167144 100755 --- a/StaticAnalyzer/views/android/static_analyzer.py +++ b/StaticAnalyzer/views/android/static_analyzer.py @@ -24,7 +24,10 @@ from MobSF.utils import ( print_n_send_error_response, ) -from StaticAnalyzer.models import StaticAnalyzerAndroid +from StaticAnalyzer.models import ( + StaticAnalyzerAndroid, + StaticAnalyzerIOS, +) from StaticAnalyzer.views.android.binary_analysis import (elf_analysis, res_analysis) from StaticAnalyzer.views.android.cert_analysis import ( @@ -281,6 +284,11 @@ def static_analyzer(request, api=False): else: return render(request, template, context) elif typ == 'zip': + ios_ret = HttpResponseRedirect( + '/StaticAnalyzer_iOS/?name=' + + app_dic['app_name'] + + '&type=ios&checksum=' + + app_dic['md5']) # Check if in DB # pylint: disable=E1101 cert_dic = { @@ -299,8 +307,15 @@ def static_analyzer(request, api=False): app_dic['app_dir'] = app_dic['app_dir'].as_posix() + '/' db_entry = StaticAnalyzerAndroid.objects.filter( MD5=app_dic['md5']) + ios_db_entry = StaticAnalyzerIOS.objects.filter( + MD5=app_dic['md5']) if db_entry.exists() and rescan == '0': context = get_context_from_db_entry(db_entry) + elif ios_db_entry.exists() and rescan == '0': + if api: + return {'type': 'ios'} + else: + return ios_ret else: logger.info('Extracting ZIP') app_dic['files'] = unzip( @@ -312,11 +327,7 @@ def static_analyzer(request, api=False): if api: return {'type': 'ios'} else: - return HttpResponseRedirect( - '/StaticAnalyzer_iOS/?name=' - + app_dic['app_name'] - + '&type=ios&checksum=' - + app_dic['md5']) + return ios_ret app_dic['certz'] = get_hardcoded_cert_keystore( app_dic['files']) app_dic['zipped'] = pro_type diff --git a/StaticAnalyzer/views/ios/static_analyzer.py b/StaticAnalyzer/views/ios/static_analyzer.py index d5c6d242..ffa112c6 100755 --- a/StaticAnalyzer/views/ios/static_analyzer.py +++ b/StaticAnalyzer/views/ios/static_analyzer.py @@ -66,15 +66,14 @@ def static_analyzer_ios(request, api=False): app_dict['directory'] = Path(settings.BASE_DIR) # BASE DIR app_dict['file_name'] = filename # APP ORGINAL NAME app_dict['md5_hash'] = checksum # MD5 - app_dict['app_dir'] = Path(settings.UPLD_DIR) / checksum + app_dir = Path(settings.UPLD_DIR) / checksum tools_dir = app_dict[ 'directory'] / 'StaticAnalyzer' / 'tools' / 'ios' tools_dir = tools_dir.as_posix() if file_type == 'ipa': app_dict['app_file'] = app_dict[ 'md5_hash'] + '.ipa' # NEW FILENAME - app_dict['app_path'] = app_dict[ - 'app_dir'] / app_dict['app_file'] + app_dict['app_path'] = app_dir / app_dict['app_file'] app_dict['app_path'] = app_dict['app_path'].as_posix() # DB ipa_db = StaticAnalyzerIOS.objects.filter( @@ -82,11 +81,8 @@ def static_analyzer_ios(request, api=False): if ipa_db.exists() and rescan == '0': context = get_context_from_db_entry(ipa_db) else: - logger.info('iOS Binary (IPA) Analysis Started') - app_dict['bin_dir'] = app_dict['app_dir'] / 'Payload' - app_dict['bin_dir'] = app_dict['bin_dir'].as_posix() + '/' - app_dict['app_dir'] = app_dict['app_dir'].as_posix() + '/' + app_dict['app_dir'] = app_dir.as_posix() + '/' app_dict['size'] = str( file_size(app_dict['app_path'])) + 'MB' # FILE SIZE app_dict['sha1'], app_dict['sha256'] = hash_gen( @@ -94,8 +90,27 @@ def static_analyzer_ios(request, api=False): logger.info('Extracting IPA') # EXTRACT IPA unzip(app_dict['app_path'], app_dict['app_dir']) - # Get Files, normalize + to x, - # and convert binary plist -> xml + # Identify Payload directory + dirs = app_dir.glob('**/*') + for _dir in dirs: + if 'payload' in _dir.as_posix().lower(): + app_dict['bin_dir'] = app_dict['app_dir'] / _dir + break + else: + msg = ('IPA is malformed! ' + 'MobSF cannot find Payload directory') + if api: + return print_n_send_error_response( + request, + msg, + True) + else: + return print_n_send_error_response( + request, + msg, + False) + app_dict['bin_dir'] = app_dict['bin_dir'].as_posix() + '/' + # Get Files all_files = ios_list_files( app_dict['bin_dir'], app_dict['md5_hash'], True, 'ipa') infoplist_dict = plist_analysis(app_dict['bin_dir'], False) @@ -171,12 +186,10 @@ def static_analyzer_ios(request, api=False): logger.info('iOS Source Code Analysis Started') app_dict['app_file'] = app_dict[ 'md5_hash'] + '.zip' # NEW FILENAME - app_dict['app_path'] = app_dict[ - 'app_dir'] / app_dict['app_file'] + app_dict['app_path'] = app_dir / app_dict['app_file'] app_dict['app_path'] = app_dict['app_path'].as_posix() - app_dict['app_dir'] = app_dict['app_dir'].as_posix() + '/' + app_dict['app_dir'] = app_dir.as_posix() + '/' # ANALYSIS BEGINS - Already Unzipped - logger.info('ZIP Already Extracted') app_dict['size'] = str( file_size(app_dict['app_path'])) + 'MB' # FILE SIZE app_dict['sha1'], app_dict['sha256'] = hash_gen( diff --git a/StaticAnalyzer/views/ios/view_source.py b/StaticAnalyzer/views/ios/view_source.py index c7ea0eb6..a40308a9 100644 --- a/StaticAnalyzer/views/ios/view_source.py +++ b/StaticAnalyzer/views/ios/view_source.py @@ -5,6 +5,7 @@ import json import logging import ntpath import os +from pathlib import Path import biplist @@ -61,12 +62,20 @@ def run(request, api=False): if api: return err return print_n_send_error_response(request, err, False, exp) + base = Path(settings.UPLD_DIR) / md5_hash if mode == 'ipa': - src = os.path.join(settings.UPLD_DIR, - md5_hash + '/Payload/') + src1 = base / 'payload' + src2 = base / 'Payload' + if src1.exists(): + src = src1 + elif src2.exists(): + src = src2 + else: + raise Exception('MobSF cannot find Payload directory') elif mode == 'ios': - src = os.path.join(settings.UPLD_DIR, md5_hash + '/') - sfile = os.path.join(src, fil) + src = base + sfile = src / fil + sfile = sfile.as_posix() if not is_safe_path(src, sfile): msg = 'Path Traversal Detected!' if api: