Skip to content

Commit

Permalink
4.1.5 (#2445)
Browse files Browse the repository at this point in the history
* Support custom home from environment variables
* Reduce iOS binary findings severity to warning from high
* Code QA and dependency updates
* docker-compose QA, added example nginx config
* Added docker-compose_swarm.yml by @antonkap add support for docker secrets
* IPA PNG Uncrush support for Windows and Linux #2397
  • Loading branch information
ajinabraham authored Nov 7, 2024
1 parent e4406e9 commit e5af3a8
Show file tree
Hide file tree
Showing 19 changed files with 364 additions and 240 deletions.
2 changes: 1 addition & 1 deletion .sonarcloud.properties
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
sonar.sources=.
sonar.exclusions=mobsf/static/**/*,mobsf/templates/**/*
sonar.sourceEncoding=UTF-8
sonar.python.version=3.10, 3.11
sonar.python.version=3.10, 3.11, 3.12
37 changes: 0 additions & 37 deletions docker-compose.yml

This file was deleted.

47 changes: 47 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
services:

postgres:
image: "postgres:13"
restart: always
volumes:
- $HOME/MobSF/postgresql_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mobsf
networks:
- mobsf_network

nginx:
image: nginx:latest
restart: always
ports:
- "80:4000"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- mobsf
networks:
- mobsf_network

mobsf:
image: opensecurity/mobile-security-framework-mobsf:latest
restart: always
volumes:
- $HOME/MobSF/mobsf_data:/home/mobsf/.MobSF
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=mobsf
- POSTGRES_HOST=postgres
- POSTGRES_PORT=5432
healthcheck:
test: curl -f http://localhost:8000/login/ || exit 1
depends_on:
- postgres
networks:
- mobsf_network

networks:
mobsf_network:
driver: bridge
48 changes: 48 additions & 0 deletions docker/docker-compose_swarm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
services:

postgres:
image: "postgres:${POSTGRES_VERSION:-17.0-bookworm}"
restart: always
volumes:
- $HOME/MobSF/postgresql_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD_FILE=/run/secrets/mobsfDB_password
- POSTGRES_DB=mobsf
networks:
- mobsf_network
secrets:
- mobsfDB_password

mobsf:
image: ${MOBSF_IMAGE:-opensecurity/mobile-security-framework-mobsf:latest}
restart: always
ports:
- "8000:8000"
volumes:
- $HOME/MobSF/mobsf_data:/home/mobsf/.MobSF
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD_FILE=/run/secrets/mobsfDB_password
- POSTGRES_DB=mobsf
- POSTGRES_HOST=postgres
- POSTGRES_PORT=5432
- MOBSF_API_KEY_FILE=/run/secrets/mobsf_api_key
healthcheck:
test: curl -f http://localhost:8000/login/ || exit 1
depends_on:
- postgres
networks:
- mobsf_network
secrets:
- mobsfDB_password
- mobsf_api_key

networks:
mobsf_network:

secrets:
mobsfDB_password:
external: true
mobsf_api_key:
external: true
20 changes: 20 additions & 0 deletions docker/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
user nginx;
events {
worker_connections 1000;
}
http {
server {
listen 4000;
location / {
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port 443;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_pass http://mobsf:8000;
proxy_redirect off;
proxy_read_timeout 900;
proxy_buffering on;
}
client_max_body_size 256M;
}
}
128 changes: 87 additions & 41 deletions mobsf/MobSF/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import sys
import shutil
import threading
from hashlib import sha256
from pathlib import Path
from importlib import (
machinery,
util,
Expand All @@ -16,7 +18,7 @@

logger = logging.getLogger(__name__)

VERSION = '4.1.4'
VERSION = '4.1.5'
BANNER = r"""
__ __ _ ____ _____ _ _ _
| \/ | ___ | |__/ ___|| ___|_ _| || | / |
Expand All @@ -29,16 +31,17 @@

def first_run(secret_file, base_dir, mobsf_home):
# Based on https://gist.github.com/ndarville/3452907#file-secret-key-gen-py
if 'MOBSF_SECRET_KEY' in os.environ:
base_dir = Path(base_dir)
mobsf_home = Path(mobsf_home)
secret_file = Path(secret_file)
if os.getenv('MOBSF_SECRET_KEY'):
secret_key = os.environ['MOBSF_SECRET_KEY']
elif os.path.isfile(secret_file):
secret_key = open(secret_file).read().strip()
elif secret_file.exists() and secret_file.is_file():
secret_key = secret_file.read_text().strip()
else:
try:
secret_key = get_random()
secret = open(secret_file, 'w')
secret.write(secret_key)
secret.close()
secret_file.write_text(secret_key)
except IOError:
raise Exception('Secret file generation failed' % secret_file)
# Run Once
Expand All @@ -48,20 +51,19 @@ def first_run(secret_file, base_dir, mobsf_home):
thread = threading.Thread(
target=install_jadx,
name='install_jadx',
args=(mobsf_home,))
args=(mobsf_home.as_posix(),))
thread.start()
# Windows Setup
windows_config_local(mobsf_home)
windows_config_local(mobsf_home.as_posix())
return secret_key


def create_user_conf(mobsf_home, base_dir):
try:
config_path = os.path.join(mobsf_home, 'config.py')
if not os.path.isfile(config_path):
sample_conf = os.path.join(base_dir, 'MobSF/settings.py')
with open(sample_conf, 'r') as f:
dat = f.readlines()
config_path = mobsf_home / 'config.py'
if not config_path.exists():
sample_conf = base_dir / 'MobSF' / 'settings.py'
dat = sample_conf.read_text().splitlines()
config = []
add = False
for line in dat:
Expand All @@ -72,20 +74,20 @@ def create_user_conf(mobsf_home, base_dir):
if add:
config.append(line.lstrip())
config.pop(0)
conf_str = ''.join(config)
with open(config_path, 'w') as f:
f.write(conf_str)
conf_str = '\n'.join(config)
config_path.write_text(conf_str)
except Exception:
logger.exception('Cannot create config file')


def django_operation(cmds, base_dir):
"""Generic Function for Djano operations."""
manage = os.path.join(base_dir, '../manage.py')
if not os.path.exists(manage):
manage = base_dir.parent / 'manage.py'
if manage.exists() and manage.is_file():
# Bail out for package
return
args = [sys.executable, manage]
print(manage)
args = [sys.executable, manage.as_posix()]
args.extend(cmds)
subprocess.call(args)

Expand Down Expand Up @@ -116,42 +118,43 @@ def get_random():

def get_mobsf_home(use_home, base_dir):
try:
base_dir = Path(base_dir)
mobsf_home = ''
if use_home:
mobsf_home = os.path.join(os.path.expanduser('~'), '.MobSF')
mobsf_home = Path.home() / '.MobSF'
custom_home = os.getenv('MOBSF_HOME_DIR')
if custom_home:
p = Path(custom_home)
if p.exists() and p.is_absolute() and p.is_dir():
mobsf_home = p
# MobSF Home Directory
if not os.path.exists(mobsf_home):
os.makedirs(mobsf_home)
if not mobsf_home.exists():
mobsf_home.mkdir(parents=True, exist_ok=True)
create_user_conf(mobsf_home, base_dir)
else:
mobsf_home = base_dir
# Download Directory
dwd_dir = os.path.join(mobsf_home, 'downloads/')
if not os.path.exists(dwd_dir):
os.makedirs(dwd_dir)
dwd_dir = mobsf_home / 'downloads'
dwd_dir.mkdir(parents=True, exist_ok=True)
# Screenshot Directory
screen_dir = os.path.join(dwd_dir, 'screen/')
if not os.path.exists(screen_dir):
os.makedirs(screen_dir)
screen_dir = mobsf_home / 'screen'
screen_dir.mkdir(parents=True, exist_ok=True)
# Upload Directory
upload_dir = os.path.join(mobsf_home, 'uploads/')
if not os.path.exists(upload_dir):
os.makedirs(upload_dir)
upload_dir = mobsf_home / 'uploads'
upload_dir.mkdir(parents=True, exist_ok=True)
# Downloaded tools
downloaded_tools_dir = os.path.join(mobsf_home, 'tools/')
if not os.path.exists(downloaded_tools_dir):
os.makedirs(downloaded_tools_dir)
# Signature Directory
sig_dir = os.path.join(mobsf_home, 'signatures/')
downloaded_tools_dir = mobsf_home / 'tools'
downloaded_tools_dir.mkdir(parents=True, exist_ok=True)
# Signatures Directory
sig_dir = mobsf_home / 'signatures'
sig_dir.mkdir(parents=True, exist_ok=True)
if use_home:
src = os.path.join(base_dir, 'signatures/')
src = Path(base_dir) / 'signatures'
try:
shutil.copytree(src, sig_dir, dirs_exist_ok=True)
except Exception:
pass
elif not os.path.exists(sig_dir):
os.makedirs(sig_dir)
return mobsf_home
return mobsf_home.as_posix()
except Exception:
logger.exception('Creating MobSF Home Directory')

Expand All @@ -166,3 +169,46 @@ def load_source(modname, filename):
module = util.module_from_spec(spec)
loader.exec_module(module)
return module


def get_docker_secret_by_file(secret_key):
try:
secret_path = os.environ.get(secret_key)
path = Path(secret_path)
if path.exists() and path.is_file():
return path.read_text().strip()
except Exception:
logger.exception('Cannot read secret from %s', secret_path)
raise Exception('Cannot read secret from file')


def get_secret_from_file_or_env(env_secret_key):
docker_secret_key = f'{env_secret_key}_FILE'
if os.environ.get(docker_secret_key):
return get_docker_secret_by_file(docker_secret_key)
else:
return os.environ[env_secret_key]


def api_key(home_dir):
"""Print REST API Key."""
# Form Docker Secrets
if os.environ.get('MOBSF_API_KEY_FILE'):
logger.info('\nAPI Key read from docker secrets')
try:
return get_docker_secret_by_file('MOBSF_API_KEY_FILE')
except Exception:
logger.exception('Cannot read API Key from docker secrets')
# From Environment Variable
if os.environ.get('MOBSF_API_KEY'):
logger.info('\nAPI Key read from environment variable')
return os.environ['MOBSF_API_KEY']
home_dir = Path(home_dir)
secret_file = home_dir / 'secret'
if secret_file.exists() and secret_file.is_file():
try:
_api_key = secret_file.read_bytes().strip()
return sha256(_api_key).hexdigest()
except Exception:
logger.exception('Cannot Read API Key')
return None
Loading

0 comments on commit e5af3a8

Please sign in to comment.