MobSF SSRF Vulnerability on assetlinks_check(act_name, well_knowns)
Description
Mobile Security Framework (MobSF) is a pen-testing, malware analysis and security assessment framework capable of performing static and dynamic analysis. In version 3.9.5 Beta and prior, MobSF does not perform any input validation when extracting the hostnames in android:host, so requests can also be sent to local hostnames. This can lead to server-side request forgery. An attacker can cause the server to make a connection to internal-only services within the organization's infrastructure. Commit 5a8eeee73c5f504a6c3abdf2a139a13804efdb77 has a hotfix for this issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
mobsfscanPyPI | < 0.3.8 | 0.3.8 |
Affected products
1- Range: <= 3.9.5 Beta
Patches
2cd01b71770a6fix possible redirect ssrf
2 files changed · +2 −2
mobsfscan/__init__.py+1 −1 modified@@ -6,7 +6,7 @@ __title__ = 'mobsfscan' __authors__ = 'Ajin Abraham' __copyright__ = f'Copyright {datetime.now().year} Ajin Abraham, OpenSecurity' -__version__ = '0.3.7' +__version__ = '0.3.8' __version_info__ = tuple(int(i) for i in __version__.split('.')) __all__ = [ '__title__',
mobsfscan/manifest.py+1 −1 modified@@ -323,7 +323,7 @@ def check_url(self, w_url): try: r = requests.get( w_url, - allow_redirects=True, + allow_redirects=False, timeout=5) if not (str(r.status_code).startswith('2') and iden in str(r.json())):
61fd40b477bb[SECURITY]Fix SSRF, dep bump
5 files changed · +109 −34
mobsfscan/__init__.py+1 −1 modified@@ -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__',
mobsfscan/manifest.py+13 −4 modified@@ -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}'
mobsfscan/utils.py+59 −0 modified@@ -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
Pipfile.lock+29 −22 modified@@ -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,18 +569,19 @@ }, "wcmatch": { "hashes": [ - "sha256:14554e409b142edeefab901dc68ad570b30a72a8ab9a79106c5d5e9a6d241bd5", - "sha256:86c17572d0f75cbf3bcb1a18f3bf2f9e72b39a9c08c9b4a74e991e1882a8efb3" + "sha256:24c19cedc92bc9c9e27f39db4e1824d72f95bd2cea32b254a47a45b1a1b227ed", + "sha256:c0088c7f6426cf6bf27e530e2b7b734031905f7e490475fd83c7c5008ab581b3" ], "markers": "python_version >= '3.8'", - "version": "==8.5" + "version": "==8.5.1" }, "xmltodict": { "hashes": [ "sha256:341595a488e3e01a85a9d8911d8912fd922ede5fecc4dce437eb4b6c8d037e56", "sha256:aa89e8fd76320154a40d19a0df04a4695fb9dc5ba977cbb68ab3e4eb225e7852" ], "index": "pypi", + "markers": "python_version >= '3.4'", "version": "==0.13.0" } },
requirements.txt+7 −7 modified@@ -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
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
8- github.com/advisories/GHSA-wfgj-wrgh-h3r3ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-29190ghsaADVISORY
- drive.google.com/file/d/1nbKMd2sKosbJef5Mh4DxjcHcQ8Hw0BNR/viewghsax_refsource_MISCWEB
- github.com/MobSF/Mobile-Security-Framework-MobSF/commit/5a8eeee73c5f504a6c3abdf2a139a13804efdb77ghsax_refsource_MISCWEB
- github.com/MobSF/Mobile-Security-Framework-MobSF/security/advisories/GHSA-wfgj-wrgh-h3r3ghsax_refsource_CONFIRMWEB
- github.com/MobSF/mobsfscan/commit/61fd40b477bbf9d204eb8c5a83a86c396d839798ghsaWEB
- github.com/MobSF/mobsfscan/commit/cd01b71770a6e56c1c71b0e5f454e7b6c9c64ef4ghsaWEB
- github.com/pypa/advisory-database/tree/main/vulns/mobsf/PYSEC-2024-257.yamlghsaWEB
News mentions
0No linked articles in our index yet.