hakiri 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ capybara-*.html
15
15
  /spec/tmp/*
16
16
  **.orig
17
17
  *.gem
18
+ /manifest.json
data/Gemfile.lock CHANGED
@@ -1,10 +1,11 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hakiri (0.2.0)
4
+ hakiri (0.2.1)
5
5
  active_support
6
6
  commander
7
7
  i18n
8
+ rake
8
9
  rest-client
9
10
  terminal-table
10
11
 
@@ -19,6 +20,7 @@ GEM
19
20
  highline (1.6.19)
20
21
  i18n (0.6.4)
21
22
  mime-types (1.23)
23
+ rake (10.1.0)
22
24
  rest-client (1.6.7)
23
25
  mime-types (>= 1.16)
24
26
  terminal-table (1.4.5)
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2013 Vasily Vasinov
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,31 +1,124 @@
1
- # Hakiri
2
- Hakiri is a command line interface for the Hakiri platform. It allows Ruby on Rails developers to collect versions of servers, databases and other technologies that they use in their stacks. It also shows CVE vulnerabilities found in their system software versions.
1
+ # Secure Rails with Hakiri
2
+
3
+ Hakiri is a command line interface (CLI) for the Hakiri platform. It allows Ruby on Rails developers to automate version scraping of servers, databases and other technologies used in their stacks. For each technology Hakiri shows CVE vulnerabilities. Here is a snippet of how it works:
4
+
5
+ ~~~
6
+ $ hakiri system:scan
7
+ -----> Scanning system for software versions...
8
+ Found Ruby 1.9.3.429
9
+ Found Ruby on Rails 3.2.11
10
+ -----> Searching for vulnerabilities...
11
+ Found 17 vulnerabilities in Ruby on Rails 3.2.11
12
+ Show all of them? (yes or no)
13
+
14
+ CVE-2013-0276
15
+ ActiveRecord in Ruby on Rails before 2.3.17, 3.1.x before 3.1.11, and 3.2.x before 3.2.12 allows remote attackers to bypass the attr_protected protection mechanism and modify protected model attributes via a crafted request.
16
+
17
+ ...
18
+ ~~~
19
+
20
+ Wanna try it on your system?
3
21
 
4
22
  ## Installation
5
- ```
6
- gem install hakiri
7
- ```
8
23
 
9
- ## Authentication Token
10
- For some extra functionality, you'll have to get an authentication token from Hakiri.
24
+ Hakiri CLI is a Ruby gem that can be installed by
25
+
26
+ ~~~
27
+ $ gem install hakiri
28
+ ~~~
29
+
30
+ After it's installed, restart your command line and you should be good to go.
31
+
32
+ ## Test Your System in 2 Minutes
33
+
34
+ Once you have Hakiri CLI installed, it's really easy to start using it. You can scan your Rails stack in a matter of seconds.
35
+
36
+ One way to do so is to run a command line wizard that will ask you about your technologies in 5 steps:
37
+
38
+ ~~~
39
+ $ hakiri system:steps
40
+ ~~~
41
+
42
+ After you are done, Hakiri CLI will scrape versions of technologies in your stack and show you all active CVE vulnerabilities.
43
+
44
+ The wizard is a good way to get a taste of Hakiri but it's not really useful for real work. A much better setup suitable for production is a manifest file that the user can configure with technologies that are part of the stack and then run tests against it.
45
+
46
+ Hakiri CLI can generate a generic manifest file with the following command:
47
+
48
+ ~~~
49
+ $ hakiri manifest:generate
50
+ ~~~
51
+
52
+ This will generate a `manifest.json` file in your current directory. It will contain all technologies supported by Hakiri. You can choose which ones you need by editing this file.
11
53
 
12
- TBD
54
+ Once you are done, run the following command in the directory where you've created the manifest file:
13
55
 
14
- ## Getting Started
15
- ### System Scan
16
- You can scan your system for vulnerabilities. Supply a JSON file with technologies that you are interested in and run this command.
17
- ```
18
- $ hakiri system:scan -s my_stack.json
19
- ```
56
+ ~~~
57
+ $ hakiri system:scan
58
+ ~~~
20
59
 
21
- ### Step by Step
22
- TBD
60
+ It will attempt to scrape versions of technologies in your current directory and then make a request to the Hakiri API to see if there are open CVE vulnerabilities. If any vulnerabilities are found, Hakiri CLI will ask you whether you want to see all of them. The output will look something like this:
23
61
 
24
- ### Sync Stack
25
- TBD
62
+ ~~~
63
+ -----> Scanning system for software versions...
64
+ Found Ruby 1.9.3.429
65
+ Found Ruby on Rails 3.2.11
66
+ Found Unicorn 4.6.3
67
+ -----> Searching for vulnerabilities...
68
+ Found 17 vulnerabilities in Ruby on Rails 3.2.11
69
+ Show all of them? (yes or no) yes
70
+
71
+ CVE-2013-0276
72
+ ActiveRecord in Ruby on Rails before 2.3.17, 3.1.x before 3.1.11, and 3.2.x before 3.2.12 allows remote attackers to bypass the attr_protected protection mechanism and modify protected model attributes via a crafted request.
73
+
74
+ ...
75
+ ~~~
76
+
77
+ Simple, right? If you manifest file is in a different directory or named differently you can specify it in a parameter:
78
+
79
+ ~~~
80
+ $ hakiri system:scan -m ../my_stack.json
81
+ ~~~
82
+
83
+ You can learn more about configuring the manifest in [Hakiri docs](https://www.hakiriup.com/docs/manifest-file).
84
+
85
+ ## Advanced Usage
86
+
87
+ We just went through the most basic Hakiri use case. Here are links to docs describing how to do more:
88
+
89
+ - [Learn about](https://www.hakiriup.com/docs/manifest-file) advanced manifest file options.
90
+ - [Setup your](https://www.hakiriup.com/docs/authentication-token) authentication token.
91
+ - [Sync your stack technologies](https://www.hakiriup.com/docs/stack-syncing) with the cloud and get notified when new vulnerabilities come out.
92
+ - [Check out technologies](https://www.hakiriup.com/docs/technologies-version-formats) the lsit of supported technologies and version formats.
26
93
 
27
94
  ## Contribute
95
+
28
96
  - Fork the project.
29
97
  - Write code for a feature or bug fix.
30
98
  - Commit, do not make changes to version.
31
- - Submit a pull request.
99
+ - Submit a pull request.
100
+
101
+ ## License
102
+
103
+ (The MIT license)
104
+
105
+ Copyright (c) 2013 Vasily Vasinov
106
+
107
+ Permission is hereby granted, free of charge, to any person obtaining
108
+ a copy of this software and associated documentation files (the
109
+ "Software"), to deal in the Software without restriction, including
110
+ without limitation the rights to use, copy, modify, merge, publish,
111
+ distribute, sublicense, and/or sell copies of the Software, and to
112
+ permit persons to whom the Software is furnished to do so, subject to
113
+ the following conditions:
114
+
115
+ The above copyright notice and this permission notice shall be
116
+ included in all copies or substantial portions of the Software.
117
+
118
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
119
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
120
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
121
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
122
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
123
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
124
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
File without changes
data/bin/hakiri CHANGED
@@ -3,23 +3,33 @@
3
3
  require 'rubygems'
4
4
  require 'commander/import'
5
5
  require 'hakiri'
6
- require 'terminal-table'
7
6
 
8
7
  program :name, 'hakiri'
9
8
  program :version, Hakiri::VERSION
10
9
  program :description, 'Hakiri CLI'
11
10
 
11
+ command 'manifest:generate' do |c|
12
+ c.syntax = 'hakiri manifest:generate'
13
+ c.summary = 'Generates a manifest file with example technologies.'
14
+ c.description = 'This command generates a JSON file with technologies supported by Hakiri.'
15
+
16
+ c.action do |args, options|
17
+ cli = Hakiri::Manifest.new(args, options)
18
+ cli.generate
19
+ end
20
+ end
21
+
12
22
  command 'system:scan' do |c|
13
23
  c.syntax = 'hakiri system:scan [options]'
14
- c.summary = 'Configure your stack with a JSON file.'
24
+ c.summary = 'Configure your stack with a manifest JSON file.'
15
25
  c.description = 'This command grabs your custom stack JSON file and shows vulnerabilities in your project.'
16
- c.option '--stack STRING', String, 'Path to your JSON file'
26
+ c.option '--manifest STRING', String, 'Path to your manifest JSON file'
17
27
 
18
28
  c.action do |args, options|
19
- options.default stack: './technologies.json'
29
+ options.default manifest: './manifest.json'
20
30
 
21
- cli = Hakiri::SystemScan.new(args, options)
22
- cli.command
31
+ cli = Hakiri::System.new(args, options)
32
+ cli.scan
23
33
  end
24
34
  end
25
35
 
@@ -27,15 +37,15 @@ command 'system:sync' do |c|
27
37
  c.syntax = 'hakiri system:sync [options]'
28
38
  c.summary = 'Sync your system\'s software versions with the server.'
29
39
  c.description = 'This command grabs your custom stack JSON file, and syncs it with your project on www.hakiriup.com.'
30
- c.option '--stack STRING', String, 'Path to your JSON file stack'
40
+ c.option '--manifest STRING', String, 'Path to your manifest JSON file stack'
31
41
  c.option '--project INTEGER', Integer, 'Your project ID.'
42
+ c.option '--force', 'Force syncing without asking for it first.'
32
43
 
33
44
  c.action do |args, options|
34
- options.default stack: './technologies.json'
45
+ options.default manifest: './manifest.json'
35
46
  options.default project: nil
36
-
37
- cli = Hakiri::SystemSync.new(args, options)
38
- cli.command
47
+ cli = Hakiri::System.new(args, options)
48
+ cli.sync
39
49
  end
40
50
  end
41
51
 
@@ -45,7 +55,7 @@ command 'system:steps' do |c|
45
55
  c.description = 'This command launches a step by step walkthrough that will help you customize your stack.'
46
56
 
47
57
  c.action do |args, options|
48
- cli = Hakiri::SystemSteps.new(args, options)
49
- cli.command
58
+ cli = Hakiri::System.new(args, options)
59
+ cli.steps
50
60
  end
51
61
  end
data/hakiri.gemspec CHANGED
@@ -4,8 +4,8 @@ require 'hakiri/version'
4
4
  Gem::Specification.new do |s|
5
5
  s.name = 'hakiri'
6
6
  s.version = Hakiri::VERSION
7
- s.summary = 'CLI for Hakiri'
8
- s.description = 'Hakiri is a CLI for www.hakiriup.com—a cloud security platform for Ruby on rails apps.'
7
+ s.summary = 'Secure Rails with Hakiri'
8
+ s.description = 'Hakiri is a CLI for www.hakiriup.com—a cloud security platform for Ruby on Rails apps.'
9
9
  s.authors = ['Vasily Vasinov']
10
10
  s.email = 'vasinov@me.com'
11
11
  s.files = `git ls-files`.split("\n")
@@ -14,6 +14,7 @@ Gem::Specification.new do |s|
14
14
  s.homepage = 'http://www.hakiriup.com'
15
15
  s.license = 'MIT'
16
16
 
17
+ s.add_dependency 'rake'
17
18
  s.add_dependency 'commander'
18
19
  s.add_dependency 'terminal-table'
19
20
  s.add_dependency 'active_support'
data/lib/hakiri.rb CHANGED
@@ -7,9 +7,8 @@ require 'http'
7
7
  require 'open-uri'
8
8
 
9
9
  require 'hakiri/cli/cli'
10
- require 'hakiri/cli/system_sync'
11
- require 'hakiri/cli/system_scan'
12
- require 'hakiri/cli/system_steps'
10
+ require 'hakiri/cli/system'
11
+ require 'hakiri/cli/manifest'
13
12
 
14
13
  require 'hakiri/stack'
15
14
  require 'hakiri/version'
@@ -0,0 +1,19 @@
1
+ {
2
+ "apache": { "command": "", "version": "" },
3
+ "apache-tomcat": { "command": "", "version": "" },
4
+ "java": { "command": "", "version": "" },
5
+ "jruby": { "command": "", "version": "" },
6
+ "linux-kernel": { "command": "", "version": "" },
7
+ "memcached": { "command": "", "version": "" },
8
+ "mongodb": { "command": "", "version": "" },
9
+ "mysql": { "command": "", "version": "" },
10
+ "nginx": { "command": "", "version": "" },
11
+ "phusion-passenger": { "command": "", "version": "" },
12
+ "postgres": { "command": "", "version": "" },
13
+ "redis": { "command": "", "version": "" },
14
+ "ruby": { "command": "", "version": "" },
15
+ "ruby-on-rails": { "command": "", "version": "" },
16
+ "thin": { "command": "", "version": "" },
17
+ "trinidad": { "command": "", "version": "" },
18
+ "unicorn": { "command": "", "version": "" }
19
+ }
@@ -0,0 +1,14 @@
1
+ require 'fileutils'
2
+
3
+ class Hakiri::Manifest < Hakiri::Cli
4
+ #
5
+ # Generates a JSON manifest file
6
+ #
7
+ def generate
8
+ FileUtils::copy_file "#{File.dirname(__FILE__)}/manifest.json", "#{Dir.pwd}/manifest.json"
9
+ File.chmod 0755, "#{Dir.pwd}/manifest.json"
10
+ say '-----> Generating the manifest file...'
11
+ say "-----> Generated the manifest file in #{Dir.pwd}/manifest.json"
12
+ say "-----> Edit it and run \"hakiri system:scan\""
13
+ end
14
+ end
@@ -0,0 +1,235 @@
1
+ class Hakiri::System < Hakiri::Cli
2
+ #
3
+ # Walks the user through system scanning process.
4
+ #
5
+ def scan
6
+ if File.exist? @options.manifest
7
+ @stack.build_from_json_file(@options.manifest)
8
+ @stack.fetch_versions
9
+
10
+ # GETTING VERSIONS
11
+ say '-----> Scanning system for software versions...'
12
+
13
+ if @stack.technologies.empty?
14
+ say ' No versions were found...'
15
+ else
16
+ @stack.technologies.each do |technology_slug, payload|
17
+ say " Found #{payload[:name]} #{payload[:version]}"
18
+ end
19
+
20
+ # GETTING VULNERABILITIES
21
+ say '-----> Searching for vulnerabilities...'
22
+ params = ({ technologies: @stack.technologies }.to_param)
23
+ response = @http_client.get_issues(params)
24
+
25
+ if response[:errors]
26
+ response[:errors].each do |error|
27
+ say "! Server Error: #{error}"
28
+ end
29
+ else
30
+ authenticated = response[:meta][:authenticated]
31
+
32
+ if response[:technologies].empty?
33
+ say ' No vulnerabilities found. Keep it up!'
34
+ else
35
+ response[:technologies].each do |technology|
36
+ unless technology[:issues_count] == 0
37
+ say "! Found #{technology[:issues_count].to_i} #{'vulnerability'.pluralize if technology[:issues_count].to_i != 1} in #{technology[:name]} #{technology[:version]}"
38
+ end
39
+ end
40
+
41
+ if agree 'Show all of them? (yes or no) '
42
+ puts ' '
43
+ response[:technologies].each do |technology|
44
+ technology[:issues].each do |issue|
45
+ say issue[:name]
46
+ say issue[:description]
47
+ puts ' '
48
+ end
49
+ end
50
+ end
51
+
52
+ unless authenticated
53
+ say '****** Signup on www.hakiriup.com to get notified when new vulnerabilities come out.'
54
+ end
55
+ end
56
+ end
57
+ end
58
+ else
59
+ say '! You have to create a manifest file with "hakiri manifest:generate"'
60
+ end
61
+ end
62
+
63
+ #
64
+ # Walks the user through the version syncing process.
65
+ #
66
+ def sync
67
+ @stack.build_from_json_file(@options.manifest)
68
+ @stack.fetch_versions
69
+
70
+ if @http_client.auth_token
71
+ # GETTING VERSIONS
72
+ say '-----> Scanning system for software versions...'
73
+
74
+ if @stack.technologies.empty?
75
+ say ' No versions were found...'
76
+ else
77
+ @stack.technologies.each do |technology_name, payload|
78
+ say " Found #{payload[:name]} #{payload[:version]}"
79
+ end
80
+
81
+ # CHECK VERSIONS ON THE SERVER
82
+ params = ({ project_id: @options.project, technologies: @stack.technologies }.to_param)
83
+ say '-----> Checking software versions on www.hakiriup.com...'
84
+ response = @http_client.check_versions_diff(params)
85
+
86
+ if response[:errors]
87
+ response[:errors].each do |error|
88
+ say "! Server Error: #{error}"
89
+ end
90
+ else
91
+ if response[:diffs].any?
92
+ @stack.technologies = {}
93
+ response[:diffs].each do |diff|
94
+ if diff[:success]
95
+ @stack.technologies[diff[:technology][:slug]] = { version: diff[:system_version] }
96
+
97
+ if diff[:hakiri_version]
98
+ if diff[:system_version_newer]
99
+ say " System version of #{diff[:technology][:name]} is newer (#{diff[:system_version]} > #{diff[:hakiri_version]})"
100
+ else
101
+ say " System version of #{diff[:technology][:name]} is older (#{diff[:system_version]} < #{diff[:hakiri_version]})"
102
+ end
103
+ else
104
+ say " New technology detected: #{diff[:technology][:name]} #{diff[:system_version]}"
105
+ end
106
+ else
107
+ say "! Error in #{diff[:technology][:name]}: #{diff[:errors][:value][0]}"
108
+ end
109
+ end
110
+
111
+ # UPDATE VERSIONS ON THE SERVER
112
+ unless @options.force
113
+ update = agree "Do you want to update \"#{response[:project][:name]}\" with system versions? (yes or no) "
114
+ end
115
+
116
+ if update or @options.force
117
+ say '-----> Syncing versions with www.hakiriup.com...'
118
+ params = ({ project_id: @options.project, technologies: @stack.technologies }.to_param)
119
+ response = @http_client.sync_project_versions(response[:project][:id], params)
120
+
121
+ if response[:errors]
122
+ response[:errors].each do |error|
123
+ say "! Server Error: #{error}"
124
+ end
125
+ else
126
+ if response[:updated].any?
127
+ response[:updated].each do |update|
128
+ if update[:success]
129
+ say " #{update[:technology][:name]} was updated to #{update[:new_version]}"
130
+ else
131
+ say "! Error syncing #{update[:technology][:name]}: #{update[:errors][:value][0]}"
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ else
138
+ say ' No differences were found. Everything is up to date.'
139
+ end
140
+ end
141
+ end
142
+ else
143
+ say '! You have to setup HAKIRI_AUTH_TOKEN environmental variable with your Hakiri authentication token.'
144
+ end
145
+ end
146
+
147
+ #
148
+ # Walks the user through manual technologies selection.
149
+ #
150
+ def steps
151
+ say 'Hakiri Walkthrough will help you configure your @stack step by step and show '
152
+ say 'you vulnerabilities at the end.'
153
+ puts ' '
154
+ say 'Step 1 of 5: Rails Server'
155
+ say '1. Unicorn'
156
+ say '2. Phusion Passenger'
157
+ say '3. Thin'
158
+ say '4. Trinidad'
159
+ say '5. None of the above'
160
+
161
+ server = ask('What do you use as your Rails server? (1, 2, 3, 4 or 5) ', Integer) { |q| q.in = 1..5 }
162
+ puts ' '
163
+ say 'Step 2 of 5: Secondary Server'
164
+ say '1. Apache'
165
+ say '2. nginx'
166
+ say '3. Both'
167
+ say '4. Neither'
168
+
169
+ extra_server = ask('Do you use Apache or nginx? (1, 2, 3 or 4) ', Integer) { |q| q.in = 1..4 }
170
+ puts ' '
171
+ say 'Step 3 of 5: Database'
172
+ say '1. MySQL'
173
+ say '2. Postgres'
174
+ say '3. MongoDB'
175
+ say '4. None of the above'
176
+
177
+ db = ask('What database do you use? (1, 2, 3 or 4) ', Integer) { |q| q.in = 1..4 }
178
+ puts ' '
179
+ redis = agree 'Step 4 of 5: do you use Redis? (yes or no) '
180
+ puts ' '
181
+ memcached = agree 'Step 5 of 5: do you use Memcached? (yes or no) '
182
+
183
+ say '-----> Retrieving software versions versions on your system...'
184
+
185
+ @stack.build_from_input(server, extra_server, db, redis, memcached)
186
+ @stack.fetch_versions
187
+
188
+ if @stack.technologies.empty?
189
+ say ' No versions were found...'
190
+ else
191
+ @stack.technologies.each do |technology_slug, payload|
192
+ say " Found #{payload[:name]} #{payload[:version]}"
193
+ end
194
+
195
+ say '-----> Searching for vulnerabilities...'
196
+ params = ({ technologies: @stack.technologies }.to_param)
197
+ response = @http_client.get_issues(params)
198
+
199
+ if response[:errors]
200
+ response[:errors].each do |error|
201
+ say "! Server Error: #{error}"
202
+ end
203
+ else
204
+ authenticated = response[:meta][:authenticated]
205
+
206
+ if response[:technologies].empty?
207
+ say ' No vulnerabilities found. Keep it up!'
208
+ else
209
+ response[:technologies].each do |technology|
210
+ unless technology[:issues_count] == 0
211
+ say "! Found #{technology[:issues_count].to_i} #{'vulnerability'.pluralize if technology[:issues_count].to_i != 1} in #{technology[:name]} #{technology[:version]}"
212
+ puts ' '
213
+ end
214
+ end
215
+
216
+
217
+ if agree 'Show all of them? (yes or no) '
218
+ puts ' '
219
+ response[:technologies].each do |technology|
220
+ technology[:issues].each do |issue|
221
+ say issue[:name]
222
+ say issue[:description]
223
+ puts ' '
224
+ end
225
+ end
226
+ end
227
+
228
+ unless authenticated
229
+ say '****** Signup on www.hakiriup.com to get notified when new vulnerabilities come out.'
230
+ end
231
+ end
232
+ end
233
+ end
234
+ end
235
+ end