intrigue-ident 0.1 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b379c724034923eb05671859aaaaa17ad8ee2be348bdf4c272c428c16121d3fb
4
- data.tar.gz: 138245f1078a14b88fa1651fbd61fa8be202c7bc92fe13a9cae90abf91934415
3
+ metadata.gz: 1d05d96fbb44b3e9ea2ed428a0c63873fcfe5679a74882faa3534051ffe51338
4
+ data.tar.gz: 56e52215528ae59c96cdeb9a832ea2e9a7655a607da986499dc714b9a90fa74d
5
5
  SHA512:
6
- metadata.gz: e7330591c145a0357ca6ded382d1407bff366fab69146f1cf73b8f1cb9aab1e8fca6c3798c7d462753405870def4d115f524f11a0cf022b4ee57eb82898d7c3a
7
- data.tar.gz: 55d7000e202d10a0fb7ce64d34f12163ef73d4caf244ddab04c5d1add173e1db3caba6b5e3ada16bc9b875e74dfc096c0485e53bf60184ca11574f0f75bcf9f5
6
+ metadata.gz: 17b3fe532217c204bd8ac15f42e395268ea010f409f9b37d623d115f4fa24b5a245b77a0b79e9fd5d1a76fd9558443ad13280245d15e012e3f0180f23e6f4b47
7
+ data.tar.gz: 664d65996160c1ce2ab55569e76b9342f4574a34a6e2aec92f20810590f31056ec568191b14828a35f6745892f6820e24ab863fff50a62b44aae3ad1e8e794ae
data/Gemfile CHANGED
@@ -2,3 +2,4 @@ source 'https://rubygems.org'
2
2
  ruby '2.5.1'
3
3
 
4
4
  gem "rspec"
5
+ gem "pry"
data/Gemfile.lock CHANGED
@@ -1,7 +1,12 @@
1
1
  GEM
2
2
  remote: https://rubygems.org/
3
3
  specs:
4
+ coderay (1.1.2)
4
5
  diff-lcs (1.3)
6
+ method_source (0.9.0)
7
+ pry (0.11.3)
8
+ coderay (~> 1.1.0)
9
+ method_source (~> 0.9.0)
5
10
  rspec (3.7.0)
6
11
  rspec-core (~> 3.7.0)
7
12
  rspec-expectations (~> 3.7.0)
@@ -20,6 +25,7 @@ PLATFORMS
20
25
  ruby
21
26
 
22
27
  DEPENDENCIES
28
+ pry
23
29
  rspec
24
30
 
25
31
  RUBY VERSION
data/ident.rb CHANGED
@@ -11,7 +11,7 @@ Dir["#{check_folder}/*.rb"].each { |file| require_relative file }
11
11
  module Intrigue
12
12
  module Ident
13
13
 
14
- VERSION=0.1
14
+ VERSION=0.2
15
15
 
16
16
  def generate_requests_and_check(url)
17
17
 
@@ -42,7 +42,7 @@ module Intrigue
42
42
  if response
43
43
  # call each check, collecting the product if it's a match
44
44
  ggc.last.each do |check|
45
- results << _check_response(check, response)
45
+ results << _match_http_response(check, response)
46
46
  end
47
47
  end
48
48
  end
@@ -53,54 +53,107 @@ module Intrigue
53
53
 
54
54
  private
55
55
 
56
- # this method takes a check and returns a ~match object if it matches, otherwise
57
- # returns nil.
58
- def _check_response(check, response)
59
-
60
- # if type "content", do the content check
61
- if check[:type] == :content_body
62
- match = {
63
- :version => (check[:dynamic_version].call(response) if check[:dynamic_version]) || check[:version],
64
- :name => check[:name],
65
- :match => check[:type],
66
- :hide => check[:hide]
67
- } if "#{response.body}" =~ check[:content]
56
+ def _construct_match_response(check, data)
57
+ {
58
+ :version => (check[:dynamic_version].call(data) if check[:dynamic_version]) || check[:version],
59
+ :name => check[:name],
60
+ :tags => check[:tags],
61
+ :match => check[:type],
62
+ :hide => check[:hide]
63
+ }
64
+ end
68
65
 
69
- elsif check[:type] == :content_headers
66
+ def _match_uri(check,data)
70
67
 
71
- # construct the headers into a big string block
72
- header_string = ""
73
- response.each_header do |h,v|
74
- header_string << "#{h}: #{v}\n"
75
- end
68
+ # data[:body] => page body
69
+ # data[:headers] => block of text with headers, one per line
70
+ # data[:cookies] => set_cookie header
71
+ # data[:body_md5] => md5 hash of the body
72
+ # if type "content", do the content check
76
73
 
77
- match = {
78
- :version => (check[:dynamic_version].call(response) if check[:dynamic_version]) || check[:version],
79
- :name => check[:name],
80
- :match => check[:type],
81
- :hide => check[:hide]
82
- } if header_string =~ check[:content]
83
74
 
75
+ if check[:type] == :content_body
76
+ match = _construct_match_response(check,data) if data["details"]["hidden_response_data"] =~ check[:content]
77
+ elsif check[:type] == :content_headers
78
+ match = _construct_match_response(check,data) if data["details"]["headers"].join("\n") =~ check[:content]
84
79
  elsif check[:type] == :content_cookies
85
80
  # Check only the set-cookie header
86
- match = {
87
- :version => (check[:dynamic_version].call(response) if check[:dynamic_version]) || check[:version],
88
- :name => check[:name],
89
- :match => check[:type],
90
- :hide => check[:hide]
91
- } if response.header['set-cookie'] =~ check[:content]
92
-
81
+ match = _construct_match_response(check,data) if data["details"]["cookies"] =~ check[:content]
93
82
  elsif check[:type] == :checksum_body
94
- match = {
95
- :version => (check[:dynamic_version].call(response) if check[:dynamic_version]) || check[:version],
96
- :name => check[:name],
97
- :match => check[:type],
98
- :hide => check[:hide]
99
- } if Digest::MD5.hexdigest("#{response.body}") == check[:checksum]
83
+ match = _construct_match_response(check,data) if Digest::MD5.hexdigest(data["details"]["response_data_hash"]) == check[:checksum]
100
84
  end
85
+
101
86
  match
102
87
  end
103
88
 
89
+ # this method takes a check and a net/http response object and
90
+ # constructs it into a format that's matchable. it then attempts
91
+ # to match, and returns a match object if it matches, otherwise
92
+ # returns nil.
93
+ def _match_http_response(check, response)
94
+
95
+ # Construct an Intrigue Entity of type Uri so we can match it
96
+ data = []
97
+ =begin
98
+ json = '{
99
+ "id": 1572,
100
+ "type": "Intrigue::Entity::Uri",
101
+ "name": "http://69.162.37.69:80",
102
+ "deleted": false,
103
+ "hidden": false,
104
+ "detail_string": "Server: | App: | Title: Index page",
105
+ "details": {
106
+ "uri": "http://69.162.37.69:80",
107
+ "code": "200",
108
+ "port": 80,
109
+ "forms": false,
110
+ "title": "Index page",
111
+ "verbs": null,
112
+ "headers": ["content-length: 701", "last-modified: Tue, 03 Jul 2018 16:55:36 GMT", "cache-control: no-cache", "content-type: text/html"],
113
+ "host_id": 1571,
114
+ "scripts": [],
115
+ "products": [],
116
+ "protocol": "tcp",
117
+ "ip_address": "69.162.37.69",
118
+ "javascript": [],
119
+ "fingerprint": [],
120
+ "api_endpoint": false,
121
+ "masscan_string": "sudo masscan -p80,443,2004,3389,7001,8000,8080,8081,8443,U:161,U:500 --max-rate 10000 -oL /tmp/masscan20180703-9816-18n0ri --range 69.162.0.0/18",
122
+ "app_fingerprint": [],
123
+ "hidden_original": "http://69.162.37.69:80",
124
+ "response_data_hash": "7o0r6ie5DOrJJnz1sS7RGO4XWsNn3hWykbwGkGnySWU=",
125
+ "server_fingerprint": [],
126
+ "enrichment_complete": ["enrich/uri"],
127
+ "include_fingerprint": [],
128
+ "enrichment_scheduled": ["enrich/uri"],
129
+ "hidden_response_data": "",
130
+ "hidden_screenshot_contents": """
131
+ },
132
+ "task_results": [{
133
+ "id": 32,
134
+ "name": "masscan_scan_on_69.162.0.0/18",
135
+ "base_entity_name": "69.162.0.0/18",
136
+ "base_entity_type": "Intrigue::Entity::NetBlock"
137
+ }],
138
+ "generated_at": "2018-07-04T03:43:11+00:00"
139
+ }'
140
+ =end
141
+ data = {}
142
+ data["details"] = {}
143
+ data["details"]["hidden_response_data"] = "#{response.body}"
144
+ # construct the headers into a big string block
145
+ headers = []
146
+ response.each_header do |h,v|
147
+ headers << "#{h}: #{v}"
148
+ end
149
+ data["details"]["headers"] = headers
150
+ data["details"]["cookies"] = response.header['set-cookie']
151
+ data["details"]["response_data_hash"] = Digest::SHA256.base64digest("#{response.body}")
152
+
153
+ # call the actual matcher & return
154
+ _match_uri check, data
155
+ end
156
+
104
157
  def _http_request(method, uri_string, credentials=nil, headers={}, data=nil, limit = 10, open_timeout=15, read_timeout=15)
105
158
 
106
159
  response = nil
@@ -121,7 +174,6 @@ module Intrigue
121
174
  end
122
175
 
123
176
  until( found || attempts >= max_attempts)
124
- #puts "Getting #{uri}, attempt #{attempts}"
125
177
  attempts+=1
126
178
 
127
179
  # proxy configuration, disabled for now
@@ -134,8 +186,6 @@ module Intrigue
134
186
  proxy_addr = nil
135
187
  proxy_port = nil
136
188
 
137
-
138
-
139
189
  # set options
140
190
  opts = {}
141
191
  if uri.instance_of? URI::HTTPS
data/lib/checks/amazon.rb CHANGED
@@ -14,7 +14,7 @@ class Amazon < Intrigue::Ident::Check::Base
14
14
  :type => :content_headers,
15
15
  :content => /awselb\/\d.\d/,
16
16
  :hide => true,
17
- :dynamic_version => lambda { |x| x["server"].match(/awselb\/(\d.\d)/).captures[0] },
17
+ :dynamic_version => lambda { |x| x[:headers].match(/awselb\/(\d.\d)/).captures[0] },
18
18
  :verify_sites => ["http://52.4.103.22:80"],
19
19
  :paths => ["#{uri}"]
20
20
  }
data/lib/checks/aruba.rb CHANGED
@@ -6,7 +6,6 @@ class Aruba < Intrigue::Ident::Check::Base
6
6
  def generate_checks(url)
7
7
  [
8
8
  {
9
- :name => "Aruba Wireless Controller",
10
9
  :description => "Aruba Wireless Controller",
11
10
  :version => nil,
12
11
  :type => :content_body,
@@ -6,6 +6,7 @@ class AspNet < Intrigue::Ident::Check::Base
6
6
  def generate_checks(uri)
7
7
  [
8
8
  {
9
+ :accept => "Intrigue::Entity::Uri",
9
10
  :name => "ASP.NET",
10
11
  :description => "ASP.Net Error Message",
11
12
  :version => nil,
@@ -16,6 +17,7 @@ class AspNet < Intrigue::Ident::Check::Base
16
17
  :paths => ["#{uri}"]
17
18
  },
18
19
  {
20
+ :accept => "Intrigue::Entity::Uri",
19
21
  :name => "ASP.NET",
20
22
  :description => "X-AspNet Header",
21
23
  :version => nil,
data/lib/checks/oracle.rb CHANGED
@@ -13,7 +13,7 @@ module Check
13
13
  :type => :content_headers,
14
14
  :content => /Sun GlassFish Enterprise Server/,
15
15
  :hide => true,
16
- :dynamic_version => lambda { |x| x["server"].match(/Sun GlassFish Enterprise Server v([\d\.])/).captures[0] },
16
+ :dynamic_version => lambda { |x| x["details"]["headers"].join("\n").match(/Sun GlassFish Enterprise Server v([\d\.])/).captures[0] },
17
17
  :examples => ["http://52.4.12.185/"],
18
18
  :paths => ["#{uri}"]
19
19
  },
@@ -25,7 +25,7 @@ module Check
25
25
  :type => :content_headers,
26
26
  :content => /GlassFish Server Open Source Edition/,
27
27
  :hide => true,
28
- :dynamic_version => lambda { |x| x["server"].match(/GlassFish Server Open Source Edition\s+([\d\.]+)$/).captures[0] },
28
+ :dynamic_version => lambda { |x| x["details"]["headers"].join("\n").match(/GlassFish Server Open Source Edition\s+([\d\.]+)$/).captures[0] },
29
29
  :examples => ["http://52.2.97.57:80"],
30
30
  :paths => ["#{uri}"]
31
31
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: intrigue-ident
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.1'
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - jcran