Extract hostnames and domains from DDoSia MISP object

DDoSia

DDoSia is a distributed denial-of-service (DDoS) attack tool reportedly employed by pro-Russian hacktivist groups. The tool coordinates large networks of compromised devices to flood targeted websites or services with excessive traffic, overwhelming their capacity and rendering them inaccessible to legitimate users. It has been used to disrupt government, financial, and media platforms, aiming to create instability and hinder critical infrastructure.

The DDoSia configuration, basically the instructions for the attack tool, have been shared via the MISP platform as MISP objects (ddos-config object).

Extract hostnames and domains

I created a small tool to

  • Search for the events with the DDoSia config file;
  • Extract the unique hostnames and domains;
  • Print the summary, and optionally send it to Mattermost.

The script requires the pymisp and tldextract Python libraries.

Sample output

Parsed 9 events and found 65 unique hostnames for 49 domains - (2024-10-08)
Hostnames
 1535.omr.gov.ua
 authentication.antwerpen.be
 cabinet.teplo.od.ua
 cci.sumy.ua
 citizen.omr.gov.ua
 dsns.gov.ua
 gouvernement.cfwb.be
 itd.rada.gov.ua
 kassa.bus.com.ua
 komfinbank.rada.gov.ua
 komit.rada.gov.ua
 komnbor.rada.gov.ua
 kompek.rada.gov.ua




Script

You can find the script on GitHub at https://github.com/cudeso/tools/blob/master/ddosia-extract/parse_ddosia.py. Make sure you

  • Set the misp_url and misp_key. Point it to your MISP server;
  • Set the date_filter to limit the results;
  • Choose if you want to send results to Mattermost with send_mattermost (and set mattermost_hook)

import urllib3
import sys
import json
import requests
import tldextract
from datetime import datetime

from pymisp import *

# Get events from MISP with the DDoSia configuration object.
# Extract unique hostnames and domains
# Optionally send to Mattermost
#
# Koen Van Impe - 2024

# Credentials
misp_url = "MISP"
misp_key = "KEY"
misp_verifycert = True
mattermost_hook = ""
teams_hook = ""
ddosia_file_output = "/var/www/MISP/app/webroot/misp-export/ddosia.txt"

# Output
target_hostnames = []
target_domains = []

# Send to Mattermost?
send_mattermost = False

# Send to Teams
send_teams = False

# Write to file
write_to_ddosia_file_output = False

# MISP organisation "witha.name"
query_org = "ae763844-03bf-4588-af75-932d5ed2df8c"

# Published?
published = True

# Limit for recent events
date_filter = "1d"

# Create PyMISP object and test connectivity
misp = PyMISP(misp_url, misp_key, misp_verifycert)
print(f"Extract hostnames from {misp_url}")

# Search for events
events = misp.search("events", pythonify=True, org=query_org, published=published, date=date_filter)

# Process events
if len(events) > 0:
    print("Parsing {} events".format(len(events)))
    for event in events:
        print(" Event {} ({})".format(event.info, event.uuid))
        for object in event.objects:
            if object.name == "ddos-config":
                for attribute in object.Attribute:
                    if attribute.type == "hostname":
                        check_value = attribute.value.lower().strip()
                        if check_value not in target_hostnames:
                            target_hostnames.append(check_value)
                            print(f"  Found {check_value}")

                        extracted = tldextract.extract(check_value)
                        domain = '.'.join([extracted.domain, extracted.suffix])
                        if domain not in target_domains:
                            target_domains.append(domain)

    if len(target_hostnames) > 0:
        target_hostnames.sort()
        target_domains.sort()
        
        title = "DDoSia config: Parsed {} MISP events and found {} unique hostnames for {} domains - ({}, last {})".format(len(events), len(target_hostnames), len(target_domains), datetime.now().date(), date_filter)
        summary = "Hostnames\n------------\n"
        summary_md = "# Hostnames\n"

        for t in target_hostnames:
            summary += "\n{}".format(t)
            summary_md += "\n- {}".format(t)

        summary += "\n\nDomains\n----------\n"
        summary_md += "\n\n# Domains\n"
        for t in target_domains:
            summary += "\n{}".format(t)
            summary_md += "\n- {}".format(t)
        summary_md += "\n"
        
        if send_mattermost:
            summary_md = title + summary_md + "\n"
            message = {"username": "witha.name-reporters", "text": summary_md}
            r = requests.post(mattermost_hook, data=json.dumps(message))
            print(r, r.status_code, r.text)
                        
        if send_teams:
            message = {
                    "type": "message",
                    "attachments": [
                        {
                            "contentType": "application/vnd.microsoft.teams.card.o365connector",
                            "content": {
                                "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                                "type": "MessageCard",
                                "context": "https://schema.org/extensions",
                                "title": title,
                                "version": "1.0",
                                "sections": [
                                    {
                                        "text": summary_md
                                    }
                                ]
                            }
                        }
                    ]
                }
            r = requests.post(teams_hook, json=message)
            
        if write_to_ddosia_file_output:
            summary = title + "\n\n" + summary + "\n"
            with open(ddosia_file_output, 'w') as file:
                file.write(summary)

else:
    print("No events found.")

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.