arachni 0.2.2.1 → 0.2.2.2

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.
Files changed (44) hide show
  1. data/CHANGELOG.md +30 -0
  2. data/CONTRIBUTORS.md +1 -0
  3. data/README.md +28 -8
  4. data/Rakefile +1 -0
  5. data/bin/arachni_web_autostart +46 -0
  6. data/lib/anemone/page.rb +1 -0
  7. data/lib/arachni.rb +1 -1
  8. data/lib/framework.rb +8 -3
  9. data/lib/http.rb +9 -39
  10. data/lib/mixins/observable.rb +87 -0
  11. data/lib/module/auditor.rb +14 -0
  12. data/lib/module/base.rb +0 -14
  13. data/lib/nokogiri/xml/node.rb +42 -0
  14. data/lib/ui/cli/cli.rb +1 -1
  15. data/lib/ui/web/log.rb +21 -14
  16. data/lib/ui/web/report_manager.rb +100 -15
  17. data/lib/ui/web/server.rb +24 -33
  18. data/lib/ui/web/server/public/reports/demo.testfire.net:Sun Mar 20 02:48:10 2011.afr +104829 -0
  19. data/lib/ui/web/server/views/layout.erb +1 -1
  20. data/lib/ui/web/server/views/options.erb +10 -2
  21. data/lib/ui/web/server/views/plugins.erb +1 -1
  22. data/lib/ui/web/server/views/reports.erb +8 -4
  23. data/lib/ui/xmlrpc/xmlrpc.rb +1 -1
  24. data/metamodules/autothrottle.rb +2 -2
  25. data/metamodules/timeout_notice.rb +1 -1
  26. data/modules/audit/sqli_blind_rdiff.rb +1 -1
  27. data/modules/recon/common_files/filenames.txt +2 -0
  28. data/modules/recon/directory_listing.rb +1 -0
  29. data/modules/recon/interesting_responses.rb +3 -3
  30. data/path_extractors/generic.rb +5 -1
  31. data/plugins/autologin.rb +15 -4
  32. data/plugins/content_types.rb +2 -2
  33. data/plugins/cookie_collector.rb +9 -16
  34. data/plugins/profiler.rb +237 -0
  35. data/reports/html.rb +21 -6
  36. data/reports/html/default.erb +4 -2
  37. data/reports/plugin_formatters/html/autologin.rb +63 -0
  38. data/reports/plugin_formatters/html/profiler.rb +71 -0
  39. data/reports/plugin_formatters/html/profiler/template.erb +177 -0
  40. data/reports/plugin_formatters/stdout/autologin.rb +55 -0
  41. data/reports/plugin_formatters/stdout/profiler.rb +90 -0
  42. data/reports/plugin_formatters/xml/autologin.rb +68 -0
  43. data/reports/plugin_formatters/xml/profiler.rb +120 -0
  44. metadata +23 -68
data/reports/html.rb CHANGED
@@ -111,12 +111,14 @@ class HTML < Arachni::Report::Base
111
111
  }
112
112
  }
113
113
 
114
+ @total_severities = 0
115
+ @total_elements = 0
116
+ @total_verifications = 0
114
117
  @audit_store.issues.each_with_index {
115
118
  |issue, i|
116
119
 
117
120
  @graph_data[:severities][issue.severity] ||= 0
118
121
  @graph_data[:severities][issue.severity] += 1
119
- @total_severities ||= 0
120
122
  @total_severities += 1
121
123
 
122
124
  @graph_data[:issues][issue.name] ||= 0
@@ -124,19 +126,20 @@ class HTML < Arachni::Report::Base
124
126
 
125
127
  @graph_data[:elements][issue.elem] ||= 0
126
128
  @graph_data[:elements][issue.elem] += 1
127
- @total_elements ||= 0
128
129
  @total_elements += 1
129
130
 
130
131
  verification = issue.verification ? 'Yes' : 'No'
131
132
  @graph_data[:verification][verification] ||= 0
132
133
  @graph_data[:verification][verification] += 1
133
- @total_verifications ||= 0
134
134
  @total_verifications += 1
135
135
 
136
136
  issue.variations.each_with_index {
137
137
  |variation, j|
138
138
 
139
139
  if( variation['response'] && !variation['response'].empty? )
140
+
141
+ variation['response'] = variation['response'].force_encoding( 'utf-8' )
142
+
140
143
  @audit_store.issues[i].variations[j]['escaped_response'] =
141
144
  Base64.encode64( variation['response'] ).gsub( /\n/, '' )
142
145
  end
@@ -158,17 +161,29 @@ class HTML < Arachni::Report::Base
158
161
 
159
162
  @graph_data[:severities].each {
160
163
  |severity, cnt|
161
- @graph_data[:severities][severity] = ((cnt/Float(@total_severities)) * 100).to_i
164
+ begin
165
+ @graph_data[:severities][severity] = ((cnt/Float(@total_severities)) * 100).to_i
166
+ rescue
167
+ @graph_data[:severities][severity] = 0
168
+ end
162
169
  }
163
170
 
164
171
  @graph_data[:elements].each {
165
172
  |elem, cnt|
166
- @graph_data[:elements][elem] = ((cnt/Float(@total_elements)) * 100).to_i
173
+ begin
174
+ @graph_data[:elements][elem] = ((cnt/Float(@total_elements)) * 100).to_i
175
+ rescue
176
+ @graph_data[:elements][elem] = 0
177
+ end
167
178
  }
168
179
 
169
180
  @graph_data[:verification].each {
170
181
  |verification, cnt|
171
- @graph_data[:verification][verification] = ((cnt/Float(@total_verifications)) * 100).to_i
182
+ begin
183
+ @graph_data[:verification][verification] = ((cnt/Float(@total_verifications)) * 100).to_i
184
+ rescue
185
+ @graph_data[:verification][verification] = 0
186
+ end
172
187
  }
173
188
 
174
189
  end
@@ -1,3 +1,5 @@
1
+ <%# Encoding: utf-8%>
2
+
1
3
  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
4
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3
5
 
@@ -180,7 +182,7 @@
180
182
 
181
183
  var verification;
182
184
  $(document).ready(function() {
183
- elements = new Highcharts.Chart({
185
+ verification = new Highcharts.Chart({
184
186
  chart: {
185
187
  renderTo: 'chart-verification',
186
188
  backgroundColor: '#ccc'
@@ -949,7 +951,7 @@
949
951
  <p> &nbsp; </p>
950
952
 
951
953
  <%@plugins.values.each do |plugin|%>
952
- <p><%=plugin%></p>
954
+ <p><%=plugin.force_encoding( 'utf-8' )%></p>
953
955
  <%end%>
954
956
  </section>
955
957
 
@@ -0,0 +1,63 @@
1
+ =begin
2
+ Arachni
3
+ Copyright (c) 2010-2011 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
4
+
5
+ This is free software; you can copy and distribute and modify
6
+ this program under the term of the GPL v2.0 License
7
+ (See LICENSE file for details)
8
+
9
+ =end
10
+
11
+ module Arachni
12
+
13
+ module Reports
14
+
15
+ class HTML
16
+ module PluginFormatters
17
+
18
+ #
19
+ # HTML formatter for the results of the AutoLogin plugin
20
+ #
21
+ # @author: Tasos "Zapotek" Laskos
22
+ # <tasos.laskos@gmail.com>
23
+ # <zapotek@segfault.gr>
24
+ # @version: 0.1
25
+ #
26
+ class AutoLogin < Arachni::Plugin::Formatter
27
+
28
+ def initialize( plugin_data )
29
+ @results = plugin_data[:results]
30
+ @description = plugin_data[:description]
31
+ end
32
+
33
+ def run
34
+ return ERB.new( tpl ).result( binding )
35
+ end
36
+
37
+ def tpl
38
+ %q{
39
+ <h3>AutoLogin</h3>
40
+ <blockquote><pre><%=::Arachni::Reports::HTML.prep_description(@description)%></pre></blockquote>
41
+
42
+ <h4>Result</h4>
43
+ <blockquote><%=@results[:msg]%></blockquote>
44
+
45
+ <% if @results[:cookies].is_a?( Hash )%>
46
+ <h5>Cookies were set to:</h5>
47
+ <ul>
48
+ <% @results[:cookies].each_pair do |name, val|%>
49
+ <li><%=name%> = <%=val%></li>
50
+ <%end%>
51
+ <ul>
52
+ <%end%>
53
+ }
54
+
55
+ end
56
+
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,71 @@
1
+ =begin
2
+ Arachni
3
+ Copyright (c) 2010-2011 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
4
+
5
+ This is free software; you can copy and distribute and modify
6
+ this program under the term of the GPL v2.0 License
7
+ (See LICENSE file for details)
8
+
9
+ =end
10
+
11
+ require 'json'
12
+
13
+ module Arachni
14
+
15
+ module Reports
16
+
17
+ class HTML
18
+ module PluginFormatters
19
+
20
+ #
21
+ # HTML formatter for the results of the Profiler plugin
22
+ #
23
+ # @author: Tasos "Zapotek" Laskos
24
+ # <tasos.laskos@gmail.com>
25
+ # <zapotek@segfault.gr>
26
+ # @version: 0.1
27
+ #
28
+ class Profiler < Arachni::Plugin::Formatter
29
+
30
+ def initialize( plugin_data )
31
+ @results = plugin_data[:results]
32
+ @description = plugin_data[:description]
33
+ end
34
+
35
+ def run
36
+
37
+ @results['times'].each_with_index {
38
+ |itm, i|
39
+ @results['times'][i] = escape_hash( itm )
40
+ }
41
+
42
+ times = @results['times'].map{ |item| item['time'] }
43
+ total_time = 0
44
+ times.each {
45
+ |time|
46
+ total_time += time
47
+ }
48
+
49
+ avg_time = total_time / times.size
50
+ times.reject!{ |time| time < avg_time }
51
+
52
+ return ERB.new( IO.read( File.dirname( __FILE__ ) + '/profiler/template.erb' ) ).result( binding )
53
+ end
54
+
55
+ def escape_hash( hash )
56
+ hash.each_pair {
57
+ |k, v|
58
+ hash[k] = CGI.escape( v ) if v.is_a?( String )
59
+ hash[k] = escape_hash( v ) if v.is_a? Hash
60
+ }
61
+
62
+ return hash
63
+ end
64
+
65
+ end
66
+
67
+ end
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,177 @@
1
+ <h3>Profiler</h3>
2
+ <blockquote><pre><%=::Arachni::Reports::HTML.prep_description(@description)%></pre></blockquote>
3
+
4
+ <script type="text/javascript">
5
+
6
+ var tooltip_data = <%=@results['times'].to_json%>;
7
+ var chart;
8
+ $(document).ready(function() {
9
+ chart = new Highcharts.Chart({
10
+ chart: {
11
+ renderTo: 'chart-response-times',
12
+ zoomType: 'x',
13
+ spacingRight: 20,
14
+ backgroundColor: '#ccc'
15
+ },
16
+ title: {
17
+ text: 'Response times exceeding the average (<%=times.size%> out of <%=@results['times'].size%> responses)'
18
+ },
19
+ subtitle: {
20
+ text: document.ontouchstart === undefined ?
21
+ 'Click and drag in the plot area to zoom in' :
22
+ 'Drag your finger over the plot to zoom in'
23
+ },
24
+ xAxis: {
25
+ title: {
26
+ text: null
27
+ }
28
+ },
29
+ yAxis: {
30
+ title: {
31
+ text: 'Seconds'
32
+ },
33
+ min: <%=times.min%>,
34
+ startOnTick: false,
35
+ showFirstLabel: false
36
+ },
37
+ tooltip: {
38
+ formatter: function() {
39
+ return 'URL: <b>' + unescape( tooltip_data[this.x]['url'] ) + '</b><br/>' +
40
+ 'Response time: <b>' + this.y +'</b> seconds<br/>';
41
+ }
42
+ },
43
+ legend: {
44
+ enabled: false
45
+ },
46
+ plotOptions: {
47
+ area: {
48
+ fillColor: {
49
+ linearGradient: [0, 0, 0, 300],
50
+ stops: [
51
+ [0, 'rgba(0,0,0,0)'],
52
+ [1, 'rgba(2,0,0,0)']
53
+ ]
54
+ },
55
+ lineWidth: 1,
56
+ marker: {
57
+ enabled: false,
58
+ states: {
59
+ hover: {
60
+ enabled: true,
61
+ radius: 5
62
+ }
63
+ }
64
+ },
65
+ shadow: false,
66
+ states: {
67
+ hover: {
68
+ lineWidth: 1
69
+ }
70
+ }
71
+ }
72
+ },
73
+
74
+ series: [{
75
+ type: 'area',
76
+ pointInterval: 1,
77
+ data: <%=times.to_s%>
78
+ }]
79
+ });
80
+
81
+
82
+ });
83
+ </script>
84
+
85
+
86
+ <h4>Response time analysis</h4>
87
+
88
+ <strong>Average response time</strong>: <%=avg_time%> seconds <br/>
89
+ <strong>Max</strong>: <%=times.max%> seconds <br/>
90
+ <strong>Min</strong>: <%=@results['times'].map{ |item| item['time'] }.min%> seconds <br/>
91
+ <strong>Sample size</strong>: <%=@results['times'].size%> responses <br/>
92
+
93
+ <div id="chart-response-times" style="width: 1000px"></div>
94
+
95
+ <p>&nbsp;</p>
96
+
97
+ <h4>Inputs that affect output (Taint analysis)</h4>
98
+ <% @results['inputs'].each_with_index do |item, idx| %>
99
+
100
+ <h5>
101
+ <%=item['element']['type'].capitalize%>
102
+
103
+ <%if item['element']['name']%>
104
+ named '<%=item['element']['name']%>'
105
+ <%end%>
106
+
107
+ <%if item['element']['altered']%>
108
+ using the '<%=item['element']['altered']%>' input
109
+ <%end%>
110
+
111
+ <%if item['element']['owner']%>
112
+ at <a href="<%=CGI.escapeHTML( item['element']['owner'] )%>"> <%=item['element']['owner']%> </a>
113
+ <%end%>
114
+
115
+ <%if item['element']['action']%>
116
+ pointing to <a href="<%=CGI.escapeHTML( item['element']['action'] )%>"> <%=item['element']['action']%> </a>
117
+ <%end%>
118
+
119
+ <%if item['element']['method']%>
120
+ using <%=item['request']['method']%>
121
+ <%end%>
122
+ </h5>
123
+
124
+ <p>
125
+ It was submitted using the following parameters:
126
+ <ul>
127
+ <%item['element']['auditable'].each_pair do |k, v| %>
128
+ <li><%=k%> = <%=v%></li>
129
+ <%end%>
130
+ </ul>
131
+
132
+ The taint landed in the following elements at <a href="<%=CGI.escapeHTML( item['request']['url'] )%>"> <%=item['request']['url']%> </a>:
133
+ <ul>
134
+ <%item['landed'].each do |elem| %>
135
+ <li>
136
+ <%=elem['type'].capitalize%>
137
+
138
+ <%if elem['name']%>
139
+ named '<%=elem['name']%>'
140
+ <%end%>
141
+
142
+ <%if elem['altered']%>
143
+ using the '<%=elem['altered']%>' input
144
+ <%end%>
145
+
146
+ <%if elem['auditable']%>
147
+ <ul>
148
+ <%elem['auditable'].each_pair do |k, v| %>
149
+ <li><%=k%> = <%=v%></li>
150
+ <%end%>
151
+ </ul>
152
+ <%end%>
153
+ </li>
154
+ <%end%>
155
+ </ul>
156
+
157
+ <div class="hidden" id="inspection-dialog_<%=idx%>" title="Relevant content is shown in red.">
158
+ <% match = CGI.escapeHTML( item['response']['body'] )%>
159
+ <pre> <%=CGI.escapeHTML( item['response']['body'] ).gsub( item['taint'], '<strong style="color: red">' + item['taint'] + '</strong>' ) %> </pre>
160
+ </div>
161
+
162
+ <form style="display:inline" action="#">
163
+ <input onclick="javascript:inspect( '#inspection-dialog_<%=idx%>')" type="button" value="Inspect" />
164
+ </form>
165
+
166
+ <form style="display:inline" action="<%=item['request']['url']%>" target="_blank" method="<%=item['request']['method']%>">
167
+ <% item['request']['params'].each_pair do |name, value|%>
168
+ <input type="hidden" name="<%=CGI.escapeHTML(name)%>" value="<%=CGI.escapeHTML( value )%>" />
169
+ <%end%>
170
+ <input type="submit" value="Replay" />
171
+ </form>
172
+
173
+ </p>
174
+
175
+ <p>&nbsp;</p>
176
+
177
+ <%end%>
@@ -0,0 +1,55 @@
1
+ =begin
2
+ Arachni
3
+ Copyright (c) 2010-2011 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com>
4
+
5
+ This is free software; you can copy and distribute and modify
6
+ this program under the term of the GPL v2.0 License
7
+ (See LICENSE file for details)
8
+
9
+ =end
10
+
11
+ module Arachni
12
+ module Reports
13
+
14
+ class Stdout
15
+ module PluginFormatters
16
+
17
+ #
18
+ # Stdout formatter for the results of the AutoLogin plugin
19
+ #
20
+ #
21
+ # @author: Tasos "Zapotek" Laskos
22
+ # <tasos.laskos@gmail.com>
23
+ # <zapotek@segfault.gr>
24
+ # @version: 0.1
25
+ #
26
+ class AutoLogin < Arachni::Plugin::Formatter
27
+
28
+ def initialize( plugin_data )
29
+ @results = plugin_data[:results]
30
+ @description = plugin_data[:description]
31
+ end
32
+
33
+ def run
34
+ print_status( 'AutoLogin' )
35
+ print_info( '~~~~~~~~~~~~~~' )
36
+
37
+ print_info( 'Description: ' + @description )
38
+ print_line
39
+ print_ok( @results[:msg] )
40
+
41
+ return if !@results[:cookies]
42
+ print_info( 'Cookies set to:' )
43
+ @results[:cookies].each_pair {
44
+ |name, val|
45
+ print_info( ' * ' + name + ' = ' + val )
46
+ }
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+ end
55
+ end