├── AWS
└── Enumerate.rb
├── ActiveDirectory
└── LastLogin.ps1
├── Bro
├── anomalousOutbound.bro
├── conns.sh
├── long_conns.bro
├── outbound.bro
├── phishing-2.2.bro
├── phishing.bro
├── threshold.bro
├── thresholds.bro
└── watch_conns.sh
├── DNS
├── brute.rb
├── ip_address.rb
└── mapper.rb
├── PAE
├── Makefile
├── pae.c
└── plot.py
├── PCI
├── cisp_analyze
├── cisp_ciphers
├── cisp_scanner
├── cisp_sniffer
├── cisp_vuln_scan
└── sample_pci_report.html
├── README
├── Scapy
├── 4whs.py
├── TBR.py
└── windos.py
├── Statistics
└── Calculate Samples and Errors.xlsx
├── Syslog
└── correctTimestamp.rb
├── Tools Reference AUD507.pdf
├── Useful Documents
└── Calculate Samples and Errors.xlsx
└── Wireless
├── find_netbios
├── netbios.pl
├── netbios.rb
└── rfind_netbios
/AWS/Enumerate.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | require 'json'
3 | require 'aws-sdk'
4 |
5 | File.open('node.cfg', 'w') do |file|
6 | File.open('pssh_hosts', 'w') do |pssh_file|
7 |
8 | file.write("
9 | [manager]
10 | type=manager
11 | host=10.95.190.205
12 |
13 | [proxy]
14 | type=proxy
15 | host=10.95.190.205
16 |
17 | ")
18 |
19 | regions = `aws ec2 describe-regions --output text | cut -f3`
20 | regions.split(/\n/).each do |region|
21 | puts region
22 | ec2 = Aws::EC2::Resource.new(region: region)
23 | ec2.instances.each do |i|
24 | i.tags.each do |tag|
25 | if (tag.key == "Name" && tag.value.include?("VPN")) then
26 | file.write("[#{tag.value}]\ntype=worker\nhost=#{i.private_ip_address}\n\n")
27 | pssh_file.write("#{i.private_ip_address}\n")
28 | end
29 | end
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/ActiveDirectory/LastLogin.ps1:
--------------------------------------------------------------------------------
1 | $Domain = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
2 | $ADSearch = New-Object System.DirectoryServices.DirectorySearcher
3 | $ADSearch.PageSize = 100
4 | $ADSearch.SearchScope = "subtree"
5 | $ADSearch.SearchRoot = "LDAP://$Domain"
6 |
7 | $ADSearch.Filter = "(objectClass=user)"
8 |
9 | $ADSearch.PropertiesToLoad.Add("distinguishedName")
10 | $ADSearch.PropertiesToLoad.Add("sAMAccountName")
11 | $ADSearch.PropertiesToLoad.Add("lastLogonTimeStamp")
12 |
13 | $userObjects = $ADSearch.FindAll()
14 | foreach ($user in $userObjects)
15 | {
16 | $dn = $user.Properties.Item("distinguishedName")
17 | $sam = $user.Properties.Item("sAMAccountName")
18 | $logon = $user.Properties.Item("lastLogonTimeStamp")
19 | if($logon.Count -eq 0)
20 | {
21 | $lastLogon = "Never"
22 | }
23 | else
24 | {
25 | $lastLogon = [DateTime]$logon[0]
26 | $lastLogon = $lastLogon.AddYears(1600)
27 | }
28 |
29 | """$dn"",$sam,$lastLogon"
30 | }
--------------------------------------------------------------------------------
/Bro/anomalousOutbound.bro:
--------------------------------------------------------------------------------
1 | # Bro script to find outbound connections for which there are no corresponding DNS lookups.
2 | # David Hoelzer, Enclave Forensics, Inc - Copyright 2018
3 |
4 | global knownAddresses: set[addr] &read_expire = 7 days &synchronized;
5 | global internalAddresses: set[subnet] = {192.168.0.0/16};
6 |
7 | event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a:addr)
8 | {
9 | add knownAddresses[a];
10 | }
11 |
12 | event connection_SYN_packet(c: connection, packet:SYN_packet)
13 | {
14 | if(c$id$orig_h !in internalAddresses) { return; }
15 | if(c$id$resp_h in internalAddresses) { return; }
16 | if(c$id$resp_h in knownAddresses) { return; }
17 |
18 | local message: string;
19 | message = fmt("Outbound connection %s:%s > %s:%s without a DNS lookup.", c$id$orig_h, c$id$orig_p,
20 | c$id$resp_h, c$id$resp_p);
21 | NOTICE([$note=Weird::Activity, $msg=message, $conn=c]);
22 | }
--------------------------------------------------------------------------------
/Bro/conns.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | SECTIONS=4
4 | COLS=$(tput cols)
5 | ROWS=$(tput lines)
6 | SPLIT=$(($ROWS-$SECTIONS-4))
7 | SPLIT=$(($SPLIT/$SECTIONS))
8 | function sep
9 | {
10 | string=$1
11 | line="+---[ $string ]"
12 | strlen=${#line}
13 | padding=$(($COLS-$strlen-1))
14 | printf -v output '%*s' "$padding"
15 | echo $line${output// /-}+
16 | }
17 | sep Connections
18 | if [ -e conn.log ] ; then
19 | cat conn.log | bro-cut -d ts id.orig_h id.orig_p id.resp_h id.resp_p proto orig_bytes resp_bytes orig_pkts resp_pkts | tail -$SPLIT
20 | fi
21 | sep Weird
22 | if [ -e weird.log ] ; then
23 | cat weird.log | bro-cut -d ts id.orig_h id.orig_p id.resp_h id.resp_p name| tail -$SPLIT
24 | fi
25 | sep "DNS Queries"
26 | if [ -e dns.log ] ; then
27 | cat dns.log | bro-cut -d ts id.orig_h query answers auth | tail -$SPLIT
28 | fi
29 | sep Notices
30 | if [ -e notice.log ] ; then
31 | cat notice.log | bro-cut -d ts id.orig_h id.resp_h note msg | tail -$SPLIT
32 | fi
33 |
--------------------------------------------------------------------------------
/Bro/long_conns.bro:
--------------------------------------------------------------------------------
1 | @load base/protocols/conn
2 | @load base/utils/time
3 |
4 |
5 | # This is probably not so great to reach into the Conn namespace..
6 | module Conn;
7 |
8 | export {
9 | function set_conn_log_data_hack(c: connection)
10 | {
11 | Conn::set_conn(c, T);
12 | }
13 | }
14 |
15 | # Now onto the actual code for this script...
16 |
17 | module LongConnection;
18 |
19 | export {
20 | redef enum Log::ID += { LOG };
21 |
22 | redef enum Notice::Type += {
23 | ## Notice for when a long connection is found.
24 | ## The `sub` field in the notice represents the number
25 | ## of seconds the connection has currently been alive.
26 | LongConnection::found
27 | };
28 |
29 | ## Aliasing vector of interval values as
30 | ## "Durations"
31 | type Durations: vector of interval;
32 |
33 | ## The default duration that you are locally
34 | ## considering a connection to be "long".
35 | ## After the durations run out we'll just keep tacking on 24 hours.
36 | const default_durations = Durations(4hr, 8hr, 12hr) &redef;
37 |
38 | ## These are special cases for particular hosts or subnets
39 | ## that you may want to watch for longer or shorter
40 | ## durations than the default.
41 | const special_cases: table[subnet] of Durations = {} &redef;
42 | const monitoring_hosts: set[subnet] = {
43 | 10.0.0.0/8
44 | };
45 |
46 | }
47 |
48 | event bro_init() &priority=5
49 | {
50 | Log::create_stream(LOG, [$columns=Conn::Info, $path="conn_long"]);
51 | }
52 |
53 | function get_durations(c: connection): Durations
54 | {
55 | local check_it: Durations;
56 | if ( c$id$orig_h in special_cases )
57 | check_it = special_cases[c$id$orig_h];
58 | else if ( c$id$resp_h in special_cases )
59 | check_it = special_cases[c$id$resp_h];
60 | else
61 | check_it = default_durations;
62 |
63 | return check_it;
64 | }
65 |
66 | function duration_to_string(duration: interval) : string
67 | {
68 | local seconds = double_to_count(interval_to_double(duration));
69 | local days = seconds/86400;
70 | local hours = (seconds - (days * 86400))/3600;
71 | local minutes = (seconds - (days * 86400) - (hours * 3600))/60;
72 | return fmt("%d day, %d hours, %d minutes", days, hours, minutes);
73 | }
74 |
75 | function long_callback(c: connection, cnt: count): interval
76 | {
77 | local check_it = get_durations(c);
78 | local next_checkpoint :interval;
79 |
80 | Conn::set_conn_log_data_hack(c);
81 | Log::write(LongConnection::LOG, c$conn);
82 |
83 | local message = fmt("%s -> %s:%s remained alive for longer than %s",
84 | c$id$orig_h, c$id$resp_h, c$id$resp_p, duration_to_string(c$duration));
85 | NOTICE([$note=LongConnection::found,
86 | $msg=message,
87 | $sub=fmt("%.2f", c$duration),
88 | $conn=c]);
89 |
90 | # Keep watching if there are potentially more thresholds.
91 | if (cnt < |check_it|)
92 | next_checkpoint = check_it[cnt];
93 | else
94 | next_checkpoint = ((cnt - |check_it|) * 86400sec);
95 | return next_checkpoint;
96 | }
97 |
98 | event connection_established(c: connection)
99 | {
100 | local check = get_durations(c);
101 | if(c$id$orig_h in monitoring_hosts && c$id$resp_h in monitoring_hosts) { return; }
102 | if ( |check| > 0 )
103 | {
104 | ConnPolling::watch(c, long_callback, 1, check[0]);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/Bro/outbound.bro:
--------------------------------------------------------------------------------
1 | @load base/protocols/conn/main.bro
2 |
3 | module Outbound;
4 |
5 | export {
6 | redef enum Log::ID += { LOG };
7 | type Info: record {
8 | ts: time &log;
9 | id: conn_id &log;
10 | uid: string &log;
11 | proto: string &log;
12 | };
13 |
14 | const internal_networks: set[subnet] = {
15 | 10.0.0.0/8
16 | };
17 |
18 | const bro_manager: set[addr] = {
19 | 10.186.52.51
20 | };
21 |
22 | const known_endpoints: set[addr] = {
23 | 108.60.137.12,
24 | 169.254.169.254,
25 | 8.8.8.8
26 | };
27 |
28 | const whitelisted_services: set[port] = {
29 | 123/udp,
30 | 67/udp
31 | };
32 | }
33 |
34 | event bro_init()
35 | {
36 | Log::create_stream(Outbound::LOG, [$columns=Info, $path="outbound"]);
37 | }
38 |
39 | function log_it(c:connection, proto:string)
40 | {
41 | local rec: Outbound::Info = [$ts=network_time(), $id = c$id, $uid = c$uid, $proto = proto];
42 | Log::write(Outbound::LOG, rec);
43 | }
44 | event connection_attempt(c: connection)
45 | {
46 | if(c$id$orig_h in bro_manager && c$id$resp_h in internal_networks){ return; }
47 | if(c$id$orig_h in internal_networks && c$id$resp_h in internal_networks) { return; }
48 | if(c$id$orig_h in internal_networks && c$id$resp_h !in known_endpoints)
49 | {
50 | log_it(c, "tcp");
51 | }
52 | }
53 |
54 | event connection_established(c: connection)
55 | {
56 | if(c$id$orig_h in bro_manager && c$id$resp_h in internal_networks){ return; }
57 | if(c$id$orig_h in internal_networks && c$id$resp_h in internal_networks) { return; }
58 | if(c$id$orig_h in internal_networks && c$id$resp_h !in known_endpoints && c$orig$state == TCP_ESTABLISHED)
59 | {
60 | log_it(c, "tcp");
61 | }
62 | }
63 |
64 | event icmp_sent(c:connection, icmp:icmp_conn)
65 | {
66 | if(c$id$orig_h in bro_manager && c$id$resp_h in internal_networks){ return; }
67 | if(c$id$orig_h in internal_networks && c$id$resp_h in internal_networks) { return; }
68 | if(c$id$orig_h in internal_networks && c$id$resp_h !in known_endpoints)
69 | {
70 | log_it(c, "icmp");
71 | }
72 | }
73 |
74 | event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string)
75 | {
76 | if(c$id$orig_h in bro_manager && c$id$resp_h in internal_networks){ return; }
77 | if(c$id$orig_h in internal_networks && c$id$resp_h in internal_networks) { return; }
78 | if(c$id$orig_h in internal_networks && c$id$resp_h !in known_endpoints)
79 | {
80 | log_it(c, "icmp");
81 | }
82 | }
83 |
84 | event udp_request(c:connection)
85 | {
86 | if(c$id$orig_h in bro_manager && c$id$resp_h in internal_networks){ return; }
87 | if(c$id$orig_h in internal_networks && c$id$resp_h in internal_networks) { return; }
88 | if(c$id$resp_p in whitelisted_services) { return; }
89 | if(c$id$orig_p in whitelisted_services) { return; }
90 | if(c$id$orig_h in internal_networks && c$id$resp_h !in known_endpoints)
91 | {
92 | log_it(c, "udp");
93 | }
94 | }
95 |
96 | event udp_reply(c:connection)
97 | {
98 | if(c$id$resp_p in whitelisted_services) { return; }
99 | if(c$id$orig_p in whitelisted_services) { return; }
100 | if(c$id$orig_h in bro_manager && c$id$resp_h in internal_networks){ return; }
101 | if(c$id$orig_h in internal_networks && c$id$resp_h in internal_networks) { return; }
102 | if(c$id$orig_h in internal_networks && c$id$resp_h !in known_endpoints)
103 | {
104 | log_it(c, "udp");
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/Bro/phishing-2.2.bro:
--------------------------------------------------------------------------------
1 | # Example behavior detection script for Bro-IDS
2 | # Available from http://github.com/dhoelzer/AuditcastsScripts/Bro
3 | #
4 | # Find URLs in MIME content. For all URLs found, record the host name.
5 | # Identify DNS lookups that involve host names that appeared in MIME data. Record the addresses.
6 | # Find outbound web and other connections to addresses identified above and generate alerts.
7 |
8 | global host_names_in_emails: string_set;
9 | global possible_bad_addresses: addr_set;
10 |
11 |
12 | event mime_entity_data(c: connection, length: count, data: string)
13 | {
14 | for (a in find_all(data, /http:\/\/[^\/]+/))
15 | {
16 | add host_names_in_emails[split(a, /\//)[3]];
17 | }
18 | }
19 |
20 |
21 | event dns_A_reply(c:connection, msg:dns_msg, ans:dns_answer, a:addr)
22 | {
23 | if(ans$query in host_names_in_emails)
24 | {
25 | add possible_bad_addresses[a];
26 | }
27 | }
28 |
29 | event http_request(c:connection, method:string, original_URI:string, unescaped_URI:string, version:string)
30 | {
31 | if(c$id$resp_h in possible_bad_addresses)
32 | {
33 | print fmt(">> Web request to %s found in email! Requested URL -> %s", c$id$resp_h, original_URI);
34 | }
35 | }
36 |
37 |
38 | event connection_SYN_packet(c: connection, pkt: SYN_packet)
39 | {
40 | if(c$id$resp_h in possible_bad_addresses)
41 | {
42 | if(c$id$resp_p == 80/tcp)
43 | {
44 | print fmt(">> Possible Phish: Outbound connection from %s to %s : %s", c$id$orig_h, c$id$resp_h, c$id$resp_p);
45 | } else {
46 | print fmt(">> Possible C&C!! Outbound connection from %s to %s : %s", c$id$orig_h, c$id$resp_h, c$id$resp_p);
47 | }
48 |
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Bro/phishing.bro:
--------------------------------------------------------------------------------
1 | global domains_in_emails: set[string];
2 | global addresses_from_links: set[addr];
3 |
4 | event mime_entity_data (c: connection, length: count, data: string)
5 | {
6 | local urls = find_all(data, /https*:\/\/[^\/]*/);
7 | if(|urls| == 0){ return; }
8 | for(url in urls){
9 | add domains_in_emails[split_string(url, /\//)[2]];
10 | }
11 | }
12 |
13 | event dns_A_reply (c: connection, msg: dns_msg, ans: dns_answer, a: addr)
14 | {
15 | if(ans$query in domains_in_emails){
16 | add addresses_from_links[a];
17 | }
18 | }
19 |
20 | event connection_SYN_packet (c: connection, pkt: SYN_packet)
21 | {
22 | if(!(c$id$resp_h in addresses_from_links)) { return; }
23 | if(c$id$resp_p == 80/tcp) {
24 | print fmt ("Phishing related: HTTP connection from %s to %s", c$id$orig_h, c$id$resp_h);
25 | return;
26 | }
27 | if(c$id$resp_p == 443/tcp) {
28 | print fmt ("Phishing related: TLS/SSL connection from %s to %s", c$id$orig_h, c$id$resp_h);
29 | return;
30 | }
31 | print fmt (">>> Phishing related: connection to port %d from %s to %s", c$id$resp_p, c$id$orig_h, c$id$resp_h);
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Bro/threshold.bro:
--------------------------------------------------------------------------------
1 | @load base/protocols/conn/main.bro
2 |
3 | module Thresholds;
4 |
5 | export {
6 | redef enum Notice::Type += {
7 | Byte_Threshold_Exceeded,
8 | };
9 | }
10 |
11 | event connection_established(c: connection)
12 | {
13 | set_current_conn_bytes_threshold(c$id, 10000000, T);
14 | set_current_conn_bytes_threshold(c$id, 10000000, F);
15 | }
16 |
17 | event conn_bytes_threshold_crossed(c:connection, threshold:count, is_orig:bool)
18 | {
19 | local cpp = get_conn_transport_proto(c$id);
20 | local proto = "unknown";
21 | if(cpp == tcp) { proto = "tcp"; }
22 | if(cpp == udp) { proto = "udp"; }
23 | if(cpp == icmp) { proto = "icmp"; }
24 | local msg = "";
25 | if(is_orig) {
26 | msg = fmt("Originator crossed threshold of %d bytes in %d", threshold, c$duration);
27 | threshold = threshold * 2;
28 | set_current_conn_bytes_threshold(c$id, threshold, T);
29 | }
30 | if(!is_orig) {
31 | msg = fmt("Respondent crossed threshold of %d", threshold);
32 | threshold = threshold * 2;
33 | set_current_conn_bytes_threshold(c$id, threshold, F);
34 | }
35 | NOTICE([$note=Byte_Threshold_Exceeded, $msg=msg, $conn=c, $sub="Byte Threshold Crossed"]);
36 | }
37 |
--------------------------------------------------------------------------------
/Bro/thresholds.bro:
--------------------------------------------------------------------------------
1 | @load base/protocols/conn/main.bro
2 |
3 | module Thresholds;
4 |
5 | export {
6 | redef enum Notice::Type += {
7 | Byte_Threshold_Exceeded,
8 | };
9 | }
10 |
11 | event connection_established(c: connection)
12 | {
13 | set_current_conn_bytes_threshold(c$id, 10000000, T);
14 | set_current_conn_bytes_threshold(c$id, 10000000, F);
15 | }
16 |
17 | event conn_bytes_threshold_crossed(c:connection, threshold:count, is_orig:bool)
18 | {
19 | local cpp = get_conn_transport_proto(c$id);
20 | local proto = "unknown";
21 | if(cpp == tcp) { proto = "tcp"; }
22 | if(cpp == udp) { proto = "udp"; }
23 | if(cpp == icmp) { proto = "icmp"; }
24 | local msg = "";
25 | if(is_orig) {
26 | msg = fmt("Originator crossed threshold of %d bytes in %d", threshold, c$duration);
27 | threshold = threshold * 2;
28 | set_current_conn_bytes_threshold(c$id, threshold, T);
29 | }
30 | if(!is_orig) {
31 | msg = fmt("Respondent crossed threshold of %d", threshold);
32 | threshold = threshold * 2;
33 | set_current_conn_bytes_threshold(c$id, threshold, F);
34 | }
35 | NOTICE([$note=Byte_Threshold_Exceeded, $msg=msg, $conn=c, $sub="Byte Threshold Crossed"]);
36 | }
37 |
--------------------------------------------------------------------------------
/Bro/watch_conns.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | pushd /usr/local/bro/logs/current
3 | watch ~/conns.sh
4 | popd
5 |
--------------------------------------------------------------------------------
/DNS/brute.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/ruby
2 | #
3 | # Copyright 2011, David Hoelzer
4 | # All Rights Reserved
5 | #
6 | # This code is released as free open source code. You are welcome to use, modify and
7 | # redistribute this code as you see fit provided that this copyright notice remains
8 | # in place and intact.
9 |
10 | require './ip_address.rb'
11 | require 'resolv'
12 |
13 | def usage
14 | puts "#{$0} "
15 | end
16 |
17 | unless ARGV.count >= 2
18 | usage
19 | exit
20 | end
21 |
22 | nameserver = (ARGV.count >= 2 ? ARGV[0] : nil)
23 | domain = (ARGV.count >= 2 ? ARGV[1] : nil)
24 | tested = 0
25 |
26 | puts "Using #{nameserver} to find hosts in #{domain}"
27 |
28 | resolver = Resolv::DNS.new(:nameserver => [nameserver], :ndots => 1) if nameserver
29 | resolver = Resolv::DNS.new() if !nameserver
30 |
31 | #resolver.timeout = 5
32 | puts"Looking up names!"
33 | file = File.open('names', 'r')
34 | file.each_line do |host|
35 | host.chomp!
36 | host_to_test = "#{host}.#{domain}"
37 | result = resolver.getaddresses(host_to_test)
38 | if result.size != 0 then
39 | print "#{host_to_test}:\t"
40 | result.each { |name| puts "\t#{name}"}
41 | end
42 | # result = resolver.getresources(host)
43 | # if result.size != 0 then
44 | # print "#{host} (R):\t"
45 | # result.each { |name| puts "\t#{name}"}
46 | # end
47 |
48 | tested = tested + 1
49 | # puts " -> #{host_to_test}" if tested % 100 == 0
50 | end
51 |
--------------------------------------------------------------------------------
/DNS/ip_address.rb:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright 2011, David Hoelzer
3 | # All Rights Reserved
4 | #
5 | # This code is released as free open source code. You are welcome to use, modify and
6 | # redistribute this code as you see fit provided that this copyright notice remains
7 | # in place and intact.
8 | class IPAddress
9 | @address
10 |
11 | def address=(address)
12 | return 0 if address.nil?
13 | parts = address.to_s.split(".")
14 | return 0 if parts.count < 4
15 | @address = 0
16 | @address += Integer(parts[3])
17 | @address += Integer(parts[2]) << 8
18 | @address += Integer(parts[1]) << 16
19 | @address += Integer(parts[0]) << 24
20 | return @address
21 | end
22 |
23 | def raw_address
24 | @address
25 | end
26 |
27 | def address()
28 | [24, 16, 8, 0].collect {|b| (@address >> b) & 255}.join('.')
29 | end
30 |
31 | def initialize(address)
32 | self.address=(address)
33 | end
34 |
35 | def >(other_address)
36 | return false if !other_address.instance_of?(IPAddress)
37 | return true if @address > other_address.raw_address
38 | return false
39 | end
40 |
41 | def <(other_address)
42 | return false if !other_address.instance_of?(IPAddress)
43 | return true if @address < other_address.raw_address
44 | return false
45 | end
46 |
47 | def ==(other_address)
48 | return false if !other_address.instance_of?(IPAddress)
49 | return true if @address == other_address.raw_address
50 | return false
51 | end
52 |
53 | def +(amount)
54 | #return self if !amount.instance_of?(Integer)
55 | @address += amount
56 | return self
57 | end
58 | end
--------------------------------------------------------------------------------
/DNS/mapper.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/ruby
2 | #
3 | # Copyright 2011, David Hoelzer
4 | # All Rights Reserved
5 | #
6 | # This code is released as free open source code. You are welcome to use, modify and
7 | # redistribute this code as you see fit provided that this copyright notice remains
8 | # in place and intact.
9 |
10 | require './ip_address.rb'
11 | require 'resolv'
12 |
13 | def usage
14 | puts "#{$0} [nameserver]"
15 | puts "\n Simply pass in two IP addresses to discover associated host names."
16 | end
17 |
18 | unless ARGV.count >= 2
19 | usage
20 | exit
21 | end
22 |
23 | nameserver = (ARGV.count >= 3 ? ARGV[2] : nil)
24 | a = IPAddress.new(ARGV[0])
25 | b = IPAddress.new(ARGV[1])
26 | tested = 0
27 |
28 | increment = (ARGV.count == 4 ? ARGV[3].to_i : 1)
29 |
30 | resolver = Resolv::DNS.new(:nameserver => [nameserver], :search => ['.com'], :ndots => 1) if nameserver
31 | resolver = Resolv::DNS.new() if !nameserver
32 |
33 | #resolver.timeout = 5
34 | puts"Starting at #{a.address}, counting up to #{b.address}"
35 | while(a < b)
36 | result = resolver.getnames(a.address)
37 | if result.size != 0 then
38 | print "#{a.address}:\t"
39 | result.each { |name| puts "\t#{name}"}
40 | end
41 | a = a + increment
42 | tested = tested + 1
43 | # puts " -> #{a.address}" if tested % 100 == 0
44 | end
45 |
--------------------------------------------------------------------------------
/PAE/Makefile:
--------------------------------------------------------------------------------
1 | pae : pae.c
2 | gcc pae.c -g -o pae -lpcap -lm
3 |
--------------------------------------------------------------------------------
/PAE/pae.c:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * This code is Copyright (C) 2001, 2018, David Hoelzer
4 | * Please feel free to make modifications to this code, however,
5 | * license is -not- granted for redistribution of modifications
6 | * or of modified code. License is granted for all non-commercial
7 | * use, meaning, you may not use this code or portions thereof
8 | * to create some other commercial product.
9 | *
10 | */
11 |
12 | /*
13 | * This code takes a TCPDump output file and allows you to
14 | * perform some statistical analysis against the packets.
15 | * The idea is that "interesting" communication channels
16 | * may be revealed by identifying portions of packets that
17 | * repeat with some frequency. This should allow us to
18 | * identify potential covert channels (or communications
19 | * over well known ports that does not conform to the
20 | * expected behaviour of the protocol for that port) in
21 | * the vast sea of network traffic that passes by our sensors.
22 | *
23 | * libpcap 0.4 (or higher) is required.
24 | */
25 |
26 | #define VERSION "0.6"
27 | // Rev 0.1 - Initial Release
28 | // Rev 0.5 - Added checksum support
29 | // We have developed a suspicion that there are checksums that will almost never appear
30 | // and others that will be quite common. Thought we'd add something to test this out.
31 | // Rev 0.6 - Added more detailed help as requested.
32 |
33 |
34 | #include
35 | #include
36 | #include
37 | #include
38 | #include
39 | #include
40 |
41 | #define GOT_SOURCE 1
42 | #define SRC_PORTS 2
43 | #define DST_PORTS 4
44 | #define GOT_BPF 8
45 | #define IPIDS 16
46 | #define SEQ_NUMS 32
47 | #define QUIET 64
48 | #define SRC_HOSTS 128
49 | #define CHECKSUM 256
50 | #define KEYLENGTH 32
51 |
52 | struct root_struct
53 | {
54 | unsigned char key[KEYLENGTH];
55 | unsigned int count;
56 | int hash_value;
57 | struct root_struct *next_root, *prev_root;
58 | } ;
59 |
60 | void DEBUG(char *debug_string);
61 | float standard_deviation(struct root_struct *ptr);
62 | unsigned int hash(char *key);
63 | void print_results(struct root_struct *ptr);
64 | struct root_struct *find_root(unsigned char key[KEYLENGTH],
65 | struct root_struct *master_root);
66 | void insert(struct root_struct *insertme);
67 | struct root_struct *new_root();
68 | pcap_handler analyze_packets(unsigned char *p, struct pcap_pkthdr *h, unsigned char *packet);
69 | void usage();
70 | int get_header_length(unsigned char *packet);
71 | float average(struct root_struct *ptr);
72 |
73 | int significant_bytes;
74 | unsigned int node_struct_size, root_struct_size;
75 | int hash_hits, hash_misses, sigs;
76 | unsigned long int packets;
77 | char source_file[512], dest_file[512], the_filter[4096];
78 | char ebuff[4096];
79 | pcap_t *input;
80 | pcap_dumper_t *output;
81 | struct bpf_program program;
82 | struct root_struct *root, *last;
83 | struct root_struct *hash_table[1048576];
84 | unsigned int flags;
85 | int _debug = 0;
86 | float anomalosity = 1;
87 | float median = 0;
88 |
89 | void DEBUG(char *debug_string)
90 | {
91 | if(_debug) { printf("DBG: %s\n",debug_string); }
92 | }
93 |
94 | unsigned int hash(char *key)
95 | {
96 | unsigned char chars[KEYLENGTH];
97 | unsigned int hashval;
98 | int x;
99 |
100 | if(flags & (SRC_PORTS | DST_PORTS | IPIDS | CHECKSUM))
101 | {
102 | hashval = *((unsigned short int *)key);
103 | return (hashval);
104 | }
105 | if(flags & (SEQ_NUMS | SRC_HOSTS))
106 | {
107 | hashval = *((unsigned short int *)key);
108 | return (hashval);
109 | }
110 | for(x=0;x!=significant_bytes;x++) chars[x] = key[x];
111 | hashval = 0;
112 | for(x=0;x!=significant_bytes;x++) hashval ^= (chars[x] << x);
113 | // hashval = ((char1 ^ char2<<3 ^ char3<<6 ^ char4 << 9 ^
114 | // char5<<12 ^ char6<<14 ^ char7<<17 ^ char8 << 19)) & 0xfffff;
115 | hashval &= 0xfffff;
116 | return(hashval);
117 | }
118 |
119 | int main(int argc, char **argv)
120 | {
121 | char option;
122 | u_char buffer[4096];
123 |
124 | // Clear our vars
125 | strcpy(source_file, "");
126 | strcpy(dest_file, "");
127 | flags = 0;
128 | root_struct_size = sizeof(struct root_struct);
129 | root = NULL;
130 | last = root;
131 | packets = hash_hits = hash_misses = sigs = 0;
132 | bzero(hash_table, sizeof(struct root_struct *) * 65536);
133 | significant_bytes = 32;
134 |
135 | // Get command line args
136 | for(option = getopt(argc, argv, "qscdSihr:a:");
137 | option != -1;
138 | option = getopt(argc, argv, "qscdSihr:a:"))
139 | {
140 | switch(option)
141 | {
142 | case 'c':
143 | flags |= CHECKSUM;
144 | significant_bytes = 2;
145 | break;
146 | case 'h' :
147 | flags |= SRC_HOSTS;
148 | significant_bytes = 4;
149 | break;
150 | case 'q' :
151 | flags |= QUIET;
152 | break;
153 | case 'r' :
154 | strncpy(source_file, optarg, 511);
155 | flags |= GOT_SOURCE;
156 | break;
157 | case 'a' :
158 | sscanf(optarg, "%f", &anomalosity);
159 | break;
160 | case 's' :
161 | flags |= SRC_PORTS;
162 | significant_bytes = 2;
163 | break;
164 | case 'd' :
165 | flags |= DST_PORTS;
166 | significant_bytes = 2;
167 | break;
168 | case 'S' :
169 | flags |= SEQ_NUMS;
170 | significant_bytes = 4;
171 | break;
172 | case 'i' :
173 | flags |= IPIDS;
174 | significant_bytes = 2;
175 | break;
176 | default : usage();
177 | }
178 | }
179 |
180 | if(!(flags & QUIET))
181 | printf("Packet Analysis Engine Version %s\nCopyright 2001, 2018, David Hoelzer\n",
182 | VERSION);
183 | // Check for required args:
184 | if(!flags || !(flags & GOT_SOURCE)) { usage(); }
185 |
186 | if(!(flags & QUIET)) printf("Reading from %s\n", source_file);
187 |
188 | input = pcap_open_offline(source_file, ebuff);
189 | if(!input)
190 | {
191 | printf("Could not open dump file for reading!\n");
192 | exit(1);
193 | }
194 | strcpy(the_filter, (flags & SEQ_NUMS ? "tcp and tcp[4:4] != 0" :
195 | (flags & (SRC_HOSTS | CHECKSUM) ?
196 | "ip " :
197 | (flags & (SRC_PORTS | DST_PORTS) ?
198 | "(tcp or udp)" :
199 | (flags & IPIDS ? "ip and not ip[4:2]=0" :
200 | "tcp or udp")))));
201 | if(pcap_compile(input, &program, the_filter, 1, 24) < 0)
202 | {
203 | printf("BPF Filter error.\n");
204 | exit(3);
205 | }
206 |
207 | pcap_setfilter(input, &program);
208 | if(!(flags & QUIET))
209 | {
210 | /* printf("%x %x %x %x %x\n",flags, flags & SRC_PORTS,
211 | flags & DST_PORTS, flags & IPIDS, flags & SEQ_NUMS);*/
212 | printf("Producing analysis of %s.\n",
213 | (flags & SRC_PORTS ? "Source Ports" :
214 | (flags & DST_PORTS ? "Destination Ports" :
215 | (flags & IPIDS ? "IP ID Numbers" :
216 | (flags & SEQ_NUMS ? "Sequence Numbers" :
217 | (flags & CHECKSUM ? "Checksums" :
218 | (flags & SRC_HOSTS ? "Source Hosts" : "Payloads")))))));
219 | printf("Processing...\n");
220 | }
221 | /* I can't find any documentation in the man page for libpcap explaining
222 | what exactly this last argument (buffer) is for, but there it is...
223 | */
224 | DEBUG("Entering pcap loop");
225 | pcap_loop(input, 0, (pcap_handler)analyze_packets, buffer);
226 | if(!(flags & QUIET)) printf("Cleaning up.\n");
227 | pcap_close(input);
228 | print_results(root);
229 | }
230 |
231 | pcap_handler analyze_packets(unsigned char *p, struct pcap_pkthdr *h, unsigned char *packet)
232 | {
233 | /*
234 | Assumption: We are only worried about Ethernet
235 | Process: Grab the packet headers, identify protocol
236 | and attach pointers to the headers. Key the
237 | packets using a hash of the IP port pairs.
238 | Build a tree according to packet contents.
239 | Nodes will hold value and count. Top level
240 | counts can be used to deduce frequency.
241 | */
242 |
243 | unsigned char *ip_header, *saddr, *daddr, *checksum, *chkptr, *data;
244 | unsigned int ip_words[64];
245 | unsigned int i, header_length, num_words, chksum;
246 | unsigned char chkflag;
247 | unsigned int hash_value;
248 | struct root_struct *ptr;
249 |
250 | packets++;
251 | DEBUG("Handling packet");
252 | ip_header = (packet + 14);
253 | header_length = get_header_length(ip_header);
254 | switch(ip_header[9])
255 | {
256 | case 0x01 : //ICMP
257 | data = ip_header + header_length + 4;
258 | break;
259 | case 0x06 : //TCP
260 | data = ip_header + header_length + 20;
261 | break;
262 | case 0x11: //UDP
263 | data = ip_header + header_length + 8;
264 | break;
265 | case 0x32: //ESP
266 | data = ip_header + header_length + 8;
267 | break;
268 | case 0x02: //IGMP
269 | data = ip_header + header_length + 8;
270 | break;
271 | default :
272 | if(!(flags & QUIET))
273 | printf("\tUnknown: %x\n", (unsigned char)ip_header[9] );
274 | data = ip_header + header_length;
275 | break;
276 | }
277 | data = (flags & SRC_PORTS ? ip_header + header_length :
278 | (flags & DST_PORTS ? ip_header + header_length + 2 :
279 | (flags & IPIDS ? ip_header + 4 :
280 | (flags & SEQ_NUMS ? ip_header + header_length + 4 :
281 | (flags & SRC_HOSTS ? ip_header + 12 :
282 | (flags & CHECKSUM ? ip_header + 10 :
283 | data))))));
284 | if((data + significant_bytes) >
285 | (ip_header + ntohs(*((unsigned short int *)ip_header+1))))
286 | {
287 | if(!(flags & QUIET)) printf("Not enough data!\n");
288 | return 0;
289 | }
290 | ptr = find_root(data, root);
291 | DEBUG("Root found");
292 | if(ptr == NULL)
293 | {
294 | DEBUG("New root needed");
295 | ptr = new_root();
296 | DEBUG("New root allocated");
297 | sigs++;
298 | memcpy(ptr->key, data, significant_bytes);
299 | DEBUG("Completed memcpy");
300 | hash_value = hash(data);
301 | ptr -> hash_value = hash_value;
302 | if(root == NULL)
303 | {
304 | hash_table[hash_value] = ptr;
305 | root = ptr;
306 | last = root;
307 | }
308 | else
309 | {
310 | insert(ptr);
311 | }
312 | }
313 | ptr->count ++;
314 | bzero(data, significant_bytes + 1);
315 | }
316 |
317 | void insert(struct root_struct *insertme)
318 | {
319 | unsigned int hash_value;
320 | struct root_struct *ptr1, *ptr2;
321 | int comparison;
322 | int element = 0;
323 |
324 | DEBUG("Inserting");
325 | hash_value = insertme -> hash_value;
326 | // Check hash table first
327 | if(hash_table[hash_value] != NULL)
328 | {
329 | ptr1 = hash_table[hash_value];
330 | ptr2 = ptr1 -> next_root;
331 | insertme -> prev_root = ptr1;
332 | insertme -> next_root = ptr2;
333 | ptr1 -> next_root = insertme;
334 | if(ptr2 != NULL) ptr2 -> prev_root = insertme;
335 | return;
336 | }
337 |
338 | ptr1 = root;
339 | ptr2 = ptr1 -> next_root;
340 | insertme -> prev_root = ptr1;
341 | insertme -> next_root = ptr2;
342 | ptr1 -> next_root = insertme;
343 | if(ptr2) ptr2 -> prev_root = insertme;
344 | hash_table[hash_value] = insertme;
345 | /*
346 | while(ptr1 != NULL)
347 | {
348 | element ++;
349 | comparison = (ptr1 -> hash_value < insertme -> hash_value ? 0 : 1);
350 | if(comparison == 0)
351 | {
352 | ptr2 = ptr1 -> next_root;
353 | if(ptr2) ptr2 -> prev_root = insertme;
354 | insertme -> next_root = ptr2;
355 | insertme -> prev_root = ptr1;
356 | ptr1 -> next_root = insertme;
357 | return;
358 | }
359 | ptr2 = ptr1;
360 | ptr1 = ptr1->next_root;
361 | }
362 | ptr2 -> next_root = insertme;
363 | insertme -> prev_root = ptr2;
364 | hash_table[hash_value] = insertme;
365 | last = insertme;
366 | */
367 | }
368 |
369 | int get_header_length(unsigned char *packet)
370 | {
371 | unsigned char x, y;
372 |
373 | x = (unsigned char)(*packet);
374 | // y = x / 256; /* Shift right 8 bits */
375 | x = x & 0x0f; /* Mask off high nibble */
376 | return ((int)(x * 4)); /* Multiply by 4 */
377 | }
378 |
379 | void usage()
380 | {
381 | printf("Usage:\n\tpae -r source_file [-h|i|s|c|d|S] [-q] [-a ]\n\n");
382 | printf("\t-h\tThis help\n");
383 | printf("\t-i\tExtract and count occurrences of discrete IP ID values.\n");
384 | printf("\t-s\tExtract and count occurrences of discrete source port numbers.\n");
385 | printf("\t-c\tExtract and count occurrences of discrete IP checksum values.\n");
386 | printf("\t-d\tExtract and count occurrences of discrete destination port numbers.\n");
387 | printf("\t-S\tExtract and count occurrences of discrete TCP sequence numbers\n");
388 | printf("\t-q\tSuppress internal hash table statistics information\n");
389 | printf("\t-a\tConfigure an 'Anomalosity' value (how anomalous is this?) as a filter for values displayed.\n");
390 | printf("\t\tIf given no extraction options, PAE will extract and count discrete occurrences of the first 32 bytes of data\n");
391 | exit(3);
392 | }
393 |
394 | struct root_struct *new_root()
395 | {
396 | struct root_struct *node;
397 |
398 | DEBUG("New root");
399 | node = (struct root_struct *)malloc(root_struct_size);
400 | if(node == NULL)
401 | {
402 | printf("Error in Malloc (root).\n");
403 | exit(3);
404 | }
405 | node -> count = 0;
406 | node -> next_root = NULL;
407 | node -> prev_root = NULL;
408 | return node;
409 | }
410 |
411 | struct root_struct *find_root(unsigned char key[KEYLENGTH],
412 | struct root_struct *master_root)
413 | {
414 | struct root_struct *ptr;
415 | unsigned int hash_value;
416 | int comparison;
417 |
418 | ptr = master_root;
419 |
420 | DEBUG("Find root");
421 | hash_value = hash(key);
422 | if(hash_table[hash_value] == NULL)
423 | {
424 | hash_misses ++;
425 | return(NULL);
426 | }
427 | hash_hits ++;
428 | ptr = hash_table[hash_value];
429 | while(ptr != NULL)
430 | {
431 | comparison = strncmp(ptr->key, key, significant_bytes);
432 | if(comparison == 0) {return(ptr);}
433 | ptr = ptr -> next_root;
434 | if(ptr != NULL && ptr->hash_value != hash_value) return(NULL);
435 | }
436 | return(NULL);
437 | }
438 |
439 | float standard_deviation(struct root_struct *ptr)
440 | {
441 | double avg, total, n, x, y;
442 | int greatest, least, ones;
443 | struct root_struct *this;
444 |
445 | DEBUG("Standard Deviation");
446 | greatest = 0;
447 | ones = 0;
448 | least = 99999;
449 | this = ptr;
450 | if(this == NULL) return 0;
451 | x=n=total=0;
452 | avg = 0;
453 | while(this)
454 | {
455 | if(this->count == 1) ones++;
456 | if(this->count > greatest) greatest = this->count;
457 | if(this->count < least) least = this->count;
458 | total += this->count;
459 | n++;
460 | this = this->next_root;
461 | }
462 | avg = average(ptr);
463 |
464 | total = 0;
465 | this = ptr;
466 |
467 | while(this)
468 | {
469 | y = this->count - avg;
470 | total = total + (y * y);
471 | this = this->next_root;
472 | }
473 | x = sqrt(((double)total / (double)n));
474 | /* if(!(flags & QUIET)) printf("%f %f %f %f\n%d %d %d\n",
475 | total, average(ptr), n, x, greatest, least, ones);*/
476 | return (int)x;
477 | }
478 |
479 | float average(struct root_struct *ptr)
480 | {
481 | unsigned long int total;
482 | int count;
483 | struct root_struct *this;
484 |
485 | DEBUG("Average");
486 | this = ptr;
487 | total = count = 0;
488 | if(!this) return 0;
489 | while(this)
490 | {
491 | count ++;
492 | total += this->count;
493 | this = this->next_root;
494 | }
495 | return((float)((float)total / (float)count));
496 | }
497 |
498 | float get_median(struct root_struct *ptr)
499 | {
500 | unsigned long int min,max;
501 | struct root_struct *this;
502 |
503 | this = ptr;
504 | min = max = ptr -> count;
505 | while(this)
506 | {
507 | if(this -> count < min) { min = this -> count; }
508 | if(this -> count > max) { max = this -> count; }
509 | this = this -> next_root;
510 | }
511 | return((float)((float)min + (float)max)/2.0);
512 | }
513 |
514 | void print_results(struct root_struct *ptr)
515 | {
516 | int x, hashes, gt100, bucket_reuse, bmax, bmin, average_count;
517 | float std_dev;
518 | unsigned int lasthash;
519 |
520 | DEBUG("Print results");
521 | hashes = gt100 = bucket_reuse = bmax = 0;
522 | bmin = 999999;
523 |
524 | if(ptr == NULL)
525 | {
526 | printf("No packets!\n");
527 | return;
528 | }
529 | average_count = average(ptr);
530 | median = get_median(ptr);
531 | /*
532 | if(!(flags & (SEQ_NUMS | IPIDS | SRC_PORTS | DST_PORTS | SRC_HOSTS)))
533 | {
534 | average_count = (average_count + 2) * 100;
535 | }
536 | if(flags & (SRC_HOSTS | SRC_PORTS | DST_PORTS))
537 | {
538 | average_count = (average_count + 2) * 50;
539 | }
540 | if(flags & SEQ_NUMS)
541 | {
542 | average_count = (average_count * 1000);
543 | }
544 | if(flags & IPIDS)
545 | {
546 | average_count = average_count * 2;
547 | }
548 | */
549 | std_dev=standard_deviation(root);
550 | lasthash = ptr -> hash_value;
551 | hashes ++;
552 | while(ptr)
553 | {
554 | bucket_reuse++;
555 | if(lasthash != ptr -> hash_value)
556 | {
557 | hashes ++;
558 | lasthash = ptr -> hash_value;
559 | if(bmax < bucket_reuse) bmax = bucket_reuse;
560 | if(bmin > bucket_reuse) bmin = bucket_reuse;
561 | bucket_reuse = 0;
562 | }
563 | // if(abs(ptr -> count - median) > ((std_dev * anomalosity) ))
564 | {
565 | gt100 ++;
566 | if(!(flags & (SEQ_NUMS | IPIDS | SRC_PORTS | DST_PORTS | SRC_HOSTS | CHECKSUM)))
567 | {
568 | if(ptr->count > anomalosity){
569 | printf("+-------------------------------------------"\
570 | "--------------------------------------------+\n");
571 | for(x=0;x!=significant_bytes;x++)
572 | {
573 | printf("%s%x ", (ptr->key[x] < 16 ? "0" : ""),
574 | (unsigned char)(ptr->key[x]));
575 | }
576 | printf("\n");
577 | for(x=0;x!=significant_bytes;x++)
578 | {
579 | printf("%c ",(isprint(ptr->key[x])? ptr->key[x] : '.'));
580 | }
581 | printf(" -#: %d\n", ptr->count);
582 | }
583 | } else {
584 | printf("%d ",
585 | ptr->count);
586 | }
587 |
588 | if((flags & DST_PORTS) | (flags & SRC_PORTS) | (flags &IPIDS) | (flags & CHECKSUM))
589 | {
590 | unsigned short int port;
591 | port = ntohs(((unsigned short int *)ptr->key)[0]);
592 | printf("%u\n",port);
593 | }
594 | if(flags & SEQ_NUMS)
595 | {
596 | unsigned long int seq;
597 | seq = ntohl(((unsigned long int *)ptr->key)[0]);
598 | printf("%u\n",seq);
599 | }
600 | if(flags & SRC_HOSTS)
601 | {
602 | unsigned char octet;
603 | int x;
604 | for (x=0; x!= 4; x++)
605 | {
606 | octet = *((unsigned char *)(ptr->key)+x);
607 | printf("%u%c", octet, (x == 3 ? ' ' : '.'));
608 | }
609 | printf("\n");
610 | }
611 | }
612 | ptr = ptr->next_root;
613 | }
614 | if(!(flags & QUIET))
615 | {
616 | printf("Hashes: %d\nHits: %d\nMisses: %d\nSignatures: "\
617 | "%d\nHits > 100: %d\nPackets: %u\n"\
618 | "Efficiency: Max Reuse: %d Min Reuse: %d\n",
619 | hashes, hash_hits, hash_misses, sigs, gt100, packets, bmax, bmin);
620 | printf("Standard Deviation: %f Average: %f Median: %f\n",standard_deviation(root),average(root),get_median(root));
621 | }
622 | }
623 |
--------------------------------------------------------------------------------
/PAE/plot.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | import matplotlib.pyplot as plt
3 | import numpy as numpy
4 | import sys
5 |
6 |
7 | dictionary = {}
8 | inputData = sys.stdin.readlines()
9 | for line in inputData:
10 | [count, value] = line.split()
11 | dictionary[int(value)] = int(count)
12 |
13 | keys = sorted(dictionary.keys())
14 | data = []
15 | for key in keys:
16 | data.append(dictionary[key])
17 |
18 | ax=plt.axes()
19 | ax.plot(keys, data, ".")
20 |
21 | min = min(data)
22 | max = max(data)
23 | stddev = numpy.std(data)
24 | mean = numpy.mean(data)
25 |
26 | fudge = 2
27 | if(len(sys.argv) > 1):
28 | fudge = int(sys.argv[1])
29 |
30 | i = 0
31 | for key in sorted(dictionary, key=dictionary.get, reverse=True)[:10]:
32 | ax.annotate(str(key), xy=(key, dictionary[key]), xycoords='data', xytext=(10,400-(i*20)), textcoords='figure pixels', arrowprops=dict(color="red", width=0.01, headwidth=4))
33 | i = i + 1
34 | plt.show()
35 |
--------------------------------------------------------------------------------
/PCI/cisp_analyze:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | #
3 | # Automatic analysis script for PCI validation
4 | #
5 | # This script queries the user and automatically inventories available
6 | # results files to produce a report on PCI compliance.
7 | #
8 | # Copyright (C) 2005, All Rights Reserved -- Cyber-Defense.Org
9 | # David Hoelzer
10 | # http://www.cyber-defense.org
11 | #
12 | # Organizations and individuals are free to use this script for self-assessment
13 | # purposes, however you may not use this script to perform assessments for
14 | # others without a prior licensing agreement with Cyber-Defense, nor may you
15 | # incorporate this script into any other product, utility or script for
16 | # This script is provided as-is and with no warantee of any kind.
17 | #
18 | ©right;
19 |
20 | &information_flow();
21 |
22 | if(-e "inner_capture")
23 | {
24 | $score += 10;
25 | &i_cap_analyze();
26 | }
27 | else {
28 | $reports{"inbound_ports"} = "Inbound scan was not performed";
29 | }
30 | if(-e "outer_capture")
31 | {
32 | $score += 10;
33 | &o_cap_analyze();
34 | }
35 | else {
36 | $reports{"outbound_ports"} = "Outbound scan was not performed";
37 | }
38 | if(-e "e_nmap_scan")
39 | {
40 | $score += 10;
41 | &e_nmap_analyze();
42 | }
43 | else {
44 | $reports{"external_nmap"} = "External firewall scan was not performed";
45 | $reports{"external_nmap"} .= "Nothing to report
";
46 | }
47 | if(-e "i_nmap_scan")
48 | {
49 | $score += 10;
50 | &i_nmap_analyze();
51 | }
52 | else {
53 | $reports{"internal_nmap"} = "Internal firewall scan was not performed";
54 | $reports{"internal_nmap"} .= "Nothing to report
";
55 | }
56 | @ciphers = glob("ciphers_*");
57 | $num_cipher_files = @ciphers;
58 | if($num_cipher_files > 0)
59 | {
60 | $score += 10;
61 | &cipher_analysis();
62 | }
63 | else {
64 | $reports{"ciphers"} = "Cipher inventory was not performed";
65 | $reports{"ciphers"} .= "Nothing to report
";
66 | }
67 | if(-e "i_vuln_scan")
68 | {
69 | $score += 25;
70 | &i_vuln_analyze();
71 | }
72 | else {
73 | $reports{"i_vuln_scan"} = "Internal vulnerability assessment was not performed";
74 | $reports{"i_vuln_scan"} .= "Nothing to report
";
75 | }
76 | if(-e "e_vuln_scan")
77 | {
78 | $score += 25;
79 | &e_vuln_analyze();
80 | }
81 | else {
82 | $reports{"e_vuln_scan"} = "External vulnerability assessment was not performed";
83 | $reports{"e_vuln_scan"} .= "Nothing to report
";
84 | }
85 |
86 | &HTML_Report;
87 | print "Report completed. View 'pci_report.html' for the results.\n\n";
88 |
89 | sub cipher_analysis()
90 | {
91 | $cipher_detail = "";
92 | foreach(@ciphers)
93 | {
94 | print "Cipher file found: $_\n";
95 | open(CIPHER_FILE, "$_");
96 | @contents = ;
97 | close(CIPHER_FILE);
98 | $size = @contents;
99 | for($i=0; $i!=$size; $i++)
100 | {
101 | chomp();
102 | if($contents[$i] =~ /^S:/)
103 | {
104 | $validity_starts = $contents[$i];
105 | $validity_starts =~ s/^S:(.*)/\1/;
106 | }
107 | if($contents[$i] =~ /^E:/)
108 | {
109 | $validity_ends = $contents[$i];
110 | $validity_ends =~ s/^E:(.*)/\1/;
111 | }
112 | if($contents[$i] =~ /^CC:/)
113 | {
114 | $temp = $contents[$i];
115 | $temp =~ s/^CC:(.*)/\1/;
116 | $chain = $chain . $temp;
117 | }
118 | if($contents[$i] =~ /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/)
119 | {
120 | $ssl_host = $contents[$i];
121 | }
122 | if($contents[$i] =~ /cipher_type/)
123 | {
124 | $cipher_type = $contents[$i];
125 | chomp($cipher_type);
126 | $cipher_type =~ s/cipher_type:(.*$)/\1/;
127 | $cipher_desc = $contents[$i+1];
128 | chomp($cipher_desc);
129 | $cipher_supports = $contents[$i+2];
130 | chomp($cipher_supports);
131 | $cipher_desc =~ s/cipher_desc:(.*$)/\1/;
132 | $cipher_supports =~ s/supports:(.*$)/\1/;
133 | $cipher_supports =~ s/ //g;
134 | $cipher_descriptions{$cipher_type} = $cipher_desc;
135 | $ciphers_supported{$cipher_type} = $cipher_supports;
136 | }
137 | if($contents[$i] =~ /cipher_findings/)
138 | {
139 | $j = $i+1;
140 | for(;$j < $size; $j++)
141 | {
142 | $this_cipher = $contents[$j];
143 | chomp($this_cipher);
144 | ($cipher,$supported) = split(/:/, $this_cipher);
145 | if($supported == 1){ $cipher_detail .= ""; }
146 | $cipher_detail .= "$cipher is ". ($supported == 1 ? "" : "not ")."supported.
";
147 | if($supported == 1){ $cipher_detail .= ""; }
148 | $ciphers_support_status{$cipher} = $supported;
149 | }
150 | }
151 | }
152 | }
153 | print "Cipher analysis:\n";
154 | foreach(keys(%ciphers_supported))
155 | {
156 | print "Cipher type: $_\n";
157 | @ciphers = split(/,/,$ciphers_supported{$_});
158 | $t = $_;
159 | foreach(@ciphers)
160 | {
161 | if($ciphers_support_status{$_}) { $support_report{$t}++; }
162 | }
163 | $_ = $t;
164 | }
165 | foreach(keys(%support_report))
166 | {
167 | $reports{"ciphers"} .= "$support_report{$_} $_ ciphers are supported: $cipher_descriptions{$_}. ";
168 | }
169 | $this_score = 0;
170 | if($support_report{"LOW"} || $support_report{"NULL"} || $support_report{"EXP"})
171 | {
172 | $reports{"ciphers"} .= "
";
173 | $reports{"ciphers"} .= "Non-compliant with section 4.1
\n";
174 | $reports{"ciphers"} .= "SSL must use at least 128 bit encryption
";
175 | if($support_report{"LOW"})
176 | {
177 | $this_score += 5;
178 | $reports{"ciphers"} .= "LOW ciphers are not in compliance with the standard. \n" ;
179 | }
180 | if($support_report{"NULL"})
181 | {
182 | $this_score += 5;
183 | $reports{"ciphers"} .= "NULL ciphers are not in compliance with the standard. \n";
184 | }
185 | if($support_report{"EXP"})
186 | {
187 | $this_score += 5;
188 | $reports{"ciphers"} .= "EXP ciphers are not in compliance with the standard. \n";
189 | }
190 | $reports{"ciphers"} .= "
\n";
191 | }
192 | else
193 | {
194 | $reports{"ciphers"} .= "";
195 | $reports{"ciphers"} .= "Compliant
\n";
196 | }
197 | if($this_score > 10)
198 | {
199 | $score -= 10;
200 | }
201 | else
202 | {
203 | $score -= $this_score;
204 | }
205 | $reports{"ciphers"} .= "" . $cipher_detail . "
\n";
206 | $reports{"ciphers"} .= "Certificate valid from ".$validity_starts." until ".$validity_ends."
";
207 | $reports{"ciphers"} .= "Certificate Validity Chain:
";
208 | }
209 |
210 | sub i_vuln_analyze
211 | {
212 | my %nessus_results;
213 | my @results;
214 | my $hold, $host, $protocol, $ID, $type, $issue, $item;
215 |
216 | $vuln_score = 0;
217 | $medium = $high = $serious = $critical = 0;
218 | %nessus_results = &parse_nessus_file("i_vuln_scan");
219 | foreach(keys(%nessus_results))
220 | {
221 | @results = split(/~/, $nessus_results{$_});
222 | $hold = $_;
223 | foreach(@results)
224 | {
225 | $item = $_;
226 | s/Risk factor : ([a-zA-Z]*);/$1/;
227 | if($1 eq "Medium")
228 | {
229 | $vuln_score ++;
230 | $medium ++;
231 | ($host, $protocol, $ID, $type, $issue) = split(/\|/, $item);
232 | $issue =~ s/;/
/g;
233 | $i_vuln_detail{$1} .= "
";
234 | $i_vuln_detail{$1} .= "Host: $host
Service: $protocol
Type: $type
";
235 | $i_vuln_detail{$1} .= "$issue\n";
236 | }
237 | if($1 eq "High")
238 | {
239 | $vuln_score += 2;
240 | $high++;
241 | ($host, $protocol, $ID, $type, $issue) = split(/\|/, $item);
242 | $issue =~ s/;/
/g;
243 | $i_vuln_detail{$1} .= "
";
244 | $i_vuln_detail{$1} .= "Host: $host
Service: $protocol
Type: $type
";
245 | $i_vuln_detail{$1} .= "$issue\n";
246 | }
247 | if($1 eq "Serious")
248 | {
249 | $vuln_score += 3;
250 | $serious++;
251 | ($host, $protocol, $ID, $type, $issue) = split(/\|/, $item);
252 | $issue =~ s/;/
/g;
253 | $i_vuln_detail{$1} .= "
";
254 | $i_vuln_detail{$1} .= "Host: $host
Service: $protocol
Type: $type
";
255 | $i_vuln_detail{$1} .= "$issue\n";
256 | }
257 | if($1 eq "Critical")
258 | {
259 | $vuln_score += 4;
260 | $critical++;
261 | ($host, $protocol, $ID, $type, $issue) = split(/\|/, $item);
262 | $issue =~ s/;/
/g;
263 | $i_vuln_detail{$1} .= "
";
264 | $i_vuln_detail{$1} .= "Host: $host
Service: $protocol
Type: $type
";
265 | $i_vuln_detail{$1} .= "$issue\n";
266 | }
267 | }
268 | $_ = $hold;
269 | }
270 | $reports{"i_vuln_scan"} = "The total internal vulnerability score was $vuln_score out of a maximum of 25. There were $medium medium issues, $high high issues, $serious serious issues and $critical critical issues.";
271 | if($vuln_score > 0)
272 | {
273 | $reports{"i_vuln_scan"} .= "";
274 | $reports{"i_vuln_scan"} .= "Non-compliant with section 11.2
";
275 | $reports{"i_vuln_scan"} .= "All vulnerabilities classed Medium and higher must be remediated.
";
276 | $reports{"i_vuln_scan"} .= "Medium: $medium
High: $high
Serious: $serious
Critical: $critical
\n";
277 | $reports{"i_vuln_scan"} .= "";
278 | foreach(keys(%i_vuln_detail))
279 | {
280 | $reports{"i_vuln_scan"} .= $i_vuln_detail{$_};
281 | }
282 | $reports{"i_vuln_scan"} .= "
"
283 | }
284 | else
285 | {
286 | $reports{"i_vuln_scan"} .= "";
287 | $reports{"i_vuln_scan"} .= "Compliant
\n";
288 | $reports{"i_vuln_scan"} .= "Nothing to report
";
289 | }
290 | if($vuln_score > 25) { $vuln_score = 25; }
291 | $score -= $vuln_score;
292 | }
293 |
294 | sub e_vuln_analyze
295 | {
296 | my %nessus_results;
297 | my @results;
298 | my $hold, $host, $protocol, $ID, $type, $issue, $item;
299 |
300 | $vuln_score = 0;
301 | $medium = $high = $serious = $critical = 0;
302 | %nessus_results = &parse_nessus_file("e_vuln_scan");
303 | foreach(keys(%nessus_results))
304 | {
305 | @results = split(/~/, $nessus_results{$_});
306 | $hold = $_;
307 | foreach(@results)
308 | {
309 | $item = $_;
310 | s/Risk factor : ([a-zA-Z]*);/$1/;
311 | if($1 eq "Medium")
312 | {
313 | $vuln_score ++;
314 | $medium ++;
315 | ($host, $protocol, $ID, $type, $issue) = split(/\|/, $item);
316 | $issue =~ s/;/
/g;
317 | $e_vuln_detail{$1} .= "
";
318 | $e_vuln_detail{$1} .= "Host: $host
Service: $protocol
Type: $type
";
319 | $e_vuln_detail{$1} .= "$issue\n";
320 | }
321 | if($1 eq "High")
322 | {
323 | $vuln_score += 2;
324 | $high++;
325 | ($host, $protocol, $ID, $type, $issue) = split(/\|/, $item);
326 | $issue =~ s/;/
/g;
327 | $e_vuln_detail{$1} .= "
";
328 | $e_vuln_detail{$1} .= "Host: $host
Service: $protocol
Type: $type
";
329 | $e_vuln_detail{$1} .= "$issue\n";
330 | }
331 | if($1 eq "Serious")
332 | {
333 | $vuln_score += 3;
334 | $serious++;
335 | ($host, $protocol, $ID, $type, $issue) = split(/\|/, $item);
336 | $issue =~ s/;/
/g;
337 | $e_vuln_detail{$1} .= "
";
338 | $e_vuln_detail{$1} .= "Host: $host
Service: $protocol
Type: $type
";
339 | $e_vuln_detail{$1} .= "$issue\n";
340 | }
341 | if($1 eq "Critical")
342 | {
343 | $vuln_score += 4;
344 | $critical++;
345 | ($host, $protocol, $ID, $type, $issue) = split(/\|/, $item);
346 | $issue =~ s/;/
/g;
347 | $e_vuln_detail{$1} .= "
";
348 | $e_vuln_detail{$1} .= "Host: $host
Service: $protocol
Type: $type
";
349 | $e_vuln_detail{$1} .= "$issue\n";
350 | }
351 | }
352 | $_ = $hold;
353 | }
354 | $reports{"e_vuln_scan"} = "The total external vulnerability score was $vuln_score out of a maximum of 25. There were $medium medium issues, $high high issues, $serious serious issues and $critical critical issues.";
355 | if($vuln_score > 0)
356 | {
357 | $reports{"e_vuln_scan"} .= "";
358 | $reports{"e_vuln_scan"} .= "Non-compliant with section 11.2
";
359 | $reports{"e_vuln_scan"} .= "All vulnerabilities classed Medium and higher must be remediated.
";
360 | $reports{"e_vuln_scan"} .= "Medium: $medium
High: $high
Serious: $serious
Critical: $critical
\n";
361 | $reports{"e_vuln_scan"} .= "";
362 | foreach(keys(%e_vuln_detail))
363 | {
364 | $reports{"e_vuln_scan"} .= $e_vuln_detail{$_};
365 | }
366 | $reports{"e_vuln_scan"} .= "
"
367 | }
368 | else
369 | {
370 | $reports{"i_vuln_scan"} .= "";
371 | $reports{"i_vuln_scan"} .= "Compliant
\n";
372 | $reports{"i_vuln_scan"} .= "Nothing to report
";
373 | }
374 | if($vuln_score > 25) { $vuln_score = 25; }
375 | $score -= $vuln_score;
376 | }
377 |
378 | sub parse_nessus_file
379 | {
380 | my %nessus_results;
381 | $nessus_file = $_[0];
382 | print "Parsing $nessus_file\n";
383 | open(FILE, $nessus_file);
384 | foreach()
385 | {
386 | @results = split(/\|/);
387 | $nessus_results{"$results[3]"} .= $_."~";
388 | }
389 | close(FILE);
390 | return %nessus_results;
391 | }
392 |
393 | sub i_nmap_analyze
394 | {
395 | %results = &parse_nmap_file("i_nmap_scan");
396 | foreach(keys(%results))
397 | {
398 | @ports = split(/,/,$results{$_});
399 | }
400 | $open_ports = 0;
401 | foreach(@ports)
402 | {
403 | if( /.*open.*/ )
404 | {
405 | ($port, $junk) = split(/\//);
406 | $port =~ s/[^0-9]//g;
407 | if(! $req_ports_only{"$port"}) { $open_ports++; $i_nmap_ports{$port} ++;}
408 | }
409 | }
410 | $reports{"internal_nmap"} = "$open_ports undocumented ports discovered on firewall.";
411 | if($open_ports > 0)
412 | {
413 | $reports{"internal_nmap"} .= "";
414 | $reports{"internal_nmap"} .= "Non-compliant with sections 1.1.5, 1.1.6, 1.1.7, 1.2, 1.3.2, 1.3.8
";
415 | $reports{"internal_nmap"} .= "All ports open on a firewall must be thoroughly documented and controlled.
";
416 | $reports{"internal_nmap"} .= "$open_ports undocumented ports detected on the internal firewall interface.
\n";
417 | $reports{"internal_nmap"} .= "The following undocumented open ports were detected:
\n";
418 | foreach(keys(%i_nmap_ports))
419 | {
420 | $reports{"internal_nmap"} .= $_."
";
421 | }
422 | $reports{"internal_nmap"} .= "
"
423 | }
424 | else
425 | {
426 | $reports{"internal_nmap"} .= "";
427 | $reports{"internal_nmap"} .= "Compliant
\n";
428 | $reports{"internal_nmap"} .= "Nothing to report
";
429 | }
430 | if($open_ports > 10) { $open_ports = 10; }
431 | $score -= $open_ports;
432 | }
433 |
434 | sub e_nmap_analyze
435 | {
436 | %results = &parse_nmap_file("e_nmap_scan");
437 | foreach(keys(%results))
438 | {
439 | @ports = split(/,/,$results{$_});
440 | }
441 | $open_ports = 0;
442 | foreach(@ports)
443 | {
444 | if( /.*open.*/ )
445 | {
446 | ($port, $junk) = split(/\//);
447 | $port =~ s/[^0-9]//g;
448 | if(! $req_ports_only{"$port"}) { $open_ports++; $e_nmap_ports{$port} ++;}
449 | }
450 | }
451 | $reports{"external_nmap"} = "$open_ports undocumented ports discovered on firewall.";
452 | if($open_ports > 0)
453 | {
454 | $reports{"external_nmap"} .= "";
455 | $reports{"external_nmap"} .= "Non-compliant with sections 1.1.5, 1.1.6, 1.1.7, 1.2, 1.3.2, 1.3.8
";
456 | $reports{"external_nmap"} .= "All ports open on a firewall must be thoroughly documented and controlled.
";
457 | $reports{"external_nmap"} .= "$open_ports undocumented ports detected on the internal firewall interface.
\n";
458 | $reports{"external_nmap"} .= "The following undocumented open ports were detected:
\n";
459 | foreach(keys(%e_nmap_ports))
460 | {
461 | $reports{"external_nmap"} .= $_."
";
462 | }
463 | $reports{"external_nmap"} .= "
"
464 | }
465 | else
466 | {
467 | $reports{"external_nmap"} .= "";
468 | $reports{"external_nmap"} .= "Compliant
\n";
469 | $reports{"external_nmap"} .= "Nothing to report
";
470 | }
471 | if($open_ports > 10) { $open_ports = 10; }
472 | $score -= $open_ports;
473 | }
474 |
475 | sub parse_nmap_file
476 | {
477 | $file = $_[0];
478 | open(NMAP, "$file");
479 | @contents = ;
480 | foreach(@contents)
481 | {
482 | if( /^#.*/ ) { ; }
483 | else
484 | {
485 | /Host: (.*)Ports: (.*)Ignor.*/ ;
486 | $hosts{$1} = $2;
487 | }
488 | }
489 | close(NMAP);
490 | return %hosts;
491 | }
492 |
493 |
494 | sub information_flow
495 | {
496 | if(!(-e "inner_capture" || -e "outer_capture" || -e "i_nmap_scan" || -e "e_nmap_scan")) { return ; }
497 |
498 | print "\n";
499 | print "In order to correctly analyze your results, the system must first\n";
500 | print "determine basic information flow requirements for your network.\n";
501 | print "Please answer the following questions:\n\n";
502 | print "Inbound port requirements:\n";
503 | print "--------------------------\n";
504 | print "\n";
505 | $any_ports = &yorn("Are there any documented ports that should be open on the firewall?",
506 | "yn", "n");
507 | if($any_ports eq "y")
508 | {
509 | $any_ports = &yorn("Are there ports that should be open on the inside of the firewall?",
510 | "yn", "n");
511 | $more_ports = $any_ports;
512 | $num_ports = 0;
513 | while($more_ports eq "y")
514 | {
515 | $port = 0;
516 | while( ! $port)
517 | {
518 | print "Please enter the port number: ";
519 | $answer = <>;
520 | $port = $answer / 1;
521 | }
522 | $fw_internal_ports{$port} = 1;
523 | $num_ports++;
524 | $more_ports = &yorn("Are there more required ports?",
525 | "yn", "n");
526 | }
527 | print "Added $num_ports permitted inbound ports on the inside of the firewall.\n";
528 | $any_ports = &yorn("Are there ports that should be open on the outside of the firewall?",
529 | "yn", "n");
530 | $more_ports = $any_ports;
531 | $num_ports = 0;
532 | while($more_ports eq "y")
533 | {
534 | $port = 0;
535 | while( ! $port)
536 | {
537 | print "Please enter the port number: ";
538 | $answer = <>;
539 | $port = $answer / 1;
540 | }
541 | $fw_external_ports{$port} = 1;
542 | $num_ports++;
543 | $more_ports = &yorn("Are there more required ports?",
544 | "yn", "n");
545 | }
546 | print "Added $num_ports permitted inbound ports on the outside of the firewall.\n";
547 | }
548 | $any_ports = &yorn("Does your infrastructure require any inbound ports?",
549 | "yn", "y");
550 | $more_ports = $any_ports;
551 | $num_ports = 0;
552 | while($more_ports eq "y")
553 | {
554 | $protocol = &yorn("To enter a required port, you must first specify the\n".
555 | "protocol type. Is this port a TCP or a UDP port? ", "tu", "t");
556 | if($protocol eq "t") { $aprotocol="tcp"; } else { $aprotocol = "udp"; }
557 | print "$aprotocol selected. ";
558 | $port = 0;
559 | while( ! $port)
560 | {
561 | print "Please enter the inbound port number: ";
562 | $answer = <>;
563 | $port = $answer / 1;
564 | }
565 | print "$aprotocol/$port added.\n";
566 | $iport_filters[$num_ports] = "($aprotocol and dst port $port)";
567 | $ireq_ports{"$aprotocol:$port"} = 1;
568 | $ireq_ports_only{"$port"} = 1;
569 | $num_ports++;
570 | #Gather ports, protocols and addresses
571 | $more_ports = &yorn("Does your infrastructure require more inbound ports?",
572 | "yn", "n");
573 | }
574 | $inbound_filter = "not ( ";
575 | $and = 0;
576 | foreach(@iport_filters)
577 | {
578 | if($and == 1) { $inbound_filter .= " or "; }
579 | $inbound_filter .= $_;
580 | $and = 1;
581 | }
582 | $inbound_filter .= " )";
583 |
584 |
585 | $any_ports = &yorn("Does your infrastructure require any outbound ports?",
586 | "yn", "y");
587 | $more_ports = $any_ports;
588 | $num_ports = 0;
589 | while($more_ports eq "y")
590 | {
591 | $protocol = &yorn("To enter a required port, you must first specify the\n".
592 | "protocol type. Is this port a TCP or a UDP port? ", "tu", "t");
593 | if($protocol eq "t") { $aprotocol="tcp"; } else { $aprotocol = "udp"; }
594 | print "$aprotocol selected. ";
595 | $port = 0;
596 | while( ! $port)
597 | {
598 | print "Please enter the outbound port number: ";
599 | $answer = <>;
600 | $port = $answer / 1;
601 | }
602 | print "$aprotocol/$port added.\n";
603 | $oport_filters[$num_ports] = "($aprotocol and dst port $port)";
604 | $oreq_ports{"$aprotocol:$port"} = 1;
605 | $oreq_ports_only{"$port"} = 1;
606 | $num_ports++;
607 | #Gather ports, protocols and addresses
608 | $more_ports = &yorn("Does your infrastructure require more outbound ports?",
609 | "yn", "n");
610 | }
611 |
612 | $outbound_filter = "not ( ";
613 | $and = 0;
614 | foreach(@oport_filters)
615 | {
616 | if($and == 1) { $outbound_filter .= " or "; }
617 | $outbound_filter .= $_;
618 | $and = 1;
619 | }
620 | $outbound_filter .= " )";
621 | }
622 |
623 | sub o_cap_analyze
624 | {
625 | my %dports; my %tdports; my %udports; my $ports, my $local_filter,
626 | my @tdports, my @udports;
627 |
628 | #assume quickmode
629 | $quickmode = 1;
630 | if(-e "e_scan_settings")
631 | {
632 | open(SETTINGS, "e_scan_settings");
633 | @settings = ;
634 | close(SETTINGS);
635 | $quick = $settings[3];
636 | chomp($quick);
637 | if($quick ne "y") { $quickmode = 0; }
638 | }
639 | # Process TCP
640 | $local_filter = $outbound_filter;
641 | if($local_filter ne "")
642 | {
643 | $local_filter = "tcp and ($local_filter)";
644 | }
645 | else
646 | {
647 | $local_filter = "tcp";
648 | }
649 | open(PACKETS, "tcpdump -r outer_capture -n '$local_filter'|");
650 |
651 | foreach()
652 | {
653 | ($time, $proto, $source, $dir, $dest, $the_rest) = split(/ /);
654 | ($a,$b,$c,$d,$p) = split(/\./, $dest);
655 | $dest = "$a.$b.$c.$d";
656 | $dport = $p;
657 | $dport =~ s/://g;
658 | ($a,$b,$c,$d,$p) = split(/\./, $source);
659 | $source = "$a.$b.$c.$d";
660 | $sport = $p;
661 | $tdports{$dport}++;
662 | }
663 | close(PACKETS);
664 | $tports = keys(%tdports);
665 | $reports{"outbound_ports"} = "$tports unnecessary TCP ports were permitted outbound.";
666 | # Process UDP
667 | $local_filter = $outbound_filter;
668 | if($local_filter ne "")
669 | {
670 | $local_filter = "udp and ($local_filter)";
671 | }
672 | else
673 | {
674 | $local_filter = "udp";
675 | }
676 | open(PACKETS, "tcpdump -r outer_capture -n '$local_filter'|");
677 |
678 | foreach()
679 | {
680 | ($time, $proto, $source, $dir, $dest, $the_rest) = split(/ /);
681 | ($a,$b,$c,$d,$p) = split(/\./, $dest);
682 | $dest = "$a.$b.$c.$d";
683 | $dport = $p;
684 | $dport =~ s/://g;
685 | ($a,$b,$c,$d,$p) = split(/\./, $source);
686 | $source = "$a.$b.$c.$d";
687 | $sport = $p;
688 | $udports{$dport}++;
689 | }
690 | close(PACKETS);
691 | $uports = keys(%udports);
692 | $reports{"outbound_ports"} .= "$uports unnecessary UDP ports were permitted outbound.";
693 | $open_ports = $uports + $tports;
694 | if($quickmode)
695 | {
696 | $reports{"outbound_ports"} .= " -- WARNING: Quickmode was assumed or selected, so these results may not be accurate!";
697 | }
698 | if($open_ports > 0)
699 | {
700 | $reports{"outbound_ports"} .= "";
701 | $reports{"outbound_ports"} .= "Non-compliant with sections 1.1.5, 1.1.6, 1.1.7, 1.2, 1.3.2, 1.3.6, 2.2.2, 1.3.8
\n";
702 | $reports{"outbound_ports"} .= "All ports open through the perimeter must be thoroughly documented and controlled.
\n";
703 | $reports{"outbound_ports"} .= "$open_ports undocumented outbound ports detected through the firewall.
\n";
704 | $reports{"outbound_ports"} .= "The following undocumented open ports were detected:
\n";
705 | $reports{"outbound_ports"} .= "UDP Ports
\n\n";
706 | @udports = keys(%udports);
707 | foreach(sort {$a <=> $b} @udports)
708 | {
709 | $reports{"outbound_ports"} .= $_."
\n";
710 | }
711 | $reports{"outbound_ports"} .= "";
712 | $reports{"outbound_ports"} .= "
TCP Ports
\n\n";
713 | @tdports = keys(%tdports);
714 | foreach(sort {$a <=> $b} @tdports)
715 | {
716 | $reports{"outbound_ports"} .= $_."
\n";
717 | }
718 | $reports{"outbound_ports"} .= "\n";
719 | $reports{"outbound_ports"} .= "
\n"
720 | }
721 | else
722 | {
723 | $reports{"outbound_ports"} .= "";
724 | $reports{"outbound_ports"} .= "Compliant
\n";
725 | $reports{"outbound_ports"} .= "Nothing to report
";
726 | }
727 |
728 | if($ports > 10) { $ports = 10; }
729 | $score = $score - $ports;
730 | }
731 |
732 | sub i_cap_analyze
733 | {
734 | my %dports; my %tdports; my %udports; my $ports, my $local_filter,
735 | my @tdports, my @udports;
736 | #assume quickmode
737 | $quickmode = 1;
738 | if(-e "i_scan_settings")
739 | {
740 | open(SETTINGS, "i_scan_settings");
741 | @settings = ;
742 | close(SETTINGS);
743 | $quick = $settings[3];
744 | chomp($quick);
745 | if($quick ne "y") { $quickmode = 0; }
746 | }
747 | # Process TCP
748 | $local_filter = $inbound_filter;
749 | if($local_filter ne "")
750 | {
751 | $local_filter = "tcp and ($local_filter)";
752 | }
753 | else
754 | {
755 | $local_filter = "tcp";
756 | }
757 | open(PACKETS, "tcpdump -r inner_capture -n '$local_filter'|");
758 |
759 | foreach()
760 | {
761 | ($time, $proto, $source, $dir, $dest, $the_rest) = split(/ /);
762 | ($a,$b,$c,$d,$p) = split(/\./, $dest);
763 | $dest = "$a.$b.$c.$d";
764 | $dport = $p;
765 | $dport =~ s/://g;
766 | ($a,$b,$c,$d,$p) = split(/\./, $source);
767 | $source = "$a.$b.$c.$d";
768 | $sport = $p;
769 | $tdports{$dport}++;
770 | }
771 | close(PACKETS);
772 | $tports = keys(%tdports);
773 | $reports{"inbound_ports"} = "$tports unnecessary TCP ports were permitted inbound.";
774 | # Process UDP
775 | $local_filter = $inbound_filter;
776 | if($local_filter ne "")
777 | {
778 | $local_filter = "udp and ($local_filter)";
779 | }
780 | else
781 | {
782 | $local_filter = "udp";
783 | }
784 | open(PACKETS, "tcpdump -r inner_capture -n '$local_filter'|");
785 |
786 | foreach()
787 | {
788 | ($time, $proto, $source, $dir, $dest, $the_rest) = split(/ /);
789 | ($a,$b,$c,$d,$p) = split(/\./, $dest);
790 | $dest = "$a.$b.$c.$d";
791 | $dport = $p;
792 | $dport =~ s/://g;
793 | ($a,$b,$c,$d,$p) = split(/\./, $source);
794 | $source = "$a.$b.$c.$d";
795 | $sport = $p;
796 | $udports{$dport}++;
797 | }
798 | close(PACKETS);
799 | $uports = keys(%udports);
800 | $reports{"inbound_ports"} .= "$uports unnecessary UDP ports were permitted inbound.";
801 | $open_ports = $uports + $tports;
802 | if($quickmode)
803 | {
804 | $reports{"inbound_ports"} .= " -- WARNING: Quickmode was assumed or selected, so these results may not be accurate!";
805 | }
806 | if($open_ports > 0)
807 | {
808 | $reports{"inbound_ports"} .= "";
809 | $reports{"inbound_ports"} .= "Non-compliant with sections 1.1.5, 1.1.6, 1.1.7, 1.2, 1.3.2, 1.3.6, 2.2.2, 1.3.8
\n";
810 | $reports{"inbound_ports"} .= "All ports open inbound must be thoroughly documented and controlled.
\n";
811 | $reports{"inbound_ports"} .= "$open_ports undocumented inbound ports detected through the firewall.
\n";
812 | $reports{"inbound_ports"} .= "The following undocumented open ports were detected:
\n";
813 | $reports{"inbound_ports"} .= "UDP Ports
\n\n";
814 | @udports = keys(%udports);
815 | foreach(sort {$a <=> $b} @udports)
816 | {
817 | $reports{"inbound_ports"} .= $_."
\n";
818 | }
819 | $reports{"inbound_ports"} .= "";
820 | $reports{"inbound_ports"} .= "
TCP Ports
\n\n";
821 | @tdports = keys(%tdports);
822 | foreach(sort {$a <=> $b} @tdports)
823 | {
824 | $reports{"inbound_ports"} .= $_."
\n";
825 | }
826 | $reports{"inbound_ports"} .= "";
827 | $reports{"inbound_ports"} .= "
\n"
828 | }
829 | else
830 | {
831 | $reports{"inbound_ports"} .= "";
832 | $reports{"inbound_ports"} .= "Compliant
\n";
833 | $reports{"inbound_ports"} .= "Nothing to report
";
834 | }
835 | }
836 |
837 | sub yorn
838 | {
839 | my(%is_opt, $answer, $query, $args, $default, @args);
840 | ($query, $args, $default) = @_;
841 | @args = split(//, $args);
842 | foreach(@args)
843 | {
844 | $is_opt{$_} = 1;
845 | if($_ eq $default) { $_ =~ tr/a-z/A-Z/; }
846 | }
847 | $args = join('/', @args);
848 | while(!$is_opt{$answer})
849 | {
850 | print "$query [$args]";
851 | $answer = <>;
852 | chomp($answer);
853 | $answer =~ tr/A-Z/a-z/;
854 | if($answer eq "") { $answer = $default; }
855 | }
856 | return $answer;
857 | }
858 |
859 | sub HTML_Report
860 | {
861 | open(FILE, ">pci_report.html");
862 | if($score < 100)
863 | {
864 | $Compliant = "Non-Compliant
";
865 | }
866 | else
867 | {
868 | $Compliant = "Compliant
";
869 | }
870 | print FILE <
872 |
873 | PCI Validation Tool
874 |
893 |
982 |
983 |
984 |
985 |
Report Sections
986 |
Overall Score: $score
987 | $Compliant
988 |
989 |
990 |
991 | END_HTML
992 | print FILE "\n
Outbound Scan
".$reports{"outbound_ports"}."
";
993 | print FILE "\n
Inbound Scan
".$reports{"inbound_ports"}."
";
994 | print FILE "\n
SSL Cipher Validation
".$reports{"ciphers"}."
";
995 | print FILE "\n
Internal Vulnerability Scan
".$reports{"i_vuln_scan"}."
";
996 | print FILE "\n
External Vulnerability Scan
".$reports{"e_vuln_scan"}."
";
997 | print FILE "\n
Internal Firewall Scan
".$reports{"internal_nmap"}."
";
998 | print FILE "\n
External Firewall Scan
".$reports{"external_nmap"}."
";
999 | print FILE "\n
";
1000 | }
1001 |
1002 | sub copyright
1003 | {
1004 | print "Copyright (C) 2005,2009 All Rights Reserved -- Cyber-Defense.Org\n";
1005 | print "David Hoelzer\n";
1006 | print "http://www.cyber-defense.org\n";
1007 | print "----------------------------\n";
1008 | }
1009 |
--------------------------------------------------------------------------------
/PCI/cisp_ciphers:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | #
3 | # Automated cipher testing for PCI CISP
4 | #
5 | # Copyright (C) 2005, All Rights Reserved -- Cyber-Defense.Org
6 | # David Hoelzer
7 | # http://www.cyber-defense.org
8 | #
9 | # Feel free to use this script, however you may not incorporate this
10 | # script into any commercial product, utility or script for which you
11 | # charge a fee of any kind. You may use this script as-is to perform
12 | # for-profit assessments.
13 | #
14 | print "Copyright (C) 2005, All Rights Reserved -- Cyber-Defense.Org\n";
15 | print "David Hoelzer\n";
16 | print "http://www.cyber-defense.org\n";
17 | print "----------------------------\n";
18 | print "\n";
19 | print "This script will automatically test your SSL enabled web server(s)\n";
20 | print "in an effort to verify that the encryption settings are in compliant\n";
21 | print "with the PCI CISP requirements.\n\n";
22 | print "To perform the tests, the script will need to know where to contact\n";
23 | print "your SSL server. If you are outside of the firewall running this test\n";
24 | print "then you should use the public IP address of the server. If you are\n";
25 | print "running this test from within the network, you should probably enter\n";
26 | print "the internal IP address of the SSL enabled web server.\n\n";
27 | print "Which IP address should I test? ";
28 | $target = <>;
29 | $date = `date`;
30 | chomp($date);
31 | chomp($target);
32 | if(! $target)
33 | {
34 | print "No host entered for testing. Exiting.\n\n";
35 | exit;
36 | }
37 | open(REPORT, ">ciphers_$target");
38 | print REPORT "$target\n";
39 | print REPORT "$date\n";
40 | &validity;
41 | print "Thank you. Beginning tests on $target.\n\n";
42 | print "Obtaining available OpenSSL ciphers.\n";
43 | $cipher_types{"HIGH"} = "These ciphers use key lengths greater than 128 bits";
44 | $cipher_types{"MED"} = "These ciphers use key lengths of 128 bits";
45 | $cipher_types{"LOW"} = "These ciphers use key lengths of 56 or 64 bits but do not include export compatible ciphers";
46 | $cipher_types{"EXP"} = "These ciphers use key lengths of less than 64 bits and may be used without export restrictions";
47 | $cipher_types{"NULL"} = "These are ciphers with no encryption";
48 | @cipher_queries = keys(%cipher_types);
49 | foreach $cipher_type (@cipher_queries)
50 | {
51 | print "Grabbing '$cipher_type' ciphers.\n";
52 | print REPORT "cipher_type:$cipher_type\n";
53 | print REPORT "cipher_desc:".$cipher_types{"$cipher_type"}."\n";
54 |
55 | $command = "openssl ciphers $cipher_type";
56 | open(FILE, "$command|");
57 | foreach()
58 | {
59 | chomp();
60 | $ciphers_supported{"$cipher_type"} .= "$_";
61 | }
62 | print REPORT "supports:". join(", ", split(/:/, $ciphers_supported{"$cipher_type"})) . "\n";
63 | close(FILE);
64 | }
65 |
66 | print "Testing for supported cipher types on the server.\n";
67 | print REPORT "cipher_findings\n";
68 | foreach $cipher_type (@cipher_queries)
69 | {
70 | foreach $cipher (split(/:/,$ciphers_supported{"$cipher_type"}))
71 | {
72 | $command = "openssl s_client -quiet -connect $target:443 -cipher $cipher";
73 | $x=open(FILE, "echo Q | $command| ");
74 | @output = ;
75 | close(FILE);
76 | $i = 0;
77 | print "$cipher\n";
78 | print "------------\n";
79 | foreach (@output)
80 | {
81 | print "$i: $_";
82 | $i++;
83 | }
84 | $line = $output[0];
85 | if($output[0])
86 | {
87 | print REPORT "$cipher:1\n";
88 | }
89 | else
90 | {
91 | print REPORT "$cipher:0\n";
92 | }
93 | }
94 | }
95 |
96 | close(REPORT);
97 |
98 |
99 |
100 | sub validity
101 | {
102 | $command = "openssl s_client -connect $target:443 | openssl x509 -text";
103 | $x = open(FILE, "echo Q | $command|");
104 | @output = ;
105 | close(FILE);
106 | foreach $line (@output)
107 | {
108 | if($line =~ /Not Before/) { $line =~ s/.*Not Before: (.*)/\1/; print REPORT "S:$line"; }
109 | if($line =~ /Not After/) { $line =~ s/.*Not After : (.*)/\1/; print REPORT "E:$line"; }
110 | }
111 |
112 | $command = "openssl s_client -connect $target:443 -verify 20";
113 | $x = open(FILE, "echo Q | $command | ");
114 | @output = ;
115 | $chain_flag = 0;
116 | close(FILE);
117 | foreach $line (@output)
118 | {
119 | if($chain_flag)
120 | {
121 | if($line =~ /^ [0-9]+ s:/ )
122 | {
123 | $line =~ s/^ [0-9]+ s:(.*)/\1/;
124 | chomp($line);
125 | print REPORT "CC:Signature: $line\n";
126 | }
127 | if($line =~ /^[ \t]+i:/)
128 | {
129 | $line =~ s/^[ \t]+i:(.*)/\1/;
130 | chomp($line);
131 | print REPORT "CC:Issued by: $line\n";
132 | }
133 | }
134 | if($line =~ /^---/) {$chain_flag = 0; }
135 | if($line =~ /^Certificate chain/) { $chain_flag = 1; }
136 | }
137 | }
138 |
139 |
--------------------------------------------------------------------------------
/PCI/cisp_scanner:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | #
3 | # Automatic scanning script for PCI CISP validation
4 | #
5 | # The sniffer only collects packets with an ID of 444
6 | # to match what the scanner fires.
7 | #
8 | # Testing in a proxy environment is not currently supported since these
9 | # environments tend not to reflect these settings in proxied packets
10 | #
11 | # Copyright (C) 2005, All Rights Reserved -- Cyber-Defense.Org
12 | # David Hoelzer
13 | # http://www.cyber-defense.org
14 | #
15 | # Feel free to use this script, however you may not incorporate this
16 | # script into any commercial product, utility or script for which you
17 | # charge a fee of any kind. You may use this script as-is to perform
18 | # for-profit assessments.
19 | #
20 | print "Copyright (C) 2005, All Rights Reserved -- Cyber-Defense.Org\n";
21 | print "David Hoelzer\n";
22 | print "http://www.cyber-defense.org\n";
23 | print "----------------------------\n";
24 | print "\n";
25 | $reduced_top_port = 80;
26 | $top_port = 65536;
27 | $real_source = "5.1.1.1";
28 | print "The scanner will normally probe all possible ports on the destination\n";
29 | print "network. If you would like to run in 'quick' mode for testing\n";
30 | print "purposes, the scanner will only probe the first $reduced_top_port ports, thus\n";
31 | print "running approximately 60 times faster.\n\n";
32 | $quick = &yorn("Run in quick mode?", "yn", "n");
33 | if($quick eq "y") { $top_port = $reduced_top_port; }
34 | print "\nThe scanner needs information about the target network or systems.\n";
35 | print"If you are scanning from inside to outside, any external address will\n";
36 | print "do as a target, but we recommend you choose something that is\n";
37 | print "unallocated or blocked at your edge router to prevent the packets\n";
38 | print "from hitting another party. If you are scanning inbound, the target\n";
39 | print "should be a real host IP address behind the firewall.\n\n";
40 | print "Enter a target address: ";
41 | $target = <>;
42 | chomp($target);
43 | print "\nThe scanner also needs to know the address of the firewall from\n";
44 | print "the scanner's perspective. In other words, if the scanner is\n";
45 | print "being run from the outside, you should enter the external firewall\n";
46 | print "address. If the scanner is being run from inside, the internal\n";
47 | print "firewall address should be entered.\n\n";
48 | print "Enter firewall address: ";
49 | $firewall = <>;
50 | chomp($firewall);
51 | &get_scanner_ip;
52 | print "\nThe scanner needs to know if it should operate in internal or\n";
53 | print "external mode since the scans performed are slightly different.\n\n";
54 | $iore = &yorn("Operate in internal or external mode?", "ie", "i");
55 | if($iore eq "e")
56 | {
57 | print"\nIn external mode, the scanner will need to know the ethernet\n";
58 | print"address of the firewall. The scanner will automatically ping\n";
59 | print"the firewall in an effort to ascertain the MAC address. It is\n";
60 | print"critical that this scanner be located on the same physical segment\n";
61 | print"as the firewall's external interface for this to function properly.\n\n";
62 |
63 | $firewall_mac = &get_firewall_mac;
64 | print "\n\nThe scanner must use some real public IP address for the scans\n";
65 | print "from the outside. The scanner uses 5.1.1.1 by default since this\n";
66 | print "is an unallocated address. Is this acceptable?\n\n";
67 | $five = &yorn("Use 5.1.1.1 as the public address?", "yn", "y");
68 | if($five eq "n")
69 | {
70 | print "\nPlease enter a public IP address to use as one of the packet\n";
71 | print "sources during the tests. This must not be an RFC-1918 private\n";
72 | print "address.\n\n";
73 | print "Enter a source IP address: ";
74 | $real_source = <>;
75 | chomp($real_source);
76 | }
77 | }
78 |
79 | print "Thank you. Please wait while the scan runs..";
80 | open(FILE, ">".$iore."_scan_settings");
81 | print FILE "$iore\n$real_source\n$target\n$quick\n$firewall";
82 | close(FILE);
83 |
84 | if($iore eq "e")
85 | {
86 | print "\n\nPerforming external scan of firewall address.\n";
87 |
88 | $scan_targets = "-M $firewall_mac -D $target";
89 | for($dport=0;$dport!=$top_port;$dport++)
90 | {
91 | $command = "nemesis-tcp $static_ip_options $static_tcp_options -x 1025 -y $dport -S $real_source -D $firewall -fS > /dev/null";
92 | system($command);
93 | $command = "nemesis-tcp $static_ip_options $static_tcp_options -x 1025 -y $dport -S $real_source -D $firewall -fS -fA > /dev/null";
94 | system($command);
95 | }
96 | print "Initial external scan completed.\n";
97 | }
98 | else
99 | {
100 | print "\nSkipping external scan of firewall.\n";
101 | $scan_targets = "-D $target";
102 | }
103 |
104 | # Standard options sent in every packet
105 | $sources = "$real_source, 192.168.50.32, $scanner_IP";
106 | $static_ip_options = "-I 444 -T 99";
107 | $static_tcp_options = "-a 111 -s 222 -w 333";
108 |
109 | # Source ports to fire packets from
110 | $source_ports = "0,20,80,1025";
111 |
112 | # All TCP packet types to send:
113 | $tcp_packets = "-fS, -fS -fA, -fS -fF, -f-";
114 |
115 | # Fragmentation options to send:
116 | $fragment_options = "-FD, -FM, -FM 1";
117 |
118 | ################################################################
119 | #
120 | # We strongly recommend that you do not edit beyond this point.
121 | #
122 | ################################################################
123 | #
124 | # Break apart the options:
125 | @tcp_opts = split(/,/, $tcp_packets);
126 | @sports = split(/,/, $source_ports);
127 | @frags = split(/,/, $fragment_options);
128 | @sources = split(/,/, $sources);
129 | # Fire some TCP Packets!
130 | print "Beginning fragmentation and flag scanning through firewall.\n";
131 | foreach $tcp_opts (@tcp_opts) {
132 | foreach $frag (@frags) {
133 | foreach $sport (@sports) {
134 | for($dport = 0; $dport < $top_port; $dport++) {
135 | foreach $source (@sources) {
136 | $command = "nemesis-tcp $static_ip_options $static_tcp_options $tcp_opts $frag -x $sport -y $dport $scan_targets -S $source > /dev/null";
137 | system($command);
138 | }
139 | }
140 | }
141 | }
142 | print "Finished complete loop for TCP option \"$tcp_opts\".\n";
143 | }
144 |
145 | print "TCP testing completed\n";
146 | print "Beginning ICMP sweep\n";
147 | for($code=0;$code<14;$code++){
148 | for($type=0;$type<40;$type++){
149 | foreach $frag (@frags)
150 | {
151 | $command = "nemesis-icmp $static_ip_options $frag $scan_targets -S $real_source -i $type -c $code > /dev/null";
152 | system($command);
153 | }
154 | }
155 | }
156 |
157 | print "ICMP testing complete\n";
158 | print "UDP testing begins\n";
159 | for($dport=0;$dport<$top_port;$dport++){
160 | foreach $frag (@frags)
161 | {
162 | $command = "nemesis-udp $static_ip_options $frag $scan_targets -S $real_source -x 53 -y $dport > /dev/null";
163 | system($command);
164 | }
165 | }
166 |
167 | print "Performing an NMap scan of the firewall, $firewall...\n";
168 | $command = "nmap -n -O -p 1-65535 -sT -oM ".$iore."_nmap_scan $firewall > /dev/null";
169 | system($command);
170 | print "\nScan complete!\n";
171 | print "\n\nProbing Completed!";
172 | sub usage
173 | {
174 | print <;
199 | chomp($answer);
200 | $answer =~ tr/A-Z/a-z/;
201 | if($answer eq "") { $answer = $default; }
202 | }
203 | return $answer;
204 | }
205 |
206 | sub get_scanner_ip
207 | {
208 | $command = "ifconfig eth0 | grep 'inet addr' |";
209 | open(FILE, "$command");
210 | @results = ;
211 | close(FILE);
212 | $scanner_IP = $results[0];
213 | chomp($scanner_IP);
214 | $scanner_IP =~ s/.*inet addr:([0-9.]*).*Bcast.*/\1/;
215 | if(!$scanner_IP)
216 | {
217 | print "There was an error obtaining the eth0 IP address of the scanner.\n";
218 | exit;
219 | }
220 | }
221 |
222 | sub get_firewall_mac
223 | {
224 | $command = "ping -c 1 $firewall > /dev/null";
225 | system($command);
226 | $command = "arp -an | grep $firewall | cut -d ' ' -f 4";
227 | open(FILE, "$command|");
228 | @results = ;
229 | close(FILE);
230 | $firewall_mac = $results[0];
231 | chomp($firewall_mac);
232 | if(!$firewall_mac)
233 | {
234 | print "There was an error obtaining the firewall MAC address. Aborted.\n";
235 | exit;
236 | }
237 | print "The MAC of the firewall is $firewall_mac";
238 | }
239 |
240 |
--------------------------------------------------------------------------------
/PCI/cisp_sniffer:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # The sniffer only collects packets with an ID of 444
4 | # to match what the scanner fires.
5 | #
6 | # Testing in a proxy environment is not currently supported since these
7 | # environments tend not to reflect these settings in proxied packets
8 | #
9 | # Copyright (C) 2005, All Rights Reserved -- Cyber-Defense.Org
10 | # David Hoelzer
11 | # http://www.cyber-defense.org
12 | #
13 | # Feel free to use this script, however you may not incorporate this
14 | # script into any commercial product, utility or script for which you
15 | # charge a fee of any kind. You may use this script as-is to perform
16 | # for-profit assessments.
17 | #
18 |
19 | echo 'Copyright (C) 2005, All Rights Reserved -- Cyber-Defense.Org'
20 | echo 'David Hoelzer'
21 | echo 'http://www.cyber-defense.org'
22 | echo '----------------------------'
23 | echo 'PCI CISP Sniffer driver'
24 | echo
25 |
26 | done=false
27 | while [ $done = false ]; do
28 | echo -n "Is this the internal sniffer or the external sniffer? [I/E] "
29 | read INEXT
30 | if [ "$INEXT" == "i" ] || [ "$INEXT" == "I" ]; then
31 | done=true
32 | type=internal
33 | filename=inner_capture
34 | directory=`pwd`
35 | fi
36 | if [ "$INEXT" == "e" ] || [ "$INEXT" == "E" ]; then
37 | done=true
38 | type=internal
39 | filename=outer_capture
40 | directory=`pwd`
41 | fi
42 | done
43 | echo -n "Which interface should I listen on? [eth0] "
44 | read INTERFACE
45 | if [ ! $INTERFACE ]; then
46 | INTERFACE=eth0
47 | fi
48 |
49 | echo
50 | echo "Starting sniffer on $INTERFACE. The log will be stored in"
51 | echo "$directory as $filename"
52 | echo "When the scan has been completed, hit control-C to terminate."
53 | echo -------------------------
54 | tcpdump -w $filename -i $INTERFACE ip[4:2]=444
55 |
--------------------------------------------------------------------------------
/PCI/cisp_vuln_scan:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | #
3 | # Copyright (C) 2005, All Rights Reserved -- Cyber-Defense.Org
4 | # David Hoelzer
5 | # http://www.cyber-defense.org
6 | #
7 | # Feel free to use this script, however you may not incorporate this
8 | # script into any commercial product, utility or script for which you
9 | # charge a fee of any kind. You may use this script as-is to perform
10 | # for-profit assessments.
11 | #
12 |
13 | echo 'Copyright (C) 2005, All Rights Reserved -- Cyber-Defense.Org'
14 | echo 'David Hoelzer'
15 | echo 'http://www.cyber-defense.org'
16 | echo '----------------------------'
17 | echo 'PCI CISP Automated Vulnerability Assessment'
18 |
19 | echo
20 |
21 | done=false
22 | while [ $done = false ]; do
23 | echo -n "Is this the internal or the external scanning host? [I/E] "
24 | read INEXT
25 | if [ $INEXT = 'i' ] || [ $INEXT == 'I' ]; then
26 | done=true
27 | type=internal
28 | filename=i_vuln_scan
29 | directory=`pwd`
30 | fi
31 | if [ $INEXT = e ] || [ $INEXT = E ]; then
32 | done=true
33 | type=internal
34 | filename=e_vuln_scan
35 | directory=`pwd`
36 | fi
37 | done
38 | echo "In order to perform the scan, you must first provide a list of IP addresses"
39 | echo "that represent the targets. For an external scan please provide the external"
40 | echo "IP address of the firewall. For an internal scan please provide the IP"
41 | echo "addresses of all of the hosts that make up your perimeter including the"
42 | echo "internal address of the firewall. When you have finished, please press"
43 | echo "control-D. If you make an error, please press control-C and restart this"
44 | echo "script."
45 | echo "------------------------------------------------------------------------"
46 | echo "(Please enter 1 address per line):"
47 | cat > hosts
48 | echo "Thank you. The scan will now run. Please be patient!"
49 | echo 0 | nessus -q 127.0.0.1 1241 pcicisp pcicisp hosts $filename > /dev/null
50 | echo "Scan completed."
51 |
--------------------------------------------------------------------------------
/PCI/sample_pci_report.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | PCI Validation Tool
4 |
23 |
112 |
113 |
114 |
115 |
Report Sections
116 |
Overall Score: 48
117 |
Non-Compliant
118 |
119 |
120 |
121 |
122 |
Outbound Scan
82 unnecessary TCP ports were permitted outbound.0 unnecessary UDP ports were permitted outbound. -- WARNING: Quickmode was assumed or selected, so these results may not be accurate!
Non-compliant with sections 1.1.5, 1.1.6, 1.1.7, 1.2, 1.3.2, 1.3.6, 2.2.2, 1.3.8
All ports open through the perimeter must be thoroughly documented and controlled.
82 undocumented outbound ports detected through the firewall.
123 |
The following undocumented open ports were detected:
UDP Ports
124 |
TCP Ports
125 | 0
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
21282
32964
126 |
Inbound Scan
81 unnecessary TCP ports were permitted inbound.0 unnecessary UDP ports were permitted inbound. -- WARNING: Quickmode was assumed or selected, so these results may not be accurate!
Non-compliant with sections 1.1.5, 1.1.6, 1.1.7, 1.2, 1.3.2, 1.3.6, 2.2.2, 1.3.8
All ports open inbound must be thoroughly documented and controlled.
81 undocumented inbound ports detected through the firewall.
127 |
The following undocumented open ports were detected:
UDP Ports
128 |
TCP Ports
129 | 0
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
47796
130 |
SSL Cipher Validation
9 EXP ciphers are supported: These ciphers use key lengths of less than 64 bits and may be used without export restrictions.
1 LOW ciphers are supported: These ciphers use key lengths of 56 or 64 bits but do not include export compatible ciphers.
1 HIGH ciphers are supported: These ciphers use key lengths greater than 128 bits.
Non-compliant with section 4.1
131 | SSL must use at least 128 bit encryption
LOW ciphers are not in compliance with the standard.
132 | EXP ciphers are not in compliance with the standard.
133 |
134 |
EXP1024-DHE-DSS-RC4-SHA is not supported.
EXP1024-RC4-SHA is supported.
EXP1024-DHE-DSS-DES-CBC-SHA is not supported.
EXP1024-DES-CBC-SHA is supported.
EXP1024-RC2-CBC-MD5 is supported.
EXP1024-RC4-MD5 is supported.
EXP-EDH-RSA-DES-CBC-SHA is not supported.
EXP-EDH-DSS-DES-CBC-SHA is not supported.
EXP-DES-CBC-SHA is supported.
EXP-RC2-CBC-MD5 is supported.
EXP-RC4-MD5 is supported.
EXP-ADH-DES-CBC-SHA is not supported.
EXP-ADH-RC4-MD5 is not supported.
EXP-RC2-CBC-MD5 is supported.
EXP-RC4-MD5 is supported.
EDH-RSA-DES-CBC-SHA is not supported.
EDH-DSS-DES-CBC-SHA is not supported.
DES-CBC-SHA is supported.
RC4-64-MD5 is not supported.
DES-CBC-MD5 is not supported.
NULL-SHA is not supported.
NULL-MD5 is not supported.
EDH-RSA-DES-CBC3-SHA is not supported.
EDH-DSS-DES-CBC3-SHA is not supported.
DES-CBC3-SHA is supported.
DES-CBC3-MD5 is not supported.
135 |
136 |
Internal Vulnerability Scan
The total internal vulnerability score was 19 out of a maximum of 25. There were 19 medium issues, 0 high issues, 0 serious issues and 0 critical issues.
Non-compliant with section 11.2
All vulnerabilities classed Medium and higher must be remediated.
Medium: 19
High: 0
Serious: 0
Critical: 0
137 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: NOTE
The remote webserver supports the TRACE and/or TRACK methods. TRACE and TRACK
are HTTP methods which are used to debug web server connections.
It has been shown that servers supporting this method are subject
to cross-site-scripting attacks, dubbed XST for
"Cross-Site-Tracing", when used in conjunction with
various weaknesses in browsers.
An attacker may use this flaw to trick your legitimate web users to
give him their credentials.
Solution :
Add the following lines for each virtual host in your configuration file :
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE
138 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: NOTE
The remote webserver supports the TRACE and/or TRACK methods. TRACE and TRACK
are HTTP methods which are used to debug web server connections.
It has been shown that servers supporting this method are subject
to cross-site-scripting attacks, dubbed XST for
"Cross-Site-Tracing", when used in conjunction with
various weaknesses in browsers.
An attacker may use this flaw to trick your legitimate web users to
give him their credentials.
Solution :
Add the following lines for each virtual host in your configuration file :
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE
139 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: NOTE
The remote webserver supports the TRACE and/or TRACK methods. TRACE and TRACK
are HTTP methods which are used to debug web server connections.
It has been shown that servers supporting this method are subject
to cross-site-scripting attacks, dubbed XST for
"Cross-Site-Tracing", when used in conjunction with
various weaknesses in browsers.
An attacker may use this flaw to trick your legitimate web users to
give him their credentials.
Solution :
Add the following lines for each virtual host in your configuration file :
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE
140 |
Host: 128.226.1.10
Service: ssh (22/tcp)
Type: NOTE
Remote SSH version : SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3
Remote SSH supported authentication : publickey,password,keyboard-interactive
141 |
142 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: NOTE
The remote web server type is :
Apache/1.3.26 (Unix) Debian GNU/Linux PHP/4.1.2
Solution : You can set the directive 'ServerTokens Prod' to limit
the information emanating from the server in its response headers.
143 |
144 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: NOTE
The remote web server type is :
Apache/1.3.26 Ben-SSL/1.48 (Unix) Debian GNU/Linux PHP/4.1.2
Solution : You can set the directive 'ServerTokens Prod' to limit
the information emanating from the server in its response headers.
145 |
146 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: NOTE
A web server is running on this port
147 |
148 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: NOTE
A web server is running on this port through SSL
149 |
150 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: NOTE
A SSLv2 server answered on this port
151 |
152 |
Host: 128.226.1.10
Service: ssh (22/tcp)
Type: NOTE
An ssh server is running on this port
153 |
154 |
Host: 128.226.1.10
Service: domain (53/udp)
Type: NOTE
BIND 'NAMED' is an open-source DNS server from ISC.org.
Many proprietary DNS servers are based on BIND source code.
The BIND based NAMED servers (or DNS servers) allow remote users
to query for version and type information. The query of the CHAOS
TXT record 'version.bind', will typically prompt the server to send
the information back to the querying source.
The remote bind version is : 9.2.1
Solution :
Using the 'version' directive in the 'options' section will block
the 'version.bind' query, but it will not log such attempts.
155 |
156 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: INFO
The remote host is running a version of PHP <= 4.2.2.
The mail() function does not properly sanitize user input.
This allows users to forge email to make it look like it is
coming from a different source other than the server.
Users can exploit this even if SAFE_MODE is enabled.
Solution : Contact your vendor for the latest PHP release.
Risk factor : Medium
CVE : CVE-2002-0985, CVE-2002-0986
BID : 5562
157 |
158 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: INFO
The remote host is running a version of PHP <= 4.2.2.
The mail() function does not properly sanitize user input.
This allows users to forge email to make it look like it is
coming from a different source other than the server.
Users can exploit this even if SAFE_MODE is enabled.
Solution : Contact your vendor for the latest PHP release.
Risk factor : Medium
CVE : CVE-2002-0985, CVE-2002-0986
BID : 5562
159 |
160 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The remote host is running a version of PHP <= 4.2.2.
The mail() function does not properly sanitize user input.
This allows users to forge email to make it look like it is
coming from a different source other than the server.
Users can exploit this even if SAFE_MODE is enabled.
Solution : Contact your vendor for the latest PHP release.
Risk factor : Medium
CVE : CVE-2002-0985, CVE-2002-0986
BID : 5562
161 |
162 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The SSL certificate of the remote service expired Jun 29 17:02:51 2005 GMT!
163 |
164 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The remote host appears to be running Apache 1.3.33 or older.
There is a local buffer overflow in the 'htpasswd' command in these
versions that may allow a local user to gain elevated privileges if
'htpasswd' is run setuid or a remote user to run arbitrary commands
remotely if the script is accessible through a CGI.
*** Note that Nessus solely relied on the version number
*** of the remote server to issue this warning. This might
*** be a false positive
See also : http://archives.neohapsis.com/archives/bugtraq/2004-10/0345.html
Solution : Make sure htpasswd does not run setuid and is not accessible
through any CGI scripts.
Risk factor : Medium
BID : 13777, 13778
165 |
166 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The remote web server appears to be running a version of Apache that is older
than version 1.3.32.
This version is vulnerable to a heap based buffer overflow in proxy_util.c
for mod_proxy. This issue may lead remote attackers to cause a denial of
service and possibly execute arbitrary code on the server.
Solution: Don't use mod_proxy or upgrade to a newer version.
Risk factor: Medium
CVE : CVE-2004-0492
BID : 10508
167 |
168 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The target is running an Apache web server that may not properly handle
access controls. In effect, on big-endian 64-bit platforms, Apache
fails to match allow or deny rules containing an IP address but not a
netmask.
***** Nessus has determined the vulnerability exists only by looking at
***** the Server header returned by the web server running on the target.
***** If the target is not a big-endian 64-bit platform, consider this a
***** false positive.
Additional information on the vulnerability can be found at :
- http://www.apacheweek.com/features/security-13
- http://marc.theaimsgroup.com/?l=apache-cvs&m=107869603013722
- http://nagoya.apache.org/bugzilla/show_bug.cgi?id=23850
Solution : Upgrade to Apache version 1.3.31 or newer.
Risk factor : Medium
CVE : CVE-2003-0993
BID : 9829
Other references : GLSA:GLSA 200405-22, MDKSA:MDKSA-2004:046, OpenPKG-SA:OpenPKG-SA-2004.021-apache, SSA:SSA:2004-133-01, TSLSA:TSLSA-2004-0027
169 |
170 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The remote web server appears to be running a version of
Apache that is less that 2.0.49 or 1.3.31.
These versions are vulnerable to a denial of service attack where a remote
attacker can block new connections to the server by connecting to a listening
socket on a rarely accessed port.
Solution: Upgrade to Apache 2.0.49 or 1.3.31.
CVE : CVE-2004-0174
BID : 9921
171 |
172 |
173 |
External Vulnerability Scan
The total external vulnerability score was 19 out of a maximum of 25. There were 19 medium issues, 0 high issues, 0 serious issues and 0 critical issues.
Non-compliant with section 11.2
All vulnerabilities classed Medium and higher must be remediated.
Medium: 19
High: 0
Serious: 0
Critical: 0
174 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: NOTE
The remote webserver supports the TRACE and/or TRACK methods. TRACE and TRACK
are HTTP methods which are used to debug web server connections.
It has been shown that servers supporting this method are subject
to cross-site-scripting attacks, dubbed XST for
"Cross-Site-Tracing", when used in conjunction with
various weaknesses in browsers.
An attacker may use this flaw to trick your legitimate web users to
give him their credentials.
Solution :
Add the following lines for each virtual host in your configuration file :
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE
175 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: NOTE
The remote webserver supports the TRACE and/or TRACK methods. TRACE and TRACK
are HTTP methods which are used to debug web server connections.
It has been shown that servers supporting this method are subject
to cross-site-scripting attacks, dubbed XST for
"Cross-Site-Tracing", when used in conjunction with
various weaknesses in browsers.
An attacker may use this flaw to trick your legitimate web users to
give him their credentials.
Solution :
Add the following lines for each virtual host in your configuration file :
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE
176 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: NOTE
The remote webserver supports the TRACE and/or TRACK methods. TRACE and TRACK
are HTTP methods which are used to debug web server connections.
It has been shown that servers supporting this method are subject
to cross-site-scripting attacks, dubbed XST for
"Cross-Site-Tracing", when used in conjunction with
various weaknesses in browsers.
An attacker may use this flaw to trick your legitimate web users to
give him their credentials.
Solution :
Add the following lines for each virtual host in your configuration file :
RewriteEngine on
RewriteCond %{REQUEST_METHOD} ^(TRACE
177 |
Host: 128.226.1.10
Service: ssh (22/tcp)
Type: NOTE
Remote SSH version : SSH-2.0-OpenSSH_3.4p1 Debian 1:3.4p1-1.woody.3
Remote SSH supported authentication : publickey,password,keyboard-interactive
178 |
179 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: NOTE
The remote web server type is :
Apache/1.3.26 (Unix) Debian GNU/Linux PHP/4.1.2
Solution : You can set the directive 'ServerTokens Prod' to limit
the information emanating from the server in its response headers.
180 |
181 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: NOTE
The remote web server type is :
Apache/1.3.26 Ben-SSL/1.48 (Unix) Debian GNU/Linux PHP/4.1.2
Solution : You can set the directive 'ServerTokens Prod' to limit
the information emanating from the server in its response headers.
182 |
183 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: NOTE
A web server is running on this port
184 |
185 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: NOTE
A web server is running on this port through SSL
186 |
187 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: NOTE
A SSLv2 server answered on this port
188 |
189 |
Host: 128.226.1.10
Service: ssh (22/tcp)
Type: NOTE
An ssh server is running on this port
190 |
191 |
Host: 128.226.1.10
Service: domain (53/udp)
Type: NOTE
BIND 'NAMED' is an open-source DNS server from ISC.org.
Many proprietary DNS servers are based on BIND source code.
The BIND based NAMED servers (or DNS servers) allow remote users
to query for version and type information. The query of the CHAOS
TXT record 'version.bind', will typically prompt the server to send
the information back to the querying source.
The remote bind version is : 9.2.1
Solution :
Using the 'version' directive in the 'options' section will block
the 'version.bind' query, but it will not log such attempts.
192 |
193 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: INFO
The remote host is running a version of PHP <= 4.2.2.
The mail() function does not properly sanitize user input.
This allows users to forge email to make it look like it is
coming from a different source other than the server.
Users can exploit this even if SAFE_MODE is enabled.
Solution : Contact your vendor for the latest PHP release.
Risk factor : Medium
CVE : CVE-2002-0985, CVE-2002-0986
BID : 5562
194 |
195 |
Host: 128.226.1.10
Service: www (80/tcp)
Type: INFO
The remote host is running a version of PHP <= 4.2.2.
The mail() function does not properly sanitize user input.
This allows users to forge email to make it look like it is
coming from a different source other than the server.
Users can exploit this even if SAFE_MODE is enabled.
Solution : Contact your vendor for the latest PHP release.
Risk factor : Medium
CVE : CVE-2002-0985, CVE-2002-0986
BID : 5562
196 |
197 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The remote host is running a version of PHP <= 4.2.2.
The mail() function does not properly sanitize user input.
This allows users to forge email to make it look like it is
coming from a different source other than the server.
Users can exploit this even if SAFE_MODE is enabled.
Solution : Contact your vendor for the latest PHP release.
Risk factor : Medium
CVE : CVE-2002-0985, CVE-2002-0986
BID : 5562
198 |
199 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The SSL certificate of the remote service expired Jun 29 17:02:51 2005 GMT!
200 |
201 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The remote host appears to be running Apache 1.3.33 or older.
There is a local buffer overflow in the 'htpasswd' command in these
versions that may allow a local user to gain elevated privileges if
'htpasswd' is run setuid or a remote user to run arbitrary commands
remotely if the script is accessible through a CGI.
*** Note that Nessus solely relied on the version number
*** of the remote server to issue this warning. This might
*** be a false positive
See also : http://archives.neohapsis.com/archives/bugtraq/2004-10/0345.html
Solution : Make sure htpasswd does not run setuid and is not accessible
through any CGI scripts.
Risk factor : Medium
BID : 13777, 13778
202 |
203 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The remote web server appears to be running a version of Apache that is older
than version 1.3.32.
This version is vulnerable to a heap based buffer overflow in proxy_util.c
for mod_proxy. This issue may lead remote attackers to cause a denial of
service and possibly execute arbitrary code on the server.
Solution: Don't use mod_proxy or upgrade to a newer version.
Risk factor: Medium
CVE : CVE-2004-0492
BID : 10508
204 |
205 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The target is running an Apache web server that may not properly handle
access controls. In effect, on big-endian 64-bit platforms, Apache
fails to match allow or deny rules containing an IP address but not a
netmask.
***** Nessus has determined the vulnerability exists only by looking at
***** the Server header returned by the web server running on the target.
***** If the target is not a big-endian 64-bit platform, consider this a
***** false positive.
Additional information on the vulnerability can be found at :
- http://www.apacheweek.com/features/security-13
- http://marc.theaimsgroup.com/?l=apache-cvs&m=107869603013722
- http://nagoya.apache.org/bugzilla/show_bug.cgi?id=23850
Solution : Upgrade to Apache version 1.3.31 or newer.
Risk factor : Medium
CVE : CVE-2003-0993
BID : 9829
Other references : GLSA:GLSA 200405-22, MDKSA:MDKSA-2004:046, OpenPKG-SA:OpenPKG-SA-2004.021-apache, SSA:SSA:2004-133-01, TSLSA:TSLSA-2004-0027
206 |
207 |
Host: 128.226.1.10
Service: https (443/tcp)
Type: INFO
The remote web server appears to be running a version of
Apache that is less that 2.0.49 or 1.3.31.
These versions are vulnerable to a denial of service attack where a remote
attacker can block new connections to the server by connecting to a listening
socket on a rarely accessed port.
Solution: Upgrade to Apache 2.0.49 or 1.3.31.
CVE : CVE-2004-0174
BID : 9921
208 |
209 |
210 |
Internal Firewall Scan
2 undocumented ports discovered on firewall.
Non-compliant with sections 1.1.5, 1.1.6, 1.1.7, 1.2, 1.3.2, 1.3.8
All ports open on a firewall must be thoroughly documented and controlled.
2 undocumented ports detected on the internal firewall interface.
211 |
The following undocumented open ports were detected:
212 | 22
111
213 |
External Firewall Scan
2 undocumented ports discovered on firewall.
Non-compliant with sections 1.1.5, 1.1.6, 1.1.7, 1.2, 1.3.2, 1.3.8
All ports open on a firewall must be thoroughly documented and controlled.
2 undocumented ports detected on the internal firewall interface.
214 |
The following undocumented open ports were detected:
215 | 22
111
216 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | This repository contains all manner of useful scripts targeted primarily at IT Auditors and
2 | security professionals. You will find that the scripts are in a number of languages
3 | including Powershell, Perl, Ruby and others.
4 |
5 | If you have suggestions or useful scripts that you'd like to contribute or see discussed
6 | on http://auditcasts.com, please feel free to send me a note!
7 |
--------------------------------------------------------------------------------
/Scapy/4whs.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | from scapy.all import *
3 |
4 | # My starting sequence number
5 | sequence=100
6 |
7 | # Wait for an inbound syn
8 | packets=sniff(filter="tcp[13]&0x02 != 0", count=1, iface="eth0")
9 | syn = packets[0]
10 | my_ack = syn.getlayer("TCP").seq + 1
11 | dest = syn.getlayer("IP").src
12 | sport = syn.getlayer("TCP").dport
13 | dport = syn.getlayer("TCP").sport
14 |
15 | target = IP(dst=dest)
16 | tcp_layer = TCP(sport=sport, dport=dport, ack=my_ack, seq=sequence, flags="S")
17 | response = sr1(target/tcp_layer)
18 | synack = response[0]
19 | target = IP(dst=dest)
20 | tcp_layer=TCP(sport=sport, dport=dport, ack=my_ack, seq=sequence+1, flags="A")
21 | send(target/tcp_layer)
22 |
--------------------------------------------------------------------------------
/Scapy/TBR.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | import threading
3 | from scapy.all import *
4 | import sys
5 |
6 | ones = "11111111"
7 | twos = "22222222"
8 | threes = "33333333"
9 | fours = "44444444"
10 | fives = "55555555"
11 | sixes = "66666666"
12 | checksums = []
13 | possible_payloads = { }
14 |
15 | payload = 3*ones+2*fours+1*twos+3*threes+3*sixes
16 | possible_payloads[payload] = "BSD"
17 | payload = 1*ones + 3*fours + 2*twos + 3*fives + 3*sixes
18 | possible_payloads[payload] = "BSD Right"
19 | payload = 3*ones + 2*fours + 1*twos + 3*fives + 3*sixes
20 | possible_payloads[payload] = "Linux"
21 | payload = 3*ones + 1*fours + 2*twos + 3*threes + 3*sixes
22 | possible_payloads[payload] = "First"
23 | payload = 1*ones + 4*fours + 1*twos + 3*fives + 3*sixes
24 | possible_payloads[payload] = "Last / RFC 791"
25 | payload = 3*ones + 1*fours + 1*twos + 3*threes + 3*sixes
26 | possible_payloads[payload] = "OS X"
27 |
28 | def send_packets(chk):
29 | packet1 = IP(dst=target, flags="MF", frag=0)/ICMP(type=8,code=0, chksum=chk)/(3*ones)
30 | packet2 = IP(dst=target, flags="MF", frag=4, proto=1)/(2*twos)
31 | packet3 = IP(dst=target, flags="MF", frag=6, proto=1)/(3*threes)
32 | packet4 = IP(dst=target, flags="MF", frag=1, proto=1)/(4*fours)
33 | packet5 = IP(dst=target, flags="MF", frag=6, proto=1)/(3*fives)
34 | packet6 = IP(dst=target, frag=9, proto=1)/(3*sixes)
35 | send(packet1, verbose = False)
36 | send(packet2, verbose = False)
37 | send(packet3, verbose = False)
38 | send(packet4, verbose = False)
39 | send(packet5, verbose = False)
40 | send(packet6, verbose = False)
41 |
42 | def capture_response():
43 | packets = sniff(filter=("icmp[0] = 0 and src host %s" % target), count = 1, iface = "eth0")
44 | packet = packets[0]
45 | print possible_payloads[str(packet.getlayer("ICMP").payload)]
46 |
47 | if len(sys.argv) < 2:
48 | print "You must supply a target IP address."
49 | sys.exit(1)
50 | target = sys.argv[1]
51 |
52 | for payload in possible_payloads:
53 | packet = IP(dst=target)/ICMP(type=8,code=0)/payload
54 | send(packet, verbose=False)
55 | packet = packet.__class__(str(packet))
56 | checksums.append((packet.getlayer(ICMP).chksum))
57 |
58 | # This is a fixup to the payload table because Google has a really
59 | # weird response, truncating the response.
60 | payload = 3*ones + 1*fours + 2*twos + 2*threes
61 | possible_payloads[payload] = "Google - Truncated response"
62 |
63 | thread = threading.Thread(target=capture_response)
64 | thread.start()
65 | for x in checksums:
66 | send_packets(x)
67 | thread.join()
68 |
--------------------------------------------------------------------------------
/Scapy/windos.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | from scapy.all import *
3 |
4 |
5 | def handle_packet(packet):
6 | response=IP(dst=packet[IP].src,src=packet[IP].dst)/TCP(window=5, sport=packet[TCP].dport, dport=packet[TCP].sport)
7 | payload="GET / HTTP/1.0\r\n\r\n"
8 | respond = False
9 | if(packet[TCP].flags == 0x12):
10 | response[TCP].seq = sequence + 1
11 | response[TCP].ack = packet[TCP].seq+1
12 | response[TCP].flags = "A"
13 | response = response / Raw(load=payload)
14 | respond = True
15 | if(packet[TCP].flags == 0x10 or packet[TCP].flags == 0x18):
16 | response[TCP].seq = sequence + 1 + len(payload)
17 | response[TCP].ack = packet[TCP].seq
18 | response[TCP].window=0
19 | response[TCP].flags = "A"
20 | respond = True
21 | if respond:
22 | send(response)
23 |
24 |
25 | target = "204.51.94.202"
26 | target_port = 443
27 | source = "192.168.56.130"
28 | sequence = 101010
29 |
30 | ip=IP(dst=target, src=source)
31 | tcp=TCP(flags="S", sport=2000, dport=target_port, seq=sequence)
32 | #wrpcap("/tmp/packet.pcap",Ether()/ip/tcp)
33 | send(ip/tcp)
34 |
35 | sniff(filter="tcp and dst host 192.168.56.130", prn=handle_packet)
36 |
--------------------------------------------------------------------------------
/Statistics/Calculate Samples and Errors.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dhoelzer/AuditcastsScripts/0e4dfc25d971e3a1ff9de919f65096ae4ff17a6e/Statistics/Calculate Samples and Errors.xlsx
--------------------------------------------------------------------------------
/Syslog/correctTimestamp.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/ruby
2 |
3 | require 'time'
4 |
5 | if(ARGV.length < 1 || ARGV.length > 1) then
6 | puts "You must give me a correction offset in minutes!"
7 | exit 1
8 | end
9 |
10 | correction = ARGV.first
11 | puts "Correcting by #{correction}"
12 | input = IO.new STDIN.fileno
13 | input.each_line do |line|
14 | timestamp = line[0,15]
15 | rest = line[16..-1]
16 | timestamp = Time.parse(timestamp)
17 | timestamp = timestamp + (correction.to_i * 60)
18 | puts "#{timestamp.strftime("%b %d %k:%M:%S")} #{rest}"
19 | end
20 |
--------------------------------------------------------------------------------
/Tools Reference AUD507.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dhoelzer/AuditcastsScripts/0e4dfc25d971e3a1ff9de919f65096ae4ff17a6e/Tools Reference AUD507.pdf
--------------------------------------------------------------------------------
/Useful Documents/Calculate Samples and Errors.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dhoelzer/AuditcastsScripts/0e4dfc25d971e3a1ff9de919f65096ae4ff17a6e/Useful Documents/Calculate Samples and Errors.xlsx
--------------------------------------------------------------------------------
/Wireless/find_netbios:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ -z $1 ] ; then
4 | echo "Usage: $0 capture_file"
5 | echo
6 | echo "You must provide a packet capture file as an argument!"
7 | exit 1
8 | fi
9 | strings -16 $1 | sort -u | awk '/^ [A-P]+$/ {print $1}' | perl -e "`cat netbios.pl`"
10 |
--------------------------------------------------------------------------------
/Wireless/netbios.pl:
--------------------------------------------------------------------------------
1 | #!/usr/bin/perl
2 | use feature "switch";
3 |
4 | @names = ;
5 | for $name (@names){
6 | chomp($name);
7 | @chars = split(//,$name);
8 | for($x=0;$x<32;$x+=2)
9 | {
10 | $a = $chars[$x];
11 | $b = $chars[$x+1];
12 |
13 | $a = ord($a) - ord('A');
14 | $b = ord($b) - ord('A');
15 | $character = ($a << 4) + $b;
16 | print chr($character);
17 | if($x == 30) {
18 | if ($character == 0x00) { print "\t<- Domain Name / Workstation Service / IIS";}
19 | if ($character == 0x01) { print "\t<- Master Browser / Messenger Service"; }
20 | if ($character == 0x03) { print "\t<- Messenger Service"; }
21 | if ($character == 0x06) { print "\t<- RAS Service"; }
22 | if ($character == 0x1b) { print "\t<- Domain Master Browser"; }
23 | if ($character == 0x1c) { print "\t<- Domain Controller / IIS"; }
24 | if ($character == 0x1d) { print "\t<- Master Browser"; }
25 | if ($character == 0x1e) { print "\t<- Browser Service Election Announcement"; }
26 | if ($character == 0x1f) { print "\t<- NetDDE Service"; }
27 | if ($character == 0x20) { print "\t<- File Server Service"; }
28 | if ($character == 0x21) { print "\t<- RAS Client Service"; }
29 | if ($character == 0x22) { print "\t<- Microsoft Exchange Connector"; }
30 | if ($character == 0x23) { print "\t<- Microsoft Exchange Store"; }
31 | if ($character == 0x24) { print "\t<- Microsoft Exchange Directory"; }
32 | if ($character == 0x30) { print "\t<- Modem Sharing Server Service"; }
33 | if ($character == 0x31) { print "\t<- Modem Sharing Client Service"; }
34 | if ($character == 0x43) { print "\t<- SMS Clients Remote Control"; }
35 | if ($character == 0x44) { print "\t<- SMS Clients Remote Control Tool"; }
36 | if ($character == 0x45) { print "\t<- SMS Clients Remote Chat"; }
37 | if ($character == 0x46) { print "\t<- SMS Clients Remote Transfer"; }
38 | if ($character == 0x4c) { print "\t<- DEC Pathworks"; }
39 | if ($character == 0x42) { print "\t<- Mcaffee Antivirus"; }
40 | if ($character == 0x52) { print "\t<- DEC Pathworks"; }
41 | if ($character == 0x87) { print "\t<- Microsoft Exchange MTA"; }
42 | if ($character == 0x6a) { print "\t<- Microsoft Exchange"; }
43 | if ($character == 0xbe) { print "\t<- Network Monitoring Agent"; }
44 | if ($character == 0xbf) { print "\t<- Network Monitoring Application"; }
45 | if ($character == 0x03) { print "\t<- Messenger Service"; }
46 | }
47 | }
48 | print "\n";
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/Wireless/netbios.rb:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | ARGF.each do |line|
4 | line.chomp.scan(/[A-Z][A-Z]/).each do |pair|
5 | letters = pair.split(//)
6 | print ((letters[0].ord-'A'.ord)*16 + (letters[1].ord-'A'.ord)).chr
7 | end
8 | puts
9 | end
10 |
11 |
--------------------------------------------------------------------------------
/Wireless/rfind_netbios:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | if [ -z $1 ] ; then
4 | echo "Usage: $0 capture_file"
5 | echo
6 | echo "You must provide a packet capture file as an argument!"
7 | exit 1
8 | fi
9 | strings -16 $1 | sort -u | awk '/^ [A-P]+$/ {print $1}' | ./netbios.rb
10 |
--------------------------------------------------------------------------------