Files
Mobile-Security-Framework-M…/mobsf/templates/dynamic_analysis/android/dynamic_analysis.html
T
Ajin AbrahamandCursor a23ff75ec0 Fix CSRF in dynamic analysis actions (#2679)
* Harden path traversal checks for Windows root-relative escapes.

Reject POSIX/Windows absolute paths in is_path_traversal and require post-join containment at icon, network-config, and archive extraction sinks.

Co-authored-by: Cursor <[email protected]>

* Restrict network security config names to a basename.

CodeQL flagged the manifest-derived join; reduce the resource name first so path construction cannot escape xml_dir.

Co-authored-by: Cursor <[email protected]>

* Use os.path.basename for CodeQL-recognized path sanitization.

Path.name did not clear py/path-injection taint; basename plus existing containment checks keep the network-config read inside xml_dir.

Co-authored-by: Cursor <[email protected]>

* Drop CodeQL-appeasement basename sanitization from network config reads.

is_safe_path after join already rejects traversal, absolute, and Windows root-relative names; CodeQL py/path-injection is a false positive.

Co-authored-by: Cursor <[email protected]>

* Bound androguard ZIP member decompression

Use the configured per-file ZIP limit for apkinspector reads and cap
actual raw-DEFLATE output. Keep decompression-limit failures out of the
tampered-entry fallback so malicious compressed data cannot be treated
as stored bytes.

Co-authored-by: Cursor <[email protected]>

* Reject inactive SAML users before ACS group updates.

Existing accounts mapped from a valid IdP assertion should not have groups replaced or be passed to login() when is_active is False.

Co-authored-by: Cursor <[email protected]>

* Return the ACS error page for inactive users instead of raising Exception.

Co-authored-by: Cursor <[email protected]>

* Fix iOS plist-derived path traversal

Select and validate one contained IPA app bundle, reject unsafe plist
executable values, and guard icon and Mach-O inputs before access.
Harden equivalent source icon, plist, library, and dynamic icon paths.

Co-authored-by: Cursor <[email protected]>

* correct version

* fix CSRF in dynamic analysis actions

Co-authored-by: Ajin Abraham <[email protected]>

* document HTTPTools host header SSRF advisory

Co-authored-by: Ajin Abraham <[email protected]>

---------

Co-authored-by: Cursor <[email protected]>
2026-09-20 16:36:10 -07:00

343 lines
14 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base/base_layout.html" %}
{% load static %}
{% block sidebar_option %}
sidebar-collapse
{% endblock %}
{% block extra_css %}
<!-- DataTables -->
<link href="{% static "datatables/css/datatables.combined.min.css" %}" rel="stylesheet">
<link rel="stylesheet" href="{% static "others/css/spinner.css" %}">
<link href="{% static "adminlte/plugins/sweetalert2/sweetalert2.min.css" %}" rel="stylesheet">
<style>
#app_icon{
width: 64px;
height: 64px;
}
textarea {
width: 100%;
height: 500px;
-moz-border-bottom-colors: none;
-moz-border-left-colors: none;
-moz-border-right-colors: none;
-moz-border-top-colors: none;
background: none repeat scroll 0 0 rgba(0, 0, 0, 0.07);
border-color: -moz-use-text-color #FFFFFF #FFFFFF -moz-use-text-color;
border-image: none;
border-radius: 6px 6px 6px 6px;
border-style: none solid solid none;
border-width: medium 1px 1px medium;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.12) inset;
color: #555555;
font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
font-size: 1em;
line-height: 1.4em;
padding: 5px 8px;
transition: background-color 0.2s ease 0s;
}
textarea:focus {
background: none repeat scroll 0 0 #FFFFFF;
outline-width: 0;
}
/* disable button */
{% if not identifier %}
.disable {
background-color: #7b7b7b;
pointer-events: none;
cursor: default;
}
{% endif %}
</style>
{% endblock %}
{% block content %}
<div class="content-wrapper">
<div class="content-header">
</div>
<div class="container-fluid">
<div class="row">
{% if not identifier %}
<div class="col-md-12">
<div class="card bg-gradient-danger">
<div class="card-header">
<h3 class="card-title">Android Runtime not found!</h3>
<!-- /.card-tools -->
</div>
<!-- /.card-header -->
<div class="card-body">
<p> MobSF cannot find android instance identifier. Make sure that an android instance is running and refresh this page.</p><p> If this error persists, Please set <i>ANALYZER_IDENTIFIER</i> in <strong>{{ settings_loc }}</strong> or via environment variable <strong>MOBSF_ANALYZER_IDENTIFIER</strong>.
</p>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
<!-- /.col -->
{% endif %}
<div class="col-md-12">
<div class="card bg-gradient-primary">
<!-- /.card-header -->
<div class="card-body">
<div class="row">
<div class="col-md-9">
<h4>MobSF Dynamic Analyzer Supports</h4>
<h5>
<strong>• Genymotion Android VM</strong> version 4.1 - 11.0 (arm64, x86, and x86_64 upto API 30)<br/>
<strong>• Android Emulator AVD</strong> (non production) version 5.0 - 11.0 (arm, arm64, x86, and x86_64 upto API 30)<br/>
<strong>• Corellium Android VM</strong> (userdebug builds) version 7.1.2 - 11.0 (arm64 upto API 30)
</h5>
<p>
{% if android_version %}
Android version >= <strong>9.0</strong> recommended<br/>
Detected Android Version: <strong>{{android_version}}</strong>, SDK: API level <strong>{{ android_sdk }}</strong> <br/>
{% if android_sdk|floatformat > android_supported|floatformat %}
<script src="{% static "adminlte/plugins/sweetalert2/sweetalert2.min.js" %}"></script>
<script>
Swal.fire(
'Android Version/SDK not supported',
'You are running Android Version <strong>{{ android_version }}</strong> and SDK <strong>{{ android_sdk }}</strong> which is not supported by MobSF. Please use a supported Android version/API level.',
'error'
)
</script>
{% endif %}
{% endif %}
{% if android_version < 5 %}
Xposed Framework is used for instrumentation and you must MobSFy and reboot the Android Runtime prior to Dynamic Analysis.
{% if android_version < 4.4 %}
<br/>For Android version <strong>4.1 - 4.3</strong>, set Android VM proxy as <strong>{% if proxy_ip %} {{ proxy_ip }}{% else %} <i>&lt;Host IP&gt;</i>{% endif %}:{{proxy_port}}</strong>
{% endif %}
{% endif %}
</p>
</div>
<div class="col-md-3">
<br/>
<br/>
<br/>
<p>
<button class="btn btn-info disable" role="button" data-toggle="modal" data-target="#mmobsfy">MobSFy Android Runtime</button> <p>Android instance: <strong>{{ identifier }}</strong></p></div>
</p>
</div>
</div>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
<!-- /.col -->
<div class="col-md-12">
<div class="card card-default">
<div class="card-header">
<h3 class="card-title"><i class="fa fa-rocket"></i> MobSF Dynamic Analysis</h3>
</div>
<div class="card-body">
<div class="table-responsive">
<h4> Apps in Device</h4>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>APP</th>
<th>LOCATION IN DEVICE</th>
<th>ACTION</th>
</tr>
</thead>
<tbody>
{% if device_packages %}
{% for hash, det in device_packages.items %}
<tr>
<td align="center">
<img id="app_icon" src="/download/{{ hash }}-icon.png" onerror="this.onerror=null;this.src='{% static 'img/no_icon.png' %}'"/>
<br/><strong>{{ det.0 }}</strong>
</td>
<td>
{{ det.1}}
</td>
<td align="center">
<div class="mb-3">
<form method="post" action="{% url "dynamic_analyzer" checksum=hash %}">
{% csrf_token %}
<input type="hidden" name="re_install" value="0">
<input type="hidden" name="install" value="0">
<button type="submit" class="btn btn-primary disable" onclick="dynamic_loader()"><i class="fab fa-android"></i> Start Dynamic Analysis</button>
</form>
</div>
<div class="mb-3">
<form method="post" action="{% url "static_scan" checksum=hash %}">
{% csrf_token %}
<button type="submit" class="btn btn-warning disable" onclick="dynamic_loader()"><i class="fa fa-download"></i> Pull &amp; Static Analysis</button>
</form>
</div>
<p>
<a class="btn btn-info" href="{% url "dynamic_report" checksum=hash %}"><i class="fa fa-mobile"></i> View Report </a>
</p>
</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</br>
<h4> Apps Available</h4>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>APP</th>
<th>FILE NAME</th>
<th>PACKAGE</th>
<th>ACTION</th>
</tr>
</thead>
<tbody>
{% if apps %}
{% for e in apps %}
<tr>
<td align="center">
<img id="app_icon" src="{% if e.ICON_PATH %}/download/{{ e.ICON_PATH }}{% else %}{% static 'img/no_icon.png' %}{% endif %}"/>
<br/><strong>{{ e.APP_NAME }} - {{ e.VERSION_NAME }}</strong>
</td>
<td>
{{ e.FILE_NAME }}
</td>
<td>
{{ e.PACKAGE_NAME }}
</td>
<td align="center">
<div class="mb-3">
<form method="post" action="{% url "dynamic_analyzer" checksum=e.MD5 %}">
{% csrf_token %}
<button type="submit" class="btn btn-success disable" onclick="dynamic_loader()"><i class="fab fa-android"></i> Start Dynamic Analysis</button>
</form>
</div>
<div class="mb-3">
<form method="post" action="{% url "dynamic_analyzer" checksum=e.MD5 %}">
{% csrf_token %}
<input type="hidden" name="re_install" value="0">
<button type="submit" class="btn btn-primary btn-sm disable" onclick="dynamic_loader()"><i class="fab fa-android"></i> Start Dynamic Analysis (No reinstall)</button>
</form>
</div>
<p>
<a class="btn btn-info {% if not e.DYNAMIC_REPORT_EXISTS %}disabled{% endif %}" href="{% url "dynamic_report" checksum=e.MD5 %}"><i class="fa fa-mobile"></i> View Report </a>
</p>
</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</div>
</div>
<!-- /.card-body -->
</div>
<!-- /.card -->
</div>
<!-- /.col -->
</div>
</div>
</div>
</div>
</div>
</div>
<!--Modal-->
<div class="modal" id="mmobsfy" tabindex="-1" role="dialog">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">MobSFy Android Runtime</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form role="form">
<div class="form-group">
<label>IP &amp; Port/Identifier</label>
<input id="identifier" type="text" class="form-control" value="{{ identifier }}">
</div>
<div class="form-group">
<label>Status</label>
<textarea id="stat" class="form-control" rows="10" placeholder="" disabled=""></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button id="mobsfy" type="button" class="btn btn-primary disable">MobSFy!</button>
</div>
</div>
<!-- /.modal-content -->
</div>
<!-- /.modal-dialog -->
</div>
<!--Loader-->
<div class="hidden loading">
<div class='uil-ring-css' style='transform:scale(0.79);'>
<div></div>
</div>
</div>
{% endblock %}
{% block extra_scripts %}
<!-- DataTables -->
<script src="{% static "datatables/js/pdfmake.min.js" %}"></script>
<script src="{% static "datatables/js/vfs_fonts.js" %}"></script>
<script src="{% static "datatables/js/datatables.combined.min.js" %}"></script>
<script src="{% static "others/js/datatables_init.js" %}"></script>
<script>
function dynamic_loader(){
var loadingOverlay = document.querySelector('.loading');
loadingOverlay.classList.remove('hidden');
}
//MobSFy AJAX
$("#mobsfy").one( "click", function() {
$('#stat').append("\nMobSFying Android Runtime\n");
$.ajax({
url : "{% url 'mobsfy' %}",
type : "POST",
dataType: "json",
data : {
csrfmiddlewaretoken: '{{ csrf_token }}',
identifier: $('#identifier').val() ,
},
success : function(json) {
if (json.status==="ok"){
$('#stat').append("\nSucessfully created MobSF Dynamic Analysis environment.");
if (json.android_version < 5){
$('#stat').append("\n* Download & Install Xposed Framework.\n* Restart the device.");
$('#stat').append("\n* Enable all the Xposed modules.\n* Restart the device once more.");
} else{
$('#stat').append("\nMobSF agents and Frida server installed.");
}
}
else if(json.status === "failed"){
$('#stat').append(json.message);
}
$('#stat').scrollTop($('#stat')[0].scrollHeight);
},
error : function(xhr, errmsg, err) {
$('#stat').append("\nERROR!!! \n\n"+ err);
$('#stat').scrollTop($('#stat')[0].scrollHeight);
}
});
return false;
});
</script>
{% endblock %}