arachni 1.0.4 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -0
  3. data/README.md +8 -4
  4. data/bin/arachni_console +1 -1
  5. data/components/checks/active/no_sql_injection.rb +4 -4
  6. data/components/checks/passive/common_directories/directories.txt +1 -0
  7. data/components/checks/passive/common_files/filenames.txt +1 -0
  8. data/components/plugins/login_script.rb +156 -0
  9. data/components/reporters/plugin_formatters/html/login_script.rb +48 -0
  10. data/components/reporters/plugin_formatters/stdout/login_script.rb +23 -0
  11. data/components/reporters/plugin_formatters/xml/login_script.rb +26 -0
  12. data/components/reporters/xml/schema.xsd +17 -0
  13. data/lib/arachni/browser.rb +7 -4
  14. data/lib/arachni/browser/javascript.rb +40 -4
  15. data/lib/arachni/browser/javascript/proxy.rb +1 -1
  16. data/lib/arachni/browser_cluster/worker.rb +14 -4
  17. data/lib/arachni/check/auditor.rb +24 -7
  18. data/lib/arachni/check/manager.rb +6 -0
  19. data/lib/arachni/framework.rb +54 -6
  20. data/lib/arachni/http/client.rb +41 -23
  21. data/lib/arachni/http/headers.rb +5 -1
  22. data/lib/arachni/http/message.rb +0 -7
  23. data/lib/arachni/http/request.rb +40 -32
  24. data/lib/arachni/http/response.rb +8 -1
  25. data/lib/arachni/platform/manager.rb +7 -0
  26. data/lib/arachni/rpc/server/framework/multi_instance.rb +1 -1
  27. data/lib/arachni/session.rb +88 -58
  28. data/lib/arachni/state/framework.rb +34 -5
  29. data/lib/arachni/support/profiler.rb +2 -0
  30. data/lib/arachni/uri.rb +2 -1
  31. data/lib/version +1 -1
  32. data/spec/arachni/browser/javascript_spec.rb +15 -0
  33. data/spec/arachni/check/manager_spec.rb +17 -0
  34. data/spec/arachni/framework_spec.rb +4 -2
  35. data/spec/arachni/http/client_spec.rb +1 -1
  36. data/spec/arachni/session_spec.rb +80 -37
  37. data/spec/arachni/state/framework_spec.rb +34 -1
  38. data/spec/arachni/uri_spec.rb +7 -0
  39. data/spec/components/plugins/login_script_spec.rb +157 -0
  40. data/spec/support/servers/plugins/login_script.rb +13 -0
  41. data/ui/cli/output.rb +26 -9
  42. metadata +11 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 99e76bd9a28d81d3b89c8a4544dad6a6ccbe5c54
4
- data.tar.gz: 4c204ffb2b1b72f3820cda0b58681a073c9234de
3
+ metadata.gz: 113357f2e377065a79df18200488cc13fe744b6d
4
+ data.tar.gz: 41739b4e27d567d15f67f9ed86c571c24143c3a0
5
5
  SHA512:
6
- metadata.gz: 514fcc4191723fcfd0ef82355f19555ed4d21efab9cb8f6e3fd7a388aff526e8550919dbc16c18137f7310d22c30614ad165a63d0f399de36c8ddecdad9cb6e0
7
- data.tar.gz: 1eca14df793d96453809d737ad229f36632eab832e1482801ec6a1a98f78de7f6f2ee30992f694b00056658ad9e23e788496af3c0da18fbdc6d953f738859d4d
6
+ metadata.gz: 0418e763e4b5577d1d6856cbbf3cdc242ba04525e10de155b4b86484e6208acdf78cea104e0ce9e75a44aab73fb8e7d40c10be0459d58811b8f7a83b6b4971e1
7
+ data.tar.gz: 2ab357a8d52233a026374d1f0bd09ba03d8ebffa9d939d8a97f51bf76c638e95362c1f080b6ed78c54e630d1a13a0c4ddd90dbe61555259dddef762d3a3385e3
@@ -1,5 +1,47 @@
1
1
  # ChangeLog
2
2
 
3
+ ## 1.0.5 _(November 14, 2014)_
4
+
5
+ - Executables
6
+ - `arachni_console` -- Require the UI::Output interface after Arachni.
7
+ - Error log
8
+ - Redacted HTTP authentication credentials.
9
+ - `Session`
10
+ - Added `#record_login_sequence`, allowing for arbitrary login sequences to
11
+ be stored and replayed.
12
+ - `URI`
13
+ - `#domain` -- Fixed `nil` error on missing host.
14
+ - `.query_parameters` -- Recode query string before parsing to fix encoding errors.
15
+ - `UI::Output`
16
+ - `#log_error` -- Store errors in memory, as well as in logfile.
17
+ - `RPC::Server::Framework::MultiInstance`
18
+ - `#errors` -- Return errors from memory buffer instead of logfile, to
19
+ prevent "Too many open file" exceptions.
20
+ - ` Framework`
21
+ - `#audit_page` -- Keep track of checked elements at the `Framework` level
22
+ too and remove them from pages.
23
+ - `Browser`
24
+ - Fixed `nil` error on failed process spawn.
25
+ - `Javascript` -- Updated to preload and cache script sources to avoid
26
+ hitting the disk in order to prevent "Too many open file" exceptions.
27
+ - `#run_without_elements` -- Runs a script but unwraps `Watir` elements.
28
+ - `Proxy` -- Updated to use `#run_without_elements`.
29
+ - `BrowserCluster::Worker`
30
+ - Print error message on failure to respawn.
31
+ - `Check::Auditor` -- Updated audit helpers to mark elements as audited at the
32
+ check component level, to avoid sending redundant workload to the analysis
33
+ classes only to be ignored there.
34
+ - `#skip?` -- Optimized redundant issue checks.
35
+ - Checks
36
+ - Active
37
+ - `no_sql_injection` -- Updated payloads to be per platform.
38
+ - Passive
39
+ - `common_files` -- Added more filenames. [PR #504]
40
+ - Plugins
41
+ - Added
42
+ - `login_script` -- Exposes a Watir WebDriver interface to an external
43
+ script in order to allow for arbitrary login sequences.
44
+
3
45
  ## 1.0.4 _(October 25, 2014)_
4
46
 
5
47
  - CLI options
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  <table>
4
4
  <tr>
5
5
  <th>Version</th>
6
- <td>1.0.4</td>
6
+ <td>1.0.5</td>
7
7
  </tr>
8
8
  <tr>
9
9
  <th>Homepage</th>
@@ -121,7 +121,7 @@ you with its findings.
121
121
  - Proxy authentication.
122
122
  - Site authentication (Automated form-based, Cookie-Jar, Basic-Digest, NTLMv1 and others).
123
123
  - Automatic log-out detection and re-login during the scan (when the initial
124
- login was performed via the `autologin` or `proxy` plugins).
124
+ login was performed via the `autologin`, `login_script` or `proxy` plugins).
125
125
  - Custom 404 page detection.
126
126
  - UI abstraction:
127
127
  - [Command-line Interface](https://github.com/Arachni/arachni/wiki/Executables).
@@ -419,7 +419,10 @@ Active checks engage the web application via its inputs.
419
419
  - Path XSS (`xss_path`).
420
420
  - XSS in event attributes of HTML elements (`xss_event`).
421
421
  - XSS in HTML tags (`xss_tag`).
422
- - XSS in "script" context (`xss_script_context`).
422
+ - XSS in script context (`xss_script_context`).
423
+ - DOM XSS (`xss_dom`).
424
+ - DOM XSS inputs (`xss_dom_inputs`).
425
+ - DOM XSS script context (`xss_dom_script_context`).
423
426
  - Source code disclosure (`source_code_disclosure`)
424
427
 
425
428
  ##### Passive
@@ -475,7 +478,8 @@ core remains lean and makes it easy for anyone to add arbitrary functionality.
475
478
 
476
479
  - Passive Proxy (`proxy`) -- Analyzes requests and responses between the web app and
477
480
  the browser assisting in AJAX audits, logging-in and/or restricting the scope of the audit.
478
- - Form based AutoLogin (`autologin`).
481
+ - Form based login (`autologin`).
482
+ - Script based login (`login_script`).
479
483
  - Dictionary attacker for HTTP Auth (`http_dicattack`).
480
484
  - Dictionary attacker for form based authentication (`form_dicattack`).
481
485
  - Cookie collector (`cookie_collector`) -- Keeps track of cookies while establishing a timeline of changes.
@@ -7,8 +7,8 @@
7
7
  web site for more information on licensing and terms of use.
8
8
  =end
9
9
 
10
- require_relative '../ui/cli/output'
11
10
  require_relative '../lib/arachni'
11
+ require_relative '../ui/cli/output'
12
12
  require 'irb'
13
13
  require 'irb/completion'
14
14
 
@@ -7,7 +7,7 @@
7
7
  =end
8
8
 
9
9
  # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
10
- # @version 0.1
10
+ # @version 0.1.1
11
11
  class Arachni::Checks::NoSqlInjection < Arachni::Check::Base
12
12
 
13
13
  def self.error_patterns
@@ -31,7 +31,7 @@ class Arachni::Checks::NoSqlInjection < Arachni::Check::Base
31
31
  # Prepares the payloads that will hopefully cause the webapp to output SQL
32
32
  # error messages if included as part of an SQL query.
33
33
  def self.payloads
34
- @payloads ||= [ '\';.")' ]
34
+ @payloads ||= { mongodb: '\';.")' }
35
35
  end
36
36
 
37
37
  def self.options
@@ -57,8 +57,8 @@ NoSQL injection check, uses known DB errors to identify vulnerabilities.
57
57
  elements: [Element::Link, Element::Form, Element::Cookie,
58
58
  Element::Header, Element::LinkTemplate ],
59
59
  author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
60
- version: '0.1',
61
- platforms: options[:regexp].keys,
60
+ version: '0.1.1',
61
+ platforms: payloads.keys,
62
62
 
63
63
  issue: {
64
64
  name: %q{NoSQL Injection},
@@ -258,6 +258,7 @@ network
258
258
  xamp
259
259
  xampp
260
260
  lamp
261
+ phpmyadmin
261
262
  AD
262
263
  AE
263
264
  AF
@@ -19,6 +19,7 @@ config.php
19
19
  php.ini
20
20
  error_log
21
21
  elmah.axd
22
+ server-status
22
23
  WEB-INF (copy)/web.xml
23
24
  WEB-INF - Copy/web.xml
24
25
  Copy of WEB-INF/web.xml
@@ -0,0 +1,156 @@
1
+ =begin
2
+ Copyright 2010-2014 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
+
4
+ This file is part of the Arachni Framework project and is subject to
5
+ redistribution and commercial restrictions. Please see the Arachni Framework
6
+ web site for more information on licensing and terms of use.
7
+ =end
8
+
9
+ # Automated login plugin using a custom login script.
10
+ #
11
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
12
+ class Arachni::Plugins::LoginScript < Arachni::Plugin::Base
13
+
14
+ STATUSES = {
15
+ success: 'Login was successful.',
16
+ failure: 'The script was executed successfully, but the login check failed.',
17
+ error: 'A runtime error was encountered while executing the login script.',
18
+ missing_check: 'No session check was provided, either via interface options or the script.'
19
+ }
20
+
21
+ def prepare
22
+ script = IO.read( @options[:script] )
23
+ @script = proc { |browser| eval script }
24
+
25
+ framework_pause
26
+ print_info 'System paused.'
27
+ end
28
+
29
+ def run
30
+ session.record_login_sequence do |browser|
31
+ print_info 'Running the script.'
32
+ @script.call browser ? browser.watir : nil
33
+ print_info 'Execution completed.'
34
+ end
35
+
36
+ begin
37
+ session.login
38
+ rescue => e
39
+ set_status :error
40
+ print_exception e
41
+ return
42
+ end
43
+
44
+ if !session.logged_in?
45
+ set_status :failure, :error
46
+ return
47
+ end
48
+
49
+ cookies = http.cookies.inject({}){ |h, c| h.merge!( c.simple ) }
50
+
51
+ set_status :success, :ok, { 'cookies' => cookies }
52
+
53
+ print_info 'Cookies set to:'
54
+ cookies.each do |name, val|
55
+ print_info " * #{name.inspect} = #{val.inspect}"
56
+ end
57
+
58
+ rescue Arachni::Session::Error::NoLoginCheck
59
+ set_status :missing_check, :error
60
+ rescue => e
61
+ set_status :error
62
+ print_exception e
63
+ end
64
+
65
+ def clean_up
66
+ if @failed
67
+ print_info 'Aborting the scan.'
68
+ framework_abort
69
+ return
70
+ end
71
+
72
+ framework_resume
73
+ end
74
+
75
+ def set_status( status, type = nil, extra = {} )
76
+ type ||= status
77
+
78
+ register_results(
79
+ {
80
+ 'status' => status.to_s,
81
+ 'message' => STATUSES[status]
82
+ }.merge( extra )
83
+ )
84
+
85
+ @failed = true if type == :error
86
+ send "print_#{type}", STATUSES[status]
87
+ end
88
+
89
+ def self.info
90
+ {
91
+ name: 'Login script',
92
+ description: %q{
93
+ Loads and sets an external script as the system's login sequence, to be executed
94
+ prior to the scan and whenever a log-out is detected.
95
+
96
+ The script needn't necessarily perform an actual login operation. If another
97
+ process is used to manage sessions, the script can be used to communicate with
98
+ that process and, for example, load and set cookies from a shared cookie-jar.
99
+
100
+ **With browser (slow):**
101
+
102
+ If a [browser](http://watirwebdriver.com/) is available, it will be exposed to
103
+ the script via the `browser` variable. Otherwise, that variable will have a
104
+ value of `nil`.
105
+
106
+ browser.goto 'http://testfire.net/bank/login.aspx'
107
+
108
+ form = browser.form( id: 'login' )
109
+ form.text_field( name: 'uid' ).set 'jsmith'
110
+ form.text_field( name: 'passw' ).set 'Demo1234'
111
+
112
+ form.submit
113
+
114
+ # You can also configure the session check from the script, dynamically,
115
+ # if you don't want to set static options via the user interface.
116
+ framework.options.session.check_url = browser.url
117
+ framework.options.session.check_pattern = /Sign Off|MY ACCOUNT/
118
+
119
+ **Without browser (fast):**
120
+
121
+ If a real browser environment is not required for the login operation, then
122
+ using the system-wide HTTP interface is preferable, as it will be much faster
123
+ and consume much less resources.
124
+
125
+ response = http.post( 'http://testfire.net/bank/login.aspx',
126
+ parameters: {
127
+ 'uid' => 'jsmith',
128
+ 'passw' => 'Demo1234'
129
+ },
130
+ mode: :sync,
131
+ update_cookies: true
132
+ )
133
+
134
+ framework.options.session.check_url = to_absolute( response.headers.location, response.url )
135
+ framework.options.session.check_pattern = /Sign Off|MY ACCOUNT/
136
+
137
+ **From cookie-jar:**
138
+
139
+ If an external process is used to manage sessions, you can keep Arachni in sync
140
+ by loading cookies from a shared Netscape-style cookie-jar file.
141
+
142
+ http.cookie_jar.load 'cookies.txt'
143
+ },
144
+ author: 'Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>',
145
+ version: '0.1',
146
+ options: [
147
+ Options::Path.new( :script,
148
+ required: true,
149
+ description: 'Script that includes the login sequence.'
150
+ ),
151
+ ],
152
+ priority: 0 # run before any other plugin
153
+ }
154
+ end
155
+
156
+ end
@@ -0,0 +1,48 @@
1
+ =begin
2
+ Copyright 2010-2014 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
+
4
+ This file is part of the Arachni Framework project and is subject to
5
+ redistribution and commercial restrictions. Please see the Arachni Framework
6
+ web site for more information on licensing and terms of use.
7
+ =end
8
+
9
+ class Arachni::Reporters::HTML
10
+
11
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
12
+ class PluginFormatters::LoginScript < Arachni::Plugin::Formatter
13
+ include TemplateUtilities
14
+
15
+ def run
16
+ ERB.new( tpl ).result( binding )
17
+ end
18
+
19
+ def tpl
20
+ <<-HTML
21
+ <% if results['status'] == 'success' %>
22
+ <p class="alert alert-success">
23
+ <%= results['message'] %>
24
+ </p>
25
+
26
+ <h3>Cookies set to:</h3>
27
+
28
+ <dl class="dl-horizontal">
29
+ <% results['cookies'].each do |k, v| %>
30
+ <dt>
31
+ <code><%= escapeHTML( k ) %></code>
32
+ </dt>
33
+ <dd>
34
+ <code><%= escapeHTML( v ) %></code>
35
+ </dd>
36
+ <% end %>
37
+ </dl>
38
+ <% else %>
39
+ <p class="alert alert-danger">
40
+ <%= results['message'] %>
41
+ </p>
42
+ <% end %>
43
+ HTML
44
+ end
45
+
46
+ end
47
+
48
+ end
@@ -0,0 +1,23 @@
1
+ =begin
2
+ Copyright 2010-2014 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
+
4
+ This file is part of the Arachni Framework project and is subject to
5
+ redistribution and commercial restrictions. Please see the Arachni Framework
6
+ web site for more information on licensing and terms of use.
7
+ =end
8
+
9
+ class Arachni::Reporters::Stdout
10
+
11
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
12
+ class PluginFormatters::LoginScript < Arachni::Plugin::Formatter
13
+
14
+ def run
15
+ print_ok results['message']
16
+
17
+ return if !results['cookies']
18
+ print_info 'Cookies set to:'
19
+ results['cookies'].each_pair { |name, val| print_info " * #{name} = #{val}" }
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ =begin
2
+ Copyright 2010-2014 Tasos Laskos <tasos.laskos@arachni-scanner.com>
3
+
4
+ This file is part of the Arachni Framework project and is subject to
5
+ redistribution and commercial restrictions. Please see the Arachni Framework
6
+ web site for more information on licensing and terms of use.
7
+ =end
8
+
9
+ class Arachni::Reporters::XML
10
+
11
+ # @author Tasos "Zapotek" Laskos <tasos.laskos@arachni-scanner.com>
12
+ class PluginFormatters::LoginScript < Arachni::Plugin::Formatter
13
+
14
+ def run( xml )
15
+ xml.message results['message']
16
+ xml.status results['status']
17
+
18
+ if results['cookies']
19
+ xml.cookies {
20
+ results['cookies'].each { |name, value| xml.cookie name: name, value: value }
21
+ }
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -25,6 +25,7 @@
25
25
  <xs:choice minOccurs="0" maxOccurs="9">
26
26
  <xs:element name="healthmap" type="plugin_healthmap" maxOccurs="1"/>
27
27
  <xs:element name="autologin" type="plugin_autologin" maxOccurs="1"/>
28
+ <xs:element name="login_script" type="plugin_login_script" maxOccurs="1"/>
28
29
  <xs:element name="content_types" type="plugin_content_types" maxOccurs="1"/>
29
30
  <xs:element name="cookie_collector" type="plugin_cookie_collector" maxOccurs="1"/>
30
31
  <xs:element name="form_dicattack" type="plugin_form_dicattack" maxOccurs="1"/>
@@ -187,6 +188,22 @@
187
188
  </xs:all>
188
189
  </xs:complexType>
189
190
 
191
+ <xs:complexType name="plugin_login_script">
192
+ <xs:all>
193
+ <xs:element name="name" type="xs:string"/>
194
+ <xs:element name="description" type="xs:string"/>
195
+ <xs:element name="results" type="plugin_login_script_results"/>
196
+ </xs:all>
197
+ </xs:complexType>
198
+
199
+ <xs:complexType name="plugin_login_script_results">
200
+ <xs:all>
201
+ <xs:element name="status" type="xs:string"/>
202
+ <xs:element name="message" type="xs:string"/>
203
+ <xs:element name="cookies" type="cookies" minOccurs="0"/>
204
+ </xs:all>
205
+ </xs:complexType>
206
+
190
207
  <xs:complexType name="plugin_healthmap">
191
208
  <xs:all>
192
209
  <xs:element name="name" type="xs:string"/>
@@ -820,7 +820,7 @@ class Browser
820
820
  c[:value] = Cookie.decode( c[:value].to_s )
821
821
  c[:httponly] = !js_cookies.include?( original_name )
822
822
 
823
- Cookie.new c.merge( url: @last_url )
823
+ Cookie.new c.merge( url: @last_url || url )
824
824
  end
825
825
  end
826
826
 
@@ -1007,8 +1007,10 @@ class Browser
1007
1007
  print_debug 'Spawn timed-out.'
1008
1008
  end
1009
1009
 
1010
- last_attempt_output = IO.read( @process.io.stdout )
1011
- print_debug last_attempt_output
1010
+ if @process.io.stdout
1011
+ last_attempt_output = IO.read( @process.io.stdout )
1012
+ print_debug last_attempt_output
1013
+ end
1012
1014
 
1013
1015
  if done
1014
1016
  print_debug 'PhantomJS is ready.'
@@ -1046,12 +1048,13 @@ class Browser
1046
1048
  end
1047
1049
 
1048
1050
  @process = nil
1051
+ @watir = nil
1049
1052
  @pid = nil
1050
1053
  @browser_url = nil
1051
1054
  end
1052
1055
 
1053
1056
  def browser_alive?
1054
- @process && @process.alive?
1057
+ @watir && @process && @process.alive?
1055
1058
  rescue Errno::ECHILD
1056
1059
  false
1057
1060
  end