diff --git a/mobsf/DynamicAnalyzer/views/android/dynamic_analyzer.py b/mobsf/DynamicAnalyzer/views/android/dynamic_analyzer.py index aaa8422316..d80a75298c 100755 --- a/mobsf/DynamicAnalyzer/views/android/dynamic_analyzer.py +++ b/mobsf/DynamicAnalyzer/views/android/dynamic_analyzer.py @@ -121,7 +121,7 @@ def dynamic_analyzer(request, checksum, api=False): # in REST API return print_n_send_error_response( request, - 'Invalid Parameters', + 'Invalid Hash', api) package = get_package_name(checksum) if not package: diff --git a/mobsf/DynamicAnalyzer/views/android/report.py b/mobsf/DynamicAnalyzer/views/android/report.py index 453e5bb770..2f1380ca41 100644 --- a/mobsf/DynamicAnalyzer/views/android/report.py +++ b/mobsf/DynamicAnalyzer/views/android/report.py @@ -58,7 +58,7 @@ def view_report(request, checksum, api=False): # in REST API return print_n_send_error_response( request, - 'Invalid Parameters', + 'Invalid Hash', api) package = get_package_name(checksum) if not package: diff --git a/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py b/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py index b729de176a..e6a16b15ed 100644 --- a/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py +++ b/mobsf/DynamicAnalyzer/views/ios/corellium_instance.py @@ -386,7 +386,7 @@ def setup_environment(request, checksum, api=False): try: if not is_md5(checksum): # Additional Check for REST API - data['message'] = 'Invalid MD5 Hash' + data['message'] = 'Invalid Hash' return send_response(data, api) instance_id = request.POST['instance_id'] failed = common_check(instance_id) @@ -410,13 +410,16 @@ def setup_environment(request, checksum, api=False): # Install IPA msg = ca.install_ipa() if msg != OK: - out = '' if 'Please re-sign.' in msg: # Try AppSync IPA Install ci = CorelliumInstanceAPI(apikey, instance_id) out = appsync_ipa_install(ci.get_ssh_connection_string()) - if out != OK: - data['message'] = out + if out and out != OK: + data['message'] = out + return send_response(data, api) + else: + # Other install errors + data['message'] = msg return send_response(data, api) msg = 'Testing Environment is Ready!' logger.info(msg) @@ -687,7 +690,7 @@ def download_data(request, checksum, api=False): try: if not is_md5(checksum): # Additional Check for REST API - data['message'] = 'Invalid MD5 Hash' + data['message'] = 'Invalid Hash' return send_response(data, api) instance_id = request.POST['instance_id'] failed = common_check(instance_id) diff --git a/mobsf/DynamicAnalyzer/views/ios/report.py b/mobsf/DynamicAnalyzer/views/ios/report.py index db32182106..9e9e196c50 100644 --- a/mobsf/DynamicAnalyzer/views/ios/report.py +++ b/mobsf/DynamicAnalyzer/views/ios/report.py @@ -42,7 +42,7 @@ def ios_view_report(request, checksum, api=False): # in REST API return print_n_send_error_response( request, - 'Invalid Parameters', + 'Invalid Hash', api) instance_id = request.GET.get('instance_id') if instance_id and not common_check(instance_id): diff --git a/mobsf/MobSF/views/api/api_static_analysis.py b/mobsf/MobSF/views/api/api_static_analysis.py index e61cebf36b..bf3bcaaf4a 100755 --- a/mobsf/MobSF/views/api/api_static_analysis.py +++ b/mobsf/MobSF/views/api/api_static_analysis.py @@ -1,13 +1,14 @@ # -*- coding: utf_8 -*- """MobSF REST API V 1.""" -import re - from django.http import HttpResponse from django.views.decorators.csrf import csrf_exempt from mobsf.StaticAnalyzer.models import ( RecentScansDB, ) +from mobsf.MobSF.utils import ( + is_md5, +) from mobsf.MobSF.views.helpers import request_method from mobsf.MobSF.views.home import RecentScans, Upload, delete_scan from mobsf.MobSF.views.api.api_middleware import make_api_response @@ -56,7 +57,7 @@ def api_scan(request): return make_api_response( {'error': 'Missing Parameters'}, 422) checksum = request.POST['hash'] - if not re.match('^[0-9a-f]{32}$', checksum): + if not is_md5(checksum): return make_api_response( {'error': 'Invalid Checksum'}, 500) robj = RecentScansDB.objects.filter(MD5=checksum) diff --git a/mobsf/MobSF/views/home.py b/mobsf/MobSF/views/home.py index 6f071416db..c4cf9a2a7a 100755 --- a/mobsf/MobSF/views/home.py +++ b/mobsf/MobSF/views/home.py @@ -25,6 +25,7 @@ get_md5, is_dir_exists, is_file_exists, + is_md5, is_safe_path, key, print_n_send_error_response, @@ -334,8 +335,7 @@ def generate_download(request): logger.info('Generating Downloads') md5 = request.GET['hash'] file_type = request.GET['file_type'] - match = re.match('^[0-9a-f]{32}$', md5) - if (not match + if (not is_md5(md5) or file_type not in binary + source): msg = 'Invalid download type or hash' logger.exception(msg) diff --git a/mobsf/StaticAnalyzer/forms.py b/mobsf/StaticAnalyzer/forms.py index 83fef5b5d5..5bd6d0587f 100644 --- a/mobsf/StaticAnalyzer/forms.py +++ b/mobsf/StaticAnalyzer/forms.py @@ -3,6 +3,8 @@ from django import forms +from mobsf.MobSF.utils import is_md5 + class AttackDetect(forms.Form): file = forms.CharField() @@ -36,8 +38,7 @@ class APIChecks(forms.Form): def clean_hash(self): """Hash is valid.""" md5 = self.cleaned_data['hash'] - md5_match = re.match('^[0-9a-f]{32}$', md5) - if not md5_match: + if not is_md5(md5): raise forms.ValidationError('Invalid Hash') return md5 @@ -48,8 +49,7 @@ class WebChecks(forms.Form): def clean_md5(self): """Hash is valid.""" md5 = self.cleaned_data['md5'] - md5_match = re.match('^[0-9a-f]{32}$', md5) - if not md5_match: + if not is_md5(md5): raise forms.ValidationError('Invalid Hash') return md5 diff --git a/mobsf/StaticAnalyzer/views/android/find.py b/mobsf/StaticAnalyzer/views/android/find.py index 5dc19acec6..da3351ea48 100755 --- a/mobsf/StaticAnalyzer/views/android/find.py +++ b/mobsf/StaticAnalyzer/views/android/find.py @@ -2,7 +2,6 @@ """Find in java or smali files.""" import logging -import re import json from pathlib import Path @@ -10,7 +9,10 @@ from django.http import JsonResponse from django.utils.html import escape -from mobsf.MobSF.utils import print_n_send_error_response +from mobsf.MobSF.utils import ( + is_md5, + print_n_send_error_response, +) from mobsf.StaticAnalyzer.views.common.shared_func import ( find_java_source_folder, ) @@ -21,9 +23,8 @@ def run(request): """Find filename/content in source files (ajax response).""" try: - match = re.match('^[0-9a-f]{32}$', request.POST['md5']) - if not match: - raise ValueError('Invalid MD5 hash') + if not is_md5(request.POST['md5']): + raise ValueError('Invalid Hash') md5 = request.POST['md5'] query = request.POST['q'] code = request.POST['code'] diff --git a/mobsf/StaticAnalyzer/views/android/manifest_view.py b/mobsf/StaticAnalyzer/views/android/manifest_view.py index e64fcebd47..61929c0386 100755 --- a/mobsf/StaticAnalyzer/views/android/manifest_view.py +++ b/mobsf/StaticAnalyzer/views/android/manifest_view.py @@ -3,13 +3,15 @@ import logging import os -import re from pathlib import Path from django.conf import settings from django.shortcuts import render -from mobsf.MobSF.utils import print_n_send_error_response +from mobsf.MobSF.utils import ( + is_md5, + print_n_send_error_response, +) from mobsf.StaticAnalyzer.views.android.manifest_utils import ( get_manifest_file, ) @@ -20,10 +22,10 @@ def run(request, checksum): """View the manifest.""" try: + supported = ['eclipse', 'studio', 'apk', 'aar'] directory = settings.BASE_DIR # BASE DIR typ = request.GET['type'] # APK or SOURCE - match = re.match('^[0-9a-f]{32}$', checksum) - if match and (typ in ['eclipse', 'studio', 'apk', 'aar']): + if is_md5(checksum) and (typ in supported): app_dir = os.path.join( settings.UPLD_DIR, checksum + '/') # APP DIRECTORY tools_dir = os.path.join( diff --git a/mobsf/StaticAnalyzer/views/android/source_tree.py b/mobsf/StaticAnalyzer/views/android/source_tree.py index dede2b3644..206e75b049 100644 --- a/mobsf/StaticAnalyzer/views/android/source_tree.py +++ b/mobsf/StaticAnalyzer/views/android/source_tree.py @@ -2,7 +2,6 @@ """List all java files.""" import logging -import re from pathlib import Path from django.conf import settings @@ -13,6 +12,7 @@ from mobsf.MobSF.utils import ( api_key, + is_md5, print_n_send_error_response, ) from mobsf.StaticAnalyzer.views.common.shared_func import ( @@ -45,8 +45,7 @@ def run(request): """Source Tree - Java/Smali view.""" try: logger.info('Listing Source files') - match = re.match('^[0-9a-f]{32}$', request.GET['md5']) - if not match: + if not is_md5(request.GET['md5']): return print_n_send_error_response(request, 'Scan hash not found') md5 = request.GET['md5'] typ = request.GET['type'] diff --git a/mobsf/StaticAnalyzer/views/android/static_analyzer.py b/mobsf/StaticAnalyzer/views/android/static_analyzer.py index c5e129484d..2390d32ed8 100755 --- a/mobsf/StaticAnalyzer/views/android/static_analyzer.py +++ b/mobsf/StaticAnalyzer/views/android/static_analyzer.py @@ -3,7 +3,6 @@ import logging import os -import re import shutil from pathlib import Path @@ -23,6 +22,7 @@ file_size, is_dir_exists, is_file_exists, + is_md5, key, print_n_send_error_response, ) @@ -106,13 +106,17 @@ def static_analyzer(request, checksum, api=False): rescan = True # Input validation app_dic = {} - if not re.match('^[0-9a-f]{32}$', checksum): - msg = 'Invalid checksum' - return print_n_send_error_response(request, msg, api) + if not is_md5(checksum): + return print_n_send_error_response( + request, + 'Invalid Hash', + api) robj = RecentScansDB.objects.filter(MD5=checksum) if not robj.exists(): - msg = 'The file is not uploaded/available' - return print_n_send_error_response(request, msg, api) + return print_n_send_error_response( + request, + 'The file is not uploaded/available', + api) typ = robj[0].SCAN_TYPE filename = robj[0].FILE_NAME allowed_exts = ( @@ -121,8 +125,10 @@ def static_analyzer(request, checksum, api=False): allowed_typ = [i.replace('.', '') for i in allowed_exts] if (not filename.lower().endswith(allowed_exts) or typ not in allowed_typ): - msg = 'Invalid file extension or file type' - return print_n_send_error_response(request, msg, api) + return print_n_send_error_response( + request, + 'Invalid file extension or file type', + api) app_dic['dir'] = Path(settings.BASE_DIR) # BASE DIR app_dic['app_name'] = filename # APP ORIGINAL NAME diff --git a/mobsf/StaticAnalyzer/views/common/appsec.py b/mobsf/StaticAnalyzer/views/common/appsec.py index 7d167275b8..fe0887e1d8 100644 --- a/mobsf/StaticAnalyzer/views/common/appsec.py +++ b/mobsf/StaticAnalyzer/views/common/appsec.py @@ -10,6 +10,7 @@ from mobsf.MobSF import settings from mobsf.MobSF.utils import ( + is_md5, print_n_send_error_response, ) from mobsf.StaticAnalyzer.models import ( @@ -349,6 +350,13 @@ def get_ios_dashboard(context, from_ctx=False): def appsec_dashboard(request, checksum, api=False): """Provide data for appsec dashboard.""" try: + if not is_md5(checksum): + # We need this check since checksum is not validated + # in REST API + return print_n_send_error_response( + request, + 'Invalid Hash', + api) android_static_db = StaticAnalyzerAndroid.objects.filter( MD5=checksum) ios_static_db = StaticAnalyzerIOS.objects.filter( @@ -362,7 +370,7 @@ def appsec_dashboard(request, checksum, api=False): return {'not_found': 'Report not found or supported'} else: msg = 'Report not found or supported' - return print_n_send_error_response(request, msg) + return print_n_send_error_response(request, msg, api) context['version'] = settings.MOBSF_VER context['title'] = 'AppSec Scorecard' context['efr01'] = True if settings.EFR_01 == '1' else False diff --git a/mobsf/StaticAnalyzer/views/common/pdf.py b/mobsf/StaticAnalyzer/views/common/pdf.py index bf26244abd..dc0661adf4 100644 --- a/mobsf/StaticAnalyzer/views/common/pdf.py +++ b/mobsf/StaticAnalyzer/views/common/pdf.py @@ -7,7 +7,6 @@ import json import logging import os -import re import platform from django.http import HttpResponse @@ -16,6 +15,7 @@ import mobsf.MalwareAnalyzer.views.VirusTotal as VirusTotal from mobsf.MobSF import settings from mobsf.MobSF.utils import ( + is_md5, print_n_send_error_response, upstream_proxy, ) @@ -52,13 +52,12 @@ def pdf(request, checksum, api=False, jsonres=False): try: - hash_match = re.match('^[0-9a-f]{32}$', checksum) - if not hash_match: + if not is_md5(checksum): if api: - return {'error': 'Invalid scan hash'} + return {'error': 'Invalid Hash'} else: return HttpResponse( - json.dumps({'md5': 'Invalid scan hash'}), + json.dumps({'md5': 'Invalid Hash'}), content_type=ctype, status=500) # Do Lookups android_static_db = StaticAnalyzerAndroid.objects.filter( diff --git a/mobsf/StaticAnalyzer/views/ios/static_analyzer.py b/mobsf/StaticAnalyzer/views/ios/static_analyzer.py index 5c9f918f6b..5446ce5e4f 100755 --- a/mobsf/StaticAnalyzer/views/ios/static_analyzer.py +++ b/mobsf/StaticAnalyzer/views/ios/static_analyzer.py @@ -1,7 +1,6 @@ # -*- coding: utf_8 -*- """iOS Static Code Analysis.""" import logging -import re from pathlib import Path import mobsf.MalwareAnalyzer.views.Trackers as Trackers @@ -12,6 +11,7 @@ from mobsf.MobSF.utils import ( file_size, + is_md5, print_n_send_error_response, ) from mobsf.StaticAnalyzer.models import ( @@ -78,21 +78,27 @@ def static_analyzer_ios(request, checksum, api=False): if re_scan == '1': rescan = True app_dict = {} - if not re.match('^[0-9a-f]{32}$', checksum): - msg = 'Invalid checksum' - return print_n_send_error_response(request, msg, api) + if not is_md5(checksum): + return print_n_send_error_response( + request, + 'Invalid Hash', + api) robj = RecentScansDB.objects.filter(MD5=checksum) if not robj.exists(): - msg = 'The file is not uploaded/available' - return print_n_send_error_response(request, msg, api) + return print_n_send_error_response( + request, + 'The file is not uploaded/available', + api) file_type = robj[0].SCAN_TYPE filename = robj[0].FILE_NAME allowed_exts = ('ios', '.ipa', '.zip', '.dylib', '.a') allowed_typ = [i.replace('.', '') for i in allowed_exts] if (not filename.lower().endswith(allowed_exts) or file_type not in allowed_typ): - msg = 'Invalid file extension or file type' - return print_n_send_error_response(request, msg, api) + return print_n_send_error_response( + request, + 'Invalid file extension or file type', + api) app_dict['directory'] = Path(settings.BASE_DIR) # BASE DIR app_dict['file_name'] = filename # APP ORIGINAL NAME diff --git a/mobsf/StaticAnalyzer/views/windows/windows.py b/mobsf/StaticAnalyzer/views/windows/windows.py index 9d4f051023..6f6a3fb12d 100755 --- a/mobsf/StaticAnalyzer/views/windows/windows.py +++ b/mobsf/StaticAnalyzer/views/windows/windows.py @@ -25,6 +25,7 @@ from mobsf.MobSF.utils import ( file_size, get_config_loc, + is_md5, print_n_send_error_response, ) from mobsf.MobSF.views.home import update_scan_timestamp @@ -70,18 +71,24 @@ def staticanalyzer_windows(request, checksum, api=False): re_scan = request.GET.get('rescan', 0) if re_scan == '1': rescan = True - if not re.match('^[0-9a-f]{32}$', checksum): - msg = 'Invalid checksum' - return print_n_send_error_response(request, msg, api) + if not is_md5(checksum): + return print_n_send_error_response( + request, + 'Invalid Hash', + api) robj = RecentScansDB.objects.filter(MD5=checksum) if not robj.exists(): - msg = 'The file is not uploaded/available' - return print_n_send_error_response(request, msg, api) + return print_n_send_error_response( + request, + 'The file is not uploaded/available', + api) typ = robj[0].SCAN_TYPE filename = robj[0].FILE_NAME if typ != 'appx': - msg = 'File type not supported' - return print_n_send_error_response(request, msg, api) + return print_n_send_error_response( + request, + 'File type not supported', + api) app_dic['app_name'] = filename # APP ORIGINAL NAME app_dic['md5'] = checksum