-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 KL-001-2024-007: Journyx Unauthenticated Password Reset Bruteforce Title: Journyx Unauthenticated Password Reset Bruteforce Advisory ID: KL-001-2024-007 Publication Date: 2024.08.07 Publication URL: https://korelogic.com/Resources/Advisories/KL-001-2024-007.txt 1. Vulnerability Details Affected Vendor: Journyx Affected Product: Journyx (jtime) Affected Version: 11.5.4 Platform: GNU/Linux CWE Classification: CWE-321: Use of Hard-coded Cryptographic Key, CWE-334: Small Space of Random Values, CWE-799: Improper Control of Interaction Frequency CVE ID: CVE-2024-6890 2. Vulnerability Description Password reset tokens are generated using an insecure source of randomness. Attackers who know the username of the Journyx installation user can bruteforce the password reset and change the administrator password. 3. Technical Description From an unauthenticated perspective, a user can initiate the password reset flow by clicking the "Reset your password" button on the Journyx login screen and supplying a valid username. A password reset link containing a "random" token is sent to the email address associated with the username. The password reset token is generated using the current epoch and the user ID associated with the request. The user ID is a 128-bit UUID for every user *except* for the user created during the initial setup of the Journyx instance, i.e., the system administrator account. For this single user, the user ID defaults to the username. By targeting this user, the need to leak a UUID is removed entirely. If the Journyx instance was configured according to the official System Administration guide (https://journyx.com/Files/Journyx_Sysadmin_and_Recovery_v11.pdf), the username is "journyx". Alternatively, the username can be leaked via stacktraces. When generating the token, a secret key is created by inserting the user ID inbetween the strings 'chuck' and 'palahniuk': mysessiontoken = 'chuck%spalahniuk' % me This key is used to XOR the string literal representation of the list object "[userID, time.time()]". The output of the XOR function is then base64 encoded: eStr = xor_str(istr, key) aStr = binascii.b2a_base64(eStr).strip() Since the user ID is a known value, only the output of "time.time()" (the epoch at the time of "encryption") is unknown. However, by opening a TCP connection and noting the epoch immediately after sending an HTTP request to initiate the password reset flow, a pool of tokens can be generated by incrementing the epoch. There is a high degree of certainty the valid reset token is contained within a pool larger than 50,000 tokens. Depending upon network latency and other external factors, a successful bruteforce attack using these tokens can take anywhere from several minutes to over an hour. 4. Mitigation and Remediation Recommendation The vendor reports that this issue was remediated in Journyx v12.0.0, which is the first wholly cloud-hosted version of this product. For self-hosted versions of Journyx, one incremental improvement is to disable user-initiated password reset functionality in the application settings. 1) Log into the JournyX web application as an administrator 2) Navigate to Configuration -> System Settings -> Security Settings 3) Ensure the checkbox labeled "Show a password reset button on login screen" is disabled. 4) Click the "Save" button Another option would be to monkey patch the .pyc file that contains these hardcoded strings, ./wtdoc.pyc, by deploying a .py file that uses unique strings and then loads wtdoc_original.pyc (see KL-001-2024-008 and KL-001-2024-009 for examples). 5. Credit This vulnerability was discovered by Jaggar Henry of KoreLogic, Inc. 6. Disclosure Timeline 2024.01.31 - KoreLogic notifies Journyx support of the intention to report vulnerabilities discovered in the licensed, on-premises version of the product. 2024.01.31 - Journyx acknowledges receipt. 2024.02.02 - KoreLogic requests a meeting with Journyx support to share vulnerability details. 2024.02.07 - KoreLogic reports vulnerability details to Journyx. 2024.02.09 - Journyx responds that this vulnerability has been remediated in the cloud-hosted version of the product. 2024.02.21 - KoreLogic offers to test the cloud version to confirm the fix; no response. 2024.07.01 - KoreLogic notifies Journyx of impending public disclosure. 2024.07.09 - Journyx confirms version number of the remediation. 2024.08.07 - KoreLogic public disclosure. 7. Proof of Concept The following script automatically exploits this issue by initiating a password reset flow and bruteforces the value after generating a list of 50,000 tokens. [attacker@box]$ python unauth2rce.py --url http://redacted.com:8080/ --username foo --command id [*] Beginning Attack. Using the following timestamp: "1706708084.2051988" [+] New Password Generated: 2DCD5AE1F0F34B84A1E0F1FB5768219B The contents of this advisory are copyright(c) 2024 KoreLogic, Inc. and are licensed under a Creative Commons Attribution Share-Alike 4.0 (United States) License: http://creativecommons.org/licenses/by-sa/4.0/ KoreLogic, Inc. is a founder-owned and operated company with a proven track record of providing security services to entities ranging from Fortune 500 to small and mid-sized companies. We are a highly skilled team of senior security consultants doing by-hand security assessments for the most important networks in the U.S. and around the world. We are also developers of various tools and resources aimed at helping the security community. https://www.korelogic.com/about-korelogic.html Our public vulnerability disclosure policy is available at: https://korelogic.com/KoreLogic-Public-Vulnerability-Disclosure-Policy -----BEGIN PGP SIGNATURE----- iQJOBAEBCAA4FiEEB12WYZwbVwYTJ/b2DKLsCTlWkekFAma0BxsaHGRpc2Nsb3N1 cmVzQGtvcmVsb2dpYy5jb20ACgkQDKLsCTlWkemQgQ/+M0hcpHsmJT5xdBX/+rlq vYD2vQktIjYiHgVl6oPwy7cNUwY5vyMQQMprI29jvcMBzVh+nwO6aEcv4hdp87XQ 247va6ytojDxrDtPacdwIADYc0GrDu/C6nL3zih1BXvAsSP5OjH+wCnQlJQEAmRh dgqzTYsvgBk4IoL3kUffVrK2Z7/11W5RQofQqzgdP7wSh0Z9fjy6qYa1tRBakR0b Gz7xQCuhaF/SxvNLuOY/Cljetc6P16eCx2rUzyEhRCgD71BV8QptRuYnjFjf4aej Q29nJYJoZrZBgnnbKiouph2XXpZG/ibvzngUWaOioLYOX/vXKt41OQdsHR1DcsvD NLrde8B0lJjHJRV2y0RQl0y0NntTPMMvYJRPIiRmT9FdUIvix9IkZITU0wW8VdMy oIGN2SYJnaJuKr7qAfOqUXT7uFjWejSkkr1uL8egkwVeFRjFM9OcNsbgwOHJaeY3 Xu/G8vu1IjjNt116KAiaxnauqztdzHRtpN6FBBjrDQrljNqnH8mhnMbbr3CTXo3c 3hbKYe1UojLHlPVD6QLtOb6+bb6dTkzyoNpkxyG/uOddSkNyNdIG3/E/bHgkjoi4 nWWg5qh+bMe58E+QE3ak5mcbANk2SFb+mWmyW7Xeamq/OaPFASM62a6Dn/rjaMnl dyp6nHNXVPhfaTm7hv6m+kc= =eCRK -----END PGP SIGNATURE-----