diff --git a/Pipfile.lock b/Pipfile.lock index 9bdfe11..dc7fd03 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -41,11 +41,11 @@ }, "certifi": { "hashes": [ - "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1", - "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474" + "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f", + "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1" ], "markers": "python_version >= '3.6'", - "version": "==2023.11.17" + "version": "==2024.2.2" }, "charset-normalizer": { "hashes": [ @@ -140,7 +140,7 @@ "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519", "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561" ], - "markers": "python_version >= '3.7'", + "markers": "python_full_version >= '3.7.0'", "version": "==3.3.2" }, "click": { @@ -156,7 +156,7 @@ "sha256:38a26d963ee3ad93332ddf782f9259c5bdfe405e73408d943ef5e7d0c3767ec7", "sha256:97d06703873518cc5038509443742b25069a3c7562d1ea72ff08bfadde1ce777" ], - "markers": "python_version >= '3.6' and python_version < '4.0'", + "markers": "python_version >= '3.6' and python_version < '4'", "version": "==0.5.6" }, "colorama": { @@ -165,6 +165,7 @@ "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6" ], "index": "pypi", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'", "version": "==0.4.6" }, "defusedxml": { @@ -203,15 +204,16 @@ "sha256:8a703ca7604d42d74b2815eecf99a33359a8dccbb80806cce386d5e2dd992b05" ], "index": "pypi", + "markers": "python_version >= '2.7'", "version": "==1.2.3" }, "jsonpickle": { "hashes": [ - "sha256:4a8442d97ca3f77978afa58068768dba7bff2dbabe79a9647bc3cdafd4ef019f", - "sha256:e37abba4bfb3ca4a4647d28bb9f4706436f7b46c8a8333b4a718abafa8e46b37" + "sha256:5691f44495327858ab3a95b9c440a79b41e35421be1a6e09a47b6c9b9421fd06", + "sha256:e8d6dcc58f6722bea0321cd328fbda81c582461185688a535df02be0f699afb4" ], "markers": "python_version >= '3.7'", - "version": "==3.0.2" + "version": "==3.0.3" }, "jsonschema": { "hashes": [ @@ -227,6 +229,7 @@ "sha256:8bf0ef3ad31864fcdcf073840c5875e9a2fcdb9f895617141f30c953e361577d" ], "index": "pypi", + "markers": "python_version >= '3.8' and python_version < '4.0'", "version": "==2.0.3" }, "packaging": { @@ -247,17 +250,17 @@ }, "peewee": { "hashes": [ - "sha256:3a56967f28a43ca7a4287f4803752aeeb1a57a08dee2e839b99868181dfb5df8" + "sha256:e009ac4227c4fdc0058a56e822ad5987684f0a1fbb20fed577200785102581c3" ], - "version": "==3.17.0" + "version": "==3.17.1" }, "pyparsing": { "hashes": [ - "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb", - "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db" + "sha256:a1bac0ce561155ecc3ed78ca94d3c9378656ad4c94c1270de543f621420f94ad", + "sha256:f9db75911801ed778fe61bb643079ff86601aca99fcae6345aa67292038fb742" ], "markers": "python_full_version >= '3.6.8'", - "version": "==3.1.1" + "version": "==3.1.2" }, "pyrsistent": { "hashes": [ @@ -335,6 +338,7 @@ "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4", "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba", "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8", + "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef", "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5", "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd", "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3", @@ -438,6 +442,7 @@ "sha256:cd5f416b3083e00d402a92e449a7ff67af46f11241073eea0461802a3b5aef98" ], "index": "pypi", + "markers": "python_version >= '2.7'", "version": "==1.0.4" }, "semgrep": { @@ -456,6 +461,7 @@ "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f" ], "index": "pypi", + "markers": "python_version >= '3.7'", "version": "==0.9.0" }, "tomli": { @@ -468,19 +474,19 @@ }, "tqdm": { "hashes": [ - "sha256:d302b3c5b53d47bce91fea46679d9c3c6508cf6332229aa1e7d8653723793386", - "sha256:d88e651f9db8d8551a62556d3cff9e3034274ca5d66e93197cf2490e2dcb69c7" + "sha256:1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9", + "sha256:6cd52cdf0fef0e0f543299cfc96fec90d7b8a7e88745f411ec33eb44d5ed3531" ], "markers": "python_version >= '3.7'", - "version": "==4.66.1" + "version": "==4.66.2" }, "typing-extensions": { "hashes": [ - "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783", - "sha256:af72aea155e91adfc61c3ae9e0e342dbc0cba726d6cba4b6c72c1f34e47291cd" + "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475", + "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb" ], "markers": "python_version >= '3.8'", - "version": "==4.9.0" + "version": "==4.10.0" }, "ujson": { "hashes": [ @@ -563,11 +569,11 @@ }, "wcmatch": { "hashes": [ - "sha256:14554e409b142edeefab901dc68ad570b30a72a8ab9a79106c5d5e9a6d241bd5", - "sha256:86c17572d0f75cbf3bcb1a18f3bf2f9e72b39a9c08c9b4a74e991e1882a8efb3" + "sha256:24c19cedc92bc9c9e27f39db4e1824d72f95bd2cea32b254a47a45b1a1b227ed", + "sha256:c0088c7f6426cf6bf27e530e2b7b734031905f7e490475fd83c7c5008ab581b3" ], "markers": "python_version >= '3.8'", - "version": "==8.5" + "version": "==8.5.1" }, "xmltodict": { "hashes": [ @@ -575,6 +581,7 @@ "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852" ], "index": "pypi", + "markers": "python_version >= '3.4'", "version": "==0.13.0" } }, diff --git a/mobsfscan/__init__.py b/mobsfscan/__init__.py index 22b8fe2..efcb680 100644 --- a/mobsfscan/__init__.py +++ b/mobsfscan/__init__.py @@ -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__', diff --git a/mobsfscan/manifest.py b/mobsfscan/manifest.py index 7d7e6f7..f563eea 100644 --- a/mobsfscan/manifest.py +++ b/mobsfscan/manifest.py @@ -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 @@ -50,6 +53,7 @@ '32': '12L', '33': '13', '34': '14', + '35': '15', } @@ -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}' diff --git a/mobsfscan/utils.py b/mobsfscan/utils.py index 965b639..e541000 100644 --- a/mobsfscan/utils.py +++ b/mobsfscan/utils.py @@ -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 @@ -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 diff --git a/requirements.txt b/requirements.txt index c8e04f6..9d459d6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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 @@ -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 @@ -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