dap 0.0.1 → 0.0.2

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.
@@ -0,0 +1,68 @@
1
+ require_relative '../../../data/vulndb'
2
+
3
+ module Dap
4
+ module Filter
5
+
6
+ module BaseVulnMatch
7
+ def search(hash, service)
8
+ SEARCHES[service].each do | entry |
9
+ entry[:regex].each do | regex, value |
10
+ if regex =~ hash[entry[:hash_key]].force_encoding('BINARY')
11
+ # Handle cases that could be multiple hits, not for upnp but could be others.
12
+ hash[entry[:output_key]] = ( hash[entry[:output_key]] ? hash[entry[:output_key]] + value : value )
13
+ end
14
+ end if hash[entry[:hash_key]]
15
+ end
16
+ hash
17
+ end
18
+
19
+ def lookup(hash, service)
20
+ SEARCHES[service].each do | entry |
21
+ if hash[entry[:hash_key]]
22
+ res = entry[:cvemap][hash[entry[:hash_key]]]
23
+ if res
24
+ hash[entry[:output_key]] = res
25
+ end
26
+ end
27
+ end
28
+ hash
29
+ end
30
+ end
31
+
32
+ class FilterVulnMatchUPNP
33
+ include Base
34
+ include BaseVulnMatch
35
+
36
+ def process(doc)
37
+ doc = search(doc, :upnp)
38
+ [ doc ]
39
+ end
40
+ end
41
+
42
+ class FilterVulnMatchIPMI
43
+ include Base
44
+ include BaseVulnMatch
45
+
46
+ def process(doc)
47
+ doc = search(doc, :ipmi)
48
+
49
+ if (doc['data.ipmi_user_non_null'] == "0") && (doc['data.ipmi_user_null'] == "0")
50
+ doc["vulnerability"] = ( doc["vulnerability"] ? doc["vulnerability"] + ["IPMI-ANON"] : ["IPMI-ANON"] )
51
+ end
52
+
53
+ [ doc ]
54
+ end
55
+ end
56
+
57
+ class FilterVulnMatchMSSQL
58
+ include Base
59
+ include BaseVulnMatch
60
+
61
+ def process(doc)
62
+ doc = lookup(doc, :mssql)
63
+ [ doc ]
64
+ end
65
+ end
66
+
67
+ end
68
+ end
data/lib/dap/output.rb CHANGED
@@ -1,15 +1,18 @@
1
+ require 'oj'
2
+ require 'csv'
3
+
4
+
1
5
  module Dap
2
6
  module Output
3
7
 
4
- require 'oj'
5
8
 
6
9
  module FileDestination
7
-
10
+
8
11
  attr_accessor :fd
9
12
 
10
13
  def open(file_name)
11
14
  close
12
- self.fd = ['-', 'stdout', nil].include?(file_name) ?
15
+ self.fd = ['-', 'stdout', nil].include?(file_name) ?
13
16
  $stdout : ::File.open(file_name, "wb")
14
17
  end
15
18
 
@@ -26,6 +29,33 @@ module Output
26
29
  def stop
27
30
  end
28
31
 
32
+ # String sanitizer for UTF-8
33
+ def sanitize(o)
34
+
35
+ # Handle strings
36
+ if o.kind_of? ::String
37
+ return o.to_s.encode(o.encoding, "UTF-8", :invalid => :replace, :undef => :replace, :replace => '')
38
+ end
39
+
40
+ # Handle hashes
41
+ if o.kind_of? ::Hash
42
+ r = {}
43
+ o.each_pair do |k,v|
44
+ k = sanitize(k)
45
+ v = sanitize(v)
46
+ r[k] = v
47
+ end
48
+ return r
49
+ end
50
+
51
+ # Handle arrays
52
+ if o.kind_of? ::Array
53
+ return o.map{|x| sanitize(x) }
54
+ end
55
+
56
+ # Leave as-is
57
+ o
58
+ end
29
59
  end
30
60
 
31
61
 
@@ -34,7 +64,7 @@ module Output
34
64
  # XXX: Quoted field handling is not supported, CSV should be a new output type
35
65
  #
36
66
  class OutputLines
37
-
67
+
38
68
  attr_accessor :fields, :delimiter
39
69
  FIELD_WILDCARD = '_'
40
70
 
@@ -44,7 +74,7 @@ module Output
44
74
  file = nil
45
75
  self.delimiter = ","
46
76
  self.fields = FIELD_WILDCARD
47
-
77
+
48
78
  header = false
49
79
 
50
80
  args.each do |str|
@@ -57,7 +87,7 @@ module Output
57
87
  when 'fields'
58
88
  self.fields = v.split(',')
59
89
  when 'delimiter'
60
- self.delimiter =
90
+ self.delimiter =
61
91
  case v.to_s
62
92
  when 'tab'
63
93
  "\t"
@@ -72,6 +102,7 @@ module Output
72
102
 
73
103
  if header and not fields.include?(FIELD_WILDCARD)
74
104
  self.fd.puts self.fields.join(self.delimiter)
105
+ self.fd.flush
75
106
  end
76
107
 
77
108
  end
@@ -81,17 +112,18 @@ module Output
81
112
 
82
113
  if self.fields.include?(FIELD_WILDCARD)
83
114
  doc.each_pair do |k,v|
84
- out << v.to_s
115
+ out << sanitize(v.to_s)
85
116
  end
86
117
  else
87
118
  self.fields.each do |k|
88
- out << doc[k].to_s
119
+ out << sanitize(doc[k].to_s)
89
120
  end
90
121
  end
91
122
 
92
123
  return unless out.length > 0
93
124
 
94
125
  self.fd.puts out.join(self.delimiter)
126
+ self.fd.flush
95
127
  end
96
128
 
97
129
  end
@@ -100,15 +132,83 @@ module Output
100
132
  # JSON Output (line-delimited records)
101
133
  #
102
134
  class OutputJSON
103
-
135
+
104
136
  include FileDestination
105
137
 
106
138
  def initialize(args)
107
139
  self.open(args.first)
108
140
  end
109
141
 
110
- def write_record(doc)
111
- self.fd.puts Oj.dump(doc)
142
+ def write_record(doc)
143
+ self.fd.puts Oj.dump(sanitize(doc))
144
+ self.fd.flush
145
+ end
146
+
147
+ end
148
+
149
+
150
+ #
151
+ # CSV Output
152
+ #
153
+ class OutputCSV
154
+
155
+ attr_accessor :fields, :delimiter
156
+ FIELD_WILDCARD = '_'
157
+
158
+ include FileDestination
159
+
160
+ def initialize(args)
161
+ file = nil
162
+ self.delimiter = ","
163
+ self.fields = FIELD_WILDCARD
164
+
165
+ header = false
166
+
167
+ args.each do |str|
168
+ k,v = str.split('=', 2)
169
+ case k
170
+ when 'file'
171
+ file = v
172
+ when 'header'
173
+ header = ( v =~ /^[ty1]/i ? true : false )
174
+ when 'fields'
175
+ self.fields = v.split(',')
176
+ when 'delimiter'
177
+ self.delimiter =
178
+ case v.to_s
179
+ when 'tab'
180
+ "\t"
181
+ when 'null'
182
+ "\x00"
183
+ else
184
+ v
185
+ end
186
+ end
187
+ end
188
+ self.open(file)
189
+
190
+ if header and not fields.include?(FIELD_WILDCARD)
191
+ self.fd.puts self.fields.to_csv
192
+ end
193
+
194
+ end
195
+
196
+ def write_record(doc)
197
+ out = []
198
+
199
+ if self.fields.include?(FIELD_WILDCARD)
200
+ doc.each_pair do |k,v|
201
+ out << sanitize(v.to_s)
202
+ end
203
+ else
204
+ self.fields.each do |k|
205
+ out << sanitize(doc[k].to_s)
206
+ end
207
+ end
208
+
209
+ return unless out.length > 0
210
+
211
+ self.fd.puts out.to_csv
112
212
  end
113
213
 
114
214
  end
@@ -0,0 +1,114 @@
1
+ # -*- coding: binary -*-
2
+ module Dap
3
+ module Proto
4
+ module MSSQL
5
+
6
+ #
7
+ # Data condensed from http://sqlserverbuilds.blogspot.com/
8
+ # Given a version like 8.00.2039, this data structure allows
9
+ # us to determine that the year version is 2000 sp4.
10
+ # The version_num_to_name method implements this conversion.
11
+ #
12
+ MSSQL_VERSIONS = {
13
+ '7.00'=> {
14
+ :year=>'7.0',
15
+ :service_packs=> {
16
+ 623=>'-',
17
+ 699=>'sp1',
18
+ 842=>'sp2',
19
+ 961=>'sp3',
20
+ 1063=>'sp4'
21
+ }
22
+ },
23
+ '8.00'=> {
24
+ :year=>'2000',
25
+ :service_packs=> {
26
+ 194=>'-',
27
+ 384=>'sp1',
28
+ 534=>'sp2',
29
+ 760=>'sp3',
30
+ 2039=>'sp4'
31
+ }
32
+ },
33
+ '9.00'=> {
34
+ :year=>'2005',
35
+ :service_packs=> {
36
+ 1399=>'-',
37
+ 2047=>'sp1',
38
+ 3042=>'sp2',
39
+ 4035=>'sp3',
40
+ 5000=>'sp4'
41
+ }
42
+ },
43
+ '10.00'=> {
44
+ :year=>'2008',
45
+ :service_packs=> {
46
+ 1600=>'-',
47
+ 2531=>'sp1',
48
+ 4000=>'sp2',
49
+ 5500=>'sp3'
50
+ }
51
+ },
52
+ '10.50'=> {
53
+ :year=>'2008',
54
+ :service_packs=> {
55
+ 1600=>'r2',
56
+ 2500=>'r2 sp1',
57
+ 4000=>'r2 sp2'
58
+ }
59
+ },
60
+ '11.00'=> {
61
+ :year=>'2012',
62
+ :service_packs=> {
63
+ 2100=>'-',
64
+ 3000=>'sp1'
65
+ }
66
+ },
67
+ '12.00'=> {
68
+ :year=>'2014',
69
+ :service_packs=> {
70
+ 2000=>'-'
71
+ }
72
+ }
73
+ }
74
+
75
+ #
76
+ # Given a XX.YY.ZZ[.AA] version, will attempt to get the sql server
77
+ # year/service pack version for it.
78
+ def self.version_num_to_name(version)
79
+ rx = /(\d+)\.(\d+)\.(\d+).*/
80
+ if version =~ rx
81
+ v1 = $1.to_i
82
+ v2 = $2.to_i
83
+ v3 = $3.to_i
84
+ else
85
+ return [ nil, nil ]
86
+ end
87
+ #puts("v1=#{v1}, v2=#{v2}, v3=#{v3}")
88
+ key = sprintf("%d.%02d",v1,v2)
89
+ svc_pack = nil
90
+ year = nil
91
+ if MSSQL_VERSIONS[key]
92
+ year = MSSQL_VERSIONS[key][:year]
93
+ svc_packs = MSSQL_VERSIONS[key][:service_packs]
94
+ is_first=true
95
+ svc_packs.each do | k, v|
96
+ #puts( "k=#{k}, v=#{v}")
97
+ if v3 <= k and is_first
98
+ svc_pack = v
99
+ break
100
+ elsif v3 == k
101
+ svc_pack = v
102
+ break
103
+ else
104
+ svc_pack = v
105
+ end
106
+ is_first=false
107
+ end
108
+ end
109
+ [ year, svc_pack]
110
+ end
111
+
112
+ end
113
+ end
114
+ end
data/lib/dap/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Dap
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -7,10 +7,10 @@ module IPMI
7
7
 
8
8
  describe Channel_Auth_Reply do
9
9
  it "valid with the proper rmcp version and message length" do
10
- expect(subject.valid?).to be_false
11
- expect(Channel_Auth_Reply.new(rmcp_version: 6).valid?).to be_false
12
- expect(Channel_Auth_Reply.new(message_length: 16).valid?).to be_false
13
- expect(Channel_Auth_Reply.new(rmcp_version: 6, message_length: 16).valid?).to be_true
10
+ expect(subject.valid?).to be false
11
+ expect(Channel_Auth_Reply.new(rmcp_version: 6).valid?).to be false
12
+ expect(Channel_Auth_Reply.new(message_length: 16).valid?).to be false
13
+ expect(Channel_Auth_Reply.new(rmcp_version: 6, message_length: 16).valid?).to be true
14
14
  end
15
15
  end
16
16
 
@@ -16,10 +16,18 @@ class GeoIPSummary
16
16
  @tree['count'] = 0
17
17
  end
18
18
 
19
+ def stringify(o)
20
+ if o.kind_of?( ::String )
21
+ o.to_s.encode(o.encoding, "UTF-8", :invalid => :replace, :undef => :replace, :replace => '')
22
+ else
23
+ o.to_s
24
+ end
25
+ end
26
+
19
27
  def process_hash( json_hash )
20
- country = json_hash[@country_name]
21
- region = json_hash[@region_name] || 'Undefined Region'
22
- city = json_hash[@city_name] || 'Undefined City'
28
+ country = stringify( json_hash[@country_name] )
29
+ region = stringify( json_hash[@region_name] || 'Undefined Region' )
30
+ city = stringify( json_hash[@city_name] || 'Undefined City' )
23
31
 
24
32
  # Create subhashes and values as needed on down the tree
25
33
  @tree[country] ||= {}
@@ -123,7 +131,7 @@ def parse_command_line(args)
123
131
  opts.on('--var top-level-var', 'Sets the top level json name, for defining all of country/region/city') do | val |
124
132
  options[:var] = val
125
133
  options[:country] = "#{val}.country_name"
126
- options[:region] = "#{val}.region"
134
+ options[:region] = "#{val}.region_name"
127
135
  options[:city] = "#{val}.city"
128
136
  end
129
137
 
@@ -136,14 +144,20 @@ def parse_command_line(args)
136
144
  end
137
145
  options
138
146
  end
139
- opts = parse_command_line(ARGV)
140
- raise 'Need json key names for country,region and city.' if opts[:country].nil? || opts[:region].nil? || opts[:city].nil?
147
+ opts = parse_command_line(ARGV)
141
148
 
142
- summarizer = GeoIPSummary.new(opts[:country], opts[:region], opts[:city])
143
- while line=gets
144
- summarizer.process_hash(Oj.load(line.strip))
145
- end
146
149
 
147
- Oj.default_options={:indent=>2}
150
+ raise 'Need json key names for country,region and city.' if opts[:country].nil? || opts[:region].nil? || opts[:city].nil?
151
+
152
+ summarizer = GeoIPSummary.new(opts[:country], opts[:region], opts[:city])
153
+
154
+
155
+ $stdin.each_line do |line|
156
+ json = Oj.load(line.unpack("C*").pack("C*").strip) rescue nil
157
+ next unless json
158
+ summarizer.process_hash(json)
159
+ end
160
+
161
+ Oj.default_options={:indent=>2}
148
162
 
149
- puts Oj.dump(summarizer.order_tree)
163
+ puts Oj.dump(summarizer.order_tree)