├── 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:

    ".$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 |
Cyber-Defense PCI Scoring Tool
984 |
985 |

Report Sections

986 |

Overall Score: $score

987 | $Compliant 988 |

Toggle details

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 |
    Cyber-Defense PCI Scoring Tool
    114 |
    115 |

    Report Sections

    116 |

    Overall Score: 48

    117 |

    Non-Compliant

    118 |

    Toggle details

    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 | --------------------------------------------------------------------------------