arachni 0.2.2.2 → 0.2.3
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.
- data/CHANGELOG.md +18 -1
- data/README.md +50 -139
- data/bin/arachni_web +1 -0
- data/data/crypto/public.pem +9 -0
- data/getoptslong.rb +1 -0
- data/lib/arachni.rb +1 -1
- data/lib/crypto/rsa_aes_cbc.rb +98 -0
- data/lib/rpc/xml/client/base.rb +8 -3
- data/lib/rpc/xml/client/instance.rb +3 -3
- data/lib/rpc/xml/server/base.rb +27 -5
- data/lib/rpc/xml/server/dispatcher.rb +14 -6
- data/lib/rpc/xml/server/instance.rb +3 -3
- data/lib/ui/web/dispatcher_manager.rb +98 -0
- data/lib/ui/web/server/views/{dispatcher.erb → dispatchers.erb} +31 -16
- data/lib/ui/web/server/views/dispatchers_edit.erb +42 -0
- data/lib/ui/web/server/views/home.erb +12 -1
- data/lib/ui/web/server/views/instance.erb +7 -7
- data/lib/ui/web/server/views/layout.erb +2 -2
- data/lib/ui/web/server/views/welcome.erb +3 -4
- data/lib/ui/web/server.rb +194 -105
- data/lib/ui/xmlrpc/dispatcher_monitor.rb +1 -5
- data/lib/ui/xmlrpc/xmlrpc.rb +2 -6
- data/modules/audit/path_traversal.rb +13 -6
- data/reports/html/default.erb +82 -27
- data/reports/html.rb +32 -1
- data/reports/metareport.rb +1 -0
- data/reports/plugin_formatters/stdout/metaformatters/timeout_notice.rb +2 -0
- metadata +7 -4
- data/lib/ui/web/server/public/reports/demo.testfire.net:Sun Mar 20 02:48:10 2011.afr +0 -104829
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,24 @@
|
|
1
1
|
|
2
2
|
# ChangeLog
|
3
3
|
|
4
|
-
## Version 0.2.
|
4
|
+
## Version 0.2.3 _(Under development)_
|
5
|
+
- WebUI
|
6
|
+
- Added connection cache for XMLRPC server instances to remove HTTPS handshake overhead and take advantage of keep-alive support.
|
7
|
+
- Added initial support for management of multiple Dispatchers.
|
8
|
+
- XMLRPC Client->Dispatch Server
|
9
|
+
- Updated to always use SSL [Issue #28]
|
10
|
+
- Added per instance authentication tokens [Issue #28]
|
11
|
+
- Modules
|
12
|
+
- Audit
|
13
|
+
- Path traversal: added double encoded traversals [Issue #29]
|
14
|
+
- Reports
|
15
|
+
- HTML
|
16
|
+
- Fixed "invalid byte sequence in UTF-8" using iconv [Issue #27]
|
17
|
+
- Added false positive reporting. Data are encrypted using 256bit AES (with AES primitives encrypted using RSA) and sent over HTTPS. [Issue #30]
|
18
|
+
- Metareport
|
19
|
+
- Fixed bug caused by not explicitly closed file handle.
|
20
|
+
|
21
|
+
## Version 0.2.2.2 _(March 22, 2011)_
|
5
22
|
- Added "arachni_web_autostart" under bin -- Automatically starts all systems required by the WebUI and makes shutting down everything easier too (Original by: Brandon Potter <bpotter8705@gmail.com>)
|
6
23
|
- Overrided Nokogiri to revert to UTF-8 when it comes across an unknown charset instead of throwing exceptions
|
7
24
|
- Dependency versions are now defined explicitly [Issue #23]
|
data/README.md
CHANGED
@@ -1,15 +1,49 @@
|
|
1
1
|
# Arachni - Web Application Security Scanner Framework
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
2
|
+
<table>
|
3
|
+
<tr>
|
4
|
+
<th>Version</th>
|
5
|
+
<td>0.2.3</td>
|
6
|
+
</tr>
|
7
|
+
<tr>
|
8
|
+
<th>Homepage</th>
|
9
|
+
<td><a href="http://arachni.segfault.gr">http://arachni.segfault.gr</a></td>
|
10
|
+
</tr>
|
11
|
+
<tr>
|
12
|
+
<th>Blog</th>
|
13
|
+
<td><a href="http://trainofthought.segfault.gr/category/projects/arachni/">http://trainofthought.segfault.gr/category/projects/arachni/</a></td>
|
14
|
+
<tr>
|
15
|
+
<th>Github page</th>
|
16
|
+
<td><a href="http://github.com/zapotek/arachni">http://github.com/zapotek/arachni</a></td>
|
17
|
+
<tr/>
|
18
|
+
<tr>
|
19
|
+
<th>Documentation</th>
|
20
|
+
<td><a href="http://github.com/Zapotek/arachni/wiki">http://github.com/Zapotek/arachni/wiki</a></td>
|
21
|
+
</tr>
|
22
|
+
<tr>
|
23
|
+
<th>Code Documentation</th>
|
24
|
+
<td><a href="http://zapotek.github.com/arachni/">http://zapotek.github.com/arachni/</a></td>
|
25
|
+
</tr>
|
26
|
+
<tr>
|
27
|
+
<th>Google Group</th>
|
28
|
+
<td><a href="http://groups.google.com/group/arachni">http://groups.google.com/group/arachni</a></td>
|
29
|
+
</tr>
|
30
|
+
<tr>
|
31
|
+
<th>Author</th>
|
32
|
+
<td><a href="mailto:tasos.laskos@gmail.com">Tasos</a> <a href="mailto:zapotek@segfault.gr">Zapotek</a> <a href="mailto:tasos.laskos@gmail.com">Laskos</a></td>
|
33
|
+
</tr>
|
34
|
+
<tr>
|
35
|
+
<th>Twitter</th>
|
36
|
+
<td><a href="http://twitter.com/Zap0tek">@Zap0tek</a></td>
|
37
|
+
</tr>
|
38
|
+
<tr>
|
39
|
+
<th>Copyright</th>
|
40
|
+
<td>2010-2011</td>
|
41
|
+
</tr>
|
42
|
+
<tr>
|
43
|
+
<th>License</th>
|
44
|
+
<td><a href="file.LICENSE.html">GNU General Public License v2</a></td>
|
45
|
+
</tr>
|
46
|
+
</table>
|
13
47
|
|
14
48
|

|
15
49
|
|
@@ -186,136 +220,10 @@ Still, this can be an invaluable asset to Fuzzer modules.
|
|
186
220
|
|
187
221
|
## Usage
|
188
222
|
|
189
|
-
### WebUI
|
223
|
+
### [WebUI](https://github.com/Zapotek/arachni/wiki/Web-user-interface)
|
190
224
|
|
191
|
-
The Web User Interface is basically a Sinatra app which acts as an Arachni XMLRPC client and connects to a running XMLRPC Dispatch server.
|
192
225
|
|
193
|
-
|
194
|
-
|
195
|
-
There's an autostart script to start all systems that are required by the WebUI:
|
196
|
-
$ arachni_web_autostart
|
197
|
-
|
198
|
-
**Note:**: _The "arachni_xmlrpcd" and "arachni_web" executables will need to be in your PATH._
|
199
|
-
|
200
|
-
#### Manually
|
201
|
-
|
202
|
-
You first need to start a Dispatcher like so:
|
203
|
-
$ arachni_xmlrpcd &
|
204
|
-
|
205
|
-
Then start the WebUI by running:
|
206
|
-
$ arachni_web
|
207
|
-
|
208
|
-
_If you get any permission errors then you probably installed the Gem using 'sudo', so use 'sudo' to start the servers too._
|
209
|
-
|
210
|
-
And finally open up a browser window and visit: http://localhost:4567/
|
211
|
-
|
212
|
-
#### Options
|
213
|
-
|
214
|
-
You can see all available options using:
|
215
|
-
$ arachni_web -h
|
216
|
-
|
217
|
-
#### Shutdown
|
218
|
-
You can kill the WebUI by sending _Ctrl+C_ to the console from which you started it.
|
219
|
-
|
220
|
-
However, in order to kill the Dispatcher (and all the processes in its pool) you will need to _killall -9 arachni_xmlrpcd_ (or _killall -9 ruby_ depending on your setup) or hunt them down manually.
|
221
|
-
This inconvenience is by design; it guarantees that Arachni instances will be available (and usable) instantly and that running scans will continue unaffected even if the dispatcher has (for some reason) died.
|
222
|
-
|
223
|
-
#### Parallel scans
|
224
|
-
As you might have guessed by the use of the word _pool_ in the previous paragraph, the WebUI allows you to run as many scans as you wish at the same time.
|
225
|
-
Of course, the amount of parallel scans you'll be able to perform will be limited by your available resources (Network bandwidth/RAM/CPU).
|
226
|
-
|
227
|
-
Should you shutdown the WebUI while a scan is running you'll be able to re-attach to the running process and view its progress or (if the scan has already finished) grab the report the next time you visit the WebUI.
|
228
|
-
In most cases, you won't even need to re-attach to a process in order to get the report of the finished scan, the WebUI's zombie reaper will grab and save the report for you.
|
229
|
-
|
230
|
-
#### General
|
231
|
-
In cases where the Dispatcher is started with its default settings on localhost (like the above example) the WebUI will connect to it automatically.
|
232
|
-
|
233
|
-
However, if you see an error message informing you that the WebUI could not find a dispatcher to connect to then you probably visited the WebUI before it had a chance to connect to the Dispatcher, you can just click on the "Dispatcher" tab to force it to try again; if the error does not re-appear then it connected successfully.
|
234
|
-
|
235
|
-
If you get a scary "Broken pipe" exception a simple refresh will solve the problem.
|
236
|
-
|
237
|
-
#### Remote deployment
|
238
|
-
As noted above, the WebUI is, in essence, a user-friendly Arachni XMLRPC client, this means that you can start a Dispatcher on a remote host and manage it via the WebUI.
|
239
|
-
Simple as that really.
|
240
|
-
|
241
|
-
#### Encryption & Authentication
|
242
|
-
WebUI-client (browser) and XMLRPC Client-Dispatch server authentication takes place using SSL certificate/key pairs.
|
243
|
-
|
244
|
-
These are the 3 basic models:
|
245
|
-
|
246
|
-
- No encryption & no authentication -- Default behavior
|
247
|
-
- Encryption & no authentication -- Just enable SSL in the WebUI configuration file (_conf/webui.yaml_) and the Dispatcher and all components will generate their own certificate/key pairs and disable peer verification.
|
248
|
-
- Encryption & authentication -- Enable SSL and use your own cert/key pairs to authenticate clients to the WebUI and vice verse, and authenticate the XMLRPC clients controlled by the WebUI to the Dispatcher and vice versa.
|
249
|
-
|
250
|
-
However, you can go even further and create combinations specific to each component.
|
251
|
-
|
252
|
-
*Beware:* This interface is brand new so if you encounter any issues please do report them.
|
253
|
-
|
254
|
-
### Command line interface
|
255
|
-
|
256
|
-
The command-line interface is the oldest, most tested and thus more reliable.
|
257
|
-
|
258
|
-
#### Help
|
259
|
-
In order to see everything Arachni has to offer execute:
|
260
|
-
$ arachni -h
|
261
|
-
|
262
|
-
Or visit the Wiki.
|
263
|
-
|
264
|
-
#### Examples
|
265
|
-
You can simply run Arachni like so:
|
266
|
-
|
267
|
-
$ arachni http://test.com
|
268
|
-
|
269
|
-
which will load all modules and audit all forms, links and cookies.
|
270
|
-
|
271
|
-
In the following example all modules will be run against <i>http://test.com</i>, auditing links/forms/cookies and following subdomains --with verbose output enabled.<br/>
|
272
|
-
The results of the audit will be saved in the the file <i>test.com.afr</i>.
|
273
|
-
|
274
|
-
$ arachni -fv http://test.com --report=afr:outfile=test.com.afr
|
275
|
-
|
276
|
-
The Arachni Framework Report (.afr) file can later be loaded by Arachni to create a report, like so:
|
277
|
-
|
278
|
-
$ arachni --repload=test.com.afr --report=html:outfile=my_report.html
|
279
|
-
|
280
|
-
or any other report type as shown by:
|
281
|
-
|
282
|
-
$ arachni --lsrep
|
283
|
-
|
284
|
-
#### You can make module loading easier by using wildcards (*) and exclusions (-).
|
285
|
-
|
286
|
-
To load all _xss_ modules using a wildcard:
|
287
|
-
$ arachni http://example.net --mods=xss_*
|
288
|
-
|
289
|
-
To load all _audit_ modules using a wildcard:
|
290
|
-
$ arachni http://example.net --mods=audit*
|
291
|
-
|
292
|
-
To exclude only the _csrf_ module:
|
293
|
-
$ arachni http://example.net --mods=*,-csrf
|
294
|
-
|
295
|
-
Or you can mix and match; to run everything but the _xss_ modules:
|
296
|
-
$ arachni http://example.net --mods=*,-xss_*
|
297
|
-
|
298
|
-
For a full explanation of all available options you can consult the [User Guide](http://github.com/Zapotek/arachni/wiki/User-guide).
|
299
|
-
|
300
|
-
#### Performing a comprehensive scan quickly
|
301
|
-
|
302
|
-
Arachni comes with a preconfigured profile (_profiles/comprehensive.afp_) for a comprehensive audit.
|
303
|
-
This profile loads all modules, audits links/forms/cookies and loads the HealthMap and Content-Types plugins.
|
304
|
-
|
305
|
-
You can use it like so:
|
306
|
-
$ arachni --load-profile=profiles/comprehensive.afp http://example.net
|
307
|
-
|
308
|
-
#### Performing a full scan quickly
|
309
|
-
|
310
|
-
The _full_ profile adds header auditing to the _comprehensive_ profile.
|
311
|
-
|
312
|
-
_NOTICE: Auditing headers can increase scan time by an order of magnitude (depending on the website) and may be considered over-the-top in most scenarios._
|
313
|
-
|
314
|
-
You can use it like so:
|
315
|
-
$ arachni --load-profile=profiles/full.afp http://example.net
|
316
|
-
|
317
|
-
|
318
|
-
_If you installed the Gem then you'll have to look for the "profiles" directory in your gems path._
|
226
|
+
### [Command line interface](https://github.com/Zapotek/arachni/wiki/Command-line-user-interface)
|
319
227
|
|
320
228
|
## Installation
|
321
229
|
|
@@ -330,6 +238,7 @@ If you decide to go the CDE route you can skip the rest, you're done.
|
|
330
238
|
### Gem
|
331
239
|
|
332
240
|
To install the Gem or work with the source code you'll also need the following system libraries:
|
241
|
+
|
333
242
|
$ sudo apt-get install libxml2-dev libxslt1-dev libcurl4-openssl-dev libsqlite3-dev
|
334
243
|
|
335
244
|
You will also need to have Ruby 1.9.2 installed *including* the dev package/headers.<br/>
|
@@ -337,11 +246,13 @@ The prefered ways to accomplish this is by either using [RVM](http://rvm.beginre
|
|
337
246
|
|
338
247
|
|
339
248
|
To install Arachni:
|
249
|
+
|
340
250
|
$ gem install arachni
|
341
251
|
|
342
252
|
### Source
|
343
253
|
|
344
254
|
If you want to clone the repository and work with the source code then you'll need to run the following to install all gem dependencies and Arachni:
|
255
|
+
|
345
256
|
$ rake install
|
346
257
|
|
347
258
|
|
data/bin/arachni_web
CHANGED
@@ -21,6 +21,7 @@ options = Arachni::Options.instance
|
|
21
21
|
|
22
22
|
options.dir = Hash.new
|
23
23
|
options.dir['root'] = File.expand_path( cwd + '/../' ) + '/'
|
24
|
+
options.dir['data'] = options.dir['root'] + 'data/'
|
24
25
|
options.dir['modules'] = options.dir['root'] + 'modules/'
|
25
26
|
options.dir['reports'] = options.dir['root'] + 'reports/'
|
26
27
|
options.dir['plugins'] = options.dir['root'] + 'plugins/'
|
@@ -0,0 +1,9 @@
|
|
1
|
+
-----BEGIN PUBLIC KEY-----
|
2
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvyhiZE8Npa3GIlstM/N5
|
3
|
+
pVfvP4cHeMJ/n5psnnDyF8/BK9bNawB8z4+7pXZJgvlD8E18ewsM9UZvekaBTdF8
|
4
|
+
wGsAYHPV50H/pVn+e6foQPB/txGR7oSKdUKoTswPj2hDPnbPAUSLhLfYhXzFz0HW
|
5
|
+
OZJKQt14qeOsYiMNYKrvAUGlwvhEPDLSEDhIvy7udX9ZFODt6X4Pm3lJwnydmdIY
|
6
|
+
SgnB8QdL0A1bnj91TO0Ey+lF+MkK3bZ0mtCgsQ0yYtZsVeHaYmu0YnmdsNyX2wMK
|
7
|
+
ElZlnLemhmLbKLnQXsR2dL54kpkjW6liN2HUEDi8K5Mv9aOCRorDJqn77kUzF8fn
|
8
|
+
WQIDAQAB
|
9
|
+
-----END PUBLIC KEY-----
|
data/getoptslong.rb
CHANGED
@@ -63,6 +63,7 @@ options = Arachni::Options.instance
|
|
63
63
|
|
64
64
|
options.dir = Hash.new
|
65
65
|
options.dir['root'] = File.dirname( File.expand_path(__FILE__) ) + '/'
|
66
|
+
options.dir['data'] = options.dir['root'] + 'data/'
|
66
67
|
options.dir['modules'] = options.dir['root'] + 'modules/'
|
67
68
|
options.dir['reports'] = options.dir['root'] + 'reports/'
|
68
69
|
options.dir['plugins'] = options.dir['root'] + 'plugins/'
|
data/lib/arachni.rb
CHANGED
@@ -0,0 +1,98 @@
|
|
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 'openssl'
|
12
|
+
require "yaml"
|
13
|
+
require "base64"
|
14
|
+
|
15
|
+
#
|
16
|
+
# Simple hybrid crypto class using RSA for public key encryption and AES with CBC
|
17
|
+
# for bulk data encryption/decryption.
|
18
|
+
#
|
19
|
+
# RSA is used to encrypt the AES primitives which are used to encrypt the plaintext.
|
20
|
+
#
|
21
|
+
# @author: Tasos "Zapotek" Laskos
|
22
|
+
# <tasos.laskos@gmail.com>
|
23
|
+
# <zapotek@segfault.gr>
|
24
|
+
# @version: 0.1
|
25
|
+
#
|
26
|
+
class RSA_AES_CBC
|
27
|
+
|
28
|
+
#
|
29
|
+
# If only encryption is required the private key parameter can be omitted.
|
30
|
+
#
|
31
|
+
# @param [String] public_pem location of the Public key in PEM format
|
32
|
+
# @param [String] private_pem location of the Private key in PEM format
|
33
|
+
#
|
34
|
+
def initialize( public_pem, private_pem = nil )
|
35
|
+
@public_pem = public_pem
|
36
|
+
@private_pem = private_pem
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# Encrypts data and returns a Base64 representation of the ciphertext
|
41
|
+
# and AES CBC primitives encrypted using the public key.
|
42
|
+
#
|
43
|
+
# @param [String] data
|
44
|
+
#
|
45
|
+
# @return [String] Base64 representation of the ciphertext
|
46
|
+
# and AES CBC primitives encrypted using the public key.
|
47
|
+
#
|
48
|
+
def encrypt( data )
|
49
|
+
rsa = OpenSSL::PKey::RSA.new( File.read( @public_pem ) )
|
50
|
+
|
51
|
+
# encrypt with 256 bit AES with CBC
|
52
|
+
aes = OpenSSL::Cipher::Cipher.new( 'aes-256-cbc' )
|
53
|
+
aes.encrypt
|
54
|
+
|
55
|
+
# use random key and IV
|
56
|
+
aes.key = key = aes.random_key
|
57
|
+
aes.iv = iv = aes.random_iv
|
58
|
+
|
59
|
+
# this will hold all primitives and ciphertext
|
60
|
+
primitives = {}
|
61
|
+
|
62
|
+
primitives['ciphertext'] = aes.update( data )
|
63
|
+
primitives['ciphertext'] << aes.final
|
64
|
+
|
65
|
+
primitives['key'] = rsa.public_encrypt( key )
|
66
|
+
primitives['iv'] = rsa.public_encrypt( iv )
|
67
|
+
|
68
|
+
# serialize everything and base64 encode it
|
69
|
+
Base64.encode64( primitives.to_yaml )
|
70
|
+
end
|
71
|
+
|
72
|
+
#
|
73
|
+
# Decrypts data.
|
74
|
+
#
|
75
|
+
# @param [String] data
|
76
|
+
#
|
77
|
+
# @return [String] plaintext
|
78
|
+
#
|
79
|
+
def decrypt( data )
|
80
|
+
rsa = OpenSSL::PKey::RSA.new( File.read( @private_pem ) )
|
81
|
+
|
82
|
+
# decrypt with 256 bit AES with CBC
|
83
|
+
aes = OpenSSL::Cipher::Cipher.new( 'aes-256-cbc' )
|
84
|
+
aes.decrypt
|
85
|
+
|
86
|
+
# unencode and unserialize to get the primitives and ciphertext
|
87
|
+
primitives = YAML::load( Base64.decode64( data ) )
|
88
|
+
|
89
|
+
aes.key = rsa.private_decrypt( primitives['key'] )
|
90
|
+
aes.iv = rsa.private_decrypt( primitives['iv'] )
|
91
|
+
|
92
|
+
plaintext = aes.update( primitives['ciphertext'] )
|
93
|
+
plaintext << aes.final
|
94
|
+
|
95
|
+
return plaintext
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
data/lib/rpc/xml/client/base.rb
CHANGED
@@ -22,16 +22,21 @@ module Client
|
|
22
22
|
# @author: Tasos "Zapotek" Laskos
|
23
23
|
# <tasos.laskos@gmail.com>
|
24
24
|
# <zapotek@segfault.gr>
|
25
|
-
# @version: 0.1
|
25
|
+
# @version: 0.1.1
|
26
26
|
#
|
27
27
|
class Base
|
28
28
|
|
29
|
-
def initialize( opts, url )
|
29
|
+
def initialize( opts, url, token = nil )
|
30
30
|
|
31
31
|
@opts = opts
|
32
32
|
|
33
|
+
url = URI( url )
|
34
|
+
url.scheme = 'https'
|
35
|
+
|
33
36
|
# start the XMLRPC client
|
34
|
-
@server = ::XMLRPC::Client.new2( url )
|
37
|
+
@server = ::XMLRPC::Client.new2( url.to_s )
|
38
|
+
|
39
|
+
@server.cookie = 'token=' + token + ';' if token
|
35
40
|
|
36
41
|
# there'll be a HELL of lot of output so things might get..laggy.
|
37
42
|
# a big timeout is required to avoid Timeout exceptions...
|
@@ -25,7 +25,7 @@ module Client
|
|
25
25
|
# @author: Tasos "Zapotek" Laskos
|
26
26
|
# <tasos.laskos@gmail.com>
|
27
27
|
# <zapotek@segfault.gr>
|
28
|
-
# @version: 0.1.
|
28
|
+
# @version: 0.1.2
|
29
29
|
#
|
30
30
|
class Instance < Base
|
31
31
|
|
@@ -70,8 +70,8 @@ class Instance < Base
|
|
70
70
|
|
71
71
|
end
|
72
72
|
|
73
|
-
def initialize( opts, url )
|
74
|
-
super( opts, url )
|
73
|
+
def initialize( opts, url, token = nil )
|
74
|
+
super( opts, url, token )
|
75
75
|
|
76
76
|
@opts = OptsMapper.new( @server, 'opts' )
|
77
77
|
@framework = Mapper.new( @server, 'framework' )
|
data/lib/rpc/xml/server/base.rb
CHANGED
@@ -10,6 +10,8 @@
|
|
10
10
|
|
11
11
|
require 'socket'
|
12
12
|
require 'sys/proctable'
|
13
|
+
require 'webrick'
|
14
|
+
require 'cgi'
|
13
15
|
|
14
16
|
module Arachni
|
15
17
|
module RPC
|
@@ -22,11 +24,30 @@ module Server
|
|
22
24
|
# @author: Tasos "Zapotek" Laskos
|
23
25
|
# <tasos.laskos@gmail.com>
|
24
26
|
# <zapotek@segfault.gr>
|
25
|
-
# @version: 0.1
|
27
|
+
# @version: 0.1.1
|
26
28
|
#
|
27
29
|
class Base
|
28
30
|
|
29
|
-
|
31
|
+
#
|
32
|
+
# This one doesn't add much new functionality,
|
33
|
+
# it just checks for a cookie token before processing each request.
|
34
|
+
#
|
35
|
+
# If it can't find a valid token then it returns nothing.
|
36
|
+
#
|
37
|
+
class WebServ < ::WEBrick::HTTPServer
|
38
|
+
|
39
|
+
def service( req, res )
|
40
|
+
|
41
|
+
if @config[:Token]
|
42
|
+
return if @config[:Token] != ::CGI.parse( req.cookies.join )['token'][0]
|
43
|
+
end
|
44
|
+
|
45
|
+
super( req, res )
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
def initialize( opts, token = nil )
|
30
51
|
|
31
52
|
pkey = ::OpenSSL::PKey::RSA.new( File.read( opts.ssl_pkey ) ) if opts.ssl_pkey
|
32
53
|
cert = ::OpenSSL::X509::Certificate.new( File.read( opts.ssl_cert ) ) if opts.ssl_cert
|
@@ -37,14 +58,15 @@ class Base
|
|
37
58
|
verification = ::OpenSSL::SSL::VERIFY_NONE
|
38
59
|
end
|
39
60
|
|
40
|
-
@server =
|
61
|
+
@server = WebServ.new(
|
41
62
|
:Port => opts.rpc_port,
|
42
|
-
:SSLEnable =>
|
63
|
+
:SSLEnable => true,
|
43
64
|
:SSLVerifyClient => verification,
|
44
65
|
:SSLCertName => [ [ "CN", ::WEBrick::Utils::getservername ] ],
|
45
66
|
:SSLCertificate => cert,
|
46
67
|
:SSLPrivateKey => pkey,
|
47
|
-
:SSLCACertificateFile => opts.ssl_ca
|
68
|
+
:SSLCACertificateFile => opts.ssl_ca,
|
69
|
+
:Token => token
|
48
70
|
)
|
49
71
|
|
50
72
|
print_status( 'Initing XMLRPC Server...' )
|
@@ -39,7 +39,7 @@ module Server
|
|
39
39
|
# @author: Tasos "Zapotek" Laskos
|
40
40
|
# <tasos.laskos@gmail.com>
|
41
41
|
# <zapotek@segfault.gr>
|
42
|
-
# @version: 0.1.
|
42
|
+
# @version: 0.1.2
|
43
43
|
#
|
44
44
|
class Dispatcher < Base
|
45
45
|
|
@@ -221,10 +221,6 @@ class Dispatcher < Base
|
|
221
221
|
(All SSL options will be honored by the dispatched XMLRPC instances as well.)
|
222
222
|
(Do *not* use encrypted keys!)
|
223
223
|
|
224
|
-
--ssl use SSL?
|
225
|
-
(If you want encryption without authentication
|
226
|
-
you can skip rest of the SSL options.)
|
227
|
-
|
228
224
|
--ssl-pkey <file> location of the SSL private key (.pem)
|
229
225
|
(Used to verify the server to the clients.)
|
230
226
|
|
@@ -252,10 +248,11 @@ USAGE
|
|
252
248
|
|
253
249
|
# get an available port for the child
|
254
250
|
@opts.rpc_port = avail_port( )
|
251
|
+
@token = secret()
|
255
252
|
|
256
253
|
pid = Kernel.fork {
|
257
254
|
exception_jail {
|
258
|
-
server = Arachni::RPC::XML::Server::Instance.new( @opts )
|
255
|
+
server = Arachni::RPC::XML::Server::Instance.new( @opts, @token )
|
259
256
|
trap( "INT", "IGNORE" )
|
260
257
|
server.run
|
261
258
|
}
|
@@ -271,6 +268,7 @@ USAGE
|
|
271
268
|
"Port: #{@opts.rpc_port} - Owner: #{owner}" )
|
272
269
|
|
273
270
|
@pool << {
|
271
|
+
'token' => @token,
|
274
272
|
'pid' => pid,
|
275
273
|
'port' => @opts.rpc_port,
|
276
274
|
'owner' => owner,
|
@@ -279,6 +277,7 @@ USAGE
|
|
279
277
|
|
280
278
|
# let the child go about his business
|
281
279
|
Process.detach( pid )
|
280
|
+
@token = nil
|
282
281
|
}
|
283
282
|
}
|
284
283
|
|
@@ -331,6 +330,15 @@ USAGE
|
|
331
330
|
range[ rand( 65535 - 1025 ) ]
|
332
331
|
end
|
333
332
|
|
333
|
+
def secret
|
334
|
+
secret = ''
|
335
|
+
1000.times {
|
336
|
+
secret += rand( 1000 ).to_s
|
337
|
+
}
|
338
|
+
|
339
|
+
return Digest::MD5.hexdigest( secret )
|
340
|
+
end
|
341
|
+
|
334
342
|
#
|
335
343
|
# Checks whether the port number is available
|
336
344
|
#
|
@@ -35,7 +35,7 @@ module Server
|
|
35
35
|
# @author: Tasos "Zapotek" Laskos
|
36
36
|
# <tasos.laskos@gmail.com>
|
37
37
|
# <zapotek@segfault.gr>
|
38
|
-
# @version: 0.1.
|
38
|
+
# @version: 0.1.4
|
39
39
|
#
|
40
40
|
class Instance < Base
|
41
41
|
|
@@ -52,13 +52,13 @@ class Instance < Base
|
|
52
52
|
#
|
53
53
|
# @param [Options] opts
|
54
54
|
#
|
55
|
-
def initialize( opts )
|
55
|
+
def initialize( opts, token )
|
56
56
|
|
57
57
|
prep_framework
|
58
58
|
banner
|
59
59
|
|
60
60
|
@opts = opts
|
61
|
-
super( @opts )
|
61
|
+
super( @opts, token )
|
62
62
|
|
63
63
|
if @opts.debug
|
64
64
|
debug!
|
@@ -0,0 +1,98 @@
|
|
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 'datamapper'
|
12
|
+
|
13
|
+
module Arachni
|
14
|
+
module UI
|
15
|
+
module Web
|
16
|
+
|
17
|
+
#
|
18
|
+
#
|
19
|
+
# Provides nice little wrapper for the Arachni::Report::Manager while also handling<br/>
|
20
|
+
# conversions, storing etc.
|
21
|
+
#
|
22
|
+
# @author: Tasos "Zapotek" Laskos
|
23
|
+
# <tasos.laskos@gmail.com>
|
24
|
+
# <zapotek@segfault.gr>
|
25
|
+
# @version: 0.1
|
26
|
+
#
|
27
|
+
class DispatcherManager
|
28
|
+
|
29
|
+
class Dispatcher
|
30
|
+
include DataMapper::Resource
|
31
|
+
|
32
|
+
property :id, Serial
|
33
|
+
property :url, String
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def initialize( opts, settings )
|
38
|
+
@opts = opts
|
39
|
+
@settings = settings
|
40
|
+
|
41
|
+
DataMapper::setup( :default, "sqlite3://#{@settings.db}/default.db" )
|
42
|
+
DataMapper.finalize
|
43
|
+
|
44
|
+
Dispatcher.auto_upgrade!
|
45
|
+
end
|
46
|
+
|
47
|
+
def new( opts )
|
48
|
+
Dispatcher.create( :url => opts[:url] )
|
49
|
+
end
|
50
|
+
|
51
|
+
def connect( url )
|
52
|
+
@@cache ||= {}
|
53
|
+
|
54
|
+
begin
|
55
|
+
if @@cache[url] && @@cache[url].alive?
|
56
|
+
return @@cache[url]
|
57
|
+
elsif ( tmp = Arachni::RPC::XML::Client::Dispatcher.new( @opts, url ) ) &&
|
58
|
+
tmp.alive?
|
59
|
+
return @@cache[url] = tmp
|
60
|
+
end
|
61
|
+
rescue Exception => e
|
62
|
+
return nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def alive?( url )
|
67
|
+
begin
|
68
|
+
return connect( url ).alive?
|
69
|
+
rescue
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# Returns the paths of all saved report files as an array
|
76
|
+
#
|
77
|
+
# @return [Array]
|
78
|
+
#
|
79
|
+
def all( *args )
|
80
|
+
Dispatcher.all( *args )
|
81
|
+
end
|
82
|
+
|
83
|
+
def delete_all
|
84
|
+
all.each {
|
85
|
+
|report|
|
86
|
+
delete( report.id )
|
87
|
+
}
|
88
|
+
all.destroy
|
89
|
+
end
|
90
|
+
|
91
|
+
def delete( id )
|
92
|
+
Dispatcher.get( id ).destroy
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|