Skip to content

Commit

Permalink
[EFR] AuthZ and AuthN for MobSF + Bug Fixes (#2366)
Browse files Browse the repository at this point in the history
 Authentication and Authorization (`Maintainer` , Viewer`) support in MobSF
* Basic User Management
* Bug Fixes in Runtime Executable Tampering
* Ratelimiting support for login endpoint
* Disable AuthZ/AuthN for REST API and also via ENV VAR `MOBSF_DISABLE_AUTHENTICATION=1`
* Bug Fix #2285 
* Bug Fix Icon Analysis Nonetype
* Update SSRF Filter
* Dependency Bump
* Beta to Stable release from V4
* Runs with DEBUG=False
* New home screen UI
  • Loading branch information
ajinabraham committed May 21, 2024
1 parent 31026cb commit 76187b8
Show file tree
Hide file tree
Showing 63 changed files with 1,976 additions and 671 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/mobsf-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on:
pull_request:
branches: [ master ]

env:
MOBSF_DISABLE_AUTHENTICATION: "1"

jobs:
build:
strategy:
Expand Down Expand Up @@ -59,6 +62,7 @@ jobs:
poetry run python manage.py makemigrations
poetry run python manage.py makemigrations StaticAnalyzer
poetry run python manage.py migrate
poetry run python manage.py create_roles
- name: Unit Tests on Ubuntu, macOS and Windows
run: |
Expand Down
5 changes: 4 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,13 @@ COPY . .
# Check if Postgres support needs to be enabled.
# Disabled by default
ARG POSTGRES=False

ENV POSTGRES_USER=postgres \
POSTGRES_PASSWORD=password \
POSTGRES_DB=mobsf \
POSTGRES_HOST=postgres
POSTGRES_HOST=postgres \
DJANGO_SUPERUSER_USERNAME=mobsf \
DJANGO_SUPERUSER_PASSWORD=mobsf

RUN ./scripts/postgres_support.sh $POSTGRES

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Mobile Security Framework (MobSF)
Version: v3.9 beta
Version: v4.0

![](https://cloud.githubusercontent.com/assets/4301109/20019521/cc61f7fc-a2f2-11e6-95f3-407030d9fdde.png)

Expand Down
17 changes: 17 additions & 0 deletions mobsf/DynamicAnalyzer/views/android/dynamic_analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,19 @@
)
from mobsf.MobSF.views.scanning import add_to_recent_scan
from mobsf.StaticAnalyzer.models import StaticAnalyzerAndroid
from mobsf.MobSF.views.authentication import (
login_required,
)
from mobsf.MobSF.views.authorization import (
Permissions,
permission_required,
)

logger = logging.getLogger(__name__)


@login_required
@permission_required(Permissions.SCAN)
def android_dynamic_analysis(request, api=False):
"""Android Dynamic Analysis Entry point."""
try:
Expand Down Expand Up @@ -104,6 +113,8 @@ def android_dynamic_analysis(request, api=False):
return print_n_send_error_response(request, exp, api)


@login_required
@permission_required(Permissions.SCAN)
def dynamic_analyzer(request, checksum, api=False):
"""Android Dynamic Analyzer Environment."""
try:
Expand Down Expand Up @@ -220,6 +231,8 @@ def dynamic_analyzer(request, checksum, api=False):
api)


@login_required
@permission_required(Permissions.SCAN)
def httptools_start(request):
"""Start httprools UI."""
logger.info('Starting httptools Web UI')
Expand All @@ -241,6 +254,8 @@ def httptools_start(request):
return print_n_send_error_response(request, err)


@login_required
@permission_required(Permissions.SCAN)
def logcat(request, api=False):
logger.info('Starting Logcat streaming')
try:
Expand Down Expand Up @@ -284,6 +299,8 @@ def read_process():
return print_n_send_error_response(request, err, api)


@login_required
@permission_required(Permissions.SCAN)
def trigger_static_analysis(request, checksum):
"""On device APK Static Analysis."""
try:
Expand Down
25 changes: 25 additions & 0 deletions mobsf/DynamicAnalyzer/views/android/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@
is_number,
)
from mobsf.StaticAnalyzer.models import StaticAnalyzerAndroid
from mobsf.MobSF.views.authentication import (
login_required,
)
from mobsf.MobSF.views.authorization import (
Permissions,
permission_required,
)

logger = logging.getLogger(__name__)

Expand All @@ -53,6 +60,8 @@ def get_package_name(checksum):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def mobsfy(request, api=False):
"""Configure Instance for Dynamic Analysis."""
Expand Down Expand Up @@ -87,6 +96,8 @@ def mobsfy(request, api=False):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def execute_adb(request, api=False):
"""Execute ADB Commands."""
Expand Down Expand Up @@ -115,6 +126,8 @@ def execute_adb(request, api=False):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def get_component(request):
"""Get Android Component."""
Expand All @@ -135,6 +148,8 @@ def get_component(request):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def run_apk(request):
"""Run Android APK."""
Expand All @@ -157,6 +172,8 @@ def run_apk(request):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def take_screenshot(request, api=False):
"""Take Screenshot."""
Expand Down Expand Up @@ -186,6 +203,8 @@ def take_screenshot(request, api=False):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def screen_cast(request):
"""ScreenCast."""
Expand All @@ -205,6 +224,8 @@ def screen_cast(request):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def touch(request):
"""Sending Touch/Swipe/Text Events."""
Expand Down Expand Up @@ -261,6 +282,8 @@ def touch(request):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def mobsf_ca(request, api=False):
"""Install and Remove MobSF Proxy RootCA."""
Expand All @@ -284,6 +307,8 @@ def mobsf_ca(request, api=False):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def global_proxy(request, api=False):
"""Set/unset global proxy."""
Expand Down
5 changes: 4 additions & 1 deletion mobsf/DynamicAnalyzer/views/android/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,15 @@
key,
print_n_send_error_response,
)

from mobsf.MobSF.views.authentication import (
login_required,
)

logger = logging.getLogger(__name__)
register.filter('key', key)


@login_required
def view_report(request, checksum, api=False):
"""Dynamic Analysis Report Generation."""
logger.info('Dynamic Analysis Report Generation')
Expand Down
21 changes: 21 additions & 0 deletions mobsf/DynamicAnalyzer/views/android/tests_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,22 @@
python_list,
)
from mobsf.StaticAnalyzer.models import StaticAnalyzerAndroid
from mobsf.MobSF.views.authentication import (
login_required,
)
from mobsf.MobSF.views.authorization import (
Permissions,
permission_required,
)

logger = logging.getLogger(__name__)


# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def start_activity(request, api=False):
"""Lunch a specific activity."""
Expand Down Expand Up @@ -68,6 +79,10 @@ def start_activity(request, api=False):


# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def activity_tester(request, api=False):
"""Exported & non exported activity Tester."""
Expand Down Expand Up @@ -129,6 +144,8 @@ def activity_tester(request, api=False):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def download_data(request, api=False):
"""Download Application Data from Device."""
Expand Down Expand Up @@ -164,6 +181,8 @@ def download_data(request, api=False):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def collect_logs(request, api=False):
"""Collecting Data and Cleanup."""
Expand Down Expand Up @@ -208,6 +227,8 @@ def collect_logs(request, api=False):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def tls_tests(request, api=False):
"""Perform TLS tests."""
Expand Down
12 changes: 12 additions & 0 deletions mobsf/DynamicAnalyzer/views/android/tests_frida.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,21 @@
print_n_send_error_response,
strict_package_check,
)
from mobsf.MobSF.views.authentication import (
login_required,
)
from mobsf.MobSF.views.authorization import (
Permissions,
permission_required,
)

logger = logging.getLogger(__name__)

# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def get_runtime_dependencies(request, api=False):
"""Get App runtime dependencies."""
Expand All @@ -56,6 +65,8 @@ def get_runtime_dependencies(request, api=False):
# AJAX


@login_required
@permission_required(Permissions.SCAN)
@require_http_methods(['POST'])
def instrument(request, api=False):
"""Instrument app with frida."""
Expand Down Expand Up @@ -123,6 +134,7 @@ def instrument(request, api=False):
return send_response(data, api)


@login_required
def live_api(request, api=False):
try:
if api:
Expand Down
4 changes: 4 additions & 0 deletions mobsf/DynamicAnalyzer/views/common/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
from django.shortcuts import render
from django.utils.html import escape

from mobsf.MobSF.views.authentication import (
login_required,
)
from mobsf.MobSF.utils import (
is_md5,
is_path_traversal,
Expand All @@ -24,6 +27,7 @@
logger = logging.getLogger(__name__)


@login_required
def view_file(request, api=False):
"""View File in app data directory."""
logger.info('Viewing File')
Expand Down
6 changes: 6 additions & 0 deletions mobsf/DynamicAnalyzer/views/common/frida.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
is_safe_path,
print_n_send_error_response,
)
from mobsf.MobSF.views.authentication import (
login_required,
)


logger = logging.getLogger(__name__)
Expand All @@ -25,6 +28,7 @@
# AJAX


@login_required
@require_http_methods(['POST'])
def list_frida_scripts(request, api=False):
"""List frida scripts from others."""
Expand All @@ -47,6 +51,7 @@ def list_frida_scripts(request, api=False):
# AJAX


@login_required
@require_http_methods(['POST'])
def get_script(request, api=False):
"""Get frida scripts from others."""
Expand Down Expand Up @@ -77,6 +82,7 @@ def get_script(request, api=False):
# AJAX + HTML


@login_required
def frida_logs(request, api=False):
try:
data = {
Expand Down
Loading

0 comments on commit 76187b8

Please sign in to comment.