-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathamplification-detect.pl
executable file
·122 lines (113 loc) · 3.67 KB
/
amplification-detect.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/perl -w
#
# Detect hosts vulnerable to DDoS amplification attacks.
# Prerequisites: apt install nmap libnmap-parser-perl
# Usage: amplification-detect.pl <ip/mask> <ip/mask> ...
# (c) <sa-dev@odd.systems> 2020
#
use strict;
no warnings "experimental::smartmatch";
use utf8;
use Nmap::Parser;
my $nmap_path = "nmap";
my $nmap_args = "-n -Pn -sU -pU:53,111,123,137,161,1900,11211 --script=dns-recursion,rpcinfo,ntp-monlist,nbstat,snmp-sysdescr,upnp-info,memcached-info";
my $client_by_ip = "./client_by_ip"; # must print single line, if present
my @hosts = @ARGV;
my ($np, $ip, $host, @c_arg, $udp_ports, @open_ports, $port, $o, $vuln);
my (%h, $c); # result, client
$np = new Nmap::Parser;
$np->parsescan($nmap_path, $nmap_args, @hosts);
IP: for $ip ($np->get_ips("up")){
$host = $np->get_host($ip);
@open_ports = $host->udp_open_ports();
if (scalar(@open_ports) < 1) { next IP }
$udp_ports = $host->{ports}->{udp};
$c = undef;
for $port (@open_ports) {
$vuln = undef;
#if ($port == 17) {
# TODO: script to check
# $vuln = "qotd";
# }
#if ($port == 19) {
# TODO: script to check
# $vuln = "chargen";
#}
if ($port == 53) {
$o = $udp_ports->{53}->{service}->{script}->{'dns-recursion'}->{output};
if ((defined $o) and $o =~ /recursion.*enabled/i) {
$vuln = "dns";
}
}
if ($port == 111) {
$o = $udp_ports->{111}->{service}->{script}->{rpcinfo}->{output};
if ((defined $o) and $o =~ /program\s+version/) {
$vuln = "portmap";
}
}
if ($port == 123) {
$o = $udp_ports->{123}->{service}->{script}->{'ntp-monlist'}->{output};
if ((defined $o) and $o =~ /synchronised|Servers|Clients/i) {
$vuln = "ntp";
}
}
if ($port == 137) {
# NetBIOS Name Service
if ((defined $o) and $o =~ /name/i) {
$vuln = "smb";
}
# TODO: consider NetBIOS Datagram Service (NBDS) (138/udp) too
}
if ($port == 161) {
$o = $udp_ports->{161}->{service}->{script}->{'snmp-sysdescr'}->{output};
if ((defined $o) and $o =~ /System/i) {
$vuln = "snmp";
}
}
#if ($port == 520) {
# TODO: script to check
# $vuln = "ripv1";
#}
if ($port == 1900) {
$o = $udp_ports->{1900}->{service}->{script}->{'upnp-info'}->{output};
if (defined $o) {
$vuln = "ssdp";
}
}
if ($port == 11211) {
$o = $udp_ports->{11211}->{service}->{script}->{'memcached-info'}->{output};
if (defined $o) {
$vuln = "memcached";
}
}
if (defined $vuln) {
# client: lazy initialization
unless (defined $c) {
if (-x $client_by_ip) {
@c_arg = ($client_by_ip, $ip);
open (CBI, "-|", @c_arg);
$c = <CBI>;
if (defined $c) { chomp ($c); }
close CBI;
}
if ((not defined ($c)) or $c eq "") {
$c = "undefined client";
}
} # got c
unless ($vuln ~~ @{$h{$c}->{$ip}}) {
push @{$h{$c}->{$ip}}, $vuln;
}
}
}
}
for $c (keys %h) {
print $c."\n";
for $ip (keys %{$h{$c}}) {
print " ".$ip."\n";
for $vuln (@{$h{$c}->{$ip}}) {
print " ".$vuln."\n";
}
}
print "\n";
}
1;