arachni 1.0.4 → 1.0.5
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 +4 -4
- data/CHANGELOG.md +42 -0
- data/README.md +8 -4
- data/bin/arachni_console +1 -1
- data/components/checks/active/no_sql_injection.rb +4 -4
- data/components/checks/passive/common_directories/directories.txt +1 -0
- data/components/checks/passive/common_files/filenames.txt +1 -0
- data/components/plugins/login_script.rb +156 -0
- data/components/reporters/plugin_formatters/html/login_script.rb +48 -0
- data/components/reporters/plugin_formatters/stdout/login_script.rb +23 -0
- data/components/reporters/plugin_formatters/xml/login_script.rb +26 -0
- data/components/reporters/xml/schema.xsd +17 -0
- data/lib/arachni/browser.rb +7 -4
- data/lib/arachni/browser/javascript.rb +40 -4
- data/lib/arachni/browser/javascript/proxy.rb +1 -1
- data/lib/arachni/browser_cluster/worker.rb +14 -4
- data/lib/arachni/check/auditor.rb +24 -7
- data/lib/arachni/check/manager.rb +6 -0
- data/lib/arachni/framework.rb +54 -6
- data/lib/arachni/http/client.rb +41 -23
- data/lib/arachni/http/headers.rb +5 -1
- data/lib/arachni/http/message.rb +0 -7
- data/lib/arachni/http/request.rb +40 -32
- data/lib/arachni/http/response.rb +8 -1
- data/lib/arachni/platform/manager.rb +7 -0
- data/lib/arachni/rpc/server/framework/multi_instance.rb +1 -1
- data/lib/arachni/session.rb +88 -58
- data/lib/arachni/state/framework.rb +34 -5
- data/lib/arachni/support/profiler.rb +2 -0
- data/lib/arachni/uri.rb +2 -1
- data/lib/version +1 -1
- data/spec/arachni/browser/javascript_spec.rb +15 -0
- data/spec/arachni/check/manager_spec.rb +17 -0
- data/spec/arachni/framework_spec.rb +4 -2
- data/spec/arachni/http/client_spec.rb +1 -1
- data/spec/arachni/session_spec.rb +80 -37
- data/spec/arachni/state/framework_spec.rb +34 -1
- data/spec/arachni/uri_spec.rb +7 -0
- data/spec/components/plugins/login_script_spec.rb +157 -0
- data/spec/support/servers/plugins/login_script.rb +13 -0
- data/ui/cli/output.rb +26 -9
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 113357f2e377065a79df18200488cc13fe744b6d
|
4
|
+
data.tar.gz: 41739b4e27d567d15f67f9ed86c571c24143c3a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0418e763e4b5577d1d6856cbbf3cdc242ba04525e10de155b4b86484e6208acdf78cea104e0ce9e75a44aab73fb8e7d40c10be0459d58811b8f7a83b6b4971e1
|
7
|
+
data.tar.gz: 2ab357a8d52233a026374d1f0bd09ba03d8ebffa9d939d8a97f51bf76c638e95362c1f080b6ed78c54e630d1a13a0c4ddd90dbe61555259dddef762d3a3385e3
|
data/CHANGELOG.md
CHANGED
@@ -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.
|
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
|
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
|
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.
|
data/bin/arachni_console
CHANGED
@@ -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:
|
60
|
+
version: '0.1.1',
|
61
|
+
platforms: payloads.keys,
|
62
62
|
|
63
63
|
issue: {
|
64
64
|
name: %q{NoSQL Injection},
|
@@ -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"/>
|
data/lib/arachni/browser.rb
CHANGED
@@ -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
|
-
|
1011
|
-
|
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
|