From 16773a3d9a31f4bb550c7f80f13efacf5aea1846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=9B=E8=81=BF?= Date: Tue, 15 Jul 2025 19:03:32 +0800 Subject: [PATCH 1/6] fix STATICFILES_DIRS config for runserver mode --- manage.py | 23 +++++++++++++++-------- mobsf/MobSF/settings.py | 3 ++- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/manage.py b/manage.py index 6311e7e703..41ba48e6b3 100755 --- a/manage.py +++ b/manage.py @@ -6,13 +6,20 @@ warnings.filterwarnings('ignore', category=UserWarning, module='cffi') -if __name__ == '__main__': - os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mobsf.MobSF.settings') - from django.core.management import execute_from_command_line - if 'runserver' in sys.argv: - print('We do not allow debug server anymore. ' - 'Please follow official docs: ' - 'https://mobsf.github.io/docs/') - sys.exit(0) +def main(): + """Run administrative tasks.""" + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mobsf.MobSF.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/mobsf/MobSF/settings.py b/mobsf/MobSF/settings.py index 5e338f44c4..3739b54b63 100644 --- a/mobsf/MobSF/settings.py +++ b/mobsf/MobSF/settings.py @@ -240,7 +240,8 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads') MEDIA_URL = '/uploads/' STATIC_URL = '/static/' -STATIC_ROOT = os.path.join(BASE_DIR, 'static') +# STATIC_ROOT = os.path.join(BASE_DIR, 'compressed_static') +STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")] STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage' # 256MB limit for file uploads DATA_UPLOAD_MAX_MEMORY_SIZE = 256 * 1024 * 1024 From cc31727204f2d17d46e96d9d7e07f7df20f49aea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=9B=E8=81=BF?= Date: Tue, 15 Jul 2025 19:14:17 +0800 Subject: [PATCH 2/6] remove SessionAuthenticationMiddleware, which removed from django v2.0 --- mobsf/MobSF/settings.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mobsf/MobSF/settings.py b/mobsf/MobSF/settings.py index 3739b54b63..c73b255a0b 100644 --- a/mobsf/MobSF/settings.py +++ b/mobsf/MobSF/settings.py @@ -198,7 +198,6 @@ 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django_ratelimit.middleware.RatelimitMiddleware', From b851b4533ec53e339a557cb2386a295b5885e023 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=9B=E8=81=BF?= Date: Tue, 15 Jul 2025 19:19:33 +0800 Subject: [PATCH 3/6] fix MIDDLEWARE setting, MIDDLEWARE_CLASSES has been deprecated in django 1.10 --- mobsf/MobSF/settings.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/mobsf/MobSF/settings.py b/mobsf/MobSF/settings.py index c73b255a0b..1aab2cc2dd 100644 --- a/mobsf/MobSF/settings.py +++ b/mobsf/MobSF/settings.py @@ -192,22 +192,17 @@ 'mobsf.MobSF', 'mobsf.MalwareAnalyzer', ) -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = ( 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'django_ratelimit.middleware.RatelimitMiddleware', -) -MIDDLEWARE = ( 'mobsf.MobSF.views.api.api_middleware.RestApiAuthMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', - + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django_ratelimit.middleware.RatelimitMiddleware', ) ROOT_URLCONF = 'mobsf.MobSF.urls' WSGI_APPLICATION = 'mobsf.MobSF.wsgi.application' From 38464fcc2e9491621859abfcb4125bafd315bb10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=9B=E8=81=BF?= Date: Tue, 15 Jul 2025 20:03:40 +0800 Subject: [PATCH 4/6] optimize WhiteNoise configuration --- .gitignore | 1 + mobsf/MobSF/settings.py | 11 +++++++++-- mobsf/MobSF/wsgi.py | 8 +------- mobsf/static/jsTree/custom.css | 4 +--- run.bat | 3 +++ run.sh | 4 +++- scripts/clean.sh | 2 +- scripts/entrypoint.sh | 3 +++ setup.bat | 7 +++++++ setup.sh | 6 ++++++ 10 files changed, 35 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index e7bfad96ac..7a9b6695b1 100644 --- a/.gitignore +++ b/.gitignore @@ -78,4 +78,5 @@ mobsf/secret mobsf/StaticAnalyzer/migrations mobsf/MobSF/windows_vm_priv_key.asc mobsf/setup_done.txt +mobsf/staticfiles TODO.md \ No newline at end of file diff --git a/mobsf/MobSF/settings.py b/mobsf/MobSF/settings.py index 1aab2cc2dd..02b1d9843b 100644 --- a/mobsf/MobSF/settings.py +++ b/mobsf/MobSF/settings.py @@ -234,9 +234,16 @@ MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads') MEDIA_URL = '/uploads/' STATIC_URL = '/static/' -# STATIC_ROOT = os.path.join(BASE_DIR, 'compressed_static') +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")] -STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage' +STORAGES = { + "default": { + "BACKEND": "django.core.files.storage.FileSystemStorage", + }, + "staticfiles": { + "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage", + }, +} # 256MB limit for file uploads DATA_UPLOAD_MAX_MEMORY_SIZE = 256 * 1024 * 1024 # 400MB per file limit for uncompressed files diff --git a/mobsf/MobSF/wsgi.py b/mobsf/MobSF/wsgi.py index 90b4c457c1..65e0cb3a69 100755 --- a/mobsf/MobSF/wsgi.py +++ b/mobsf/MobSF/wsgi.py @@ -11,14 +11,8 @@ from django.core.wsgi import get_wsgi_application -from whitenoise import WhiteNoise - -from . import settings - warnings.filterwarnings('ignore', category=UserWarning, module='cffi') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mobsf.MobSF.settings') -static = os.path.join(settings.BASE_DIR, 'static') -application = WhiteNoise(get_wsgi_application(), - root=static, prefix='static/') +application = get_wsgi_application() diff --git a/mobsf/static/jsTree/custom.css b/mobsf/static/jsTree/custom.css index 7068be82d6..109df86d41 100644 --- a/mobsf/static/jsTree/custom.css +++ b/mobsf/static/jsTree/custom.css @@ -1,5 +1,3 @@ -{% load static %} - html, body { height: 100% ; @@ -23,7 +21,7 @@ div#fileframe { div#contentframe { background-color: #FFFFFF ; - background-image: url( "/static/jsTree/themes/default/content_background.gif" ) ; + background-image: url(themes/default/content_background.gif) ; background-position: left top ; background-repeat: repeat-y ; float: left ; diff --git a/run.bat b/run.bat index 7af7ee0bc4..f5a110aa57 100644 --- a/run.bat +++ b/run.bat @@ -7,4 +7,7 @@ goto :run SET conf="0.0.0.0:8000 [::]:8000" :run echo Running MobSF on %conf% + +poetry run python manage.py collectstatic --noinput + poetry run waitress-serve --listen=%conf% --threads=10 --channel-timeout=3600 mobsf.MobSF.wsgi:application \ No newline at end of file diff --git a/run.sh b/run.sh index aafbc561af..1b3b856d6e 100755 --- a/run.sh +++ b/run.sh @@ -31,5 +31,7 @@ else PORT='8000' fi -python3 -m poetry run gunicorn -b ${IP}:${PORT} mobsf.MobSF.wsgi:application --workers=1 --threads=10 --timeout=3600 \ +poetry run python manage.py collectstatic --noinput + +poetry run gunicorn -b ${IP}:${PORT} mobsf.MobSF.wsgi:application --workers=1 --threads=10 --timeout=3600 \ --log-level=critical --log-file=- --access-logfile=- --error-logfile=- --capture-output diff --git a/scripts/clean.sh b/scripts/clean.sh index a5db24c837..7d262b1013 100755 --- a/scripts/clean.sh +++ b/scripts/clean.sh @@ -27,7 +27,7 @@ if [[ "$VAL" =~ ^[yY]$ ]]; then echo 'Cleaning up MobSF directories and files...' # Remove files from key directories - rm -rf ./mobsf/{uploads,downloads,StaticAnalyzer/migrations,DynamicAnalyzer/migrations,MobSF/migrations}/* + rm -rf ./mobsf/{uploads,downloads,staticfiles,StaticAnalyzer/migrations,DynamicAnalyzer/migrations,MobSF/migrations}/* echo 'Removing Python bytecode and cache files' find ./ -type f -name "*.pyc" -o -name "*.pyo" -delete diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index e6ec00668f..11693959b6 100755 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -4,6 +4,9 @@ set -e python3 manage.py makemigrations && \ python3 manage.py makemigrations StaticAnalyzer && \ python3 manage.py migrate + +python3 manage.py collectstatic --noinput + set +e python3 manage.py createsuperuser --noinput --email "" set -e diff --git a/setup.bat b/setup.bat index 5fa47e4b37..179ac2b4db 100644 --- a/setup.bat +++ b/setup.bat @@ -69,8 +69,15 @@ where python >nul 2>&1 && ( poetry run python manage.py makemigrations poetry run python manage.py makemigrations StaticAnalyzer poetry run python manage.py migrate + + echo [INSTALL] Collect Static files + poetry run python manage.py collectstatic --noinput + + echo [INSTALL] Creating Super User poetry run python manage.py createsuperuser --noinput --email "" poetry run python manage.py create_roles + + echo [INSTALL] wkhtmltopdf is not installed echo Download and Install wkhtmltopdf for PDF Report Generation - https://wkhtmltopdf.org/downloads.html echo [INSTALL] Installation Complete exit /b 0 diff --git a/setup.sh b/setup.sh index ef2f895947..b7e825511a 100755 --- a/setup.sh +++ b/setup.sh @@ -53,9 +53,15 @@ export DJANGO_SUPERUSER_PASSWORD=mobsf python3 -m poetry run python manage.py makemigrations python3 -m poetry run python manage.py makemigrations StaticAnalyzer python3 -m poetry run python manage.py migrate + +echo '[INSTALL] Collect Static files' +python3 -m poetry run python manage.py collectstatic --noinput + +echo '[INSTALL] Creating Superuser' python3 -m poetry run python manage.py createsuperuser --noinput --email "" python3 -m poetry run python manage.py create_roles +echo '[INSTALL] Checking wkhtmltopdf' # Check for wkhtmltopdf if ! command -v wkhtmltopdf &>/dev/null; then echo 'Download and Install wkhtmltopdf for PDF Report Generation - https://wkhtmltopdf.org/downloads.html' From 577f69b226a8ce9fa89e0ddf93ba9b09d641b317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=9B=E8=81=BF?= Date: Mon, 21 Jul 2025 15:05:39 +0800 Subject: [PATCH 5/6] fix unit test fail --- .github/workflows/mobsf-test.yml | 1 + mobsf/StaticAnalyzer/tests.py | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/.github/workflows/mobsf-test.yml b/.github/workflows/mobsf-test.yml index 016b89ede3..f9efc8badd 100644 --- a/.github/workflows/mobsf-test.yml +++ b/.github/workflows/mobsf-test.yml @@ -65,6 +65,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 collectstatic --noinput poetry run python manage.py create_roles - uses: actions/setup-java@v4 diff --git a/mobsf/StaticAnalyzer/tests.py b/mobsf/StaticAnalyzer/tests.py index 510fce87f9..06b19c2392 100755 --- a/mobsf/StaticAnalyzer/tests.py +++ b/mobsf/StaticAnalyzer/tests.py @@ -6,6 +6,7 @@ from mobsf.MobSF.init import api_key +from django.contrib.auth import get_user_model from django.conf import settings from django.http import HttpResponse from django.test import Client, TestCase @@ -24,6 +25,12 @@ def static_analysis_test(): uploaded = [] logger.info('Running Upload Test') http_client = Client() + + # Create Test User + user_model = get_user_model() + user_model.objects.create_user(username='mobsf_test', password='mobsf_test', is_superuser=True, is_staff=True) + http_client.login(username='mobsf_test', password='mobsf_test') + apk_dir = os.path.join(settings.BASE_DIR, 'StaticAnalyzer/test_files/') for filename in os.listdir(apk_dir): if not filename.endswith(EXTS): From 1e81a547ff11483100830b0da8b22cc2ab997e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8A=9B=E8=81=BF?= Date: Wed, 19 Nov 2025 16:46:10 +0800 Subject: [PATCH 6/6] fix for code review --- mobsf/StaticAnalyzer/tests.py | 6 ------ run.sh | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/mobsf/StaticAnalyzer/tests.py b/mobsf/StaticAnalyzer/tests.py index 06b19c2392..3c824a41c1 100755 --- a/mobsf/StaticAnalyzer/tests.py +++ b/mobsf/StaticAnalyzer/tests.py @@ -6,7 +6,6 @@ from mobsf.MobSF.init import api_key -from django.contrib.auth import get_user_model from django.conf import settings from django.http import HttpResponse from django.test import Client, TestCase @@ -26,11 +25,6 @@ def static_analysis_test(): logger.info('Running Upload Test') http_client = Client() - # Create Test User - user_model = get_user_model() - user_model.objects.create_user(username='mobsf_test', password='mobsf_test', is_superuser=True, is_staff=True) - http_client.login(username='mobsf_test', password='mobsf_test') - apk_dir = os.path.join(settings.BASE_DIR, 'StaticAnalyzer/test_files/') for filename in os.listdir(apk_dir): if not filename.endswith(EXTS): diff --git a/run.sh b/run.sh index 1b3b856d6e..35692f4616 100755 --- a/run.sh +++ b/run.sh @@ -31,7 +31,7 @@ else PORT='8000' fi -poetry run python manage.py collectstatic --noinput +python3 -m poetry run python manage.py collectstatic --noinput -poetry run gunicorn -b ${IP}:${PORT} mobsf.MobSF.wsgi:application --workers=1 --threads=10 --timeout=3600 \ +python3 -m poetry run gunicorn -b ${IP}:${PORT} mobsf.MobSF.wsgi:application --workers=1 --threads=10 --timeout=3600 \ --log-level=critical --log-file=- --access-logfile=- --error-logfile=- --capture-output