dap 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +6 -0
- data/.rspec +2 -0
- data/Gemfile +15 -0
- data/Gemfile.lock +55 -0
- data/LICENSE +20 -0
- data/README.md +15 -0
- data/bin/dap +137 -0
- data/dap.gemspec +42 -0
- data/data/.gitkeep +0 -0
- data/lib/dap.rb +101 -0
- data/lib/dap/filter.rb +8 -0
- data/lib/dap/filter/base.rb +37 -0
- data/lib/dap/filter/geoip.rb +72 -0
- data/lib/dap/filter/http.rb +173 -0
- data/lib/dap/filter/names.rb +151 -0
- data/lib/dap/filter/openssl.rb +53 -0
- data/lib/dap/filter/recog.rb +23 -0
- data/lib/dap/filter/simple.rb +340 -0
- data/lib/dap/filter/udp.rb +401 -0
- data/lib/dap/input.rb +74 -0
- data/lib/dap/input/csv.rb +60 -0
- data/lib/dap/input/warc.rb +81 -0
- data/lib/dap/output.rb +117 -0
- data/lib/dap/proto/addp.rb +0 -0
- data/lib/dap/proto/dtls.rb +21 -0
- data/lib/dap/proto/ipmi.rb +94 -0
- data/lib/dap/proto/natpmp.rb +19 -0
- data/lib/dap/proto/wdbrpc.rb +58 -0
- data/lib/dap/utils/oui.rb +16586 -0
- data/lib/dap/version.rb +3 -0
- data/samples/http_get_reply.ic12.bz2 +0 -0
- data/samples/http_get_reply.ic12.sh +1 -0
- data/samples/http_get_reply_iframes.json.bz2 +0 -0
- data/samples/http_get_reply_iframes.json.sh +1 -0
- data/samples/http_get_reply_links.json.sh +1 -0
- data/samples/iawide.warc.bz2 +0 -0
- data/samples/iawide_warc.sh +1 -0
- data/samples/ipmi_chan_auth_replies.crd.bz2 +0 -0
- data/samples/ipmi_chan_auth_replies.sh +1 -0
- data/samples/ssl_certs.bz2 +0 -0
- data/samples/ssl_certs_geo.sh +1 -0
- data/samples/ssl_certs_names.sh +1 -0
- data/samples/ssl_certs_names_expanded.sh +1 -0
- data/samples/ssl_certs_org.sh +1 -0
- data/samples/udp-netbios.csv.bz2 +0 -0
- data/samples/udp-netbios.sh +1 -0
- data/spec/dap/proto/ipmi_spec.rb +19 -0
- data/tools/geo-ip-summary.rb +149 -0
- data/tools/ipmi-vulns.rb +27 -0
- data/tools/json-summarize.rb +81 -0
- data/tools/netbios-counts.rb +271 -0
- data/tools/upnp-vulns.rb +35 -0
- data/tools/value-counts-to-md-table.rb +23 -0
- metadata +264 -0
data/lib/dap/input.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
module Dap
|
2
|
+
module Input
|
3
|
+
|
4
|
+
require 'oj'
|
5
|
+
|
6
|
+
#
|
7
|
+
# Error codes for failed reads
|
8
|
+
#
|
9
|
+
module Error
|
10
|
+
EOF = :eof
|
11
|
+
Empty = :empty
|
12
|
+
end
|
13
|
+
|
14
|
+
module FileSource
|
15
|
+
|
16
|
+
attr_accessor :fd
|
17
|
+
|
18
|
+
def open(file_name)
|
19
|
+
close
|
20
|
+
self.fd = ['-', 'stdin', nil].include?(file_name) ?
|
21
|
+
$stdin : ::File.open(file_name, "rb")
|
22
|
+
end
|
23
|
+
|
24
|
+
def close
|
25
|
+
self.close if self.fd
|
26
|
+
self.fd = nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Line Input
|
32
|
+
#
|
33
|
+
class InputLines
|
34
|
+
|
35
|
+
include FileSource
|
36
|
+
|
37
|
+
def initialize(args)
|
38
|
+
self.open(args.first)
|
39
|
+
end
|
40
|
+
|
41
|
+
def read_record
|
42
|
+
line = self.fd.readline rescue nil
|
43
|
+
return Error::EOF unless line
|
44
|
+
{ 'line' => line.chomp("\n") }
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# JSON Input (line-delimited records)
|
51
|
+
#
|
52
|
+
class InputJSON
|
53
|
+
|
54
|
+
include FileSource
|
55
|
+
|
56
|
+
def initialize(args)
|
57
|
+
self.open(args.first)
|
58
|
+
end
|
59
|
+
|
60
|
+
def read_record
|
61
|
+
line = self.fd.readline rescue nil
|
62
|
+
return Error::EOF unless line
|
63
|
+
json = Oj.load(line.strip) rescue nil
|
64
|
+
return Error::Empty unless json
|
65
|
+
json
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
require 'dap/input/warc'
|
74
|
+
require 'dap/input/csv'
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Dap
|
2
|
+
module Input
|
3
|
+
|
4
|
+
require 'csv'
|
5
|
+
|
6
|
+
#
|
7
|
+
# CSV
|
8
|
+
#
|
9
|
+
class InputCSV
|
10
|
+
|
11
|
+
include FileSource
|
12
|
+
|
13
|
+
attr_accessor :has_header, :headers
|
14
|
+
|
15
|
+
def initialize(args)
|
16
|
+
self.headers = []
|
17
|
+
|
18
|
+
fname = args.shift
|
19
|
+
self.open(fname)
|
20
|
+
|
21
|
+
args.each do |arg|
|
22
|
+
if arg =~ /^header=(.*)/
|
23
|
+
val =$1
|
24
|
+
self.has_header = !! (val =~ /^y|t|1/i)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
if self.has_header
|
29
|
+
data = read_record
|
30
|
+
unless (data == :eof or data == :empty)
|
31
|
+
self.headers = data.values.map{|x| x.to_s.strip }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def read_record
|
37
|
+
res = {}
|
38
|
+
line = self.fd.readline rescue nil
|
39
|
+
return Error::EOF unless line
|
40
|
+
|
41
|
+
# Short-circuit the slow CSV parser if the data does not contain double quotes
|
42
|
+
arr = line.index('"') ?
|
43
|
+
( CSV.parse(line) rescue nil ) :
|
44
|
+
[ line.split(',').map{|x| x.strip } ]
|
45
|
+
|
46
|
+
return Error::Empty unless arr
|
47
|
+
cnt = 0
|
48
|
+
arr.first.each do |x|
|
49
|
+
cnt += 1
|
50
|
+
if x.to_s.length > 0
|
51
|
+
res[headers[cnt-1] || cnt.to_s] = x
|
52
|
+
end
|
53
|
+
end
|
54
|
+
res
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Dap
|
2
|
+
module Input
|
3
|
+
|
4
|
+
#
|
5
|
+
# WARC
|
6
|
+
#
|
7
|
+
class InputWARC
|
8
|
+
|
9
|
+
include FileSource
|
10
|
+
|
11
|
+
attr_accessor :header, :info
|
12
|
+
|
13
|
+
def initialize(args)
|
14
|
+
self.open(args.first)
|
15
|
+
read_warc_header
|
16
|
+
end
|
17
|
+
|
18
|
+
def read_warc_header
|
19
|
+
self.header = read_record
|
20
|
+
|
21
|
+
if self.header == Error::EOF
|
22
|
+
raise RuntimeError, "Invalid WARC header"
|
23
|
+
end
|
24
|
+
|
25
|
+
unless self.header['warc_type'].to_s == "warcinfo"
|
26
|
+
raise RuntimeError, "Invalid WARC header (missing warcinfo)"
|
27
|
+
end
|
28
|
+
|
29
|
+
self.info = {}
|
30
|
+
self.header['content'].to_s.split("\n").each do |line|
|
31
|
+
k, v = line.strip.split(/\s*:\s*/, 2)
|
32
|
+
next unless v
|
33
|
+
self.info[k] = v
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def read_record
|
38
|
+
begin
|
39
|
+
|
40
|
+
version = self.fd.readline
|
41
|
+
unless version and version =~ /^WARC\/\d+\.\d+/
|
42
|
+
return Error::EOF
|
43
|
+
end
|
44
|
+
warc = {}
|
45
|
+
|
46
|
+
loop do
|
47
|
+
line = self.fd.readline
|
48
|
+
|
49
|
+
unless line.strip.length == 0
|
50
|
+
k, v = line.strip.split(/\s*:\s*/, 2)
|
51
|
+
k = k.downcase.gsub('-', '_')
|
52
|
+
warc[k] = v.to_s
|
53
|
+
next
|
54
|
+
end
|
55
|
+
|
56
|
+
unless warc['content_length']
|
57
|
+
return Error::EOF
|
58
|
+
end
|
59
|
+
|
60
|
+
warc['content'] = self.fd.read(warc['content_length'].to_i)
|
61
|
+
skip = self.fd.readline
|
62
|
+
skip = self.fd.readline
|
63
|
+
|
64
|
+
unless skip.strip.length == 0
|
65
|
+
return Error::EOF
|
66
|
+
end
|
67
|
+
|
68
|
+
break
|
69
|
+
end
|
70
|
+
|
71
|
+
return warc
|
72
|
+
|
73
|
+
rescue ::EOFError
|
74
|
+
return Error::EOF
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
data/lib/dap/output.rb
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
module Dap
|
2
|
+
module Output
|
3
|
+
|
4
|
+
require 'oj'
|
5
|
+
|
6
|
+
module FileDestination
|
7
|
+
|
8
|
+
attr_accessor :fd
|
9
|
+
|
10
|
+
def open(file_name)
|
11
|
+
close
|
12
|
+
self.fd = ['-', 'stdout', nil].include?(file_name) ?
|
13
|
+
$stdout : ::File.open(file_name, "wb")
|
14
|
+
end
|
15
|
+
|
16
|
+
def close
|
17
|
+
self.close if self.fd
|
18
|
+
self.fd = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Overload this to add headers
|
22
|
+
def start
|
23
|
+
end
|
24
|
+
|
25
|
+
# Overload this to add footers
|
26
|
+
def stop
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
#
|
33
|
+
# Line Output (CSV, TSV, etc)
|
34
|
+
# XXX: Quoted field handling is not supported, CSV should be a new output type
|
35
|
+
#
|
36
|
+
class OutputLines
|
37
|
+
|
38
|
+
attr_accessor :fields, :delimiter
|
39
|
+
FIELD_WILDCARD = '_'
|
40
|
+
|
41
|
+
include FileDestination
|
42
|
+
|
43
|
+
def initialize(args)
|
44
|
+
file = nil
|
45
|
+
self.delimiter = ","
|
46
|
+
self.fields = FIELD_WILDCARD
|
47
|
+
|
48
|
+
header = false
|
49
|
+
|
50
|
+
args.each do |str|
|
51
|
+
k,v = str.split('=', 2)
|
52
|
+
case k
|
53
|
+
when 'file'
|
54
|
+
file = v
|
55
|
+
when 'header'
|
56
|
+
header = ( v =~ /^[ty1]/i ? true : false )
|
57
|
+
when 'fields'
|
58
|
+
self.fields = v.split(',')
|
59
|
+
when 'delimiter'
|
60
|
+
self.delimiter =
|
61
|
+
case v.to_s
|
62
|
+
when 'tab'
|
63
|
+
"\t"
|
64
|
+
when 'null'
|
65
|
+
"\x00"
|
66
|
+
else
|
67
|
+
v
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
self.open(file)
|
72
|
+
|
73
|
+
if header and not fields.include?(FIELD_WILDCARD)
|
74
|
+
self.fd.puts self.fields.join(self.delimiter)
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
def write_record(doc)
|
80
|
+
out = []
|
81
|
+
|
82
|
+
if self.fields.include?(FIELD_WILDCARD)
|
83
|
+
doc.each_pair do |k,v|
|
84
|
+
out << v.to_s
|
85
|
+
end
|
86
|
+
else
|
87
|
+
self.fields.each do |k|
|
88
|
+
out << doc[k].to_s
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
return unless out.length > 0
|
93
|
+
|
94
|
+
self.fd.puts out.join(self.delimiter)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# JSON Output (line-delimited records)
|
101
|
+
#
|
102
|
+
class OutputJSON
|
103
|
+
|
104
|
+
include FileDestination
|
105
|
+
|
106
|
+
def initialize(args)
|
107
|
+
self.open(args.first)
|
108
|
+
end
|
109
|
+
|
110
|
+
def write_record(doc)
|
111
|
+
self.fd.puts Oj.dump(doc)
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
module Dap
|
3
|
+
module Proto
|
4
|
+
module DTLS
|
5
|
+
|
6
|
+
|
7
|
+
class RecordLayer < BitStruct
|
8
|
+
unsigned :content_type, 8, 'Content type'
|
9
|
+
unsigned :version, 16, 'Version'
|
10
|
+
unsigned :epoch, 16, 'Epoch'
|
11
|
+
unsigned :sequence, 48, 'Sequence number'
|
12
|
+
unsigned :payload_length, 16, 'Payload length'
|
13
|
+
rest :payload
|
14
|
+
|
15
|
+
def valid?
|
16
|
+
payload_length == payload.length
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# -*- coding: binary -*-
|
2
|
+
module Dap
|
3
|
+
module Proto
|
4
|
+
module IPMI
|
5
|
+
|
6
|
+
class Channel_Auth_Reply < BitStruct
|
7
|
+
|
8
|
+
unsigned :rmcp_version, 8, "RMCP Version"
|
9
|
+
unsigned :rmcp_padding, 8, "RMCP Padding"
|
10
|
+
unsigned :rmcp_sequence, 8, "RMCP Sequence"
|
11
|
+
unsigned :rmcp_mtype, 1, "RMCP Message Type"
|
12
|
+
unsigned :rmcp_class, 7, "RMCP Message Class"
|
13
|
+
|
14
|
+
unsigned :session_auth_type, 8, "Session Auth Type"
|
15
|
+
unsigned :session_sequence, 32, "Session Sequence Number"
|
16
|
+
unsigned :session_id, 32, "Session ID"
|
17
|
+
unsigned :message_length, 8, "Message Length"
|
18
|
+
|
19
|
+
unsigned :ipmi_tgt_address, 8, "IPMI Target Address"
|
20
|
+
unsigned :ipmi_tgt_lun, 8, "IPMI Target LUN"
|
21
|
+
unsigned :ipmi_header_checksum, 8, "IPMI Header Checksum"
|
22
|
+
unsigned :ipmi_src_address, 8, "IPMI Source Address"
|
23
|
+
unsigned :ipmi_src_lun, 8, "IPMI Source LUN"
|
24
|
+
unsigned :ipmi_command, 8, "IPMI Command"
|
25
|
+
unsigned :ipmi_completion_code, 8, "IPMI Completion Code"
|
26
|
+
|
27
|
+
unsigned :ipmi_channel, 8, "IPMI Channel"
|
28
|
+
|
29
|
+
unsigned :ipmi_compat_20, 1, "IPMI Version Compatibility: IPMI 2.0+"
|
30
|
+
unsigned :ipmi_compat_reserved1, 1, "IPMI Version Compatibility: Reserved 1"
|
31
|
+
unsigned :ipmi_compat_oem_auth, 1, "IPMI Version Compatibility: OEM Authentication"
|
32
|
+
unsigned :ipmi_compat_password, 1, "IPMI Version Compatibility: Straight Password"
|
33
|
+
unsigned :ipmi_compat_reserved2, 1, "IPMI Version Compatibility: Reserved 2"
|
34
|
+
unsigned :ipmi_compat_md5, 1, "IPMI Version Compatibility: MD5"
|
35
|
+
unsigned :ipmi_compat_md2, 1, "IPMI Version Compatibility: MD2"
|
36
|
+
unsigned :ipmi_compat_none, 1, "IPMI Version Compatibility: None"
|
37
|
+
|
38
|
+
unsigned :ipmi_user_reserved1, 2, "IPMI User Compatibility: Reserved 1"
|
39
|
+
unsigned :ipmi_user_kg, 1, "IPMI User Compatibility: KG Set to Default"
|
40
|
+
unsigned :ipmi_user_disable_message_auth, 1, "IPMI User Compatibility: Disable Per-Message Authentication"
|
41
|
+
unsigned :ipmi_user_disable_user_auth, 1, "IPMI User Compatibility: Disable User-Level Authentication"
|
42
|
+
unsigned :ipmi_user_non_null, 1, "IPMI User Compatibility: Non-Null Usernames Enabled"
|
43
|
+
unsigned :ipmi_user_null, 1, "IPMI User Compatibility: Null Usernames Enabled"
|
44
|
+
unsigned :ipmi_user_anonymous, 1, "IPMI User Compatibility: Anonymous Login Enabled"
|
45
|
+
|
46
|
+
unsigned :ipmi_conn_reserved1, 6, "IPMI Connection Compatibility: Reserved 1"
|
47
|
+
unsigned :ipmi_conn_20, 1, "IPMI Connection Compatibility: 2.0"
|
48
|
+
unsigned :ipmi_conn_15, 1, "IPMI Connection Compatibility: 1.5"
|
49
|
+
|
50
|
+
unsigned :ipmi_oem_id, 24, "IPMI OEM ID", :endian => 'little'
|
51
|
+
|
52
|
+
rest :ipm_oem_data, "IPMI OEM Data + Checksum Byte"
|
53
|
+
|
54
|
+
|
55
|
+
def valid?
|
56
|
+
(rmcp_version == 6) && (message_length == 16)
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_banner
|
60
|
+
info = self
|
61
|
+
banner = "#{(info.ipmi_compat_20 == 1) ? "IPMI-2.0" : "IPMI-1.5"} "
|
62
|
+
|
63
|
+
pass_info = []
|
64
|
+
pass_info << "oem_auth" if info.ipmi_compat_oem_auth == 1
|
65
|
+
pass_info << "password" if info.ipmi_compat_password == 1
|
66
|
+
pass_info << "md5" if info.ipmi_compat_md5 == 1
|
67
|
+
pass_info << "md2" if info.ipmi_compat_md2 == 1
|
68
|
+
pass_info << "null" if info.ipmi_compat_none == 1
|
69
|
+
|
70
|
+
user_info = []
|
71
|
+
user_info << "kg_default" if (info.ipmi_compat_20 == 1 and info.ipmi_user_kg == 1)
|
72
|
+
user_info << "auth_msg" unless info.ipmi_user_disable_message_auth == 1
|
73
|
+
user_info << "auth_user" unless info.ipmi_user_disable_user_auth == 1
|
74
|
+
user_info << "non_null_user" if info.ipmi_user_non_null == 1
|
75
|
+
user_info << "null_user" if info.ipmi_user_null == 1
|
76
|
+
user_info << "anonymous_user" if info.ipmi_user_anonymous == 1
|
77
|
+
|
78
|
+
conn_info = []
|
79
|
+
conn_info << "1.5" if info.ipmi_conn_15 == 1
|
80
|
+
conn_info << "2.0" if info.ipmi_conn_20 == 1
|
81
|
+
|
82
|
+
if info.ipmi_oem_id != 0
|
83
|
+
banner << "OEMID:#{info.ipmi_oem_id} "
|
84
|
+
end
|
85
|
+
|
86
|
+
banner << "UserAuth(#{user_info.join(", ")}) PassAuth(#{pass_info.join(", ")}) Level(#{conn_info.join(", ")}) "
|
87
|
+
banner
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|