watobo 0.9.9.pre3 → 0.9.9
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/.yardopts +24 -0
- data/CHANGELOG +17 -7
- data/README +4 -60
- data/bin/nfq_server.rb +191 -0
- data/config/interceptor.yml +2 -6
- data/lib/watobo/adapters/data_store.rb +1 -1
- data/lib/watobo/adapters/file/file_store.rb +50 -33
- data/lib/watobo/ca.rb +22 -0
- data/lib/watobo/config.rb +6 -0
- data/lib/watobo/core/ca.rb +411 -0
- data/lib/watobo/core/cert_store.rb +56 -0
- data/lib/watobo/core/forwarding_proxy.rb +38 -0
- data/lib/watobo/core/http_socket.rb +18 -0
- data/lib/watobo/core/intercept_carver.rb +179 -0
- data/lib/watobo/core/intercept_filter.rb +257 -0
- data/lib/watobo/core/interceptor.rb +342 -79
- data/lib/watobo/core/netfilter_queue.rb +191 -0
- data/lib/watobo/core/project.rb +84 -138
- data/lib/watobo/core/proxy.rb +61 -0
- data/lib/watobo/core/request.rb +40 -0
- data/lib/watobo/core/response.rb +30 -0
- data/lib/watobo/core/scanner.rb +64 -58
- data/lib/watobo/core/session.rb +70 -77
- data/lib/watobo/core.rb +1 -1
- data/lib/watobo/framework/create_project.rb +25 -10
- data/lib/watobo/framework/init.rb +13 -0
- data/lib/watobo/gui/browser_preview.rb +5 -4
- data/lib/watobo/gui/checks_policy_frame.rb +1 -0
- data/lib/watobo/gui/client_cert_dialog.rb +11 -6
- data/lib/watobo/gui/conversation_table.rb +7 -4
- data/lib/watobo/gui/fuzzer_gui.rb +9 -11
- data/lib/watobo/gui/intercept_filter_dialog.rb +210 -0
- data/lib/watobo/gui/interceptor_gui.rb +59 -21
- data/lib/watobo/gui/interceptor_settings_dialog.rb +39 -5
- data/lib/watobo/gui/list_box.rb +2 -1
- data/lib/watobo/gui/log_viewer.rb +79 -5
- data/lib/watobo/gui/main_window.rb +159 -113
- data/lib/watobo/gui/manual_request_editor.rb +11 -5
- data/lib/watobo/gui/mixins/subscriber.rb +47 -0
- data/lib/watobo/gui/project_wizzard.rb +3 -3
- data/lib/watobo/gui/proxy_dialog.rb +17 -18
- data/lib/watobo/gui/request_editor.rb +1 -1
- data/lib/watobo/gui/rewrite_filters_dialog.rb +416 -0
- data/lib/watobo/gui/rewrite_rules_dialog.rb +394 -0
- data/lib/watobo/gui/scanner_settings_dialog.rb +9 -6
- data/lib/watobo/gui/session_management_dialog.rb +33 -23
- data/lib/watobo/gui/sites_tree.rb +5 -6
- data/lib/watobo/gui/status_bar.rb +101 -49
- data/lib/watobo/gui/table_editor.rb +1 -1
- data/lib/watobo/gui/templates/plugin2.rb +23 -27
- data/lib/watobo/gui/utils/save_default_settings.rb +9 -9
- data/lib/watobo/gui/utils/save_proxy_settings.rb +25 -9
- data/lib/watobo/gui/utils/save_scanner_settings.rb +10 -7
- data/lib/watobo/gui/utils/session_history.rb +1 -1
- data/lib/watobo/gui/www_auth_dialog.rb +25 -21
- data/lib/watobo/gui.rb +3 -1
- data/lib/watobo/mixins/httpparser.rb +47 -40
- data/lib/watobo/mixins/request_parser.rb +126 -41
- data/lib/watobo/mixins/shapers.rb +124 -15
- data/lib/watobo/utils/hexprint.rb +31 -0
- data/lib/watobo/utils/load_chat.rb +2 -0
- data/lib/watobo/utils/response_builder.rb +111 -0
- data/lib/watobo.rb +4 -1
- data/modules/active/discovery/http_methods.rb +6 -4
- data/modules/active/fileinclusion/lfi_simple.rb +3 -3
- data/modules/active/sqlinjection/sqli_timing.rb +6 -6
- data/modules/passive/redirectionz.rb +5 -6
- data/plugins/catalog/catalog.rb +240 -56
- data/plugins/catalog/db_tests +1 -6483
- data/plugins/catalog/db_variables +2 -29
- data/plugins/crawler/gui/auth_frame.rb +15 -3
- data/plugins/crawler/gui/crawler_gui.rb +24 -0
- data/plugins/crawler/gui/hooks_frame.rb +7 -2
- data/plugins/crawler/gui/settings_tabbook.rb +4 -0
- data/plugins/crawler/gui.rb +3 -3
- data/plugins/crawler/lib/engine.rb +1 -1
- data/plugins/filefinder/filefinder.rb +21 -17
- data/plugins/sqlmap/bin/test.rb +100 -0
- data/plugins/sqlmap/gui/main.rb +227 -0
- data/plugins/sqlmap/gui/options_frame.rb +119 -0
- data/plugins/sqlmap/gui.rb +27 -0
- data/plugins/sqlmap/icons/sqlmap.ico +0 -0
- data/plugins/sqlmap/lib/sqlmap_ctrl.rb +116 -0
- data/plugins/sqlmap/sqlmap.rb +26 -0
- data/plugins/sslchecker/gui/gui.rb +45 -30
- metadata +32 -9
- data/certificates/cert.pem +0 -19
- data/certificates/privkey.pem +0 -15
- data/certificates/watobo_dh.key +0 -5
- data/lib/watobo/core/simple_ca.rb +0 -393
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# .
|
|
2
|
+
# ca.rb
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2012 by siberas, http://www.siberas.de
|
|
5
|
+
#
|
|
6
|
+
# This file is part of WATOBO (Web Application Tool Box)
|
|
7
|
+
# http://watobo.sourceforge.com
|
|
8
|
+
#
|
|
9
|
+
# WATOBO is free software; you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation version 2 of the License.
|
|
12
|
+
#
|
|
13
|
+
# WATOBO is distributed in the hope that it will be useful,
|
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
# GNU General Public License for more details.
|
|
17
|
+
#
|
|
18
|
+
# You should have received a copy of the GNU General Public License
|
|
19
|
+
# along with WATOBO; if not, write to the Free Software
|
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
21
|
+
# .
|
|
22
|
+
module Watobo
|
|
23
|
+
module CA
|
|
24
|
+
@cadir = File.join(Watobo.working_directory, "CA")
|
|
25
|
+
@crl_dir= File.join(@cadir, "crl")
|
|
26
|
+
@hostname = %x('hostname').strip
|
|
27
|
+
@hostname = "watobo" if @hostname.empty?
|
|
28
|
+
@domain = "#{@hostname}.watobo.local"
|
|
29
|
+
def self.ca_ready?
|
|
30
|
+
return false unless File.exists? @ca_config[:CA_dir]
|
|
31
|
+
return false unless File.exists? @ca_config[:private_dir]
|
|
32
|
+
return false unless File.exists? @ca_config[:fake_certs_dir]
|
|
33
|
+
return false unless File.exists? @ca_config[:crl_dir]
|
|
34
|
+
return false unless File.exists? @ca_config[:csr_dir]
|
|
35
|
+
return true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# return 0
|
|
39
|
+
@ca_config = {
|
|
40
|
+
:CA_dir => @cadir,
|
|
41
|
+
# need a password here .... mmmhhhhh ...,
|
|
42
|
+
:password => "watobo",
|
|
43
|
+
|
|
44
|
+
:keypair_file => File.join(@cadir, "private/cakeypair.pem"),
|
|
45
|
+
:cert_file => File.join(@cadir, "cacert.pem"),
|
|
46
|
+
:serial_file => File.join(@cadir, "serial"),
|
|
47
|
+
:fake_certs_dir => File.join(@cadir, "fake_certs"),
|
|
48
|
+
:new_keypair_dir => File.join(@cadir, "private/keypair_backup"),
|
|
49
|
+
:csr_dir => File.join(@cadir, "csr"),
|
|
50
|
+
:crl_dir => File.join(@cadir, 'crl'),
|
|
51
|
+
:private_dir => File.join(@cadir, 'private'), #, 0700
|
|
52
|
+
|
|
53
|
+
:ca_cert_days => 5 * 365, # five years
|
|
54
|
+
:ca_rsa_key_length => 2048,
|
|
55
|
+
|
|
56
|
+
:cert_days => 365, # one year
|
|
57
|
+
:cert_key_length_min => 1024,
|
|
58
|
+
:cert_key_length_max => 2048,
|
|
59
|
+
|
|
60
|
+
:crl_file => File.join(@crl_dir, "#{@hostname}.crl"),
|
|
61
|
+
:crl_pem_file => File.join(@crl_dir, "#{@hostname}.pem"),
|
|
62
|
+
:crl_days => 14,
|
|
63
|
+
:name => [
|
|
64
|
+
['C', 'DE', OpenSSL::ASN1::PRINTABLESTRING],
|
|
65
|
+
['O', @domain, OpenSSL::ASN1::UTF8STRING],
|
|
66
|
+
['OU', @hostname, OpenSSL::ASN1::UTF8STRING],
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
unless Watobo::CA.ca_ready? then
|
|
71
|
+
Dir.mkdir(@ca_config[:CA_dir])
|
|
72
|
+
Dir.mkdir @ca_config[:private_dir]
|
|
73
|
+
Dir.mkdir @ca_config[:fake_certs_dir]
|
|
74
|
+
Dir.mkdir @ca_config[:crl_dir]
|
|
75
|
+
Dir.mkdir @ca_config[:csr_dir]
|
|
76
|
+
|
|
77
|
+
File.open @ca_config[:serial_file], 'w' do |f| f << '1' end
|
|
78
|
+
|
|
79
|
+
#print "Generating CA keypair ..."
|
|
80
|
+
#puts " - rsa_key_length: " + @ca_config[:ca_rsa_key_length].to_s
|
|
81
|
+
keypair = OpenSSL::PKey::RSA.new(@ca_config[:ca_rsa_key_length])
|
|
82
|
+
#puts "done!"
|
|
83
|
+
|
|
84
|
+
#print "Create Certificate ..."
|
|
85
|
+
cert = OpenSSL::X509::Certificate.new
|
|
86
|
+
#puts "done!"
|
|
87
|
+
name = @ca_config[:name].dup << ['CN', 'CA']
|
|
88
|
+
|
|
89
|
+
cert.subject = cert.issuer = OpenSSL::X509::Name.new(name)
|
|
90
|
+
cert.not_before = Time.now
|
|
91
|
+
cert.not_after = Time.now + @ca_config[:ca_cert_days] * 24 * 60 * 60
|
|
92
|
+
cert.public_key = keypair.public_key
|
|
93
|
+
cert.serial = 0x0
|
|
94
|
+
cert.version = 2 # X509v3
|
|
95
|
+
# puts "Init ExtensionFactory ..."
|
|
96
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
|
97
|
+
ef.subject_certificate = cert
|
|
98
|
+
ef.issuer_certificate = cert
|
|
99
|
+
cert.extensions = [
|
|
100
|
+
ef.create_extension("basicConstraints","CA:TRUE", true),
|
|
101
|
+
# ef.create_extension("nsComment","Ruby/OpenSSL Generated Certificate"),
|
|
102
|
+
ef.create_extension("nsComment","WATOBO CA"),
|
|
103
|
+
ef.create_extension("subjectKeyIdentifier", "hash"),
|
|
104
|
+
ef.create_extension("keyUsage", "cRLSign,keyCertSign", true),
|
|
105
|
+
]
|
|
106
|
+
cert.add_extension ef.create_extension("authorityKeyIdentifier",
|
|
107
|
+
"keyid:always,issuer:always")
|
|
108
|
+
# puts "Sign Certificate ..."
|
|
109
|
+
cert.sign keypair, OpenSSL::Digest::SHA1.new
|
|
110
|
+
|
|
111
|
+
cb = proc do @ca_config[:password] end
|
|
112
|
+
keypair_export = keypair.export OpenSSL::Cipher::DES.new(:EDE3, :CBC),
|
|
113
|
+
&cb
|
|
114
|
+
|
|
115
|
+
#puts "Writing keypair to #{@ca_config[:keypair_file]}"
|
|
116
|
+
begin
|
|
117
|
+
fh = File.open(@ca_config[:keypair_file], "w+")
|
|
118
|
+
|
|
119
|
+
fh.puts keypair_export
|
|
120
|
+
fh.close
|
|
121
|
+
rescue => bang
|
|
122
|
+
puts "! Could not write keypair"
|
|
123
|
+
puts bang
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
#puts "Writing cert to #{@ca_config[:cert_file]}"
|
|
127
|
+
File.open @ca_config[:cert_file], "w", 0644 do |f|
|
|
128
|
+
f << cert.to_pem
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
puts "Done generating certificate for #{cert.subject}"
|
|
132
|
+
else
|
|
133
|
+
#puts "Open Cert File ..."
|
|
134
|
+
raw = File.read @ca_config[:cert_file] # DER- or PEM-encoded
|
|
135
|
+
cert = OpenSSL::X509::Certificate.new raw
|
|
136
|
+
# puts cert
|
|
137
|
+
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def self.create_cert(cert_config)
|
|
141
|
+
# puts " ... keypair ..."
|
|
142
|
+
cert_keypair = create_key(cert_config)
|
|
143
|
+
# puts "... csr ..."
|
|
144
|
+
cert_csr = create_csr(cert_config, cert_keypair)
|
|
145
|
+
# puts "... signing ..."
|
|
146
|
+
signed_cert = sign_cert(cert_config, cert_keypair, cert_csr)
|
|
147
|
+
return signed_cert, cert_keypair
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
##
|
|
151
|
+
# Creates a new RSA key from +cert_config+.
|
|
152
|
+
|
|
153
|
+
def self.create_key(cert_config)
|
|
154
|
+
#passwd_cb = nil
|
|
155
|
+
target = cert_config[:hostname] || cert_config[:user]
|
|
156
|
+
# puts target
|
|
157
|
+
dest = @ca_config[:fake_certs_dir]
|
|
158
|
+
# puts dest
|
|
159
|
+
keypair_file = File.join(dest, (target + "_keypair.pem"))
|
|
160
|
+
keypair_file.gsub!(/\*/,"_")
|
|
161
|
+
|
|
162
|
+
return keypair_file if File.exist? keypair_file
|
|
163
|
+
|
|
164
|
+
#puts "create_key: #{keypair_file}"
|
|
165
|
+
begin
|
|
166
|
+
Dir.mkdir dest #, 0700
|
|
167
|
+
rescue Errno::EEXIST
|
|
168
|
+
# puts "directory exists"
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
if not File.exists?(keypair_file) then
|
|
172
|
+
#puts "Generating RSA keypair" if $DEBUG
|
|
173
|
+
keypair = OpenSSL::PKey::RSA.new 1024
|
|
174
|
+
# puts keypair.to_pem.class
|
|
175
|
+
|
|
176
|
+
if cert_config[:password].nil? then
|
|
177
|
+
# puts "no password for cert"
|
|
178
|
+
# puts "Writing keypair to #{keypair_file}" if $DEBUG
|
|
179
|
+
begin
|
|
180
|
+
dummy = keypair.to_pem.split("\n")
|
|
181
|
+
dummy.each do |line|
|
|
182
|
+
line.strip!
|
|
183
|
+
end
|
|
184
|
+
fh = File.open( keypair_file, "wb" )
|
|
185
|
+
fh.write dummy.join("\n")
|
|
186
|
+
fh.close
|
|
187
|
+
rescue => bang
|
|
188
|
+
puts "! Could not write keypair"
|
|
189
|
+
puts bang
|
|
190
|
+
puts bang.backtrace
|
|
191
|
+
end
|
|
192
|
+
else
|
|
193
|
+
# passwd_cb = proc do cert_config[:password] end
|
|
194
|
+
keypair_export = keypair.export OpenSSL::Cipher::DES.new(:EDE3, :CBC), cert_config[:password]
|
|
195
|
+
|
|
196
|
+
# puts "Writing keypair to #{keypair_file}" if $DEBUG
|
|
197
|
+
#File.open keypair_file, "w" do |f|
|
|
198
|
+
# f << keypair_export
|
|
199
|
+
#end
|
|
200
|
+
begin
|
|
201
|
+
fh = File.open( keypair_file, "w" )
|
|
202
|
+
fh.puts keypair_export
|
|
203
|
+
fh.close
|
|
204
|
+
rescue => bang
|
|
205
|
+
|
|
206
|
+
puts "! Could not write keypair"
|
|
207
|
+
puts bang
|
|
208
|
+
puts bang.backtrace
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
return keypair_file
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
##
|
|
217
|
+
# Signs the certificate described in +cert_config+ and
|
|
218
|
+
# +csr_file+, saving it to +cert_file+.
|
|
219
|
+
|
|
220
|
+
def self.sign_cert(cert_config, cert_file, csr_file)
|
|
221
|
+
|
|
222
|
+
target = cert_config[:hostname] || cert_config[:user]
|
|
223
|
+
dest = @ca_config[:fake_certs_dir]
|
|
224
|
+
cert_file = File.join dest, "#{target}_cert.pem"
|
|
225
|
+
cert_file.gsub!(/\*/,"_")
|
|
226
|
+
return cert_file if File.exist? cert_file
|
|
227
|
+
|
|
228
|
+
csr = OpenSSL::X509::Request.new File.read(csr_file)
|
|
229
|
+
|
|
230
|
+
raise "CSR sign verification failed." unless csr.verify csr.public_key
|
|
231
|
+
|
|
232
|
+
if csr.public_key.n.num_bits < @ca_config[:cert_key_length_min] then
|
|
233
|
+
raise "Key length too short"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
if csr.public_key.n.num_bits > @ca_config[:cert_key_length_max] then
|
|
237
|
+
raise "Key length too long"
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
if csr.subject.to_a[0, @ca_config[:name].size] != @ca_config[:name] then
|
|
241
|
+
raise "DN does not match"
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# Only checks signature here. You must verify CSR according to your
|
|
245
|
+
# CP/CPS.
|
|
246
|
+
|
|
247
|
+
# CA setup
|
|
248
|
+
|
|
249
|
+
puts "Reading CA cert from #{@ca_config[:cert_file]}" if $DEBUG
|
|
250
|
+
ca = OpenSSL::X509::Certificate.new File.read(@ca_config[:cert_file])
|
|
251
|
+
|
|
252
|
+
puts "Reading CA keypair from #{@ca_config[:keypair_file]}" if $DEBUG
|
|
253
|
+
ca_keypair = OpenSSL::PKey::RSA.new File.read(@ca_config[:keypair_file]),
|
|
254
|
+
@ca_config[:password]
|
|
255
|
+
|
|
256
|
+
serial = File.read(@ca_config[:serial_file]).chomp.hex
|
|
257
|
+
File.open @ca_config[:serial_file], "w" do |f|
|
|
258
|
+
f << "%04X" % (serial + 1)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
puts "Generating cert" if $DEBUG
|
|
262
|
+
|
|
263
|
+
cert = OpenSSL::X509::Certificate.new
|
|
264
|
+
from = Time.now
|
|
265
|
+
cert.subject = csr.subject
|
|
266
|
+
cert.issuer = ca.subject
|
|
267
|
+
cert.not_before = from
|
|
268
|
+
cert.not_after = from + @ca_config[:cert_days] * 24 * 60 * 60
|
|
269
|
+
cert.public_key = csr.public_key
|
|
270
|
+
cert.serial = serial
|
|
271
|
+
cert.version = 2 # X509v3
|
|
272
|
+
|
|
273
|
+
basic_constraint = nil
|
|
274
|
+
key_usage = []
|
|
275
|
+
ext_key_usage = []
|
|
276
|
+
|
|
277
|
+
case cert_config[:type]
|
|
278
|
+
when "ca" then
|
|
279
|
+
basic_constraint = "CA:TRUE"
|
|
280
|
+
key_usage << "cRLSign" << "keyCertSign"
|
|
281
|
+
when "terminalsubca" then
|
|
282
|
+
basic_constraint = "CA:TRUE,pathlen:0"
|
|
283
|
+
key_usage << "cRLSign" << "keyCertSign"
|
|
284
|
+
when "server" then
|
|
285
|
+
basic_constraint = "CA:FALSE"
|
|
286
|
+
key_usage << "digitalSignature" << "keyEncipherment"
|
|
287
|
+
ext_key_usage << "serverAuth"
|
|
288
|
+
when "ocsp" then
|
|
289
|
+
basic_constraint = "CA:FALSE"
|
|
290
|
+
key_usage << "nonRepudiation" << "digitalSignature"
|
|
291
|
+
ext_key_usage << "serverAuth" << "OCSPSigning"
|
|
292
|
+
when "client" then
|
|
293
|
+
basic_constraint = "CA:FALSE"
|
|
294
|
+
key_usage << "nonRepudiation" << "digitalSignature" << "keyEncipherment"
|
|
295
|
+
ext_key_usage << "clientAuth" << "emailProtection"
|
|
296
|
+
else
|
|
297
|
+
raise "unknonw cert type \"#{cert_config[:type]}\""
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
ef = OpenSSL::X509::ExtensionFactory.new
|
|
301
|
+
ef.subject_certificate = cert
|
|
302
|
+
ef.issuer_certificate = ca
|
|
303
|
+
ex = []
|
|
304
|
+
ex << ef.create_extension("basicConstraints", basic_constraint, true)
|
|
305
|
+
ex << ef.create_extension("nsComment",
|
|
306
|
+
"Ruby/OpenSSL Generated Certificate")
|
|
307
|
+
ex << ef.create_extension("subjectKeyIdentifier", "hash")
|
|
308
|
+
#ex << ef.create_extension("nsCertType", "client,email")
|
|
309
|
+
unless key_usage.empty? then
|
|
310
|
+
ex << ef.create_extension("keyUsage", key_usage.join(","))
|
|
311
|
+
end
|
|
312
|
+
#ex << ef.create_extension("authorityKeyIdentifier",
|
|
313
|
+
# "keyid:always,issuer:always")
|
|
314
|
+
#ex << ef.create_extension("authorityKeyIdentifier", "keyid:always")
|
|
315
|
+
unless ext_key_usage.empty? then
|
|
316
|
+
ex << ef.create_extension("extendedKeyUsage", ext_key_usage.join(","))
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
if @ca_config[:cdp_location] then
|
|
320
|
+
ex << ef.create_extension("crlDistributionPoints",
|
|
321
|
+
@ca_config[:cdp_location])
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
if @ca_config[:ocsp_location] then
|
|
325
|
+
ex << ef.create_extension("authorityInfoAccess",
|
|
326
|
+
"OCSP;" << @ca_config[:ocsp_location])
|
|
327
|
+
end
|
|
328
|
+
cert.extensions = ex
|
|
329
|
+
cert.sign ca_keypair, OpenSSL::Digest::SHA1.new
|
|
330
|
+
|
|
331
|
+
# backup_cert_file = @ca_config[:backup_certs_dir] + "/cert_#{cert.serial}.pem"
|
|
332
|
+
# puts "Writing backup cert to #{backup_cert_file}" if $DEBUG
|
|
333
|
+
# File.open backup_cert_file, "w", 0644 do |f|
|
|
334
|
+
# f << cert.to_pem
|
|
335
|
+
# end
|
|
336
|
+
|
|
337
|
+
# Write cert
|
|
338
|
+
puts "Writing cert to #{cert_file}"
|
|
339
|
+
File.open cert_file, "w", 0644 do |f|
|
|
340
|
+
f << cert.to_pem
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
return cert_file
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
##
|
|
347
|
+
# Creates a new Certificate Signing Request for the keypair in
|
|
348
|
+
# +keypair_file+, generating and saving new keypair if nil.
|
|
349
|
+
|
|
350
|
+
def self.create_csr(cert_config, keypair_file = nil)
|
|
351
|
+
keypair = nil
|
|
352
|
+
target = cert_config[:hostname] || cert_config[:user]
|
|
353
|
+
dest = @ca_config[:csr_dir]
|
|
354
|
+
csr_file = File.join dest, "csr_#{target}.pem"
|
|
355
|
+
csr_file.gsub!(/\*/,"_")
|
|
356
|
+
|
|
357
|
+
return csr_file if File.exist? csr_file
|
|
358
|
+
|
|
359
|
+
name = @ca_config[:name].dup
|
|
360
|
+
case cert_config[:type]
|
|
361
|
+
when 'server' then
|
|
362
|
+
name << ['OU', 'CA']
|
|
363
|
+
name << ['CN', cert_config[:hostname]]
|
|
364
|
+
when 'client' then
|
|
365
|
+
name << ['CN', cert_config[:user]]
|
|
366
|
+
name << ['emailAddress', cert_config[:email]]
|
|
367
|
+
end
|
|
368
|
+
#puts "Create Certificate Signing Request ..."
|
|
369
|
+
# puts "Keypair File: " + keypair_file
|
|
370
|
+
# puts name
|
|
371
|
+
name = OpenSSL::X509::Name.new(name)
|
|
372
|
+
# puts "- - -"
|
|
373
|
+
|
|
374
|
+
if File.exists? keypair_file then
|
|
375
|
+
# puts "Get Keypair from file #{keypair_file}"
|
|
376
|
+
keypair = OpenSSL::PKey::RSA.new(File.read(keypair_file), cert_config[:password])
|
|
377
|
+
else
|
|
378
|
+
# puts "Create Certificate KeyPair ..."
|
|
379
|
+
keypair = create_key(cert_config)
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
# puts "Generating CSR for #{name}" if $DEBUG
|
|
383
|
+
|
|
384
|
+
req = OpenSSL::X509::Request.new
|
|
385
|
+
req.version = 0
|
|
386
|
+
req.subject = name
|
|
387
|
+
req.public_key = keypair.public_key
|
|
388
|
+
req.sign keypair, OpenSSL::Digest::MD5.new
|
|
389
|
+
|
|
390
|
+
# puts "Writing CSR to #{csr_file}" if $DEBUG
|
|
391
|
+
File.open csr_file, "w" do |f|
|
|
392
|
+
f << req.to_pem
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
return csr_file
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
def self.dh_key
|
|
399
|
+
dh_filename = File.join(@ca_config[:CA_dir], "watobo_dh.key")
|
|
400
|
+
unless File.exist? dh_filename
|
|
401
|
+
#puts "* no dh key file found"
|
|
402
|
+
File.open(dh_filename,"w") do |fh|
|
|
403
|
+
puts "* creating SSL key (DH 1024) ... "
|
|
404
|
+
fh.write OpenSSL::PKey::DH.new(1024).to_pem
|
|
405
|
+
print " DONE\r\n"
|
|
406
|
+
end
|
|
407
|
+
end
|
|
408
|
+
OpenSSL::PKey::DH.new(File.read(dh_filename))
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# .
|
|
2
|
+
# cert_store.rb
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2012 by siberas, http://www.siberas.de
|
|
5
|
+
#
|
|
6
|
+
# This file is part of WATOBO (Web Application Tool Box)
|
|
7
|
+
# http://watobo.sourceforge.com
|
|
8
|
+
#
|
|
9
|
+
# WATOBO is free software; you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation version 2 of the License.
|
|
12
|
+
#
|
|
13
|
+
# WATOBO is distributed in the hope that it will be useful,
|
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
# GNU General Public License for more details.
|
|
17
|
+
#
|
|
18
|
+
# You should have received a copy of the GNU General Public License
|
|
19
|
+
# along with WATOBO; if not, write to the Free Software
|
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
21
|
+
# .
|
|
22
|
+
module Watobo
|
|
23
|
+
module CertStore
|
|
24
|
+
@fake_certs = Hash.new
|
|
25
|
+
def self.acquire_ssl_ctx(target, cn)
|
|
26
|
+
ctx = OpenSSL::SSL::SSLContext.new()
|
|
27
|
+
|
|
28
|
+
unless @fake_certs.has_key? target
|
|
29
|
+
cert_prefs = {
|
|
30
|
+
:hostname => cn,
|
|
31
|
+
:type => 'server',
|
|
32
|
+
:user => 'watobo',
|
|
33
|
+
:email => 'watobo@localhost',
|
|
34
|
+
}
|
|
35
|
+
cert_file, key_file = Watobo::CA.create_cert cert_prefs
|
|
36
|
+
fake_cert = OpenSSL::X509::Certificate.new(File.read(cert_file))
|
|
37
|
+
fake_key = OpenSSL::PKey::RSA.new(File.read(key_file))
|
|
38
|
+
|
|
39
|
+
#ctx = OpenSSL::SSL::SSLContext.new('SSLv23_server')
|
|
40
|
+
@fake_certs[target] = { :cert => fake_cert, :key => fake_key }
|
|
41
|
+
|
|
42
|
+
end
|
|
43
|
+
fc = @fake_certs[target]
|
|
44
|
+
ctx.cert = fc[:cert]
|
|
45
|
+
ctx.key = fc[:key]
|
|
46
|
+
|
|
47
|
+
ctx.tmp_dh_callback = proc { |*args|
|
|
48
|
+
Watobo::CA.dh_key
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
52
|
+
ctx.timeout = 10
|
|
53
|
+
return ctx
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# .
|
|
2
|
+
# forwarding_proxy.rb
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2012 by siberas, http://www.siberas.de
|
|
5
|
+
#
|
|
6
|
+
# This file is part of WATOBO (Web Application Tool Box)
|
|
7
|
+
# http://watobo.sourceforge.com
|
|
8
|
+
#
|
|
9
|
+
# WATOBO is free software; you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation version 2 of the License.
|
|
12
|
+
#
|
|
13
|
+
# WATOBO is distributed in the hope that it will be useful,
|
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
# GNU General Public License for more details.
|
|
17
|
+
#
|
|
18
|
+
# You should have received a copy of the GNU General Public License
|
|
19
|
+
# along with WATOBO; if not, write to the Free Software
|
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
21
|
+
# .
|
|
22
|
+
module Watobo
|
|
23
|
+
module ForwardingProxy
|
|
24
|
+
|
|
25
|
+
def self.get(site=nil)
|
|
26
|
+
begin
|
|
27
|
+
return nil if Watobo::Conf::ForwardingProxy.default_proxy.empty?
|
|
28
|
+
name = Watobo::Conf::ForwardingProxy.default_proxy
|
|
29
|
+
fp = Watobo::Conf::ForwardingProxy.to_h
|
|
30
|
+
proxy = fp[name]
|
|
31
|
+
return Watobo::Proxy.new(proxy)
|
|
32
|
+
rescue => bang
|
|
33
|
+
puts bang
|
|
34
|
+
puts bang.backtrace
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -21,6 +21,24 @@
|
|
|
21
21
|
# .
|
|
22
22
|
module Watobo
|
|
23
23
|
module HTTP
|
|
24
|
+
|
|
25
|
+
def self.get_peer_subject(socket)
|
|
26
|
+
begin
|
|
27
|
+
ctx = OpenSSL::SSL::SSLContext.new()
|
|
28
|
+
ctx.tmp_dh_callback = proc { |*args|
|
|
29
|
+
OpenSSL::PKey::DH.new(128)
|
|
30
|
+
}
|
|
31
|
+
ssl_sock = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
|
32
|
+
subject = ssl_sock.peer_cert.subject
|
|
33
|
+
return subject
|
|
34
|
+
rescue => bang
|
|
35
|
+
puts bang
|
|
36
|
+
puts bang.backtrace
|
|
37
|
+
end
|
|
38
|
+
return nil
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
|
|
24
42
|
def HTTP.read_body(socket, prefs=nil)
|
|
25
43
|
buf = nil
|
|
26
44
|
max_bytes = -1
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# .
|
|
2
|
+
# intercept_carver.rb
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2012 by siberas, http://www.siberas.de
|
|
5
|
+
#
|
|
6
|
+
# This file is part of WATOBO (Web Application Tool Box)
|
|
7
|
+
# http://watobo.sourceforge.com
|
|
8
|
+
#
|
|
9
|
+
# WATOBO is free software; you can redistribute it and/or modify
|
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
|
11
|
+
# the Free Software Foundation version 2 of the License.
|
|
12
|
+
#
|
|
13
|
+
# WATOBO is distributed in the hope that it will be useful,
|
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
|
+
# GNU General Public License for more details.
|
|
17
|
+
#
|
|
18
|
+
# You should have received a copy of the GNU General Public License
|
|
19
|
+
# along with WATOBO; if not, write to the Free Software
|
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
21
|
+
# .
|
|
22
|
+
module Watobo
|
|
23
|
+
module Interceptor
|
|
24
|
+
class CarverRule
|
|
25
|
+
def action_name
|
|
26
|
+
action.to_s
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def location_name
|
|
30
|
+
location.to_s
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def pattern_name
|
|
34
|
+
Regexp.quote pattern
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def filter_name
|
|
38
|
+
# return "NA" if filter.nil?
|
|
39
|
+
return filter.class.to_s
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def set_filter(filter_chain)
|
|
43
|
+
puts "* set filter_chain"
|
|
44
|
+
puts filter_chain.class
|
|
45
|
+
@settings[:filter] = filter_chain
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def filters
|
|
49
|
+
return [] unless filter.respond_to? :list
|
|
50
|
+
filter.list
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def content_name
|
|
54
|
+
content
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def rewrite(item, l, p, c)
|
|
58
|
+
res = false
|
|
59
|
+
case l
|
|
60
|
+
when :replace_all
|
|
61
|
+
if File.exist? c
|
|
62
|
+
begin
|
|
63
|
+
puts "REPLACING RESPONSE"
|
|
64
|
+
puts "OLD >>"
|
|
65
|
+
puts item
|
|
66
|
+
puts "NEW >>"
|
|
67
|
+
item.replace Watobo::Utils.string2response(File.open(c,"rb").read)
|
|
68
|
+
|
|
69
|
+
puts item
|
|
70
|
+
rescue => bang
|
|
71
|
+
puts bang
|
|
72
|
+
puts bang.backtrace
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
puts "Could not find file > #{c}"
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
when :body
|
|
79
|
+
if item.respond_to? :body
|
|
80
|
+
if p.upcase == :ALL
|
|
81
|
+
res = item.replace_body(c)
|
|
82
|
+
else
|
|
83
|
+
puts "* rewrite body ..."
|
|
84
|
+
res = item.rewrite_body(p,c)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
when :http_parm
|
|
88
|
+
1
|
|
89
|
+
when :cookie
|
|
90
|
+
1
|
|
91
|
+
when :url
|
|
92
|
+
if item.respond_to? :url
|
|
93
|
+
item.first.gsub!(/#{p}/, c)
|
|
94
|
+
end
|
|
95
|
+
when :http_header
|
|
96
|
+
1
|
|
97
|
+
end
|
|
98
|
+
res
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def apply(item, flags)
|
|
102
|
+
begin
|
|
103
|
+
unless filter.nil?
|
|
104
|
+
return false unless filter.match?(item, flags)
|
|
105
|
+
end
|
|
106
|
+
res = case action
|
|
107
|
+
when :flag
|
|
108
|
+
puts "set flag >> #{content} (#{content.class})"
|
|
109
|
+
flags << :request
|
|
110
|
+
true
|
|
111
|
+
when :inject
|
|
112
|
+
inject_content(item, location, pattern, content)
|
|
113
|
+
when :rewrite
|
|
114
|
+
rewrite(item, location, pattern, content)
|
|
115
|
+
else
|
|
116
|
+
true
|
|
117
|
+
end
|
|
118
|
+
return res
|
|
119
|
+
rescue => bang
|
|
120
|
+
puts bang
|
|
121
|
+
puts bang.backtrace
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def initialize(parms)
|
|
126
|
+
@settings = Hash.new
|
|
127
|
+
[:action, :location, :pattern, :content, :filter].each do |k|
|
|
128
|
+
@settings[k] = parms[k]
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
private
|
|
134
|
+
|
|
135
|
+
def method_missing(name, *args, &block)
|
|
136
|
+
# puts "* instance method missing (#{name})"
|
|
137
|
+
@settings.has_key? name.to_sym || super
|
|
138
|
+
@settings[name.to_sym]
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
class Carver
|
|
143
|
+
@rules = []
|
|
144
|
+
|
|
145
|
+
def self.rules
|
|
146
|
+
@rules
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def self.shape(response, flags)
|
|
150
|
+
puts "Shape, Baby shape, ..."
|
|
151
|
+
|
|
152
|
+
@rules.each do |r|
|
|
153
|
+
res = r.apply( response, flags )
|
|
154
|
+
puts "#{r.action_name} (#{r.action.class}) >> #{res.class}"
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def self.set_carving_rules(rules)
|
|
159
|
+
@rules = rules
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def self.add_rule(rule)
|
|
163
|
+
@rules << rule if rule.respond_to? :apply
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def self.clear_rules
|
|
167
|
+
@rules.clear
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
class RequestCarver < Carver
|
|
172
|
+
@rules = []
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
class ResponseCarver < Carver
|
|
176
|
+
@rules = []
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|