gauntlt 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +11 -3
- data/Gemfile +1 -1
- data/README.md +81 -62
- data/bin/gauntlt +6 -1
- data/config/warble.rb +6 -0
- data/examples/dirb/dirb.attack +18 -0
- data/examples/nmap/nmap.attack +4 -7
- data/examples/nmap/os_detection.attack +2 -2
- data/examples/nmap/simple.attack +3 -3
- data/examples/nmap/tcp_ping_ports.attack +1 -1
- data/examples/nmap/xml_output.attack +2 -2
- data/features/attack.feature +23 -2
- data/features/attacks/dirb.feature +13 -0
- data/gauntlt.gemspec +3 -3
- data/lib/gauntlt.rb +6 -0
- data/lib/gauntlt/attack.rb +4 -35
- data/lib/gauntlt/attack_adapters/dirb.rb +29 -0
- data/lib/gauntlt/attack_adapters/generic.rb +5 -1
- data/lib/gauntlt/attack_adapters/support/cli_helper.rb +16 -1
- data/lib/gauntlt/runtime.rb +61 -0
- data/lib/gauntlt/stepdef.rb +26 -0
- data/lib/gauntlt/version.rb +1 -1
- data/ready_to_rumble.sh +45 -0
- data/test/gauntlt/attack_test.rb +11 -62
- data/test/gauntlt/runtime_test.rb +57 -0
- data/test/gauntlt/stepdef_test.rb +42 -0
- data/vendor/dirb203.tar.gz +0 -0
- metadata +21 -8
data/.travis.yml
CHANGED
@@ -6,10 +6,18 @@ before_install:
|
|
6
6
|
- git submodule update --init --recursive
|
7
7
|
before_script:
|
8
8
|
- sudo apt-get install nmap
|
9
|
-
- export SSLYZE_PATH="/home/
|
10
|
-
- export SQLMAP_PATH="/home/
|
9
|
+
- export SSLYZE_PATH="/home/travis/build/gauntlt/gauntlt/vendor/sslyze/sslyze.py"
|
10
|
+
- export SQLMAP_PATH="/home/travis/build/gauntlt/gauntlt/vendor/sqlmap/sqlmap.py"
|
11
11
|
- 'cd vendor/Garmr && sudo python setup.py install && cd ../..'
|
12
|
+
- 'cd vendor && tar xvfz dirb203.tar.gz && cd dirb && ./configure && make && sudo cp dirb /usr/local/bin/ && cd ..'
|
13
|
+
- export DIRB_WORDLISTS="/home/travis/build/gauntlt/gauntlt/vendor/dirb/wordlists"
|
12
14
|
|
13
15
|
matrix:
|
14
16
|
allow_failures:
|
15
|
-
- rvm: jruby-head
|
17
|
+
- rvm: jruby-head
|
18
|
+
|
19
|
+
notifications:
|
20
|
+
irc:
|
21
|
+
channels:
|
22
|
+
- "chat.freenode.net#gauntlt"
|
23
|
+
use_notice: true
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,7 @@ gauntlt is a ruggedization framework
|
|
4
4
|
|
5
5
|
## PROJECT STATUS
|
6
6
|
|
7
|
-
|
7
|
+
gauntlt is under active development. We welcome community feedback and contributions. Please file issues via github and follow the project on twitter: [@gauntlt](https://twitter.com/gauntlt).
|
8
8
|
|
9
9
|
Have questions? Ask us anything on the [gauntlt google group](http://bit.ly/gauntlt_group) or find us on irc at [#gauntlt](http://webchat.freenode.net/?channels=gauntlt) (irc.freenode.net).
|
10
10
|
|
@@ -16,43 +16,49 @@ You will need ruby version `1.9.3` to run gauntlt, but you can run gauntlt again
|
|
16
16
|
|
17
17
|
1. Install the gem
|
18
18
|
|
19
|
-
|
19
|
+
```shell
|
20
|
+
$ gem install gauntlt
|
21
|
+
```
|
20
22
|
|
21
23
|
2. Create an attack file and put it anywhere you like
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
25
|
+
```gherkin
|
26
|
+
# simplest.attack
|
27
|
+
Feature: simplest attack possible
|
28
|
+
Scenario:
|
29
|
+
When I launch a "generic" attack with:
|
30
|
+
"""
|
31
|
+
ls -a
|
32
|
+
"""
|
33
|
+
Then the output should contain:
|
34
|
+
"""
|
35
|
+
.
|
36
|
+
"""
|
37
|
+
```
|
34
38
|
|
35
39
|
3. Run gauntlt to launch the attack defined above
|
36
40
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
# you can also specify one or more paths yourself:
|
43
|
-
$ gauntlt my_attacks/*.attack some_other.file
|
41
|
+
```shell
|
42
|
+
$ gauntlt
|
43
|
+
# equivalent to gauntlt ./**/*.attack
|
44
|
+
# by default, gauntlt will search in the current folder
|
45
|
+
# and its subfolders for files with the .attack extension
|
44
46
|
|
47
|
+
# you can also specify one or more paths yourself:
|
48
|
+
$ gauntlt my_attacks/*.attack some_other.file
|
49
|
+
```
|
45
50
|
|
46
|
-
|
51
|
+
For more attacks, refer to the [examples](https://github.com/gauntlt/gauntlt/tree/master/examples).
|
47
52
|
|
48
53
|
4. Other commands
|
49
54
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
# get help
|
54
|
-
$ gauntlt --help
|
55
|
+
```shell
|
56
|
+
# list defined attacks
|
57
|
+
$ gauntlt --list
|
55
58
|
|
59
|
+
# get help
|
60
|
+
$ gauntlt --help
|
61
|
+
```
|
56
62
|
|
57
63
|
## ATTACK ADAPTERS
|
58
64
|
|
@@ -77,41 +83,44 @@ To use gauntlt, you will need one or more attack files. An attack file is a plai
|
|
77
83
|
|
78
84
|
### What an attack file looks like
|
79
85
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
+
```gherkin
|
87
|
+
# my.attack
|
88
|
+
Feature: Description for all scenarios in this file
|
89
|
+
Scenario: Description of this scenario
|
90
|
+
Given ...
|
91
|
+
When ...
|
92
|
+
Then ...
|
86
93
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
94
|
+
Scenario: ...
|
95
|
+
Given ...
|
96
|
+
When ...
|
97
|
+
Then ...
|
98
|
+
```
|
91
99
|
|
92
100
|
You can have as many `Scenario` entries as you like, but it is good practice to keep the number low and to ensure that the scenarios in an attack file are all related. You can create as many attack files as you like and organize them in folders and sub-folders as well.
|
93
101
|
|
94
102
|
There are a large number of step definitions available, but you can do a lot with just these 3:
|
95
103
|
|
96
|
-
|
104
|
+
```gherkin
|
105
|
+
Feature: Attack with kindness
|
97
106
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
107
|
+
Scenario: Ensure I am not mean
|
108
|
+
# verify a given attack adapter is installed
|
109
|
+
# HIGHLY RECOMMENDED to catch installation/configuration problems
|
110
|
+
Given "kindness" is installed
|
102
111
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
# Check exit status and STDOUT
|
110
|
-
Then it should pass with:
|
111
|
-
"""
|
112
|
-
very_kind
|
113
|
-
"""
|
112
|
+
# Execute the attack
|
113
|
+
When I launch a "kindness" attack with:
|
114
|
+
"""
|
115
|
+
whoami # EXACT commands to be executed on the command line
|
116
|
+
"""
|
114
117
|
|
118
|
+
# Check exit status and STDOUT
|
119
|
+
Then it should pass with:
|
120
|
+
"""
|
121
|
+
very_kind
|
122
|
+
"""
|
123
|
+
```
|
115
124
|
|
116
125
|
## FOR DEVELOPERS
|
117
126
|
|
@@ -119,30 +128,40 @@ NOTE: We currently use `ruby 1.9.3` and `JRuby 1.7.0` for development and testin
|
|
119
128
|
|
120
129
|
1. Clone the git repo and get the submodules
|
121
130
|
|
122
|
-
|
131
|
+
```shell
|
132
|
+
$ git clone --recursive git://github.com/gauntlt/gauntlt.git
|
133
|
+
```
|
123
134
|
|
124
135
|
2. Install bundler
|
125
136
|
|
126
|
-
|
137
|
+
```shell
|
138
|
+
$ gem install bundler
|
139
|
+
```
|
127
140
|
|
128
141
|
3. Install dependencies
|
129
142
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
143
|
+
```shell
|
144
|
+
$ bundle
|
145
|
+
# if you get errors, you may need to install curl libs first
|
146
|
+
# on ubuntu:
|
147
|
+
# $ sudo apt-get install libcurl4-openssl-dev
|
148
|
+
```
|
135
149
|
|
136
150
|
4. Run the cucumber features and rspec examples
|
137
151
|
|
138
|
-
|
152
|
+
```shell
|
153
|
+
$ bundle exec rake
|
154
|
+
```
|
139
155
|
|
140
156
|
5. Launch attacks with bin/gauntlt
|
141
157
|
|
142
|
-
|
158
|
+
```shell
|
159
|
+
$ bin/gauntlt attack
|
160
|
+
```
|
143
161
|
|
144
162
|
5. Refer to the features directory for usage examples and please write cucumber features for any new functionality you wish to submit.
|
145
163
|
|
164
|
+
6. Run the ready_to_rumble.sh script to make sure you have all the dependencies installed like sqlmap and sslyze. This is meant to replicate the travis setup for devs. This should be a rake task instead.
|
146
165
|
|
147
166
|
## ROADMAP
|
148
167
|
|
@@ -156,4 +175,4 @@ gauntlt is licensed under The MIT License. See the LICENSE file in the repo or v
|
|
156
175
|
[nmap]: http://nmap.org
|
157
176
|
[sslyze]: https://github.com/iSECPartners/sslyze
|
158
177
|
[sqlmap]: http://sqlmap.org
|
159
|
-
[garmr]: https://github.com/mozilla/Garmr
|
178
|
+
[garmr]: https://github.com/mozilla/Garmr
|
data/bin/gauntlt
CHANGED
@@ -21,6 +21,7 @@ EOS
|
|
21
21
|
:multi => true
|
22
22
|
|
23
23
|
opt :list, "List defined attacks"
|
24
|
+
opt :steps, "List all available step definitions"
|
24
25
|
end
|
25
26
|
|
26
27
|
opts[:path] = if ARGV.empty?
|
@@ -33,6 +34,10 @@ if opts[:list]
|
|
33
34
|
attack_list = Gauntlt.attacks.map{|s| " #{s}"}.join("\n")
|
34
35
|
puts "Defined attacks: #{}"
|
35
36
|
puts attack_list
|
37
|
+
elsif opts[:steps]
|
38
|
+
all_step_defs = Gauntlt.stepdefs( opts[:path], opts[:tags].join(',') )
|
39
|
+
puts all_step_defs[:gauntlt].sort
|
36
40
|
else
|
37
41
|
Gauntlt.attack( opts[:path], opts[:tags].join(',') )
|
38
|
-
end
|
42
|
+
end
|
43
|
+
|
data/config/warble.rb
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
Warbler::Config.new do |config|
|
2
|
+
config.dirs = %w(bin features vendor gem_tasks lib)
|
3
|
+
config.includes = FileList["*.rb"] # I don't know why I have to force the
|
4
|
+
# ruby file inclusion, but for now it solves the problem described
|
5
|
+
# at https://github.com/gauntlt/gauntlt/issues/45
|
6
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
@slow
|
2
|
+
Feature: Run dirb scan on a URL
|
3
|
+
|
4
|
+
Scenario: Use dirb to scan a website for basic security requirements and the DIRB_WORDLISTS environment variable must be set in your path. You can use different wordlists by changing the environment variable.
|
5
|
+
Given "dirb" is installed
|
6
|
+
And the following profile:
|
7
|
+
| name | value |
|
8
|
+
| hostname | https://google.com |
|
9
|
+
| dirb_wordlists_path | Overwritten by $DIRB_WORDLISTS |
|
10
|
+
| wordlist | vulns/tests.txt |
|
11
|
+
When I launch a "dirb" attack with:
|
12
|
+
"""
|
13
|
+
dirb <hostname> <dirb_wordlists_path>/<wordlist>
|
14
|
+
"""
|
15
|
+
Then the output should contain:
|
16
|
+
"""
|
17
|
+
FOUND: 0
|
18
|
+
"""
|
data/examples/nmap/nmap.attack
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
@slow
|
2
2
|
|
3
|
-
Feature: nmap attacks for
|
3
|
+
Feature: nmap attacks for scanme.nmap.org and to use this for your tests, change the value in the profile
|
4
4
|
Background:
|
5
5
|
Given "nmap" is installed
|
6
6
|
And the following profile:
|
7
7
|
| name | value |
|
8
|
-
| hostname |
|
8
|
+
| hostname | scanme.nmap.org |
|
9
9
|
| tcp_ping_ports | 22,25,80,443 |
|
10
10
|
|
11
11
|
Scenario: Verify server is open on expected set of ports using the nmap fast flag
|
@@ -16,9 +16,6 @@ Feature: nmap attacks for example.com
|
|
16
16
|
Then the output should contain:
|
17
17
|
"""
|
18
18
|
80/tcp open http
|
19
|
-
443/tcp open https
|
20
|
-
3128/tcp open squid-http
|
21
|
-
8080/tcp open http-proxy
|
22
19
|
"""
|
23
20
|
Scenario: Verify that there are no unexpected ports open
|
24
21
|
When I launch an "nmap" attack with:
|
@@ -39,7 +36,7 @@ Feature: nmap attacks for example.com
|
|
39
36
|
And the file "foo.xml" should contain XML:
|
40
37
|
| css |
|
41
38
|
| ports port[protocol="tcp"][portid="80"] state[state="open"] |
|
42
|
-
| ports port[protocol="tcp"][portid="443"] state[state="
|
39
|
+
| ports port[protocol="tcp"][portid="443"] state[state="closed"] |
|
43
40
|
And the file "foo.xml" should not contain XML:
|
44
41
|
| css |
|
45
|
-
| ports port[protocol="tcp"][portid="123"] state[state="open"] |
|
42
|
+
| ports port[protocol="tcp"][portid="123"] state[state="open"] |
|
@@ -4,7 +4,7 @@ Feature: OS detection
|
|
4
4
|
Given "nmap" is installed
|
5
5
|
And the following profile:
|
6
6
|
| name | value |
|
7
|
-
| hostname |
|
7
|
+
| hostname | scanme.nmap.org |
|
8
8
|
|
9
9
|
@slow
|
10
10
|
Scenario: Detect OS
|
@@ -14,5 +14,5 @@ Feature: OS detection
|
|
14
14
|
"""
|
15
15
|
Then the output should contain:
|
16
16
|
"""
|
17
|
-
|
17
|
+
Apache
|
18
18
|
"""
|
data/examples/nmap/simple.attack
CHANGED
@@ -4,7 +4,7 @@ Feature: simple nmap attack (sanity check)
|
|
4
4
|
Given "nmap" is installed
|
5
5
|
And the following profile:
|
6
6
|
| name | value |
|
7
|
-
| hostname |
|
7
|
+
| hostname | scanme.nmap.org |
|
8
8
|
|
9
9
|
Scenario: Verify server is available on standard web ports
|
10
10
|
When I launch an "nmap" attack with:
|
@@ -13,6 +13,6 @@ Feature: simple nmap attack (sanity check)
|
|
13
13
|
"""
|
14
14
|
Then the output should contain:
|
15
15
|
"""
|
16
|
-
80/tcp open
|
17
|
-
443/tcp
|
16
|
+
80/tcp open http
|
17
|
+
443/tcp closed https
|
18
18
|
"""
|
@@ -15,4 +15,4 @@ Feature: nmap attacks for example.com
|
|
15
15
|
Then the file "foo.xml" should contain XML:
|
16
16
|
| css |
|
17
17
|
| ports port[protocol="tcp"][portid="80"] state[state="open"] |
|
18
|
-
| ports port[protocol="tcp"][portid="22"] state[state="open"] |
|
18
|
+
| ports port[protocol="tcp"][portid="22"] state[state="open"] |
|
@@ -4,7 +4,7 @@ Feature: XML output
|
|
4
4
|
Given "nmap" is installed
|
5
5
|
And the following profile:
|
6
6
|
| name | value |
|
7
|
-
| hostname |
|
7
|
+
| hostname | scanme.nmap.org |
|
8
8
|
|
9
9
|
Scenario: Output to XML
|
10
10
|
When I launch an "nmap" attack with:
|
@@ -14,7 +14,7 @@ Feature: XML output
|
|
14
14
|
And the file "foo.xml" should contain XML:
|
15
15
|
| css |
|
16
16
|
| ports port[protocol="tcp"][portid="80"] state[state="open"] |
|
17
|
-
| ports port[protocol="tcp"][portid="443"] state[state="
|
17
|
+
| ports port[protocol="tcp"][portid="443"] state[state="closed"] |
|
18
18
|
And the file "foo.xml" should not contain XML:
|
19
19
|
| css |
|
20
20
|
| ports port[protocol="tcp"][portid="123"] state[state="open"] |
|
data/features/attack.feature
CHANGED
@@ -12,6 +12,27 @@ Feature: Verify the attack behaviour is correct
|
|
12
12
|
nmap
|
13
13
|
"""
|
14
14
|
|
15
|
+
Scenario: List defined step definitions
|
16
|
+
Given an attack "nmap" exists
|
17
|
+
And a file named "nmap.attack" with:
|
18
|
+
"""
|
19
|
+
Feature: simplest attack possible
|
20
|
+
Scenario:
|
21
|
+
When I launch a "generic" attack with:
|
22
|
+
\"\"\"
|
23
|
+
ls -a
|
24
|
+
\"\"\"
|
25
|
+
Then the output should contain:
|
26
|
+
\"\"\"
|
27
|
+
.
|
28
|
+
\"\"\"
|
29
|
+
"""
|
30
|
+
When I run `gauntlt --steps`
|
31
|
+
Then it should pass with:
|
32
|
+
"""
|
33
|
+
/^"nmap" is installed$/
|
34
|
+
"""
|
35
|
+
|
15
36
|
Scenario: Run attack
|
16
37
|
Given an attack "nmap" exists
|
17
38
|
And a file named "nmap.attack" with:
|
@@ -53,7 +74,7 @@ Feature: Verify the attack behaviour is correct
|
|
53
74
|
"""
|
54
75
|
Feature: my non-existent attack
|
55
76
|
Scenario: Fail on undefined step definition
|
56
|
-
Given
|
77
|
+
Given this_attack_would_never_exist
|
57
78
|
"""
|
58
79
|
When I run `gauntlt`
|
59
80
|
Then it should fail with:
|
@@ -73,4 +94,4 @@ Feature: Verify the attack behaviour is correct
|
|
73
94
|
Then it should fail with:
|
74
95
|
"""
|
75
96
|
No files found in path: apaththatdoesnotexist
|
76
|
-
"""
|
97
|
+
"""
|
@@ -0,0 +1,13 @@
|
|
1
|
+
@slow
|
2
|
+
Feature: dirb scan
|
3
|
+
Background:
|
4
|
+
Given an attack "dirb" exists
|
5
|
+
And I copy the attack files from the "examples/dirb" folder
|
6
|
+
And the following attack files exist:
|
7
|
+
| filename |
|
8
|
+
| dirb.attack |
|
9
|
+
When I run `gauntlt`
|
10
|
+
Then it should pass with:
|
11
|
+
"""
|
12
|
+
4 steps (4 passed)
|
13
|
+
"""
|
data/gauntlt.gemspec
CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = "gauntlt"
|
7
7
|
s.version = Gauntlt::VERSION
|
8
8
|
s.authors = ["James Wickett", "Mani Tadayon"]
|
9
|
-
s.email = ["james@
|
9
|
+
s.email = ["james@gauntlt.org"]
|
10
10
|
s.homepage = "https://github.com/gauntlt/gauntlt"
|
11
11
|
s.summary = %q{behaviour-driven security using cucumber}
|
12
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.}
|
@@ -16,11 +16,11 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
17
|
s.require_paths = ["lib"]
|
18
18
|
|
19
|
-
s.add_development_dependency "cucumber"
|
19
|
+
s.add_development_dependency "cucumber", "~>1.2.0"
|
20
20
|
s.add_development_dependency "aruba"
|
21
21
|
s.add_development_dependency "rake"
|
22
22
|
s.add_development_dependency "sinatra"
|
23
|
-
|
23
|
+
|
24
24
|
s.add_runtime_dependency "cucumber"
|
25
25
|
s.add_runtime_dependency "aruba"
|
26
26
|
s.add_runtime_dependency "nokogiri"
|
data/lib/gauntlt.rb
CHANGED
@@ -3,6 +3,7 @@ require "gauntlt/version"
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'cucumber'
|
5
5
|
require 'gauntlt/attack'
|
6
|
+
require 'gauntlt/stepdef'
|
6
7
|
|
7
8
|
module Gauntlt
|
8
9
|
CURRENT_DIR = if defined?(Pathname) # ruby 1.9
|
@@ -31,5 +32,10 @@ module Gauntlt
|
|
31
32
|
def attack(path, tags=[])
|
32
33
|
Attack.new(path, tags).run
|
33
34
|
end
|
35
|
+
|
36
|
+
def stepdefs(path, tags=[])
|
37
|
+
cuke_runtime = Gauntlt::Runtime.cuke_runtime(path, tags)
|
38
|
+
Stepdef.sources(cuke_runtime)
|
39
|
+
end
|
34
40
|
end
|
35
41
|
end
|
data/lib/gauntlt/attack.rb
CHANGED
@@ -1,46 +1,15 @@
|
|
1
|
-
require '
|
2
|
-
require 'cucumber/cli/main'
|
1
|
+
require 'gauntlt/runtime'
|
3
2
|
|
4
3
|
module Gauntlt
|
5
4
|
class Attack
|
6
|
-
|
7
|
-
class ExecutionFailed < StandardError; end
|
8
|
-
|
9
|
-
attr_accessor :path, :attack_files, :tags
|
5
|
+
attr_accessor :runtime
|
10
6
|
|
11
7
|
def initialize(path, tags=[])
|
12
|
-
self.
|
13
|
-
self.attack_files = self.class.attack_files_for(path)
|
14
|
-
self.tags = tags
|
15
|
-
|
16
|
-
raise NoFilesFound.new("No files found in path: #{path}") if attack_files.empty?
|
8
|
+
self.runtime = Runtime.new(path, tags)
|
17
9
|
end
|
18
10
|
|
19
11
|
def run
|
20
|
-
|
21
|
-
args += ['--tags', tags] unless tags.empty?
|
22
|
-
|
23
|
-
cli = Cucumber::Cli::Main.new(args)
|
24
|
-
|
25
|
-
if cli.execute! # cucumber failed, returning true
|
26
|
-
raise ExecutionFailed.new("Bad or undefined attack!")
|
27
|
-
else # cucumber executed successfully, returning false
|
28
|
-
true
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class << self
|
33
|
-
def attack_files_for(path)
|
34
|
-
path.split(' ').map{|p| Dir.glob(p)}.flatten
|
35
|
-
end
|
36
|
-
|
37
|
-
def base_dir
|
38
|
-
File.expand_path( File.dirname(__FILE__) )
|
39
|
-
end
|
40
|
-
|
41
|
-
def adapters_dir
|
42
|
-
File.join(base_dir, "attack_adapters")
|
43
|
-
end
|
12
|
+
runtime.execute!
|
44
13
|
end
|
45
14
|
end
|
46
15
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
When /^"dirb" is installed$/ do
|
2
|
+
ensure_cli_installed("dirb")
|
3
|
+
end
|
4
|
+
|
5
|
+
When /^the DIRB_WORDLISTS environment variable is set$/ do
|
6
|
+
ensure_shell_variable_set("DIRB_WORDLISTS")
|
7
|
+
end
|
8
|
+
|
9
|
+
When /^I launch a "dirb" attack with:$/ do |command|
|
10
|
+
add_to_profile('dirb_wordlists_path', get_shell_variable("DIRB_WORDLISTS"))
|
11
|
+
run_with_profile command
|
12
|
+
@raw_dirb_output = all_output
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# When I run a "dirb" scan with this word list:
|
17
|
+
# """
|
18
|
+
# Admin
|
19
|
+
# Administror
|
20
|
+
# Secret-stats
|
21
|
+
# dashboard
|
22
|
+
# devtools
|
23
|
+
# """
|
24
|
+
|
25
|
+
# When I run a "dirb" scan against an apache server
|
26
|
+
# When I run a "dirb" scan against a nginx server
|
27
|
+
# When I run a "dirb" scan with the small wordlist
|
28
|
+
# When I run a "dirb" scan with the large wordlist
|
29
|
+
# When I run a "dirb" scan with my custom wordlist: /path/to/wordlist.txt
|
@@ -14,6 +14,21 @@ module Gauntlt
|
|
14
14
|
def ensure_cli_installed(bin)
|
15
15
|
raise "#{bin} is not installed or is not in your path" unless cli_installed?(bin)
|
16
16
|
end
|
17
|
+
|
18
|
+
def ensure_shell_variable_set(shell_variable)
|
19
|
+
raise "#{shell_variable} is not set" unless shell_variable_exists?(shell_variable)
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_shell_variable(shell_variable)
|
23
|
+
ENV[shell_variable]
|
24
|
+
end
|
25
|
+
|
26
|
+
def shell_variable_exists?(shell_variable)
|
27
|
+
path = get_shell_variable(shell_variable)
|
28
|
+
File.exists?(path) if path
|
29
|
+
end
|
30
|
+
|
31
|
+
|
17
32
|
end
|
18
33
|
end
|
19
34
|
end
|
@@ -22,4 +37,4 @@ World(Gauntlt::Support::CliHelper)
|
|
22
37
|
|
23
38
|
Before('@slow') do
|
24
39
|
@aruba_timeout_seconds = 30
|
25
|
-
end
|
40
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'cucumber'
|
2
|
+
require 'cucumber/runtime'
|
3
|
+
require 'cucumber/cli/main'
|
4
|
+
|
5
|
+
module Gauntlt
|
6
|
+
class Runtime
|
7
|
+
class NoFilesFound < StandardError; end
|
8
|
+
class ExecutionFailed < StandardError; end
|
9
|
+
|
10
|
+
attr_accessor :path, :attack_files, :tags
|
11
|
+
|
12
|
+
def initialize(path, tags=[])
|
13
|
+
self.path = path
|
14
|
+
self.attack_files = self.class.attack_files_for(path)
|
15
|
+
self.tags = tags
|
16
|
+
|
17
|
+
raise NoFilesFound.new("No files found in path: #{path}") if attack_files.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def cuke_cli
|
21
|
+
args = attack_files + ['--strict', '--require', self.class.adapters_dir]
|
22
|
+
args += ['--tags', tags] unless tags.empty?
|
23
|
+
|
24
|
+
Cucumber::Cli::Main.new(args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def cuke_config
|
28
|
+
cli.config
|
29
|
+
end
|
30
|
+
|
31
|
+
def cuke_runtime
|
32
|
+
Cucumber::Runtime.new(cuke_cli.configuration)
|
33
|
+
end
|
34
|
+
|
35
|
+
def execute!
|
36
|
+
if cuke_cli.execute! # cucumber failed, returning true
|
37
|
+
raise ExecutionFailed.new("Bad or undefined attack!")
|
38
|
+
else # cucumber executed successfully, returning false
|
39
|
+
true
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class << self
|
44
|
+
def cuke_runtime(*args)
|
45
|
+
self.new(*args).cuke_runtime
|
46
|
+
end
|
47
|
+
|
48
|
+
def attack_files_for(path)
|
49
|
+
path.split(' ').map{|p| Dir.glob(p)}.flatten
|
50
|
+
end
|
51
|
+
|
52
|
+
def base_dir
|
53
|
+
File.expand_path( File.dirname(__FILE__) )
|
54
|
+
end
|
55
|
+
|
56
|
+
def adapters_dir
|
57
|
+
File.join(base_dir, "attack_adapters")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'gauntlt/runtime'
|
2
|
+
|
3
|
+
module Gauntlt
|
4
|
+
class Stepdef
|
5
|
+
class << self
|
6
|
+
def find(cuke_runtime)
|
7
|
+
cuke_runtime.send(:load_step_definitions)
|
8
|
+
cuke_runtime.instance_variable_get(:@support_code).step_definitions
|
9
|
+
end
|
10
|
+
|
11
|
+
def sources(cuke_runtime)
|
12
|
+
returner = {:aruba => [], :gauntlt => []}
|
13
|
+
|
14
|
+
self.find(cuke_runtime).each do |step_definition|
|
15
|
+
if step_definition.file =~ /aruba/
|
16
|
+
returner[:aruba] << step_definition.regexp_source
|
17
|
+
else
|
18
|
+
returner[:gauntlt] << step_definition.regexp_source
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
returner
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/gauntlt/version.rb
CHANGED
data/ready_to_rumble.sh
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
# This little script tries to mimic the .travis.yml setup so that when we are
|
3
|
+
# doing local dev, we can run tests and make sure we are passing CI.
|
4
|
+
|
5
|
+
NMAP=`which nmap`
|
6
|
+
GARMR=`which garmr`
|
7
|
+
DIRB=`which dirb`
|
8
|
+
|
9
|
+
if [ -z $NMAP ]
|
10
|
+
then
|
11
|
+
echo "nmap is not installed in your path, try installing it and adding it to your path"
|
12
|
+
exit
|
13
|
+
fi
|
14
|
+
|
15
|
+
if [ -z $SSLYZE_PATH ]
|
16
|
+
then
|
17
|
+
echo "SSLYZE_PATH environment variable unset, try setting it to ./vendor/sslyze/sslyze.py if you havent updated the submodules we use in gauntlt, run this first: git submodule update --init --recursive"
|
18
|
+
exit
|
19
|
+
fi
|
20
|
+
|
21
|
+
if [ -z $SQLMAP_PATH ]
|
22
|
+
then
|
23
|
+
echo "SQLMAP_PATH environment variable unset, try setting it to ./vendor/sslyze/sqlmap.py if you havent updated the submodules we use in gauntlt, run this first: git submodule update --init --recursive"
|
24
|
+
exit
|
25
|
+
fi
|
26
|
+
|
27
|
+
if [ -z $GARMR ]
|
28
|
+
then
|
29
|
+
echo "garmr is not installed in your path, try installing it 'cd vendor/Garmr && sudo python setup.py install && cd ../..'"
|
30
|
+
exit
|
31
|
+
fi
|
32
|
+
|
33
|
+
if [ -z $DIRB ]
|
34
|
+
then
|
35
|
+
echo "dirb is not installed in your path, try installing it 'wget http://downloads.sourceforge.net/project/dirb/dirb/2.03/dirb203.tar.gz && tar xvfz dirb203.tar.gz && cd dirb && ./configure && make && cd ..'"
|
36
|
+
exit
|
37
|
+
fi
|
38
|
+
|
39
|
+
if [ -z $DIRB_WORDLISTS ]
|
40
|
+
then
|
41
|
+
echo "DIRB_WORDLISTS environment variable not set, please set it. Usually this is where you extracted dirb in a directory called 'wordlists'"
|
42
|
+
exit
|
43
|
+
fi
|
44
|
+
|
45
|
+
echo "You are ready to rumble!"
|
data/test/gauntlt/attack_test.rb
CHANGED
@@ -1,73 +1,22 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
# .initialize
|
8
|
-
# sets path and attack_files when attack file exists
|
9
|
-
lambda do
|
10
|
-
assert subject.path, :== => :foo
|
11
|
-
assert subject.attack_files, :== => [:bar]
|
12
|
-
end.call
|
13
|
-
|
14
|
-
# .initialize
|
15
|
-
# raises an error if the attack file does not exist
|
16
|
-
lambda do
|
17
|
-
begin
|
18
|
-
stub(Gauntlt::Attack, :method => :attack_files_for, :return => []) do
|
19
|
-
Gauntlt::Attack.new(:foo)
|
20
|
-
end
|
21
|
-
rescue
|
22
|
-
assert $!, :is_a? => Gauntlt::Attack::NoFilesFound
|
23
|
-
assert $!.message, :=~ => /No files found in path/
|
24
|
-
end
|
25
|
-
end.call
|
26
|
-
|
27
|
-
# #run
|
28
|
-
# executes the attack file, specifies failure for undefined steps and specifies the attacks_dir
|
3
|
+
# #new
|
4
|
+
# initializes runtime with passed arguments
|
29
5
|
lambda do
|
30
|
-
|
31
|
-
|
32
|
-
stub(Gauntlt::Attack, :spy => :adapters_dir, :return => '/bar') do
|
33
|
-
stub(subject, :spy => :attack_files, :return => ['/bar/baz.attack']) do
|
34
|
-
stub(mock_cli, :spy => :execute!) do
|
35
|
-
stub(Cucumber::Cli::Main, :spy => :new, :return => mock_cli) do
|
36
|
-
assert subject.run, :== => true
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
6
|
+
stub(Gauntlt::Runtime, :spy => :new) do
|
7
|
+
Gauntlt::Attack.new(:foo)
|
40
8
|
end
|
41
9
|
end.call
|
42
10
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
stub(Gauntlt::Attack, :spy => :adapters_dir) do
|
49
|
-
stub(mock_cli, :spy => :execute!, :return => nil) do
|
50
|
-
stub(Cucumber::Cli::Main, :spy => :new, :return => mock_cli) do
|
51
|
-
assert subject.run, :== => true
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end.call
|
11
|
+
mock_runtime = Object.new
|
12
|
+
subject = stub(Gauntlt::Runtime, :method => :new, :return => mock_runtime) do
|
13
|
+
Gauntlt::Attack.new(:foo)
|
14
|
+
end
|
56
15
|
|
57
16
|
# #run
|
58
|
-
#
|
17
|
+
# executes and returns value
|
59
18
|
lambda do
|
60
|
-
|
61
|
-
|
62
|
-
stub(Gauntlt::Attack, :spy => :adapters_dir) do
|
63
|
-
stub(mock_cli, :spy => :execute!, :return => true) do
|
64
|
-
stub(Cucumber::Cli::Main, :spy => :new, :return => mock_cli) do
|
65
|
-
begin
|
66
|
-
subject.run
|
67
|
-
rescue
|
68
|
-
assert $!, :is_a? => subject.class::ExecutionFailed
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
19
|
+
stub(mock_runtime, :method => :execute!, :return => :anything_at_all) do
|
20
|
+
assert subject.run, :== => :anything_at_all
|
72
21
|
end
|
73
22
|
end.call
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
subject = stub(Gauntlt::Runtime, :method => :attack_files_for, :return => [:bar]) do
|
4
|
+
Gauntlt::Runtime.new(:foo)
|
5
|
+
end
|
6
|
+
|
7
|
+
# .initialize
|
8
|
+
# sets path and attack_files when attack file exists
|
9
|
+
lambda do
|
10
|
+
assert subject.path, :== => :foo
|
11
|
+
assert subject.attack_files, :== => [:bar]
|
12
|
+
end.call
|
13
|
+
|
14
|
+
# .initialize
|
15
|
+
# raises an error if the attack file does not exist
|
16
|
+
lambda do
|
17
|
+
begin
|
18
|
+
stub(Gauntlt::Runtime, :method => :attack_files_for, :return => []) do
|
19
|
+
Gauntlt::Runtime.new(:foo)
|
20
|
+
end
|
21
|
+
rescue
|
22
|
+
assert $!, :is_a? => Gauntlt::Runtime::NoFilesFound
|
23
|
+
assert $!.message, :=~ => /No files found in path/
|
24
|
+
end
|
25
|
+
end.call
|
26
|
+
|
27
|
+
# #run
|
28
|
+
# returns nil if if Cucumber::Cli::Main.execute succeeds (i.e. returns nil)
|
29
|
+
lambda do
|
30
|
+
mock_cli = Object.new
|
31
|
+
|
32
|
+
stub(Gauntlt::Runtime, :spy => :adapters_dir) do
|
33
|
+
stub(mock_cli, :spy => :execute!, :return => nil) do
|
34
|
+
stub(Cucumber::Cli::Main, :spy => :new, :return => mock_cli) do
|
35
|
+
subject.execute!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end.call
|
40
|
+
|
41
|
+
# #run
|
42
|
+
# raises an error if Cucumber::Cli::Main.execute fails (i.e. returns true)
|
43
|
+
lambda do
|
44
|
+
mock_cli = Object.new
|
45
|
+
|
46
|
+
stub(Gauntlt::Runtime, :spy => :adapters_dir) do
|
47
|
+
stub(mock_cli, :spy => :execute!, :return => true) do
|
48
|
+
stub(Cucumber::Cli::Main, :spy => :new, :return => mock_cli) do
|
49
|
+
begin
|
50
|
+
subject.execute!
|
51
|
+
rescue
|
52
|
+
assert $!, :is_a? => subject.class::ExecutionFailed
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end.call
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
mock_cuke_runtime = Object.new
|
4
|
+
def mock_cuke_runtime.load_step_definitions
|
5
|
+
mock_support_code = Object.new
|
6
|
+
def mock_support_code.step_definitions
|
7
|
+
[:foo, :bar]
|
8
|
+
end
|
9
|
+
|
10
|
+
@support_code = mock_support_code
|
11
|
+
end
|
12
|
+
|
13
|
+
# #find
|
14
|
+
# roots in cucumber innards to extract step definitions
|
15
|
+
lambda do
|
16
|
+
assert Gauntlt::Stepdef.find(mock_cuke_runtime), :== => [:foo, :bar]
|
17
|
+
end.call
|
18
|
+
|
19
|
+
# #sources
|
20
|
+
# returns regexp source for each step definition
|
21
|
+
lambda do
|
22
|
+
module StepDef
|
23
|
+
def file; end
|
24
|
+
def regexp_source; end
|
25
|
+
end
|
26
|
+
|
27
|
+
mock_step_def1 = Object.new.extend(StepDef)
|
28
|
+
mock_step_def2 = Object.new.extend(StepDef)
|
29
|
+
mock_step_definitions = [ mock_step_def1 , mock_step_def2 ]
|
30
|
+
|
31
|
+
stub(Gauntlt::Stepdef, :method => :find, :return => mock_step_definitions) do
|
32
|
+
stub(mock_step_def1, :spy => :file) do
|
33
|
+
stub(mock_step_def1, :spy => :regexp_source) do
|
34
|
+
stub(mock_step_def2, :spy => :file) do
|
35
|
+
stub(mock_step_def2, :spy => :regexp_source) do
|
36
|
+
Gauntlt::Stepdef.sources(:foo)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end.call
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gauntlt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,24 +10,24 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2013-06-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: cucumber
|
17
17
|
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
|
-
- -
|
20
|
+
- - ~>
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version:
|
22
|
+
version: 1.2.0
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
none: false
|
27
27
|
requirements:
|
28
|
-
- -
|
28
|
+
- - ~>
|
29
29
|
- !ruby/object:Gem::Version
|
30
|
-
version:
|
30
|
+
version: 1.2.0
|
31
31
|
- !ruby/object:Gem::Dependency
|
32
32
|
name: aruba
|
33
33
|
requirement: !ruby/object:Gem::Requirement
|
@@ -144,7 +144,7 @@ description: Using standard Gherkin language to define security tests, gauntlt h
|
|
144
144
|
wraps cucumber functionality and provides a security testing framework that security
|
145
145
|
engineers, developers and operations teams can collaborate on together.
|
146
146
|
email:
|
147
|
-
- james@
|
147
|
+
- james@gauntlt.org
|
148
148
|
executables:
|
149
149
|
- gauntlt
|
150
150
|
extensions: []
|
@@ -158,9 +158,11 @@ files:
|
|
158
158
|
- README.md
|
159
159
|
- Rakefile
|
160
160
|
- bin/gauntlt
|
161
|
+
- config/warble.rb
|
161
162
|
- examples/curl/cookies.attack
|
162
163
|
- examples/curl/simple.attack
|
163
164
|
- examples/curl/verbs.attack
|
165
|
+
- examples/dirb/dirb.attack
|
164
166
|
- examples/garmr/garmr.attack
|
165
167
|
- examples/generic/generic.attack
|
166
168
|
- examples/nmap/nmap.attack
|
@@ -173,6 +175,7 @@ files:
|
|
173
175
|
- examples/sslyze/sslyze.attack
|
174
176
|
- features/attack.feature
|
175
177
|
- features/attacks/curl.feature
|
178
|
+
- features/attacks/dirb.feature
|
176
179
|
- features/attacks/garmr.feature
|
177
180
|
- features/attacks/generic.feature
|
178
181
|
- features/attacks/nmap.feature
|
@@ -192,6 +195,7 @@ files:
|
|
192
195
|
- lib/gauntlt.rb
|
193
196
|
- lib/gauntlt/attack.rb
|
194
197
|
- lib/gauntlt/attack_adapters/curl.rb
|
198
|
+
- lib/gauntlt/attack_adapters/dirb.rb
|
195
199
|
- lib/gauntlt/attack_adapters/garmr.rb
|
196
200
|
- lib/gauntlt/attack_adapters/gauntlt.rb
|
197
201
|
- lib/gauntlt/attack_adapters/generic.rb
|
@@ -204,11 +208,17 @@ files:
|
|
204
208
|
- lib/gauntlt/attack_adapters/support/profile_helper.rb
|
205
209
|
- lib/gauntlt/attack_adapters/support/python_script_helper.rb
|
206
210
|
- lib/gauntlt/attack_adapters/support/xml_helper.rb
|
211
|
+
- lib/gauntlt/runtime.rb
|
212
|
+
- lib/gauntlt/stepdef.rb
|
207
213
|
- lib/gauntlt/version.rb
|
214
|
+
- ready_to_rumble.sh
|
208
215
|
- test/gauntlt/attack_test.rb
|
216
|
+
- test/gauntlt/runtime_test.rb
|
217
|
+
- test/gauntlt/stepdef_test.rb
|
209
218
|
- test/gauntlt_test.rb
|
210
219
|
- test/test_helper.rb
|
211
220
|
- test/tmf.rb
|
221
|
+
- vendor/dirb203.tar.gz
|
212
222
|
- vendor/sslyze_output.README
|
213
223
|
homepage: https://github.com/gauntlt/gauntlt
|
214
224
|
licenses: []
|
@@ -230,13 +240,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
230
240
|
version: '0'
|
231
241
|
requirements: []
|
232
242
|
rubyforge_project:
|
233
|
-
rubygems_version: 1.8.
|
243
|
+
rubygems_version: 1.8.25
|
234
244
|
signing_key:
|
235
245
|
specification_version: 3
|
236
246
|
summary: behaviour-driven security using cucumber
|
237
247
|
test_files:
|
238
248
|
- features/attack.feature
|
239
249
|
- features/attacks/curl.feature
|
250
|
+
- features/attacks/dirb.feature
|
240
251
|
- features/attacks/garmr.feature
|
241
252
|
- features/attacks/generic.feature
|
242
253
|
- features/attacks/nmap.feature
|
@@ -251,6 +262,8 @@ test_files:
|
|
251
262
|
- features/support/hooks.rb
|
252
263
|
- features/tags.feature
|
253
264
|
- test/gauntlt/attack_test.rb
|
265
|
+
- test/gauntlt/runtime_test.rb
|
266
|
+
- test/gauntlt/stepdef_test.rb
|
254
267
|
- test/gauntlt_test.rb
|
255
268
|
- test/test_helper.rb
|
256
269
|
- test/tmf.rb
|