gauntlt 0.0.0 → 0.0.5
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 +3 -0
- data/.gitmodules +6 -0
- data/.travis.yml +9 -0
- data/Gemfile +3 -2
- data/LICENSE +10 -0
- data/README.md +95 -0
- data/Rakefile +4 -0
- data/bin/gauntlt +51 -2
- data/features/attack.feature +62 -0
- data/features/attacks/cookies.feature +25 -0
- data/features/attacks/curl.feature +23 -0
- data/features/attacks/http_methods.feature +33 -0
- data/features/attacks/nmap.feature +40 -0
- data/features/attacks/sqlmap.feature +17 -0
- data/features/attacks/sslyze.feature +36 -0
- data/features/help.feature +37 -0
- data/features/report.feature +5 -0
- data/features/step_definitions/aruba_extension_steps.rb +3 -0
- data/features/step_definitions/config_steps.rb +3 -0
- data/features/step_definitions/help_steps.rb +8 -0
- data/features/step_definitions/support_steps.rb +5 -0
- data/features/support/aruba.rb +5 -0
- data/features/support/attack_steps.rb +1 -0
- data/features/support/env.rb +1 -0
- data/features/support/hooks.rb +3 -0
- data/features/support/profile/profile.xml +5 -0
- data/gauntlt.gemspec +13 -8
- data/gem_tasks/cucumber.rake +5 -0
- data/gem_tasks/rspec.rake +6 -0
- data/lib/gauntlt.rb +35 -1
- data/lib/gauntlt/attack.rb +32 -0
- data/lib/gauntlt/attack_adapters/cookies.rb +11 -0
- data/lib/gauntlt/attack_adapters/curl.rb +3 -0
- data/lib/gauntlt/attack_adapters/http_methods.rb +12 -0
- data/lib/gauntlt/attack_adapters/nmap.rb +14 -0
- data/lib/gauntlt/attack_adapters/sqlmap.rb +3 -0
- data/lib/gauntlt/attack_adapters/sslyze.rb +15 -0
- data/lib/gauntlt/attack_adapters/support/cli_helper.rb +18 -0
- data/lib/gauntlt/attack_adapters/support/cookie_helper.rb +27 -0
- data/lib/gauntlt/attack_adapters/support/env.rb +1 -0
- data/lib/gauntlt/attack_adapters/support/hooks.rb +3 -0
- data/lib/gauntlt/attack_adapters/support/nmap_helper.rb +13 -0
- data/lib/gauntlt/attack_adapters/support/profile_helper.rb +12 -0
- data/lib/gauntlt/attack_adapters/support/python_script_helper.rb +70 -0
- data/lib/gauntlt/attack_adapters/support/sslyze_output.README +91 -0
- data/lib/gauntlt/version.rb +1 -1
- data/spec/gauntlt/attack_spec.rb +58 -0
- data/spec/gauntlt_spec.rb +43 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/support/mock_constants.rb +46 -0
- metadata +199 -12
- data/Gemfile.lock +0 -44
@@ -0,0 +1,37 @@
|
|
1
|
+
Feature: Display help info
|
2
|
+
|
3
|
+
As a user of gauntlt,
|
4
|
+
I want contextual help info,
|
5
|
+
In order to learn the options required by an attack
|
6
|
+
|
7
|
+
Scenario: A user runs the help command in the core part of gauntlt
|
8
|
+
When I run `gauntlt --help`
|
9
|
+
Then I should see a help menu that explains how to invoke gauntlt
|
10
|
+
|
11
|
+
Scenario: A user runs the help command for a certain test
|
12
|
+
When I run `gauntlt attack -h -n nmap`
|
13
|
+
Then the output should contain:
|
14
|
+
"""
|
15
|
+
Command 'attack':
|
16
|
+
"""
|
17
|
+
|
18
|
+
Scenario: A user runs gauntlt without any arguments
|
19
|
+
When I run `gauntlt`
|
20
|
+
Then I should see a help menu that explains how to invoke gauntlt
|
21
|
+
|
22
|
+
Scenario: A user runs the attack command without specifying attack name
|
23
|
+
When I run `gauntlt attack`
|
24
|
+
Then the output should contain:
|
25
|
+
"""
|
26
|
+
Available attacks:
|
27
|
+
|
28
|
+
cookies
|
29
|
+
curl
|
30
|
+
http_methods
|
31
|
+
nmap
|
32
|
+
sqlmap
|
33
|
+
sslyze
|
34
|
+
|
35
|
+
try: gauntlt attack -n nmap
|
36
|
+
"""
|
37
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'gauntlt'
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'gauntlt'
|
data/gauntlt.gemspec
CHANGED
@@ -5,21 +5,26 @@ require "gauntlt/version"
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = "gauntlt"
|
7
7
|
s.version = Gauntlt::VERSION
|
8
|
-
s.authors = ["James Wickett"]
|
8
|
+
s.authors = ["James Wickett", "Mani Tadayon"]
|
9
9
|
s.email = ["james@ruggeddevops.org"]
|
10
10
|
s.homepage = ""
|
11
|
-
s.summary = %q{
|
12
|
-
s.description = %q{Using standard Gherkin language to define security tests,
|
11
|
+
s.summary = %q{behaviour-driven security using cucumber}
|
12
|
+
s.description = %q{Using standard Gherkin language to define security tests, gauntlt happily wraps cucumber functionality and provides a security testing framework that security engineers, developers and operations teams can collaborate on together.}
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
s.files = `git ls-files`.split("\n")
|
17
|
-
s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
|
14
|
+
s.files = `git ls-files`.split("\n")
|
15
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
17
|
s.require_paths = ["lib"]
|
20
18
|
|
21
19
|
# specify any dependencies here; for example:
|
22
|
-
|
20
|
+
s.add_development_dependency "cucumber"
|
21
|
+
s.add_development_dependency "rspec"
|
22
|
+
s.add_development_dependency "aruba"
|
23
|
+
s.add_development_dependency "rake"
|
24
|
+
|
23
25
|
s.add_runtime_dependency "cucumber"
|
24
26
|
s.add_runtime_dependency "aruba"
|
27
|
+
s.add_runtime_dependency "curb"
|
28
|
+
s.add_runtime_dependency "acclaim"
|
29
|
+
s.add_runtime_dependency "ribbon", "0.7.0"
|
25
30
|
end
|
data/lib/gauntlt.rb
CHANGED
@@ -1,5 +1,39 @@
|
|
1
1
|
require "gauntlt/version"
|
2
2
|
|
3
|
+
require 'rubygems'
|
4
|
+
require 'cucumber'
|
5
|
+
require 'gauntlt/attack'
|
6
|
+
|
3
7
|
module Gauntlt
|
4
|
-
|
8
|
+
CURRENT_DIR = if defined?(Pathname) # ruby 1.9
|
9
|
+
Pathname.new(__FILE__).dirname.to_s
|
10
|
+
else
|
11
|
+
File.dirname(File.expand_path(__FILE__))
|
12
|
+
end
|
13
|
+
|
14
|
+
GAUNTLT_DIR = File.join(CURRENT_DIR, 'gauntlt')
|
15
|
+
|
16
|
+
ATTACKS_DIR = File.join(GAUNTLT_DIR, 'attack_adapters')
|
17
|
+
|
18
|
+
ATTACK_GLOB_PATTERN = ATTACKS_DIR + '/*.rb'
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def attack_files
|
22
|
+
Dir.glob(ATTACK_GLOB_PATTERN)
|
23
|
+
end
|
24
|
+
|
25
|
+
def attacks
|
26
|
+
attack_files.map do |full_path|
|
27
|
+
File.basename(full_path, '.rb')
|
28
|
+
end.sort
|
29
|
+
end
|
30
|
+
|
31
|
+
def has_attack?(name)
|
32
|
+
attacks.include?(name)
|
33
|
+
end
|
34
|
+
|
35
|
+
def attack(name, options={})
|
36
|
+
Attack.new(name, options).run
|
37
|
+
end
|
38
|
+
end
|
5
39
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'cucumber'
|
2
|
+
require 'cucumber/cli/main'
|
3
|
+
|
4
|
+
module Gauntlt
|
5
|
+
class Attack
|
6
|
+
class NotFound < Exception; end
|
7
|
+
|
8
|
+
attr_accessor :name, :opts, :attack_file
|
9
|
+
|
10
|
+
def initialize(name, opts={})
|
11
|
+
if opts[:attack_file] && File.exists?( opts[:attack_file] )
|
12
|
+
self.name = name
|
13
|
+
self.opts = opts
|
14
|
+
self.attack_file = opts[:attack_file]
|
15
|
+
else
|
16
|
+
raise NotFound.new("No '#{opts[:attack_file]}' attack found")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def base_dir
|
21
|
+
File.expand_path( File.dirname(__FILE__) )
|
22
|
+
end
|
23
|
+
|
24
|
+
def attacks_dir
|
25
|
+
File.join(base_dir, "attack_adapters")
|
26
|
+
end
|
27
|
+
|
28
|
+
def run
|
29
|
+
Cucumber::Cli::Main.execute([self.attack_file, '--strict', '--require', self.attacks_dir])
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
When /^I launch a "cookies" attack$/ do
|
2
|
+
set_cookies( cookies_for(hostname) )
|
3
|
+
end
|
4
|
+
|
5
|
+
Then /^the following cookies should be received:$/ do |table|
|
6
|
+
names = table.hashes.map{|h| h['name'] }
|
7
|
+
names.each do |name|
|
8
|
+
cookies.any?{|s| s =~ /^#{name}/}.should be_true
|
9
|
+
# TODO: check other values in table
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
When /^"curl" is installed$/ do
|
2
|
+
ensure_cli_installed("curl")
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I launch a "curl" attack$/ do
|
6
|
+
@response = Curl::Easy.http_get(hostname)
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I launch a "curl" attack with:$/ do |command|
|
10
|
+
command.gsub!('<hostname>', hostname)
|
11
|
+
run command
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# TODO: figure out if there's a way to namespace these step definitions
|
2
|
+
|
3
|
+
When /^"nmap" is installed$/ do
|
4
|
+
ensure_cli_installed("nmap")
|
5
|
+
end
|
6
|
+
|
7
|
+
When /^the target hostname is "(.*?)"$/ do |host|
|
8
|
+
set_hostname host
|
9
|
+
end
|
10
|
+
|
11
|
+
When /^I launch an "nmap" attack with:$/ do |command|
|
12
|
+
command.gsub!('<hostname>', hostname)
|
13
|
+
run command
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Given /^"sslyze" is installed$/ do
|
2
|
+
ensure_python_script_installed('sslyze')
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^I launch an "sslyze" attack with:$/ do |command|
|
6
|
+
sslyze_path = path_to_python_script("sslyze")
|
7
|
+
|
8
|
+
command.gsub!('<hostname>', hostname)
|
9
|
+
command.gsub!('<sslyze_path>', sslyze_path)
|
10
|
+
run command
|
11
|
+
end
|
12
|
+
|
13
|
+
Then /^the key size should be at least (\d+)$/ do |arg1|
|
14
|
+
pending # express the regexp above with the code you wish you had
|
15
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'English'
|
2
|
+
# English.rb adds human-readable names for things like $?, $!, etc.:
|
3
|
+
# http://www.ruby-doc.org/stdlib-1.9.3/libdoc/English/rdoc/English_rb.html
|
4
|
+
|
5
|
+
module Gauntlt
|
6
|
+
module Support
|
7
|
+
module CliHelper
|
8
|
+
def cli_installed?(bin_name)
|
9
|
+
`which #{bin_name}` && $CHILD_STATUS.success?
|
10
|
+
end
|
11
|
+
|
12
|
+
def ensure_cli_installed(bin)
|
13
|
+
raise "#{bin} is not installed or is not in your path" unless cli_installed?(bin)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
World(Gauntlt::Support::CliHelper)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'curb'
|
2
|
+
|
3
|
+
module CookieHelper
|
4
|
+
def cookies_for(url)
|
5
|
+
[].tap do |returner|
|
6
|
+
c = Curl::Easy.perform(url) do |curl|
|
7
|
+
curl.follow_location = true
|
8
|
+
curl.enable_cookies = true
|
9
|
+
|
10
|
+
curl.on_header do |header|
|
11
|
+
returner << "#{$1}=#{$2}" if header =~ /^Set-Cookie: ([^=]+)=([^;]+;)/
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def cookies
|
18
|
+
raise "No cookies set" if @cookies.nil?
|
19
|
+
|
20
|
+
@cookies
|
21
|
+
end
|
22
|
+
|
23
|
+
def set_cookies(a)
|
24
|
+
@cookies = a
|
25
|
+
end
|
26
|
+
end
|
27
|
+
World(CookieHelper)
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'aruba/cucumber'
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# TODO: get this explicit require to work
|
2
|
+
# require 'gauntlt/support/cli_helper'
|
3
|
+
|
4
|
+
module Gauntlt
|
5
|
+
module Support
|
6
|
+
module PythonScriptHelper
|
7
|
+
DOWNLOAD_URLS = {
|
8
|
+
'sslyze' => 'https://github.com/iSECPartners/sslyze',
|
9
|
+
'sqlmap' => 'https://github.com/sqlmapproject/sqlmap'
|
10
|
+
}
|
11
|
+
|
12
|
+
def python_installed?
|
13
|
+
cli_installed?('python')
|
14
|
+
end
|
15
|
+
|
16
|
+
def shell_variable_name_for(script_name)
|
17
|
+
script_name.upcase + '_PATH'
|
18
|
+
end
|
19
|
+
|
20
|
+
def path_to_python_script(script_name)
|
21
|
+
shell_variable_name = shell_variable_name_for(script_name)
|
22
|
+
ENV[shell_variable_name]
|
23
|
+
end
|
24
|
+
|
25
|
+
def script_exists?(script_name)
|
26
|
+
path = path_to_python_script(script_name)
|
27
|
+
File.exists?(path) if path
|
28
|
+
end
|
29
|
+
|
30
|
+
def python_script_installed?(script_name)
|
31
|
+
python_installed? && script_exists?(script_name)
|
32
|
+
end
|
33
|
+
|
34
|
+
def ensure_python_script_installed(script_name, debug=false)
|
35
|
+
python_script_installed?(script_name) || begin
|
36
|
+
shell_variable_name = '$' + shell_variable_name_for(script_name)
|
37
|
+
|
38
|
+
msg = <<-EOS
|
39
|
+
#{script_name}.py not installed or #{shell_variable_name} not set!
|
40
|
+
|
41
|
+
1. Download #{script_name} from: #{DOWNLOAD_URLS[script_name]}
|
42
|
+
2. In your .zshrc or .bash_profile (or whatever), set #{shell_variable_name}
|
43
|
+
|
44
|
+
export #{shell_variable_name.gsub('$', '')}=/path/to/#{script_name}.py
|
45
|
+
|
46
|
+
3. Make sure you have python installed:
|
47
|
+
|
48
|
+
$ which python
|
49
|
+
|
50
|
+
|
51
|
+
EOS
|
52
|
+
|
53
|
+
if debug
|
54
|
+
msg += <<-EOS
|
55
|
+
python installed : #{python_installed?}
|
56
|
+
script_exists? : #{script_exists?(script_name)}
|
57
|
+
shell_variable_name: #{shell_variable_name_for(script_name)}
|
58
|
+
path: #{path_to_python_script(script_name)}
|
59
|
+
path_via_echo: #{`echo #{'$'+shell_variable_name_for(script_name)}`}
|
60
|
+
EOS
|
61
|
+
end
|
62
|
+
|
63
|
+
raise msg
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
World(Gauntlt::Support::PythonScriptHelper)
|