Skip to content

Instantly share code, notes, and snippets.

@ragzilla
Created February 28, 2015 20:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ragzilla/d9bf4320245097313564 to your computer and use it in GitHub Desktop.
Save ragzilla/d9bf4320245097313564 to your computer and use it in GitHub Desktop.
#! /home/maddison/.virtualenv/nfdump-notifier/bin/python
from ipwhois import IPWhois
from ipwhois.utils import unique_addresses
from pprint import pprint
from struct import unpack, pack
import socket
import select
import sys
import string
import smtplib
from email.mime.text import MIMEText
import sqlite3
results = unique_addresses(file_path='./top10000.201502281040-201502281200')
DEBUG=False #Enables basic debug info
TIMEOUT=0.33 #Read timeout in seconds
TRIES=3 #Number of times to do the monlist request
FROM_ADDR='noreply@example.com'
SMTP_SERVER='mx.example.com'
EMAIL_PAYLOAD="""
A public NTP server on your network, running on IP address {ip_address}, participated in a large-scale attack against a customer of ours today, generating UDP responses to spoofed "monlist" requests that claimed to be from the attack target.
Please consider reconfiguring this NTP server in one or more of these ways:
1. If you run ntpd, upgrading to the latest version, which removes the "monlist" command that is used for these attacks; alternately, disabling the monitoring function by adding "disable monitor" to your /etc/ntp.conf file.
2. Setting the NTP installation to act as a client only. With ntpd, that can be done with "restrict default ignore" in /etc/ntp.conf; other daemons should have a similar configuration option. More information on configuring different devices can be found here: https://www.team-cymru.org/ReadingRoom/Templates/secure-ntp-template.html.
3. Adjusting your firewall or NTP server configuration so that it only serves your users and does not respond to outside IP addresses.
If you don't mean to run a public NTP server, we recommend #1 and #2. If you do mean to run a public NTP server, we recommend #1, and also that you rate-limit responses to individual source IP addresses -- silently discarding those that exceed a low number, such as one request per IP address per second. Rate-limit functionality is built into many recently-released NTP daemons, including ntpd, but needs to be enabled; it would help with different types of attacks than this one.
Fixing open NTP servers is important; with the 400x+ amplification factor of NTP DRDoS attacks -- one 40-byte-long request usually generates 18252 bytes worth of response traffic -- it only takes one machine on an unfiltered 1 Gbps link to create a 450+ Gbps attack!
If you are an ISP, please also look at your network configuration and make sure that you do not allow spoofed traffic (that pretends to be from external IP addresses) to leave the network. Hosts that allow spoofed traffic make possible this type of attack.
Further reading:
https://cert.litnet.lt/en/docs/ntp-distributed-reflection-dos-attacks
https://isc.sans.org/forums/diary/NTP+reflection+attack/17300
http://www.symantec.com/connect/blogs/hackers-spend-christmas-break-launching-large-scale-ntp-reflection-attacks
http://kb.juniper.net/InfoCenter/index?page=content&id=JSA10613&smlogin=true
You can find more vulnerable servers on your network through this site: http://openntpproject.org/
<your signature here>
Thanks to NFOservers.com for the email text.
"""
def int_ip_to_str(ip_num):
return socket.inet_ntoa(pack('!L', ip_num))
def str_ip_to_int(ip):
return unpack('!L',socket.inet_aton(ip))
def get_payload():
return """\x17\x00\x03\x2a\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"""
def fetch(ntp_server, timeout=5):
def send_payload(sock, target):
data = get_payload()
bytes_sent = sock.sendto(data, (target, 123))
if bytes_sent != len(data) and DEBUG:
print "Failed to send payload"
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('0.0.0.0', 0))
send_payload(sock, ntp_server)
results = set()
count = 0
while True:
rlist, wlist, xlist = select.select([sock], [], [], TIMEOUT)
if sock in rlist:
data, addr = sock.recvfrom(1024)
return True
else:
count += 1
if count >= TRIES:
break
send_payload(sock, ntp_server)
return False
conn = sqlite3.connect('./notifier.sqlite3')
c = conn.cursor()
c.execute('''create table if not exists notifier(ip text unique)''')
monlist = set()
for result in results:
print result,
c.execute('''select count(*) from notifier where ip = ?''', (result,))
d = c.fetchone()[0]
if d != 0:
print 'already notified, skipping.'
continue
conn.execute('''insert into notifier values(?)''', (result,))
conn.commit()
if fetch(result):
w = IPWhois(result).lookup(get_referral=False)
abuse = list()
for net in w['nets']:
if 'abuse_emails' in net.keys():
if net['abuse_emails'] == None:
continue
for email in net['abuse_emails'].split('\n'):
abuse.append(email)
print abuse
if len(abuse) == 0:
continue
msg = MIMEText(EMAIL_PAYLOAD.format(ip_address=result))
msg['Subject'] = 'Exploitable NTP server used for an attack: ' + result
msg['To'] = ', '.join(abuse)
msg['From'] = FROM_ADDR
s = smtplib.SMTP(SMTP_SERVER)
s.sendmail(FROM_ADDR, abuse, msg.as_string())
s.quit()
else:
print 'no monlist response'
@ragzilla
Copy link
Author

uses ipwhois to get a list of unique ip addresses from a text file (in our case, nfdump output of ntp ddos sources), tries to check if the IP responds to ntp monlist (lines 51-84), and if so looks up the abuse contacts via ipwhois' lookup function and sends them an email asking them to fix their open ntp amplifier.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment