def handle_xapk(app_dic): """Unzip and Extract APK.""" data = None checksum = app_dic['md5'] xapk = app_dic['app_dir'] / f'{checksum}.xapk' apk = app_dic['app_dir'] / f'{checksum}.apk' files = unzip(xapk.as_posix(), app_dic['app_dir']) if 'manifest.json' not in files: logger.error('Manifest file not found in XAPK') return False manifest = app_dic['app_dir'] / 'manifest.json' with open(manifest, encoding='utf8', errors='ignore') as f: data = load(f) if not data: logger.error('Manifest file is empty') return False apks = data.get('split_apks') if not apks: logger.error('Split APKs not found') return False for a in apks: if a['id'] == 'base': base_apk = app_dic['app_dir'] / a['file'] if is_safe_path(app_dic['app_dir'], base_apk): move(base_apk, apk) return True return None
def view_file(request, api=False): """View File.""" logger.info('Viewing File') try: typ = '' rtyp = '' dat = '' sql_dump = {} if api: fil = request.POST['file'] md5_hash = request.POST['hash'] typ = request.POST['type'] else: fil = request.GET['file'] md5_hash = request.GET['hash'] typ = request.GET['type'] if not is_md5(md5_hash): return print_n_send_error_response(request, 'Invalid Parameters', api) src = os.path.join(settings.UPLD_DIR, md5_hash, 'DYNAMIC_DeviceData/') sfile = os.path.join(src, fil) if not is_safe_path(src, sfile) or is_path_traversal(fil): err = 'Path Traversal Attack Detected' return print_n_send_error_response(request, err, api) with io.open( sfile, # lgtm [py/path-injection] mode='r', encoding='ISO-8859-1') as flip: dat = flip.read() if fil.endswith('.xml') and typ == 'xml': rtyp = 'xml' elif typ == 'db': dat = None sql_dump = read_sqlite(sfile) rtyp = 'asciidoc' elif typ == 'others': rtyp = 'asciidoc' else: err = 'File type not supported' return print_n_send_error_response(request, err, api) fil = escape(ntpath.basename(fil)) context = { 'title': fil, 'file': fil, 'data': dat, 'sqlite': sql_dump, 'type': rtyp, 'version': settings.MOBSF_VER, } template = 'general/view.html' if api: return context return render(request, template, context) except Exception: logger.exception('Viewing File') return print_n_send_error_response(request, 'Error Viewing File', api)
def run(request, api=False): """View the source of a file.""" try: logger.info('View Android Source File') exp = 'Error Description' if api: fil = request.POST['file'] md5 = request.POST['hash'] typ = request.POST['type'] viewsource_form = ViewSourceAndroidApiForm(request.POST) else: fil = request.GET['file'] md5 = request.GET['md5'] typ = request.GET['type'] viewsource_form = ViewSourceAndroidForm(request.GET) if not viewsource_form.is_valid(): err = FormUtil.errors_message(viewsource_form) return print_n_send_error_response(request, err, api, exp) base = Path(settings.UPLD_DIR) / md5 if typ == 'smali': src = base / 'smali_source' syntax = 'smali' else: try: src, syntax, _ = find_java_source_folder(base) except StopIteration: msg = 'Invalid Directory Structure' return print_n_send_error_response(request, msg, api) sfile = src / fil if not is_safe_path(src, sfile.as_posix()): msg = 'Path Traversal Detected!' return print_n_send_error_response(request, msg, api) context = { 'title': escape(ntpath.basename(fil)), 'file': escape(ntpath.basename(fil)), 'data': sfile.read_text('utf-8', 'ignore'), 'type': syntax, 'sqlite': {}, 'version': settings.MOBSF_VER, } template = 'general/view.html' if api: return context return render(request, template, context) except Exception as exp: logger.exception('Error Viewing Source') msg = str(exp) exp = exp.__doc__ return print_n_send_error_response(request, msg, api, exp)
def handle_split_apk(app_dic): """Unzip and Extract Split APKs.""" checksum = app_dic['md5'] apks = app_dic['app_dir'] / f'{checksum}.apk' # Check if previously extracted manifest = app_dic['app_dir'] / 'AndroidManifest.xml' if manifest.exists(): return True files = unzip(apks.as_posix(), app_dic['app_dir']) for apk in files: if not apk.startswith('config.') and apk.endswith('.apk'): full_path = app_dic['app_dir'] / apk if is_safe_path(app_dic['app_dir'], full_path): move(full_path, apks) return True return None
def get_script(request, api=False): """Get frida scripts from others.""" data = {'status': 'ok', 'content': ''} try: scripts = request.POST.getlist('scripts[]') others = os.path.join(settings.TOOLS_DIR, 'frida_scripts', 'others') script_ct = [] for script in scripts: script_file = os.path.join(others, script + '.js') if not is_safe_path(others, script_file): data = { 'status': 'failed', 'message': 'Path traversal detected.' } return send_response(data, api) if is_file_exists(script_file): script_ct.append(Path(script_file).read_text()) data['content'] = '\n'.join(script_ct) except Exception: pass return send_response(data, api)
def download(request): """Download from mobsf.MobSF Route.""" if request.method == 'GET': root = settings.DWD_DIR allowed_exts = settings.ALLOWED_EXTENSIONS filename = request.path.replace('/download/', '', 1) dwd_file = os.path.join(root, filename) # Security Checks if '../' in filename or not is_safe_path(root, dwd_file): msg = 'Path Traversal Attack Detected' return print_n_send_error_response(request, msg) ext = os.path.splitext(filename)[1] if ext in allowed_exts: if os.path.isfile(dwd_file): wrapper = FileWrapper(open(dwd_file, 'rb')) # lgtm [py/path-injection] response = HttpResponse(wrapper, content_type=allowed_exts[ext]) response['Content-Length'] = os.path.getsize(dwd_file) return response if filename.endswith(('screen/screen.png', '-icon.png')): return HttpResponse('') return HttpResponse(status=404)
def run(request, api=False): """View iOS Files.""" try: logger.info('View iOS Source File') exp = 'Error Description' file_format = None if api: fil = request.POST['file'] md5_hash = request.POST['hash'] mode = request.POST['type'] viewsource_form = ViewSourceIOSApiForm(request.POST) else: fil = request.GET['file'] md5_hash = request.GET['md5'] mode = request.GET['type'] viewsource_form = ViewSourceIOSForm(request.GET) typ = set_ext_api(fil) if not viewsource_form.is_valid(): err = FormUtil.errors_message(viewsource_form) if api: return err return print_n_send_error_response(request, err, False, exp) base = Path(settings.UPLD_DIR) / md5_hash if mode == 'ipa': 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 = base sfile = src / fil sfile = sfile.as_posix() if not is_safe_path(src, sfile): msg = 'Path Traversal Detected!' if api: return {'error': 'Path Traversal Detected!'} return print_n_send_error_response(request, msg, False, exp) dat = '' sql_dump = {} if typ == 'm': file_format = 'cpp' with io.open(sfile, mode='r', encoding='utf8', errors='ignore') as flip: dat = flip.read() elif typ == 'xml': file_format = 'xml' with io.open(sfile, mode='r', encoding='utf8', errors='ignore') as flip: dat = flip.read() elif typ == 'plist': file_format = 'json' dat = biplist.readPlist(sfile) try: dat = json.dumps(dat, indent=4, sort_keys=True) except Exception: pass elif typ == 'db': file_format = 'asciidoc' sql_dump = read_sqlite(sfile) elif typ == 'txt' and fil == 'classdump.txt': file_format = 'cpp' app_dir = os.path.join(settings.UPLD_DIR, md5_hash + '/') cls_dump_file = os.path.join(app_dir, 'classdump.txt') if is_file_exists(cls_dump_file): with io.open( cls_dump_file, # lgtm [py/path-injection] mode='r', encoding='utf8', errors='ignore') as flip: dat = flip.read() else: dat = 'Class Dump result not Found' elif typ == 'txt': file_format = 'text' with io.open(sfile, mode='r', encoding='utf8', errors='ignore') as flip: dat = flip.read() else: if api: return {'error': 'Invalid Parameters'} return HttpResponseRedirect('/error/') context = { 'title': escape(ntpath.basename(fil)), 'file': escape(ntpath.basename(fil)), 'type': file_format, 'data': dat, 'sqlite': sql_dump, 'version': settings.MOBSF_VER, } template = 'general/view.html' if api: return context return render(request, template, context) except Exception as exp: logger.exception('Error Viewing Source') msg = str(exp) exp = exp.__doc__ if api: return print_n_send_error_response(request, msg, True, exp) return print_n_send_error_response(request, msg, False, exp)