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
|
@@ -20,27 +20,124 @@
|
|
|
20
20
|
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
21
21
|
# .
|
|
22
22
|
module Watobo
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
module Interceptor
|
|
24
|
+
INTERCEPT_NONE = 0x00
|
|
25
|
+
INTERCEPT_REQUEST = 0x01
|
|
26
|
+
INTERCEPT_RESPONSE = 0x02
|
|
27
|
+
INTERCEPT_BOTH = 0x03
|
|
28
|
+
|
|
29
|
+
REWRITE_NONE = 0x00
|
|
30
|
+
REWRITE_REQUEST = 0x01
|
|
31
|
+
REWRITE_RESPONSE = 0x02
|
|
32
|
+
REWRITE_BOTH = 0x04
|
|
33
|
+
|
|
34
|
+
INTERCEPT_DEFAULT_PORT = 8081
|
|
35
|
+
|
|
36
|
+
MODE_REGULAR = 0x01
|
|
37
|
+
MODE_TRANSPARENT = 0x02
|
|
38
|
+
|
|
39
|
+
@proxy_mode ||= MODE_REGULAR
|
|
40
|
+
@intercept_mode ||= INTERCEPT_NONE
|
|
41
|
+
@rewrite_mode ||= REWRITE_NONE
|
|
42
|
+
|
|
43
|
+
@proxy = nil
|
|
44
|
+
#@proxy_mode = Watobo::Conf::Interceptor.proxy_mode if Watobo::Conf::Interceptor.respond_to? :proxy_mode
|
|
45
|
+
def self.proxy_mode
|
|
46
|
+
@proxy_mode
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.proxy_mode=(mode)
|
|
50
|
+
@proxy_mode = mode
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.rewrite_mode
|
|
54
|
+
@rewrite_mode
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.rewrite_mode=(mode)
|
|
58
|
+
@rewrite_mode = mode
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def self.intercept_mode
|
|
62
|
+
@intercept_mode
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def self.intercept_mode=(mode)
|
|
66
|
+
@intercept_mode = mode
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.transparent?
|
|
70
|
+
return true if ( @proxy_mode & MODE_TRANSPARENT ) > 0
|
|
71
|
+
return false
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.intercept_requests?
|
|
75
|
+
return true if ( @intercept_mode & INTERCEPT_REQUEST ) > 0
|
|
76
|
+
return false
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def self.intercept_responses?
|
|
80
|
+
return true if ( @intercept_mode & INTERCEPT_RESPONSE ) > 0
|
|
81
|
+
return false
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def self.rewrite_requests?
|
|
85
|
+
return true if ( @rewrite_mode & REWRITE_REQUEST ) > 0
|
|
86
|
+
return false
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.rewrite_responses?
|
|
90
|
+
return true if ( @rewrite_mode & REWRITE_RESPONSE ) > 0
|
|
91
|
+
return false
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def self.active?
|
|
95
|
+
return false if @proxy.nil?
|
|
96
|
+
return true
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def self.start
|
|
100
|
+
@proxy = Watobo::InterceptProxy.new()
|
|
101
|
+
|
|
102
|
+
@proxy.subscribe(:new_interception) { |chat|
|
|
103
|
+
Thread.new(chat) { |c|
|
|
104
|
+
Watobo.project.addChat(c) unless Watobo.project.nil?
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@proxy.start()
|
|
109
|
+
puts "DEBUG: Proxy running" if $DEBUG
|
|
110
|
+
# puts "* set www_auth for interceptor"
|
|
111
|
+
# puts YAML.dump(@project.settings[:www_auth])
|
|
112
|
+
#@proxy.www_auth = Watobo.project.settings[:www_auth] unless Watobo.project.nil?
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def self.proxy
|
|
116
|
+
@proxy
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def self.stop
|
|
120
|
+
@proxy.stop
|
|
121
|
+
@proxy = nil
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
end
|
|
27
125
|
|
|
28
|
-
INTERCEPT_DEFAULT_PORT = 8081
|
|
29
126
|
# I N T E R C E P T P R O X Y
|
|
30
127
|
#
|
|
31
128
|
class InterceptProxy
|
|
32
129
|
|
|
33
130
|
include Watobo::Constants
|
|
34
|
-
#
|
|
131
|
+
# include Watobo::Interceptor
|
|
35
132
|
|
|
36
133
|
attr :port
|
|
37
134
|
|
|
38
|
-
attr_accessor :
|
|
135
|
+
attr_accessor :proxy_mode
|
|
39
136
|
|
|
40
137
|
attr_accessor :contentLength
|
|
41
138
|
attr_accessor :contentTypes
|
|
42
139
|
attr_accessor :target
|
|
43
|
-
|
|
140
|
+
attr :www_auth
|
|
44
141
|
attr_accessor :client_certificates
|
|
45
142
|
def server
|
|
46
143
|
@bind_addr
|
|
@@ -68,7 +165,16 @@ module Watobo
|
|
|
68
165
|
|
|
69
166
|
def setRequestFilter(new_settings)
|
|
70
167
|
@request_filter_settings.update new_settings unless new_settings.nil?
|
|
71
|
-
|
|
168
|
+
# puts @request_filter_settings.to_yaml
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def clear_request_carvers
|
|
172
|
+
@request_carvers.clear unless @request_carvers.nil?
|
|
173
|
+
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def clear_response_carvers
|
|
177
|
+
@response_carvers.clear unless @response_carvers.nil?
|
|
72
178
|
end
|
|
73
179
|
|
|
74
180
|
# def getRequestFilter
|
|
@@ -88,9 +194,11 @@ module Watobo
|
|
|
88
194
|
def stop()
|
|
89
195
|
begin
|
|
90
196
|
puts "[#{self.class}] stop"
|
|
91
|
-
|
|
197
|
+
if @t_server.respond_to? :status
|
|
198
|
+
puts @t_server.status
|
|
92
199
|
@t_server.kill
|
|
93
200
|
@intercept_srv.close
|
|
201
|
+
end
|
|
94
202
|
rescue IOError => bang
|
|
95
203
|
puts bang
|
|
96
204
|
puts bang.backtrace if $DEBUG
|
|
@@ -101,16 +209,16 @@ module Watobo
|
|
|
101
209
|
# R U N
|
|
102
210
|
#
|
|
103
211
|
|
|
104
|
-
def
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# @contentTypes = settings[:content_types] if settings[:content_types]
|
|
212
|
+
def start()
|
|
213
|
+
|
|
214
|
+
if transparent?
|
|
215
|
+
DRb.start_service
|
|
216
|
+
@connections = DRbObject.new nil, "druby://127.0.0.1:666"
|
|
217
|
+
end
|
|
111
218
|
|
|
219
|
+
begin
|
|
112
220
|
@intercept_srv = TCPServer.new(@bind_addr, @port)
|
|
113
|
-
@intercept_srv.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
|
221
|
+
@intercept_srv.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1 )
|
|
114
222
|
|
|
115
223
|
rescue => bang
|
|
116
224
|
puts "\n!!!Could not start InterceptProxy"
|
|
@@ -119,28 +227,32 @@ module Watobo
|
|
|
119
227
|
end
|
|
120
228
|
puts "\n* Intercepor started on #{@bind_addr}:#{@port}"
|
|
121
229
|
session_list = []
|
|
230
|
+
puts "!!! TRANSPARENT MODE ENABLED !!!" if transparent?
|
|
122
231
|
|
|
123
232
|
@t_server = Thread.new(@intercept_srv) { |server|
|
|
124
233
|
while (new_session = server.accept)
|
|
125
234
|
# new_session.sync = true
|
|
126
235
|
Thread.new(new_session) { |session|
|
|
236
|
+
flags = []
|
|
127
237
|
begin
|
|
238
|
+
|
|
128
239
|
request, c_sock = read_request(session)
|
|
129
240
|
|
|
130
241
|
if request.nil? or request.empty? then
|
|
131
242
|
# puts "! empty request ? :("
|
|
132
|
-
c_sock
|
|
243
|
+
closeSocket(c_sock)
|
|
133
244
|
Thread.current.exit
|
|
134
245
|
#return
|
|
135
246
|
end
|
|
136
247
|
puts "*[I] #{request.url}"
|
|
137
248
|
|
|
138
249
|
rescue => bang
|
|
139
|
-
|
|
140
|
-
|
|
250
|
+
puts "!!! Error reading client request "
|
|
251
|
+
puts bang
|
|
141
252
|
# puts bang.backtrace
|
|
142
253
|
# puts request
|
|
143
254
|
# puts request
|
|
255
|
+
closeSocket(c_sock)
|
|
144
256
|
Thread.current.exit
|
|
145
257
|
#break
|
|
146
258
|
end
|
|
@@ -160,17 +272,24 @@ module Watobo
|
|
|
160
272
|
closeSocket(c_sock)
|
|
161
273
|
end
|
|
162
274
|
end
|
|
163
|
-
next
|
|
275
|
+
#next
|
|
276
|
+
Thread.current.exit
|
|
164
277
|
end
|
|
278
|
+
|
|
165
279
|
request_intercepted = false
|
|
166
280
|
# no preview, check if interception request is turned on
|
|
167
|
-
if
|
|
168
|
-
|
|
281
|
+
if Watobo::Interceptor.rewrite_requests? then
|
|
282
|
+
Interceptor::RequestCarver.shape(request, flags)
|
|
283
|
+
puts "FLAGS >>"
|
|
284
|
+
puts flags
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
if @target and Watobo::Interceptor.intercept_requests? then
|
|
169
288
|
if matchRequestFilter(request)
|
|
170
289
|
@awaiting_requests += 1
|
|
171
290
|
request_intercepted = true
|
|
172
291
|
|
|
173
|
-
if @target.respond_to? :
|
|
292
|
+
if @target.respond_to? :addRequest
|
|
174
293
|
# puts "*INTERCEPT REQUEST"
|
|
175
294
|
# puts @target
|
|
176
295
|
#notify(:modify_request, request, Thread.current)
|
|
@@ -190,12 +309,14 @@ module Watobo
|
|
|
190
309
|
#p "getHTTPHeader"
|
|
191
310
|
#s_sock, req, resp = @sender.getHTTPHeader(request, :update_sids => true, :update_session => false, :update_contentlength => true)
|
|
192
311
|
begin
|
|
312
|
+
|
|
193
313
|
s_sock, req, resp = @sender.sendHTTPRequest(request, :update_sids => true, :update_session => false, :update_contentlength => true, :www_auth => @www_auth, :client_certificates => @client_certificates)
|
|
194
314
|
if s_sock.nil? then
|
|
195
315
|
c_sock.print resp.join unless resp.nil?
|
|
196
316
|
closeSocket(c_sock)
|
|
197
317
|
next
|
|
198
318
|
end
|
|
319
|
+
|
|
199
320
|
rescue => bang
|
|
200
321
|
puts bang
|
|
201
322
|
puts bang.backtrace if $DEBUG
|
|
@@ -245,7 +366,10 @@ module Watobo
|
|
|
245
366
|
|
|
246
367
|
end
|
|
247
368
|
else
|
|
369
|
+
# don't try to read body if request method is HEAD
|
|
370
|
+
unless req.method =~ /^head/i
|
|
248
371
|
@sender.readHTTPBody(s_sock, resp, req, :update_sids => true)
|
|
372
|
+
end
|
|
249
373
|
end
|
|
250
374
|
rescue => bang
|
|
251
375
|
puts "!!! could not send request !!!"
|
|
@@ -255,7 +379,17 @@ module Watobo
|
|
|
255
379
|
end
|
|
256
380
|
|
|
257
381
|
begin
|
|
258
|
-
|
|
382
|
+
Watobo::Response.create resp
|
|
383
|
+
# puts "* unchunk response ..."
|
|
384
|
+
resp.unchunk
|
|
385
|
+
# puts "* unzip response ..."
|
|
386
|
+
resp.unzip
|
|
387
|
+
|
|
388
|
+
if Watobo::Interceptor.rewrite_responses? then
|
|
389
|
+
Interceptor::ResponseCarver.shape(resp, flags)
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
if @target and Watobo::Interceptor.intercept_responses? then
|
|
259
393
|
if matchResponseFilter(resp)
|
|
260
394
|
# if resp.content_type =~ /text/ or resp.content_type =~ /application\/javascript/ then
|
|
261
395
|
if @target.respond_to? :modifyResponse
|
|
@@ -267,8 +401,12 @@ module Watobo
|
|
|
267
401
|
end
|
|
268
402
|
end
|
|
269
403
|
|
|
404
|
+
# puts ">> SEND TO CLIENT"
|
|
270
405
|
c_sock.write resp.join
|
|
271
|
-
|
|
406
|
+
# puts resp.join
|
|
407
|
+
# puts "-----"
|
|
408
|
+
# closeSocket(c_sock)
|
|
409
|
+
|
|
272
410
|
rescue Errno::ECONNRESET
|
|
273
411
|
print "x"
|
|
274
412
|
# puts "!!! ERROR (Reset): reading body"
|
|
@@ -285,8 +423,12 @@ module Watobo
|
|
|
285
423
|
#return
|
|
286
424
|
end
|
|
287
425
|
#if req then # when req == nil an error occured -> no chat necessary
|
|
288
|
-
|
|
426
|
+
|
|
427
|
+
rc = YAML.load(YAML.dump(request))
|
|
428
|
+
sc = YAML.load(YAML.dump(resp))
|
|
429
|
+
chat = Chat.new(rc, sc, :source => CHAT_SOURCE_INTERCEPT)
|
|
289
430
|
notify(:new_interception, chat)
|
|
431
|
+
closeSocket(c_sock)
|
|
290
432
|
# end
|
|
291
433
|
#else
|
|
292
434
|
# puts "* got no response"
|
|
@@ -295,6 +437,10 @@ module Watobo
|
|
|
295
437
|
end
|
|
296
438
|
}
|
|
297
439
|
end
|
|
440
|
+
|
|
441
|
+
def refresh_www_auth
|
|
442
|
+
@www_auth = Watobo::Conf::Scanner.www_auth
|
|
443
|
+
end
|
|
298
444
|
|
|
299
445
|
def initialize(settings=nil)
|
|
300
446
|
@event_dispatcher_listeners = Hash.new
|
|
@@ -307,22 +453,11 @@ module Watobo
|
|
|
307
453
|
# @port = @settings[:intercept_port]
|
|
308
454
|
# puts settings.to_yaml
|
|
309
455
|
|
|
310
|
-
@
|
|
311
|
-
@www_auth = {}
|
|
312
|
-
@client_certificates = {}
|
|
313
|
-
@target = nil
|
|
314
|
-
@sender = Watobo::Session.new(@target)
|
|
456
|
+
# @proxy_mode = Watobo::Interceptor.proxy_mode
|
|
315
457
|
|
|
316
|
-
|
|
317
|
-
puts "> Server: #{@bind_addr}"
|
|
318
|
-
@port = Watobo::Conf::Interceptor.port
|
|
319
|
-
puts "> Port: #{@port}"
|
|
458
|
+
#Watobo::Interceptor.proxy_mode = INTERCEPT_NONE
|
|
320
459
|
|
|
321
|
-
|
|
322
|
-
@contentLength = pt[:content_length]
|
|
323
|
-
puts "> PT-ContentLength: #{@contentLength}"
|
|
324
|
-
@contentTypes = pt[:content_types]
|
|
325
|
-
puts "> PT-ContentTypes: #{@contentTypes}"
|
|
460
|
+
init_instance_vars
|
|
326
461
|
|
|
327
462
|
@awaiting_requests = 0
|
|
328
463
|
@awaiting_responses = 0
|
|
@@ -358,28 +493,20 @@ module Watobo
|
|
|
358
493
|
# p @settings[:certificate_path]
|
|
359
494
|
# p @settings[:cert_file]
|
|
360
495
|
# p @settings[:key_file]
|
|
361
|
-
crt_path = Watobo::Conf::Interceptor.certificate_path
|
|
362
|
-
crt_file = Watobo::Conf::Interceptor.cert_file
|
|
363
|
-
key_file = Watobo::Conf::Interceptor.key_file
|
|
364
|
-
dh_key_file = Watobo::Conf::Interceptor.dh_key_file
|
|
365
|
-
|
|
366
|
-
crt_filename = File.join(Watobo.base_directory, crt_path, crt_file)
|
|
367
|
-
key_filename = File.join(Watobo.base_directory, crt_path, key_file)
|
|
368
|
-
dh_filename = File.join(Watobo.base_directory, crt_path, dh_key_file)
|
|
369
|
-
unless File.exist? dh_filename
|
|
370
|
-
#puts "* no dh key file found"
|
|
371
|
-
File.open(dh_filename,"w") do |fh|
|
|
372
|
-
puts "* creating SSL key (DH 1024) ... "
|
|
373
|
-
fh.write OpenSSL::PKey::DH.new(1024).to_pem
|
|
374
|
-
print " DONE\r\n"
|
|
375
|
-
end
|
|
376
|
-
end
|
|
496
|
+
# crt_path = Watobo::Conf::Interceptor.certificate_path
|
|
497
|
+
# crt_file = Watobo::Conf::Interceptor.cert_file
|
|
498
|
+
# key_file = Watobo::Conf::Interceptor.key_file
|
|
499
|
+
# dh_key_file = Watobo::Conf::Interceptor.dh_key_file
|
|
500
|
+
|
|
501
|
+
# crt_filename = File.join(Watobo.base_directory, crt_path, crt_file)
|
|
502
|
+
# key_filename = File.join(Watobo.base_directory, crt_path, key_file)
|
|
377
503
|
|
|
378
504
|
# @ctx = OpenSSL::SSL::SSLContext.new('SSLv23_server')
|
|
379
|
-
@cert = OpenSSL::X509::Certificate.new(File.read(crt_filename))
|
|
380
|
-
@key = OpenSSL::PKey::RSA.new(File.read(key_filename))
|
|
505
|
+
# @cert = OpenSSL::X509::Certificate.new(File.read(crt_filename))
|
|
506
|
+
# @key = OpenSSL::PKey::RSA.new(File.read(key_filename))
|
|
381
507
|
|
|
382
|
-
|
|
508
|
+
#@dh_key = OpenSSL::PKey::DH.new(File.read(dh_filename))
|
|
509
|
+
@dh_key = Watobo::CA.dh_key
|
|
383
510
|
# @ctx.ciphers = nil # ['TLSv1/SSLv3', 56, 56 ]
|
|
384
511
|
|
|
385
512
|
rescue => bang
|
|
@@ -391,6 +518,57 @@ module Watobo
|
|
|
391
518
|
end
|
|
392
519
|
|
|
393
520
|
private
|
|
521
|
+
|
|
522
|
+
def init_instance_vars
|
|
523
|
+
@www_auth = Watobo::Conf::Scanner.www_auth
|
|
524
|
+
@fake_certs = {}
|
|
525
|
+
@client_certificates = {}
|
|
526
|
+
@target = nil
|
|
527
|
+
@sender = Watobo::Session.new(@target)
|
|
528
|
+
|
|
529
|
+
@bind_addr = Watobo::Conf::Interceptor.bind_addr
|
|
530
|
+
puts "> Server: #{@bind_addr}"
|
|
531
|
+
@port = Watobo::Conf::Interceptor.port
|
|
532
|
+
puts "> Port: #{@port}"
|
|
533
|
+
@proxy_mode = Watobo::Conf::Interceptor.proxy_mode
|
|
534
|
+
|
|
535
|
+
pt = Watobo::Conf::Interceptor.pass_through
|
|
536
|
+
@contentLength = pt[:content_length]
|
|
537
|
+
puts "> PT-ContentLength: #{@contentLength}"
|
|
538
|
+
@contentTypes = pt[:content_types]
|
|
539
|
+
puts "> PT-ContentTypes: #{@contentTypes}"
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
def get_ssl_cert_cn(host,port)
|
|
543
|
+
cn = ""
|
|
544
|
+
begin
|
|
545
|
+
tcp_socket = TCPSocket.new( host, port )
|
|
546
|
+
tcp_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
|
547
|
+
tcp_socket.sync = true
|
|
548
|
+
ctx = OpenSSL::SSL::SSLContext.new()
|
|
549
|
+
|
|
550
|
+
ctx.tmp_dh_callback = proc { |*args|
|
|
551
|
+
OpenSSL::PKey::DH.new(128)
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, ctx)
|
|
555
|
+
|
|
556
|
+
socket.connect
|
|
557
|
+
cert = socket.peer_cert
|
|
558
|
+
|
|
559
|
+
if cert.subject.to_s =~ /cn=([^\/]*)/i
|
|
560
|
+
cn = $1
|
|
561
|
+
end
|
|
562
|
+
puts "Peer-Cert CN: #{cn}"
|
|
563
|
+
socket.io.shutdown(2)
|
|
564
|
+
rescue => bang
|
|
565
|
+
puts bang
|
|
566
|
+
cn = host
|
|
567
|
+
ensure
|
|
568
|
+
socket.close if socket.respond_to? :close
|
|
569
|
+
end
|
|
570
|
+
cn
|
|
571
|
+
end
|
|
394
572
|
|
|
395
573
|
#
|
|
396
574
|
#
|
|
@@ -531,14 +709,15 @@ module Watobo
|
|
|
531
709
|
#print "~]"
|
|
532
710
|
return if buf.nil?
|
|
533
711
|
rescue Errno::ECONNRESET
|
|
534
|
-
|
|
535
|
-
|
|
712
|
+
# puts "!!! ERROR (Reset): reading body"
|
|
713
|
+
# puts "* last data seen on socket: #{buf}"
|
|
714
|
+
print "R"
|
|
536
715
|
return if buf.nil?
|
|
537
716
|
rescue Timeout::Error
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
print "
|
|
717
|
+
#puts "!!! ERROR (Timeout): reading body"
|
|
718
|
+
#puts "* last data seen on socket:"
|
|
719
|
+
#client.write buf if buf
|
|
720
|
+
print "T"
|
|
542
721
|
return if buf.nil?
|
|
543
722
|
rescue => bang
|
|
544
723
|
puts "!!! could not read body !!!"
|
|
@@ -583,16 +762,76 @@ module Watobo
|
|
|
583
762
|
end
|
|
584
763
|
end
|
|
585
764
|
|
|
765
|
+
def transparent?
|
|
766
|
+
return true if ( @proxy_mode & Watobo::Interceptor::MODE_TRANSPARENT ) > 0
|
|
767
|
+
return false
|
|
768
|
+
end
|
|
769
|
+
|
|
586
770
|
def read_request(socket)
|
|
587
771
|
request = []
|
|
588
772
|
# read http header lines
|
|
589
773
|
session = socket
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
774
|
+
|
|
775
|
+
ra = socket.remote_address
|
|
776
|
+
cport = ra.ip_port
|
|
777
|
+
caddr = ra.ip_address
|
|
778
|
+
|
|
779
|
+
if transparent?
|
|
780
|
+
|
|
781
|
+
ci = @connections.info({ 'host' => caddr, 'port' => cport } )
|
|
782
|
+
unless ci['target'].empty? or ci['cn'].empty?
|
|
783
|
+
puts "SSL-REQUEST FROM #{caddr}:#{cport}"
|
|
784
|
+
|
|
785
|
+
ctx = Watobo::CertStore.acquire_ssl_ctx ci['target'], ci['cn']
|
|
786
|
+
|
|
787
|
+
begin
|
|
788
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
|
789
|
+
ssl_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
|
790
|
+
# ssl_socket.sync_close = true
|
|
791
|
+
ssl_socket.sync = true
|
|
792
|
+
# puts ssl_socket.methods.sort
|
|
793
|
+
session = ssl_socket.accept
|
|
794
|
+
rescue OpenSSL::SSL::SSLError => e
|
|
795
|
+
puts ">> SSLError"
|
|
796
|
+
puts e
|
|
797
|
+
return nil, session
|
|
798
|
+
rescue => bang
|
|
799
|
+
puts bang
|
|
800
|
+
puts bang.backtrace
|
|
801
|
+
return nil, session
|
|
802
|
+
end
|
|
803
|
+
else
|
|
804
|
+
puts ci['host']
|
|
805
|
+
puts ci['cn']
|
|
806
|
+
end
|
|
807
|
+
end
|
|
808
|
+
|
|
809
|
+
Watobo::HTTP.read_header(session) do |line|
|
|
810
|
+
# puts line
|
|
593
811
|
request.push line
|
|
594
812
|
end
|
|
595
813
|
|
|
814
|
+
if transparent?
|
|
815
|
+
#puts "> get hostname ..."
|
|
816
|
+
thn = nil
|
|
817
|
+
request.each do |l|
|
|
818
|
+
if l =~ /^Host: (.*)/
|
|
819
|
+
thn = $1.strip
|
|
820
|
+
# puts ">> #{thn}"
|
|
821
|
+
end
|
|
822
|
+
end
|
|
823
|
+
# puts session.class
|
|
824
|
+
# puts "* fix request line ..."
|
|
825
|
+
# puts request.first
|
|
826
|
+
# puts ">>"
|
|
827
|
+
if session.is_a? OpenSSL::SSL::SSLSocket
|
|
828
|
+
request.first.gsub!(/(^[^[:space:]]{1,}) (.*) (HTTP.*)/i,"\\1 https://#{thn}\\2 \\3")
|
|
829
|
+
else
|
|
830
|
+
request.first.gsub!(/(^[^[:space:]]{1,}) (.*) (HTTP.*)/i,"\\1 http://#{thn}\\2 \\3")
|
|
831
|
+
end
|
|
832
|
+
#puts request.first
|
|
833
|
+
end
|
|
834
|
+
|
|
596
835
|
if request.first =~ /^CONNECT (.*):(\d{1,5}) HTTP\/1\./ then
|
|
597
836
|
target = $1
|
|
598
837
|
tport = $2
|
|
@@ -606,13 +845,31 @@ module Watobo
|
|
|
606
845
|
bscount = 0 # bad handshake counter
|
|
607
846
|
# puts "* wait for ssl handshake ..."
|
|
608
847
|
begin
|
|
609
|
-
|
|
848
|
+
dst = "#{target}:#{tport}"
|
|
849
|
+
unless @fake_certs.has_key? dst
|
|
850
|
+
puts "NEW CERTIFICATE FOR >> #{dst} <<"
|
|
851
|
+
cn = get_ssl_cert_cn(target, tport)
|
|
852
|
+
puts "CN=#{cn}"
|
|
853
|
+
|
|
854
|
+
cert = {
|
|
855
|
+
:hostname => cn,
|
|
856
|
+
:type => 'server',
|
|
857
|
+
:user => 'watobo',
|
|
858
|
+
:email => 'a.schmidt@siberas.de',
|
|
859
|
+
}
|
|
860
|
+
cert_file, key_file = Watobo::CA.create_cert cert
|
|
861
|
+
@fake_certs[dst] = {
|
|
862
|
+
:cert => OpenSSL::X509::Certificate.new(File.read(cert_file)),
|
|
863
|
+
:key => OpenSSL::PKey::RSA.new(File.read(key_file))
|
|
864
|
+
}
|
|
865
|
+
end
|
|
610
866
|
ctx = OpenSSL::SSL::SSLContext.new()
|
|
611
867
|
|
|
612
|
-
ctx.cert = @cert
|
|
868
|
+
#ctx.cert = @cert
|
|
869
|
+
ctx.cert = @fake_certs[dst][:cert]
|
|
613
870
|
# @ctx.key = OpenSSL::PKey::DSA.new(File.read(key_file))
|
|
614
|
-
ctx.key = @key
|
|
615
|
-
|
|
871
|
+
#ctx.key = @key
|
|
872
|
+
ctx.key = @fake_certs[dst][:key]
|
|
616
873
|
ctx.tmp_dh_callback = proc { |*args|
|
|
617
874
|
@dh_key
|
|
618
875
|
}
|
|
@@ -622,7 +879,7 @@ module Watobo
|
|
|
622
879
|
|
|
623
880
|
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket, ctx)
|
|
624
881
|
ssl_socket.setsockopt( Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1)
|
|
625
|
-
#ssl_socket.sync_close = true
|
|
882
|
+
# ssl_socket.sync_close = true
|
|
626
883
|
ssl_socket.sync = true
|
|
627
884
|
# puts ssl_socket.methods.sort
|
|
628
885
|
|
|
@@ -652,9 +909,10 @@ module Watobo
|
|
|
652
909
|
request.first.gsub!(/(^[^[:space:]]{1,})( )(\/.*)/, "\\1 https://#{target}:#{tport}\\3")
|
|
653
910
|
end
|
|
654
911
|
#puts request
|
|
655
|
-
request.extend Watobo::Mixin::Parser::Url
|
|
656
|
-
request.extend Watobo::Mixin::Parser::Web10
|
|
657
|
-
request.extend Watobo::Mixin::Shaper::Web10
|
|
912
|
+
# request.extend Watobo::Mixin::Parser::Url
|
|
913
|
+
# request.extend Watobo::Mixin::Parser::Web10
|
|
914
|
+
# request.extend Watobo::Mixin::Shaper::Web10
|
|
915
|
+
Watobo::Request.create request
|
|
658
916
|
|
|
659
917
|
clen = request.content_length
|
|
660
918
|
if clen > 0 then
|
|
@@ -673,6 +931,8 @@ module Watobo
|
|
|
673
931
|
begin
|
|
674
932
|
reason = nil
|
|
675
933
|
clen = response.content_length
|
|
934
|
+
# no pass-through necessary if request method is HEAD
|
|
935
|
+
return false if request.method =~ /^head/i
|
|
676
936
|
|
|
677
937
|
if matchContentType?(response.content_type) then
|
|
678
938
|
# first forward headers
|
|
@@ -718,17 +978,20 @@ module Watobo
|
|
|
718
978
|
|
|
719
979
|
def closeSocket(socket)
|
|
720
980
|
#puts socket.class
|
|
981
|
+
return false if socket.nil?
|
|
721
982
|
begin
|
|
722
983
|
#if socket.class.to_s =~ /SSLSocket/
|
|
723
984
|
if socket.is_a? OpenSSL::SSL::SSLSocket
|
|
724
985
|
socket.io.shutdown(2)
|
|
986
|
+
#socket.sysclose
|
|
725
987
|
else
|
|
726
988
|
socket.shutdown(2)
|
|
727
989
|
end
|
|
728
|
-
socket.close
|
|
990
|
+
socket.close if socket.respond_to? :close
|
|
729
991
|
rescue => bang
|
|
730
992
|
puts bang
|
|
731
993
|
puts bang.backtrace if $DEBUG
|
|
994
|
+
|
|
732
995
|
end
|
|
733
996
|
end
|
|
734
997
|
|