arachni 0.2.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
![Arachni logo](http://zapotek.github.com/arachni/logo.png)
|
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
|