romanbsd-tarantula 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/CHANGELOG +47 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +162 -0
  4. data/Rakefile +69 -0
  5. data/VERSION.yml +4 -0
  6. data/examples/example_helper.rb +48 -0
  7. data/examples/relevance/core_extensions/ellipsize_example.rb +19 -0
  8. data/examples/relevance/core_extensions/file_example.rb +8 -0
  9. data/examples/relevance/core_extensions/response_example.rb +29 -0
  10. data/examples/relevance/core_extensions/test_case_example.rb +20 -0
  11. data/examples/relevance/tarantula/attack_form_submission_example.rb +79 -0
  12. data/examples/relevance/tarantula/attack_handler_example.rb +29 -0
  13. data/examples/relevance/tarantula/crawler_example.rb +386 -0
  14. data/examples/relevance/tarantula/form_example.rb +50 -0
  15. data/examples/relevance/tarantula/form_submission_example.rb +71 -0
  16. data/examples/relevance/tarantula/html_document_handler_example.rb +43 -0
  17. data/examples/relevance/tarantula/html_report_helper_example.rb +46 -0
  18. data/examples/relevance/tarantula/html_reporter_example.rb +82 -0
  19. data/examples/relevance/tarantula/invalid_html_handler_example.rb +33 -0
  20. data/examples/relevance/tarantula/io_reporter_example.rb +11 -0
  21. data/examples/relevance/tarantula/link_example.rb +67 -0
  22. data/examples/relevance/tarantula/log_grabber_example.rb +26 -0
  23. data/examples/relevance/tarantula/rails_integration_proxy_example.rb +88 -0
  24. data/examples/relevance/tarantula/result_example.rb +85 -0
  25. data/examples/relevance/tarantula/tidy_handler_example.rb +58 -0
  26. data/examples/relevance/tarantula/transform_example.rb +20 -0
  27. data/examples/relevance/tarantula/w3c_validator_example.rb +71 -0
  28. data/examples/relevance/tarantula_example.rb +23 -0
  29. data/laf/images/button_active.png +0 -0
  30. data/laf/images/button_hover.png +0 -0
  31. data/laf/images/button_inactive.png +0 -0
  32. data/laf/images/header_bg.jpg +0 -0
  33. data/laf/images/logo.png +0 -0
  34. data/laf/images/tagline.png +0 -0
  35. data/laf/javascripts/jquery-1.2.3.js +3408 -0
  36. data/laf/javascripts/jquery-ui-tabs.js +890 -0
  37. data/laf/javascripts/jquery.tablesorter.js +861 -0
  38. data/laf/javascripts/niftyLayout.js +11 -0
  39. data/laf/javascripts/niftycube-details.js +298 -0
  40. data/laf/javascripts/niftycube.js +298 -0
  41. data/laf/javascripts/tarantula.js +10 -0
  42. data/laf/stylesheets/tarantula.css +345 -0
  43. data/laf/v2/detail.html +59 -0
  44. data/laf/v2/images/button_active.png +0 -0
  45. data/laf/v2/images/button_hover.png +0 -0
  46. data/laf/v2/images/button_inactive.png +0 -0
  47. data/laf/v2/images/header_bg.jpg +0 -0
  48. data/laf/v2/images/logo.png +0 -0
  49. data/laf/v2/images/tagline.png +0 -0
  50. data/laf/v2/index.html +77 -0
  51. data/laf/v2/stylesheets/tarantula.v2.css +324 -0
  52. data/lib/relevance/core_extensions/ellipsize.rb +34 -0
  53. data/lib/relevance/core_extensions/file.rb +9 -0
  54. data/lib/relevance/core_extensions/metaclass.rb +78 -0
  55. data/lib/relevance/core_extensions/response.rb +9 -0
  56. data/lib/relevance/core_extensions/string_chars_fix.rb +11 -0
  57. data/lib/relevance/core_extensions/test_case.rb +19 -0
  58. data/lib/relevance/tarantula/attack.rb +15 -0
  59. data/lib/relevance/tarantula/attack_form_submission.rb +75 -0
  60. data/lib/relevance/tarantula/attack_handler.rb +37 -0
  61. data/lib/relevance/tarantula/crawler.rb +264 -0
  62. data/lib/relevance/tarantula/detail.html.erb +82 -0
  63. data/lib/relevance/tarantula/form.rb +21 -0
  64. data/lib/relevance/tarantula/form_submission.rb +70 -0
  65. data/lib/relevance/tarantula/html_document_handler.rb +36 -0
  66. data/lib/relevance/tarantula/html_report_helper.rb +39 -0
  67. data/lib/relevance/tarantula/html_reporter.rb +105 -0
  68. data/lib/relevance/tarantula/index.html.erb +37 -0
  69. data/lib/relevance/tarantula/invalid_html_handler.rb +18 -0
  70. data/lib/relevance/tarantula/io_reporter.rb +34 -0
  71. data/lib/relevance/tarantula/link.rb +56 -0
  72. data/lib/relevance/tarantula/log_grabber.rb +16 -0
  73. data/lib/relevance/tarantula/rails_integration_proxy.rb +68 -0
  74. data/lib/relevance/tarantula/recording.rb +12 -0
  75. data/lib/relevance/tarantula/response.rb +13 -0
  76. data/lib/relevance/tarantula/result.rb +66 -0
  77. data/lib/relevance/tarantula/test_report.html.erb +32 -0
  78. data/lib/relevance/tarantula/tidy_handler.rb +32 -0
  79. data/lib/relevance/tarantula/transform.rb +17 -0
  80. data/lib/relevance/tarantula/w3c_validator.rb +33 -0
  81. data/lib/relevance/tarantula.rb +59 -0
  82. data/tasks/tarantula_tasks.rake +36 -0
  83. data/template/tarantula_test.rb +22 -0
  84. data/vendor/w3c_validators/CHANGELOG +14 -0
  85. data/vendor/w3c_validators/LICENSE +60 -0
  86. data/vendor/w3c_validators/README +120 -0
  87. data/vendor/w3c_validators/README.svn +4 -0
  88. data/vendor/w3c_validators/lib/w3c_validators/constants.rb +80 -0
  89. data/vendor/w3c_validators/lib/w3c_validators/css_validator.rb +149 -0
  90. data/vendor/w3c_validators/lib/w3c_validators/exceptions.rb +4 -0
  91. data/vendor/w3c_validators/lib/w3c_validators/feed_validator.rb +110 -0
  92. data/vendor/w3c_validators/lib/w3c_validators/markup_validator.rb +227 -0
  93. data/vendor/w3c_validators/lib/w3c_validators/message.rb +82 -0
  94. data/vendor/w3c_validators/lib/w3c_validators/results.rb +62 -0
  95. data/vendor/w3c_validators/lib/w3c_validators/validator.rb +157 -0
  96. data/vendor/w3c_validators/lib/w3c_validators.rb +5 -0
  97. data/vendor/w3c_validators/rakefile.rb +53 -0
  98. data/vendor/w3c_validators/test/fixtures/invalid_css.css +2 -0
  99. data/vendor/w3c_validators/test/fixtures/invalid_encoding.html +10 -0
  100. data/vendor/w3c_validators/test/fixtures/invalid_feed.xml +19 -0
  101. data/vendor/w3c_validators/test/fixtures/invalid_html5.html +16 -0
  102. data/vendor/w3c_validators/test/fixtures/invalid_markup.html +11 -0
  103. data/vendor/w3c_validators/test/fixtures/valid_css.css +2 -0
  104. data/vendor/w3c_validators/test/fixtures/valid_feed.xml +20 -0
  105. data/vendor/w3c_validators/test/fixtures/valid_html5.html +16 -0
  106. data/vendor/w3c_validators/test/fixtures/valid_markup.html +11 -0
  107. data/vendor/w3c_validators/test/test_css_validator.rb +51 -0
  108. data/vendor/w3c_validators/test/test_exceptions.rb +35 -0
  109. data/vendor/w3c_validators/test/test_feed_validator.rb +61 -0
  110. data/vendor/w3c_validators/test/test_helper.rb +6 -0
  111. data/vendor/w3c_validators/test/test_html5_validator.rb +64 -0
  112. data/vendor/w3c_validators/test/test_markup_validator.rb +94 -0
  113. data/vendor/xss-shield/MIT-LICENSE +20 -0
  114. data/vendor/xss-shield/README +76 -0
  115. data/vendor/xss-shield/init.rb +16 -0
  116. data/vendor/xss-shield/lib/xss_shield/erb_hacks.rb +111 -0
  117. data/vendor/xss-shield/lib/xss_shield/haml_hacks.rb +42 -0
  118. data/vendor/xss-shield/lib/xss_shield/safe_string.rb +47 -0
  119. data/vendor/xss-shield/lib/xss_shield/secure_helpers.rb +40 -0
  120. data/vendor/xss-shield/lib/xss_shield.rb +6 -0
  121. data/vendor/xss-shield/test/test_actionview_integration.rb +40 -0
  122. data/vendor/xss-shield/test/test_erb.rb +44 -0
  123. data/vendor/xss-shield/test/test_haml.rb +43 -0
  124. data/vendor/xss-shield/test/test_helpers.rb +25 -0
  125. data/vendor/xss-shield/test/test_safe_string.rb +55 -0
  126. metadata +218 -0
@@ -0,0 +1,324 @@
1
+ /* RESET */
2
+ html, body, div, span, applet, object, iframe,
3
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
4
+ a, abbr, acronym, address, big, cite, code,
5
+ del, dfn, em, font, img, ins, kbd, q, s, samp,
6
+ small, strike, strong, sub, sup, tt, var,
7
+ b, u, i, center,
8
+ dl, dt, dd, ol, ul, li,
9
+ fieldset, form, label, legend,
10
+ table, caption, tbody, tfoot, thead, tr, th, td {
11
+ margin: 0;
12
+ padding: 0;
13
+ border: 0;
14
+ outline: 0;
15
+ font-size: 100%;
16
+ vertical-align: baseline;
17
+ background: transparent;
18
+ }
19
+ body {
20
+ line-height: 1;
21
+ }
22
+ ol, ul {
23
+ list-style: none;
24
+ }
25
+ blockquote, q {
26
+ quotes: none;
27
+ }
28
+
29
+ /* remember to define focus styles! */
30
+ :focus {
31
+ outline: 0;
32
+ }
33
+
34
+ /* remember to highlight inserts somehow! */
35
+ ins {
36
+ text-decoration: none;
37
+ }
38
+ del {
39
+ text-decoration: line-through;
40
+ }
41
+
42
+ /* tables still need 'cellspacing="0"' in the markup */
43
+ table {
44
+ border-collapse: collapse;
45
+ border-spacing: 0;
46
+ }
47
+
48
+ body {
49
+ line-height: 1em;
50
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
51
+ color: #050505;
52
+ }
53
+
54
+ /* header */
55
+ #header {
56
+ background: #37302e url(../images/header_bg.jpg) no-repeat top left;
57
+ height: 70px;
58
+ border-bottom: 2px solid #d0d0d0;
59
+ }
60
+
61
+ #header h1 {
62
+ width:206px;
63
+ height:56px;
64
+ text-indent: -9999em;
65
+ background: transparent url(../images/logo.png) no-repeat top center;
66
+ position: absolute;
67
+ top: 7px;
68
+ left: 42px;
69
+ }
70
+
71
+ #header h2 {
72
+ width:196px;
73
+ height:34px;
74
+ text-indent: -9999em;
75
+ background: transparent url(../images/tagline.png) no-repeat top center;
76
+ position: absolute;
77
+ top: 15px;
78
+ left: 257px;
79
+ }
80
+
81
+ #header p {
82
+ display: block;
83
+ position: absolute;
84
+ right: 42px;
85
+ width: 315px;
86
+ padding: 8px;
87
+ color: #fff;
88
+ font-size: 13px;
89
+ line-height: 15px;
90
+ }
91
+
92
+ #header a:link, #header a:visited, #header a {
93
+ color: #70b1ca;
94
+ }
95
+
96
+ #header a:hover {
97
+ text-decoration: none;
98
+ }
99
+
100
+ #header hr {
101
+ display: none;
102
+ }
103
+
104
+ .left { text-align: left !important; }
105
+ .right { text-align: right !important; }
106
+ .center { text-align: center !important; }
107
+
108
+ /* page */
109
+
110
+ #page {
111
+ padding: 55px 10px 0 10px;
112
+ width: 1000px;
113
+ margin: auto;
114
+ position: relative;
115
+ }
116
+
117
+ div#page ul.tabs {
118
+
119
+ clear: both;
120
+ }
121
+
122
+ div#page ul.tabs li{
123
+ display: block;
124
+ float: left;
125
+ }
126
+
127
+ div#page ul.tabs li a {
128
+ display: block;
129
+ float: left;
130
+ clear: right;
131
+ margin-right: 5px;
132
+ }
133
+
134
+ div#page ul.tabs li a.active {
135
+ background: transparent url(../images/button_active.png) no-repeat top left;
136
+ color: #050505;
137
+ }
138
+
139
+ div#page ul.tabs li a {
140
+ background: transparent url(../images/button_inactive.png) no-repeat top left;
141
+ height: 38px;
142
+ width: 110px;
143
+ color: #fff;
144
+ padding: 8px 0 0 12px;
145
+ font-size: 18px;
146
+ line-height: 18px;
147
+ text-decoration: none;
148
+ }
149
+
150
+ div#page ul.tabs li a:hover {
151
+ background: transparent url(../images/button_hover.png) no-repeat top left;
152
+ color: #613005;
153
+ }
154
+
155
+ div#page ul.tabs {
156
+ position: absolute;
157
+ top: 7px;
158
+ left: 7px;
159
+ }
160
+
161
+ #list {
162
+ width: 100%;
163
+ }
164
+
165
+ #list th, #list th a, #list tfoot td {
166
+ background: #b9b9a9;
167
+ color: #463c38;
168
+ text-decoration: none;
169
+
170
+ }
171
+
172
+ .sort {
173
+ font-size: 75%;
174
+ filter:alpha(opacity=50);
175
+ -moz-opacity:0.5;
176
+ -khtml-opacity: 0.5;
177
+ opacity: 0.5;
178
+ }
179
+
180
+ #list th, #list th a:hover span {
181
+ filter:alpha(opacity=100);
182
+ -moz-opacity:1;
183
+ -khtml-opacity: 1;
184
+ opacity: 1;
185
+ }
186
+
187
+ #list td, #list th {
188
+ text-align: center;
189
+ padding: 4px;
190
+ font-size: 14px;
191
+ }
192
+
193
+ div#page tbody a {
194
+ color: #6699cc;
195
+ }
196
+
197
+ div#page tbody a:hover {
198
+ text-decoration: none;
199
+ }
200
+
201
+ div#page table caption {
202
+ text-align: left;
203
+ padding: 7px;
204
+ background: #d0d0c4;
205
+ border-bottom: 2px solid #aba7a1;
206
+ -moz-border-radius-topleft: 2px;
207
+ -moz-border-radius-topright: 2px;
208
+ }
209
+
210
+ #list tbody td {
211
+ background: #f2f2eb;
212
+ }
213
+
214
+ #list tfoot td {
215
+ line-height: 18px;
216
+ }
217
+
218
+ tr.even td {
219
+ background: #e9e9e2 !important;
220
+ }
221
+
222
+ /* Response Codes */
223
+
224
+ span.r1, span.r2, span.r3, span.r4,
225
+ span.r5 {
226
+ display: block;
227
+ padding: .15em;
228
+ margin: .15em;
229
+ color: #dac7ad;
230
+ }
231
+
232
+ /* Informational 1xx */
233
+ span.r1 {
234
+ background-color: #3333cc;
235
+ border: 1px solid #376edc;
236
+ }
237
+
238
+ /* Successfull 2xx */
239
+ span.r2 {
240
+ background-color: #006600;
241
+ border: 1px solid #008900;
242
+ }
243
+
244
+ /* Redirection 3xx */
245
+ span.r3 {
246
+ background-color: #555652;
247
+ border: 1px solid #80817b;
248
+ }
249
+
250
+ /* Client 4xx */
251
+ span.r4 {
252
+ background-color: #857400;
253
+ border: 1px solid #baa200;
254
+ }
255
+ /* Server Error 5xx */
256
+ span.r5 {
257
+ background-color: #c40000;
258
+ border: 1px solid #dc0000;
259
+ }
260
+
261
+ /* Detail */
262
+ #report h3 {
263
+ background: #D0D0C4; font-weight: normal;
264
+ border-bottom: 2px solid #ABA7A1;
265
+ -moz-border-radius-topleft: 2px; -moz-border-radius-topright: 2px;
266
+ -webkit-border-top-left-radius: 2px; -webkit-border-top-right-radius: 2px;
267
+ }
268
+
269
+ #report h3,
270
+ #report p {
271
+ width: 50%;
272
+ padding:6px 8px;
273
+ margin: 1px 0;
274
+ }
275
+
276
+ #report a {
277
+ color: #70B1CA
278
+ }
279
+
280
+ #report a:hover {
281
+ text-decoration: none;
282
+ }
283
+
284
+ #report p b {
285
+ color: #050505;
286
+ font-weight: normal;
287
+ }
288
+
289
+ #report p {
290
+ color: #463C38;
291
+ background: #f2f2eb;
292
+ line-height: 22px;
293
+ }
294
+
295
+ #report p span {
296
+ display: inline-block;
297
+ display: -moz-inline-block;
298
+ margin: 0;
299
+ padding: 2px 6px;
300
+ line-height: 16px;
301
+ }
302
+
303
+ #report h3 em {
304
+ display: block;
305
+ font-family: Consolas, Lucida Console, Monaco, monospace;
306
+ font-size: 75%;
307
+ font-style: normal;
308
+ font-weight: normal;
309
+ color: #463C38;
310
+ line-height: 22px;
311
+ }
312
+
313
+ /* Output */
314
+ #output {margin: 10px 0; width: 100%; font-size: 82.5%;}
315
+ #output th { background: #b9b9a9; text-align: left; padding-left: 2.25em; font-weight: normal; line-height: 18px; color: #463C38; border-bottom: 1px solid #fff;
316
+ -moz-border-radius-topleft: 2px; -moz-border-radius-topright: 2px;
317
+ -webkit-border-top-left-radius: 2px; -webkit-border-top-right-radius: 2px;
318
+ }
319
+ #output td { background: #f2f2eb; padding: 1px; line-height: 18px; }
320
+ #output { font-family: Consolas, Lucida Console, Monaco, monospace; }
321
+ #output .numbers { width: 3em; text-align: right; border-right: 1px solid #fff;}
322
+ #output .lines { width: auto; text-align: left;}
323
+ #output .line { display: block; text-align: left; padding: 1px 4px;}
324
+ #output .line.number { text-align: right; color: #585850; }
@@ -0,0 +1,34 @@
1
+ module Relevance::CoreExtensions::Nil
2
+ def ellipsize(cutoff = 20)
3
+ ""
4
+ end
5
+ end
6
+
7
+ module Relevance::CoreExtensions::String
8
+ def ellipsize(cutoff = 20)
9
+ if length > cutoff
10
+ "#{self[0...cutoff]}..."
11
+ else
12
+ self
13
+ end
14
+ end
15
+ end
16
+
17
+ module Relevance::CoreExtensions::Object
18
+ def ellipsize(cutoff = 20)
19
+ inspect.ellipsize(cutoff)
20
+ end
21
+ end
22
+
23
+ class Object
24
+ include Relevance::CoreExtensions::Object
25
+ end
26
+ class String
27
+ include Relevance::CoreExtensions::String
28
+ end
29
+ class NilClass
30
+ include Relevance::CoreExtensions::Nil
31
+ end
32
+
33
+
34
+
@@ -0,0 +1,9 @@
1
+ module Relevance::CoreExtensions::File
2
+ def extension(path)
3
+ extname(path)[1..-1]
4
+ end
5
+ end
6
+
7
+ class File
8
+ extend Relevance::CoreExtensions::File
9
+ end
@@ -0,0 +1,78 @@
1
+ # This is a direct copy of the facets library metaclass stuff.
2
+ # used by Tarantula pulling in all of Facets doesn't make sense here.
3
+
4
+ # From lib/core/facets/metaid.rb
5
+ module Kernel
6
+ def meta_alias(*args)
7
+ meta_class do
8
+ alias_method(*args)
9
+ end
10
+ end
11
+
12
+ def meta_eval(str=nil, &blk)
13
+ if str
14
+ meta_class.instance_eval(str)
15
+ else
16
+ meta_class.instance_eval(&blk)
17
+ end
18
+ end
19
+
20
+ def meta_def( name, &block )
21
+ meta_class do
22
+ define_method( name, &block )
23
+ end
24
+ end
25
+
26
+ def meta_class(&block)
27
+ if block_given?
28
+ (class << self; self; end).class_eval(&block)
29
+ else
30
+ (class << self; self; end)
31
+ end
32
+ end
33
+
34
+ alias_method :metaclass, :meta_class
35
+
36
+ def eigenclass
37
+ (class << self; self; end)
38
+ end
39
+ end
40
+
41
+ class Module
42
+ def class_def name, &blk
43
+ class_eval { define_method name, &blk }
44
+ end
45
+
46
+ protected :attr
47
+ protected :attr_reader
48
+ protected :attr_writer
49
+ protected :attr_accessor
50
+ protected :remove_method
51
+ protected :undef_method
52
+ end
53
+
54
+ # From /lib/more/facets/kernel/meta.rb
55
+ module Kernel
56
+ def meta
57
+ @_meta_functor ||= Functor.new do |op,*args|
58
+ (class << self; self; end).send(op,*args)
59
+ end
60
+ end
61
+ end
62
+
63
+ # From /lib/core/facets/functor.rb
64
+ class Functor
65
+ private(*instance_methods.select { |m| m !~ /(^__|^binding$)/ })
66
+
67
+ def initialize(&function)
68
+ @function = function
69
+ end
70
+
71
+ def to_proc
72
+ @function
73
+ end
74
+
75
+ def method_missing(op, *args, &blk)
76
+ @function.call(op, *args, &blk)
77
+ end
78
+ end
@@ -0,0 +1,9 @@
1
+ # dynamically mixed in to response objects
2
+ module Relevance::CoreExtensions::Response
3
+ def html?
4
+ # some versions of Rails integration tests don't set content type
5
+ # so we are treating nil as html. A better fix would be welcome here.
6
+ ((content_type =~ %r{^text/html}) != nil) || content_type == nil
7
+ end
8
+ end
9
+
@@ -0,0 +1,11 @@
1
+ if RUBY_VERSION == "1.8.7" # fix interaction between Ruby 187 and Rails 202, so we can at least run the test suite on that combination
2
+ unless '1.9'.respond_to?(:force_encoding)
3
+ String.class_eval do
4
+ begin
5
+ remove_method :chars
6
+ rescue NameError
7
+ # OK
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ require 'action_controller/integration'
2
+
3
+ module Relevance::CoreExtensions::TestCaseExtensions
4
+
5
+ def tarantula_crawl(integration_test, options = {})
6
+ url = options[:url] || "/"
7
+ t = tarantula_crawler(integration_test, options)
8
+ t.crawl url
9
+ end
10
+
11
+ def tarantula_crawler(integration_test, options = {})
12
+ Relevance::Tarantula::RailsIntegrationProxy.rails_integration_test(integration_test, options)
13
+ end
14
+
15
+ end
16
+
17
+ if defined? ActionController::IntegrationTest
18
+ ActionController::IntegrationTest.class_eval { include Relevance::CoreExtensions::TestCaseExtensions }
19
+ end
@@ -0,0 +1,15 @@
1
+ class Relevance::Tarantula::Attack
2
+ HASHABLE_ATTRS = [:name, :input, :output, :description]
3
+ attr_accessor *HASHABLE_ATTRS
4
+ def initialize(hash)
5
+ hash.each do |k,v|
6
+ raise ArgumentError, k unless HASHABLE_ATTRS.member?(k)
7
+ self.instance_variable_set("@#{k}", v)
8
+ end
9
+ end
10
+ def ==(other)
11
+ Relevance::Tarantula::Attack === other && HASHABLE_ATTRS.all? { |attr| send(attr) == other.send(attr)}
12
+ end
13
+ end
14
+
15
+
@@ -0,0 +1,75 @@
1
+ class Relevance::Tarantula::AttackFormSubmission
2
+ attr_accessor :method, :action, :data, :attack
3
+
4
+ class << self
5
+ def attacks
6
+ # normalize from hash input to Attack
7
+ @attacks = @attacks.map do |val|
8
+ Hash === val ? Relevance::Tarantula::Attack.new(val) : val
9
+ end
10
+ @attacks
11
+ end
12
+ def attacks=(atts)
13
+ # normalize from hash input to Attack
14
+ @attacks = atts.map do |val|
15
+ Hash === val ? Relevance::Tarantula::Attack.new(val) : val
16
+ end
17
+ end
18
+ end
19
+ @attacks = []
20
+
21
+ def initialize(form, attack = nil)
22
+ @method = form.method
23
+ @action = form.action
24
+ @attack = attack
25
+ @data = mutate_selects(form).merge(mutate_text_areas(form)).merge(mutate_inputs(form))
26
+ end
27
+
28
+ def self.mutate(form)
29
+ attacks and attacks.map do |attack|
30
+ self.new(form, attack)
31
+ end
32
+ end
33
+
34
+ def to_s
35
+ "#{action} #{method} #{data.inspect} #{attack.inspect}"
36
+ end
37
+
38
+ # a form's signature is what makes it unique (e.g. action + fields)
39
+ # used to keep track of which forms we have submitted already
40
+ def signature
41
+ [action, data.keys.sort, attack.name]
42
+ end
43
+
44
+ def create_random_data_for(form, tag_selector)
45
+ form.search(tag_selector).inject({}) do |form_args, input|
46
+ # TODO: test
47
+ form_args[input['name']] = random_data(input) if input['name']
48
+ form_args
49
+ end
50
+ end
51
+
52
+ def mutate_inputs(form)
53
+ create_random_data_for(form, 'input')
54
+ end
55
+
56
+ def mutate_text_areas(form)
57
+ create_random_data_for(form, 'textarea')
58
+ end
59
+
60
+ def mutate_selects(form)
61
+ form.search('select').inject({}) do |form_args, select|
62
+ options = select.search('option')
63
+ option = options.rand
64
+ form_args[select['name']] = option['value']
65
+ form_args
66
+ end
67
+ end
68
+
69
+ def random_data(input)
70
+ case input['name']
71
+ when /^_method$/ : input['value']
72
+ else attack.input
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,37 @@
1
+ require 'hpricot'
2
+
3
+ class Relevance::Tarantula::AttackHandler
4
+ include ERB::Util
5
+
6
+ def attacks
7
+ Relevance::Tarantula::AttackFormSubmission.attacks.select(&:output)
8
+ end
9
+
10
+ def handle(result)
11
+ return unless attacks.size > 0
12
+ regexp = '(' + attacks.map {|a| Regexp.escape a.output}.join('|') + ')'
13
+ response = result.response
14
+ return unless response.html?
15
+ if n = (response.body =~ /#{regexp}/)
16
+ error_result = result.dup
17
+ error_result.success = false
18
+ error_result.description = "XSS error found, match was: #{h($1)}"
19
+ error_result.data = <<-STR
20
+ ########################################################################
21
+ # Text around unescaped string: #{$1}
22
+ ########################################################################
23
+ #{response.body[[0, n - 200].max , 400]}
24
+
25
+
26
+
27
+
28
+
29
+ ########################################################################
30
+ # Attack information:
31
+ ########################################################################
32
+ #{attacks.select {|a| a.output == $1}[0].to_yaml}
33
+ STR
34
+ error_result
35
+ end
36
+ end
37
+ end