ssh_scan 0.0.16 → 0.0.17.pre
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 +4 -4
- data/.gitignore +15 -1
- data/.travis.yml +2 -0
- data/Gemfile +1 -0
- data/README.md +35 -33
- data/Rakefile +40 -16
- data/bin/ssh_scan +91 -53
- data/bin/ssh_scan_worker +14 -0
- data/lib/ssh_scan.rb +0 -1
- data/lib/ssh_scan/client.rb +10 -4
- data/lib/ssh_scan/constants.rb +67 -18
- data/lib/ssh_scan/crypto.rb +3 -18
- data/lib/ssh_scan/error/closed_connection.rb +1 -1
- data/lib/ssh_scan/error/connect_timeout.rb +1 -1
- data/lib/ssh_scan/error/connection_refused.rb +1 -1
- data/lib/ssh_scan/error/disconnected.rb +1 -1
- data/lib/ssh_scan/error/no_banner.rb +1 -1
- data/lib/ssh_scan/error/no_kex_response.rb +1 -1
- data/lib/ssh_scan/os/raspbian.rb +2 -4
- data/lib/ssh_scan/os/ubuntu.rb +103 -58
- data/lib/ssh_scan/policy.rb +2 -1
- data/lib/ssh_scan/policy_manager.rb +67 -18
- data/lib/ssh_scan/protocol.rb +53 -21
- data/lib/ssh_scan/scan_engine.rb +78 -44
- data/lib/ssh_scan/ssh_lib/dropbear.rb +2 -4
- data/lib/ssh_scan/target_parser.rb +3 -3
- data/lib/ssh_scan/update.rb +3 -3
- data/lib/ssh_scan/version.rb +1 -2
- data/lib/ssh_scan/worker.rb +119 -0
- data/lib/string_ext.rb +2 -1
- data/ssh_scan.gemspec +4 -8
- metadata +28 -96
- data/bin/ssh_scan_api +0 -36
- data/lib/ssh_scan/api.rb +0 -124
- data/lib/ssh_scan/fingerprint_database.rb +0 -39
- data/policies/mozilla_intermediate.yml +0 -19
- data/policies/mozilla_modern.yml +0 -30
@@ -1,6 +1,8 @@
|
|
1
1
|
module SSHScan
|
2
2
|
module SSHLib
|
3
3
|
class Dropbear
|
4
|
+
attr_reader :version
|
5
|
+
|
4
6
|
class Version
|
5
7
|
def initialize(version_string)
|
6
8
|
if version_string == nil
|
@@ -33,10 +35,6 @@ module SSHScan
|
|
33
35
|
def cpe
|
34
36
|
"a:dropbear:dropbear" << (":" + version.to_s) unless version.nil?
|
35
37
|
end
|
36
|
-
|
37
|
-
def version
|
38
|
-
@version
|
39
|
-
end
|
40
38
|
end
|
41
39
|
end
|
42
40
|
end
|
@@ -19,7 +19,7 @@ module SSHScan
|
|
19
19
|
upper = NetAddr::CIDR.create(octets.join('.') + "." + range[1])
|
20
20
|
ip_array = NetAddr.range(lower, upper,:Inclusive => true)
|
21
21
|
if !port.nil?
|
22
|
-
ip_array.map! { |
|
22
|
+
ip_array.map! { |i| i.concat(":").concat(port.to_s) }
|
23
23
|
end
|
24
24
|
return ip_array
|
25
25
|
elsif ip.include? "/"
|
@@ -28,7 +28,7 @@ module SSHScan
|
|
28
28
|
ip_array.delete(cidr.network)
|
29
29
|
ip_array.delete(cidr.last)
|
30
30
|
if !port.nil?
|
31
|
-
ip_array.map! { |
|
31
|
+
ip_array.map! { |i| i.concat(":").concat(port.to_s) }
|
32
32
|
end
|
33
33
|
return ip_array
|
34
34
|
else
|
@@ -42,4 +42,4 @@ module SSHScan
|
|
42
42
|
end
|
43
43
|
end
|
44
44
|
end
|
45
|
-
end
|
45
|
+
end
|
data/lib/ssh_scan/update.rb
CHANGED
@@ -18,7 +18,7 @@ module SSHScan
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def next_minor_version(version = SSHScan::VERSION)
|
21
|
-
major, minor
|
21
|
+
major, minor = version.split(".")[0, 2]
|
22
22
|
minor_num = minor.to_i
|
23
23
|
minor_num += 1
|
24
24
|
|
@@ -26,7 +26,7 @@ module SSHScan
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def next_major_version(version = SSHScan::VERSION)
|
29
|
-
major
|
29
|
+
major = version.split(".")[0]
|
30
30
|
major_num = major.to_i
|
31
31
|
major_num += 1
|
32
32
|
|
@@ -38,7 +38,7 @@ module SSHScan
|
|
38
38
|
|
39
39
|
begin
|
40
40
|
res = Net::HTTP.get_response(uri)
|
41
|
-
rescue
|
41
|
+
rescue SocketError => e
|
42
42
|
@errors << e.message
|
43
43
|
return false
|
44
44
|
end
|
data/lib/ssh_scan/version.rb
CHANGED
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'ssh_scan/scan_engine'
|
2
|
+
require 'openssl'
|
3
|
+
require 'net/https'
|
4
|
+
|
5
|
+
module SSHScan
|
6
|
+
class Worker
|
7
|
+
def initialize(opts = {})
|
8
|
+
@server = opts["server"] || "127.0.0.1"
|
9
|
+
@scheme = opts["scheme"] || "http"
|
10
|
+
@verify = opts["verify"] || "false"
|
11
|
+
@port = opts["port"] || 8000
|
12
|
+
@logger = setup_logger(opts["logger"])
|
13
|
+
@poll_interval = 5 # seconds
|
14
|
+
@worker_id = SecureRandom.uuid
|
15
|
+
@verify_ssl = false
|
16
|
+
@auth_token = opts["auth_token"] || nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def setup_logger(logger)
|
20
|
+
case logger
|
21
|
+
when Logger
|
22
|
+
return logger
|
23
|
+
when String
|
24
|
+
return Logger.new(logger)
|
25
|
+
end
|
26
|
+
|
27
|
+
return Logger.new(STDOUT)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.from_config_file(file_string)
|
31
|
+
opts = YAML.load_file(file_string)
|
32
|
+
SSHScan::Worker.new(opts)
|
33
|
+
end
|
34
|
+
|
35
|
+
def run!
|
36
|
+
loop do
|
37
|
+
begin
|
38
|
+
response = retrieve_work
|
39
|
+
if response["work"]
|
40
|
+
job = response["work"]
|
41
|
+
results = perform_work(job)
|
42
|
+
post_results(results, job)
|
43
|
+
else
|
44
|
+
@logger.info("No jobs available (waiting 5 seconds)")
|
45
|
+
sleep 5
|
46
|
+
next
|
47
|
+
end
|
48
|
+
rescue Errno::ECONNREFUSED
|
49
|
+
@logger.error("Cannot reach API endpoint, waiting 5 seconds")
|
50
|
+
sleep 5
|
51
|
+
rescue RuntimeError => e
|
52
|
+
@logger.error(e.inspect)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def retrieve_work
|
58
|
+
(Net::HTTP::SSL_IVNAMES << :@ssl_options).uniq!
|
59
|
+
(Net::HTTP::SSL_ATTRIBUTES << :options).uniq!
|
60
|
+
|
61
|
+
Net::HTTP.class_eval do
|
62
|
+
attr_accessor :ssl_options
|
63
|
+
end
|
64
|
+
|
65
|
+
uri = URI(
|
66
|
+
"#{@scheme}://#{@server}:#{@port}/api/v#{SSHScan::API_VERSION}/\
|
67
|
+
work?worker_id=#{@worker_id}"
|
68
|
+
)
|
69
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
70
|
+
|
71
|
+
if @scheme == "https"
|
72
|
+
http.use_ssl = true
|
73
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @verify == false
|
74
|
+
options_mask =
|
75
|
+
OpenSSL::SSL::OP_NO_SSLv2 +
|
76
|
+
OpenSSL::SSL::OP_NO_SSLv3 +
|
77
|
+
OpenSSL::SSL::OP_NO_COMPRESSION
|
78
|
+
http.ssl_options = options_mask
|
79
|
+
end
|
80
|
+
|
81
|
+
request = Net::HTTP::Get.new(uri.path)
|
82
|
+
request.add_field("SSH_SCAN_AUTH_TOKEN", @auth_token) unless @auth_token.nil?
|
83
|
+
response = http.request(request)
|
84
|
+
JSON.parse(response.body)
|
85
|
+
end
|
86
|
+
|
87
|
+
def perform_work(job)
|
88
|
+
@logger.info("Started job: #{job["uuid"]}")
|
89
|
+
scan_engine = SSHScan::ScanEngine.new
|
90
|
+
results = scan_engine.scan(job)
|
91
|
+
@logger.info("Completed job: #{job["uuid"]}")
|
92
|
+
return results
|
93
|
+
end
|
94
|
+
|
95
|
+
def post_results(results, job)
|
96
|
+
uri = URI(
|
97
|
+
"#{@scheme}://#{@server}:#{@port}/api/v#{SSHScan::API_VERSION}/\
|
98
|
+
work/results/#{@worker_id}/#{job["uuid"]}"
|
99
|
+
)
|
100
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
101
|
+
|
102
|
+
if @scheme == "https"
|
103
|
+
http.use_ssl = true
|
104
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if @verify == false
|
105
|
+
options_mask =
|
106
|
+
OpenSSL::SSL::OP_NO_SSLv2 +
|
107
|
+
OpenSSL::SSL::OP_NO_SSLv3 +
|
108
|
+
OpenSSL::SSL::OP_NO_COMPRESSION
|
109
|
+
http.ssl_options = options_mask
|
110
|
+
end
|
111
|
+
|
112
|
+
request = Net::HTTP::Post.new(uri.path)
|
113
|
+
request.add_field("SSH_SCAN_AUTH_TOKEN", @auth_token) unless @auth_token.nil?
|
114
|
+
request.body = results.to_json
|
115
|
+
http.request(request)
|
116
|
+
@logger.info("Posted job: #{job["uuid"]}")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/lib/string_ext.rb
CHANGED
@@ -16,7 +16,8 @@ class String
|
|
16
16
|
begin
|
17
17
|
IPAddr.new(self)
|
18
18
|
|
19
|
-
# Using ArgumentError instead of IPAddr::InvalidAddressError
|
19
|
+
# Using ArgumentError instead of IPAddr::InvalidAddressError
|
20
|
+
# for 1.9.3 backward compatability
|
20
21
|
rescue ArgumentError
|
21
22
|
return false
|
22
23
|
end
|
data/ssh_scan.gemspec
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
$: << "lib"
|
2
2
|
require 'ssh_scan/version'
|
3
|
+
require 'date'
|
3
4
|
|
4
5
|
Gem::Specification.new do |s|
|
5
6
|
s.name = 'ssh_scan'
|
6
7
|
s.version = SSHScan::VERSION
|
7
|
-
s.authors = ["Jonathan Claudius", "Jinank Jain"]
|
8
|
+
s.authors = ["Jonathan Claudius", "Jinank Jain", "Harsh Vardhan", "Rishabh Saxena", "Ashish Gaurav"]
|
8
9
|
s.date = Date.today.to_s
|
9
|
-
s.email = '
|
10
|
+
s.email = 'jclaudius@mozilla.com'
|
10
11
|
s.platform = Gem::Platform::RUBY
|
11
12
|
s.files = Dir.glob("lib/**/*") +
|
12
13
|
Dir.glob("bin/**/*") +
|
@@ -29,14 +30,9 @@ Gem::Specification.new do |s|
|
|
29
30
|
s.add_dependency('bindata', '~> 2.0')
|
30
31
|
s.add_dependency('netaddr')
|
31
32
|
s.add_dependency('net-ssh')
|
32
|
-
s.add_dependency('sqlite3')
|
33
|
-
s.add_dependency('sinatra')
|
34
|
-
s.add_dependency('sinatra-contrib')
|
35
|
-
s.add_dependency('haml')
|
36
|
-
s.add_dependency('secure_headers')
|
37
|
-
s.add_development_dependency('rack-test')
|
38
33
|
s.add_development_dependency('pry')
|
39
34
|
s.add_development_dependency('rspec', '~> 3.0')
|
40
35
|
s.add_development_dependency('rspec-its', '~> 1.2')
|
41
36
|
s.add_development_dependency('rake', '~> 10.3')
|
37
|
+
s.add_development_dependency('rubocop')
|
42
38
|
end
|
metadata
CHANGED
@@ -1,15 +1,18 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ssh_scan
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.17.pre
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonathan Claudius
|
8
8
|
- Jinank Jain
|
9
|
+
- Harsh Vardhan
|
10
|
+
- Rishabh Saxena
|
11
|
+
- Ashish Gaurav
|
9
12
|
autorequire:
|
10
13
|
bindir: bin
|
11
14
|
cert_chain: []
|
12
|
-
date:
|
15
|
+
date: 2017-03-02 00:00:00.000000000 Z
|
13
16
|
dependencies:
|
14
17
|
- !ruby/object:Gem::Dependency
|
15
18
|
name: bindata
|
@@ -53,90 +56,6 @@ dependencies:
|
|
53
56
|
- - ">="
|
54
57
|
- !ruby/object:Gem::Version
|
55
58
|
version: '0'
|
56
|
-
- !ruby/object:Gem::Dependency
|
57
|
-
name: sqlite3
|
58
|
-
requirement: !ruby/object:Gem::Requirement
|
59
|
-
requirements:
|
60
|
-
- - ">="
|
61
|
-
- !ruby/object:Gem::Version
|
62
|
-
version: '0'
|
63
|
-
type: :runtime
|
64
|
-
prerelease: false
|
65
|
-
version_requirements: !ruby/object:Gem::Requirement
|
66
|
-
requirements:
|
67
|
-
- - ">="
|
68
|
-
- !ruby/object:Gem::Version
|
69
|
-
version: '0'
|
70
|
-
- !ruby/object:Gem::Dependency
|
71
|
-
name: sinatra
|
72
|
-
requirement: !ruby/object:Gem::Requirement
|
73
|
-
requirements:
|
74
|
-
- - ">="
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
version: '0'
|
77
|
-
type: :runtime
|
78
|
-
prerelease: false
|
79
|
-
version_requirements: !ruby/object:Gem::Requirement
|
80
|
-
requirements:
|
81
|
-
- - ">="
|
82
|
-
- !ruby/object:Gem::Version
|
83
|
-
version: '0'
|
84
|
-
- !ruby/object:Gem::Dependency
|
85
|
-
name: sinatra-contrib
|
86
|
-
requirement: !ruby/object:Gem::Requirement
|
87
|
-
requirements:
|
88
|
-
- - ">="
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
version: '0'
|
91
|
-
type: :runtime
|
92
|
-
prerelease: false
|
93
|
-
version_requirements: !ruby/object:Gem::Requirement
|
94
|
-
requirements:
|
95
|
-
- - ">="
|
96
|
-
- !ruby/object:Gem::Version
|
97
|
-
version: '0'
|
98
|
-
- !ruby/object:Gem::Dependency
|
99
|
-
name: haml
|
100
|
-
requirement: !ruby/object:Gem::Requirement
|
101
|
-
requirements:
|
102
|
-
- - ">="
|
103
|
-
- !ruby/object:Gem::Version
|
104
|
-
version: '0'
|
105
|
-
type: :runtime
|
106
|
-
prerelease: false
|
107
|
-
version_requirements: !ruby/object:Gem::Requirement
|
108
|
-
requirements:
|
109
|
-
- - ">="
|
110
|
-
- !ruby/object:Gem::Version
|
111
|
-
version: '0'
|
112
|
-
- !ruby/object:Gem::Dependency
|
113
|
-
name: secure_headers
|
114
|
-
requirement: !ruby/object:Gem::Requirement
|
115
|
-
requirements:
|
116
|
-
- - ">="
|
117
|
-
- !ruby/object:Gem::Version
|
118
|
-
version: '0'
|
119
|
-
type: :runtime
|
120
|
-
prerelease: false
|
121
|
-
version_requirements: !ruby/object:Gem::Requirement
|
122
|
-
requirements:
|
123
|
-
- - ">="
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '0'
|
126
|
-
- !ruby/object:Gem::Dependency
|
127
|
-
name: rack-test
|
128
|
-
requirement: !ruby/object:Gem::Requirement
|
129
|
-
requirements:
|
130
|
-
- - ">="
|
131
|
-
- !ruby/object:Gem::Version
|
132
|
-
version: '0'
|
133
|
-
type: :development
|
134
|
-
prerelease: false
|
135
|
-
version_requirements: !ruby/object:Gem::Requirement
|
136
|
-
requirements:
|
137
|
-
- - ">="
|
138
|
-
- !ruby/object:Gem::Version
|
139
|
-
version: '0'
|
140
59
|
- !ruby/object:Gem::Dependency
|
141
60
|
name: pry
|
142
61
|
requirement: !ruby/object:Gem::Requirement
|
@@ -193,11 +112,26 @@ dependencies:
|
|
193
112
|
- - "~>"
|
194
113
|
- !ruby/object:Gem::Version
|
195
114
|
version: '10.3'
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: rubocop
|
117
|
+
requirement: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
type: :development
|
123
|
+
prerelease: false
|
124
|
+
version_requirements: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
196
129
|
description: A Ruby-based SSH scanner for configuration and policy scanning
|
197
|
-
email:
|
130
|
+
email: jclaudius@mozilla.com
|
198
131
|
executables:
|
199
132
|
- ssh_scan
|
200
|
-
-
|
133
|
+
- ssh_scan_worker
|
134
|
+
- ssh_scan_worker_example_config.yml
|
201
135
|
extensions: []
|
202
136
|
extra_rdoc_files: []
|
203
137
|
files:
|
@@ -209,9 +143,9 @@ files:
|
|
209
143
|
- README.md
|
210
144
|
- Rakefile
|
211
145
|
- bin/ssh_scan
|
212
|
-
- bin/
|
146
|
+
- bin/ssh_scan_worker
|
147
|
+
- bin/ssh_scan_worker_example_config.yml
|
213
148
|
- lib/ssh_scan.rb
|
214
|
-
- lib/ssh_scan/api.rb
|
215
149
|
- lib/ssh_scan/banner.rb
|
216
150
|
- lib/ssh_scan/client.rb
|
217
151
|
- lib/ssh_scan/constants.rb
|
@@ -223,7 +157,6 @@ files:
|
|
223
157
|
- lib/ssh_scan/error/disconnected.rb
|
224
158
|
- lib/ssh_scan/error/no_banner.rb
|
225
159
|
- lib/ssh_scan/error/no_kex_response.rb
|
226
|
-
- lib/ssh_scan/fingerprint_database.rb
|
227
160
|
- lib/ssh_scan/os.rb
|
228
161
|
- lib/ssh_scan/os/centos.rb
|
229
162
|
- lib/ssh_scan/os/cisco.rb
|
@@ -259,9 +192,8 @@ files:
|
|
259
192
|
- lib/ssh_scan/target_parser.rb
|
260
193
|
- lib/ssh_scan/update.rb
|
261
194
|
- lib/ssh_scan/version.rb
|
195
|
+
- lib/ssh_scan/worker.rb
|
262
196
|
- lib/string_ext.rb
|
263
|
-
- policies/mozilla_intermediate.yml
|
264
|
-
- policies/mozilla_modern.yml
|
265
197
|
- ssh_scan.gemspec
|
266
198
|
homepage: http://rubygems.org/gems/ssh_scan
|
267
199
|
licenses:
|
@@ -278,12 +210,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
278
210
|
version: '0'
|
279
211
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
280
212
|
requirements:
|
281
|
-
- - "
|
213
|
+
- - ">"
|
282
214
|
- !ruby/object:Gem::Version
|
283
|
-
version:
|
215
|
+
version: 1.3.1
|
284
216
|
requirements: []
|
285
217
|
rubyforge_project:
|
286
|
-
rubygems_version: 2.
|
218
|
+
rubygems_version: 2.6.2
|
287
219
|
signing_key:
|
288
220
|
specification_version: 4
|
289
221
|
summary: Ruby-based SSH Scanner
|
data/bin/ssh_scan_api
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
$:.unshift File.join(File.dirname(__FILE__), "../lib")
|
4
|
-
|
5
|
-
require 'optparse'
|
6
|
-
require 'ssh_scan'
|
7
|
-
|
8
|
-
options = {
|
9
|
-
:port => 8000,
|
10
|
-
}
|
11
|
-
|
12
|
-
opt_parser = OptionParser.new do |opts|
|
13
|
-
opts.banner = "ssh_scan_api v#{SSHScan::API_VERSION} (https://github.com/mozilla/ssh_scan)\n\n" +
|
14
|
-
"Usage: ssh_scan [options]"
|
15
|
-
|
16
|
-
opts.on("-p", "--port [PORT]", "Listen and serve API requests on this port (Default: 8000)") do |port|
|
17
|
-
options[:port] = port.to_i
|
18
|
-
end
|
19
|
-
|
20
|
-
opts.on("-v", "--version", "Show ssh_scan API version") do
|
21
|
-
puts SSHScan::API_VERSION
|
22
|
-
exit
|
23
|
-
end
|
24
|
-
|
25
|
-
opts.on_tail("-h", "--help", "Show help") do
|
26
|
-
puts opts
|
27
|
-
puts "\nExamples:\n"
|
28
|
-
puts " ssh_scan_api -p 4567"
|
29
|
-
puts ""
|
30
|
-
exit
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
opt_parser.parse!
|
35
|
-
|
36
|
-
SSHScan::API.run!(:port => options[:port])
|