Skip to content

Instantly share code, notes, and snippets.

@kmsec-uk
Created November 30, 2023 16:42
Show Gist options
  • Save kmsec-uk/a8f5bde6f39e3d92d5e16bb289022850 to your computer and use it in GitHub Desktop.
Save kmsec-uk/a8f5bde6f39e3d92d5e16bb289022850 to your computer and use it in GitHub Desktop.
Elastic ransom analysis
#! /usr/bin/env python3.11
import argparse
import json
import requests
# input file `shodan download readme_indices 'product:elastic "read-me"'`
parser = argparse.ArgumentParser(description='Ad-hoc elasticsearch ransom hunt')
parser.add_argument('-f', required=True, type=str,
help='shodan json data file results from `shodan download [file] [query]')
args = parser.parse_args()
shodan_datafile = args.f
with open(shodan_datafile, 'r', encoding='utf-8') as shodan_data:
samples = 0
count_unmatched = 0
count_processed = 0
count_failed = 0
results = dict()
for banner in shodan_data.readlines():
samples += 1
banner_dict = json.loads(banner)
# begin vetting data
try:
count_docs = banner_dict['elastic']['indices']['read-me']['total']['docs']['count']
except KeyError:
# we don't want to enumerate if we don't see the index in shodan data
count_unmatched += 1
continue
if count_docs > 1:
count_unmatched += 1
# we don't want to enumerate if there are more than one document (there should only be one ransom note)
continue
# ingest data vetting complete
# now to enumerate
protocol = 'https' if 'ssl' in banner_dict else 'http'
ip, port = banner_dict["ip_str"], banner_dict['port']
base_URL = f'{protocol}://{ip}:{port}'
search_parameter = '/read-me/_search/'
print(f'enumerating {base_URL + search_parameter}')
try:
response = requests.get(base_URL + search_parameter, verify=None, timeout=5)
body = response.json()
matched_text = body['hits']['hits'][0]['_source']['message']
# print(matched_text)
results[base_URL] = matched_text
count_processed += 1
except Exception as e:
count_failed += 1
print(f'Error processing {base_URL}:\n{e}')
continue
# break
print('finished')
print('samples\tunmatched\tprocessed\tfailed')
print(f'{samples}\t{count_unmatched}\t\t{count_processed}\t\t{count_failed}')
print(json.dumps(results))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment