Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SECURITY] Fix SSRF in applink check, dependency update. #81

Merged
merged 1 commit into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 29 additions & 22 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mobsfscan/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
__title__ = 'mobsfscan'
__authors__ = 'Ajin Abraham'
__copyright__ = f'Copyright {datetime.now().year} Ajin Abraham, OpenSecurity'
__version__ = '0.3.6'
__version__ = '0.3.7'
__version_info__ = tuple(int(i) for i in __version__.split('.'))
__all__ = [
'__title__',
Expand Down
17 changes: 13 additions & 4 deletions mobsfscan/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@

from mobsfscan.logger import init_logger
from mobsfscan.manifest_metadata import metadata

from mobsfscan.utils import (
is_number,
valid_host,
)

logger = init_logger(__name__)
ANDROID_8_0_LEVEL = 26
Expand Down Expand Up @@ -50,6 +53,7 @@
'32': '12L',
'33': '13',
'34': '14',
'35': '15',
}


Expand Down Expand Up @@ -349,9 +353,14 @@ def assetlinks_check(self, intent):
port = applink.get('@android:port')
scheme = applink.get('@android:scheme')
# Collect possible well-known paths
if scheme and scheme in ('http', 'https') and host:
host = host.replace('*.', '')
if port:
if (scheme
and scheme in ('http', 'https')
and host
and host != '*'):
host = host.replace('*.', '').replace('#', '')
if not valid_host(host):
continue
if port and is_number(port):
c_url = f'{scheme}://{host}:{port}{well_known_path}'
else:
c_url = f'{scheme}://{host}{well_known_path}'
Expand Down
59 changes: 59 additions & 0 deletions mobsfscan/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# -*- coding: utf_8 -*-
"""Logger Config."""
import socket
import unicodedata
from urllib.parse import urlparse
from pathlib import Path

import mobsfscan.settings as config
Expand Down Expand Up @@ -112,3 +115,59 @@ def get_best_practices(extension):
all_rules[rule['id']] = rule
ids.add(rule['id'])
return ids, all_rules


def is_number(s):
if not s:
return False
if s == 'NaN':
return False
try:
float(s)
return True
except ValueError:
pass
try:
unicodedata.numeric(s)
return True
except (TypeError, ValueError):
pass
return False


def valid_host(host):
"""Check if host is valid."""
try:
prefixs = ('http://', 'https://')
if not host.startswith(prefixs):
host = f'http://{host}'
parsed = urlparse(host)
domain = parsed.netloc
path = parsed.path
if len(domain) == 0:
# No valid domain
return False
if len(path) > 0:
# Only host is allowed
return False
if ':' in domain:
# IPv6
return False
# Local network
invalid_prefix = (
'127.',
'192.',
'10.',
'172.',
'169',
'0.',
'localhost')
if domain.startswith(invalid_prefix):
return False
ip = socket.gethostbyname(domain)
if ip.startswith(invalid_prefix):
# Resolve dns to get IP
return False
return True
except Exception:
return False
14 changes: 7 additions & 7 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
attrs==21.4.0
boltons==21.0.0
bracex==2.4
certifi==2023.11.17
certifi==2024.2.2
charset-normalizer==3.3.2
click==8.1.7
click-option-group==0.5.6
Expand All @@ -11,13 +11,13 @@ face==22.0.0
glom==22.1.0
idna==3.6
jschema-to-python==1.2.3
jsonpickle==3.0.2
jsonpickle==3.0.3
jsonschema==4.17.3
libsast==2.0.3
packaging==21.3
pbr==6.0.0
peewee==3.17.0
pyparsing==3.1.1
peewee==3.17.1
pyparsing==3.1.2
pyrsistent==0.20.0
python-lsp-jsonrpc==1.0.0
PyYAML==6.0.1
Expand All @@ -28,9 +28,9 @@ sarif-om==1.0.4
semgrep==0.117.0
tabulate==0.9.0
tomli==2.0.1
tqdm==4.66.1
typing_extensions==4.9.0
tqdm==4.66.2
typing_extensions==4.10.0
ujson==5.9.0
urllib3==1.26.18
wcmatch==8.5
wcmatch==8.5.1
xmltodict==0.13.0
Loading