watobo 0.9.20 → 0.9.21
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +54 -2
- data/README.md +1 -1
- data/config/scanner.yml +1 -0
- data/custom-views/prettify-json.rb +19 -0
- data/lib/watobo/adapters/file/marshal_store.rb +297 -0
- data/lib/watobo/adapters.rb +2 -1
- data/lib/watobo/core/active_check.rb +4 -0
- data/lib/watobo/core/chat.rb +8 -0
- data/lib/watobo/core/chats.rb +2 -1
- data/lib/watobo/core/cookie.rb +3 -3
- data/lib/watobo/core/finding.rb +7 -0
- data/lib/watobo/core/request.rb +3 -3
- data/lib/watobo/core/session.rb +6 -2
- data/lib/watobo/framework/init_modules.rb +18 -16
- data/lib/watobo/gui/conversation_table.rb +13 -16
- data/lib/watobo/gui/conversation_table_ctrl2.rb +1 -0
- data/lib/watobo/gui/custom_viewer.rb +101 -76
- data/lib/watobo/gui/define_scope_frame.rb +44 -10
- data/lib/watobo/gui/edit_scope_dialog.rb +1 -1
- data/lib/watobo/gui/fuzzer_gui.rb +61 -23
- data/lib/watobo/gui/main_window.rb +1 -1
- data/lib/watobo/gui/scanner_settings_dialog.rb +15 -0
- data/lib/watobo/http/data/json.rb +6 -0
- data/lib/watobo/interceptor/html/favicon.ico +0 -0
- data/lib/watobo/interceptor/html/index.html +13 -0
- data/lib/watobo/interceptor/proxy.rb +70 -18
- data/lib/watobo/mixins/httpparser.rb +26 -16
- data/lib/watobo/mixins/shapers.rb +49 -5
- data/lib/watobo/mixins/transcoders.rb +8 -8
- data/lib/watobo/sockets/connection.rb +1 -1
- data/lib/watobo/utils/load_chat.rb +62 -0
- data/lib/watobo/utils/response_hash.rb +3 -3
- data/lib/watobo.rb +1 -1
- data/modules/active/cq5/cq5_default_selectors.rb +116 -0
- data/modules/active/cq5/cqp_user_enumeration.rb +134 -0
- data/modules/active/struts2/include_params_ognl.rb +1 -1
- data/modules/active/xml/xml_xxe.rb +6 -1
- data/modules/passive/disclosure_domino.rb +1 -1
- data/modules/passive/in_script_parameter.rb +9 -4
- data/plugins/aem/aem.rb +21 -0
- data/plugins/aem/gui/main.rb +128 -0
- data/plugins/aem/gui/tree_view.rb +180 -0
- data/plugins/aem/icons/aem.ico +0 -0
- data/plugins/aem/lib/agent.rb +140 -0
- data/plugins/aem/lib/dispatcher.rb +53 -0
- data/plugins/aem/lib/engine.rb +187 -0
- data/plugins/filefinder/dbs/cq5.db +23 -0
- data/plugins/filefinder/dbs/subs-big.lst +44 -44
- data/plugins/filefinder/filefinder.rb +4 -4
- data/plugins/sqlmap/lib/sqlmap_ctrl.rb +11 -10
- metadata +16 -2
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,55 @@
|
|
1
|
+
Version 0.9.21
|
2
|
+
===
|
3
|
+
|
4
|
+
News
|
5
|
+
---
|
6
|
+
**General**
|
7
|
+
|
8
|
+
* greatly increased speed of session import by using Marshal serialization instead of YAML for storing chats/findings.
|
9
|
+
|
10
|
+
**NOTE:** older formats will still work but they will be converted to .mrs files.
|
11
|
+
|
12
|
+
* added scanner setting 'ignore server errors' which (if enabled) will handle 5xx response codes as 'file does not exist'. It overrules custom error filters.
|
13
|
+
* introduced the watobo info page. accessible via http://watobo - where you can download the CA cert as well as some installation information
|
14
|
+
* the 'Define Target Scope' dialog now has a text filter
|
15
|
+
|
16
|
+
**Plugins**
|
17
|
+
|
18
|
+
* added Adobe Experience Manager Enumeration, crawles the site by using information of AEM/CQ5 json-Extensions
|
19
|
+
|
20
|
+
**Fuzzer**
|
21
|
+
|
22
|
+
* results are now saved in yaml format
|
23
|
+
|
24
|
+
**Modules**
|
25
|
+
|
26
|
+
* new CQ5 modules for selectors and extensions detection
|
27
|
+
* new CQ5 module for userenumeration via json and xml extensions
|
28
|
+
|
29
|
+
**CustomViewer**
|
30
|
+
|
31
|
+
* updating view after handler is loaded, no more tab/chat switch necessary
|
32
|
+
|
33
|
+
Fixes
|
34
|
+
---
|
35
|
+
**General**
|
36
|
+
|
37
|
+
* changed encoding in conversation table
|
38
|
+
* Response.header_value parsing
|
39
|
+
|
40
|
+
**Plugins**
|
41
|
+
|
42
|
+
* [sqlmap] enhanced path detection to also match 'sqlmap' without .py extension
|
43
|
+
|
44
|
+
**Fuzzer**
|
45
|
+
|
46
|
+
* multiple fixes in statistics view
|
47
|
+
|
48
|
+
**ConversationTable**
|
49
|
+
|
50
|
+
* fixed autoscroll checkbox, no more autoscrolling if unchecked
|
51
|
+
* fixed crash on Goto-Function (shift-g shortcut)
|
52
|
+
|
1
53
|
Version 0.9.20
|
2
54
|
===
|
3
55
|
|
@@ -36,12 +88,12 @@ News
|
|
36
88
|
|
37
89
|
**SSL-Checker**
|
38
90
|
|
39
|
-
* optimized ssl checks - but keep in
|
91
|
+
* optimized ssl checks - but keep in mind that the number of checked ciphers depends on your ruby version
|
40
92
|
|
41
93
|
Fixes
|
42
94
|
---
|
43
95
|
|
44
|
-
**
|
96
|
+
**General**
|
45
97
|
|
46
98
|
* post parameter values containing equal signs ('=') will no longer be truncated
|
47
99
|
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
WATOBO - THE Web Application Toolbox
|
2
2
|
===
|
3
|
-
|
3
|
+
WATABO is a security tool for testing web applications. It is intended to enable security professionals to perform efficient (semi-automated) web application security audits.
|
4
4
|
|
5
5
|
Most important features:
|
6
6
|
|
data/config/scanner.yml
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
#.
|
2
|
+
# prettify-json.rb
|
3
|
+
#.
|
4
|
+
# Copyright 2014 by siberas, http://www.siberas.de
|
5
|
+
# This file is part of WATOBO (Web Application Tool Box) http://watobo.sourceforge.com
|
6
|
+
# WATOBO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.
|
7
|
+
# WATOBO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
8
|
+
# You should have received a copy of the GNU General Public License along with WATOBO; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
9
|
+
|
10
|
+
lambda{|response|
|
11
|
+
begin
|
12
|
+
jb = JSON.parse(response.body.to_s)
|
13
|
+
out = JSON.pretty_generate jb
|
14
|
+
rescue => bang
|
15
|
+
out = "Could prettify response :(\n\n"
|
16
|
+
out << bang.to_s
|
17
|
+
end
|
18
|
+
out
|
19
|
+
}
|
@@ -0,0 +1,297 @@
|
|
1
|
+
#.
|
2
|
+
# marshal_store.rb
|
3
|
+
#.
|
4
|
+
# Copyright 2014 by siberas, http://www.siberas.de
|
5
|
+
# This file is part of WATOBO (Web Application Tool Box) http://watobo.sourceforge.com
|
6
|
+
# WATOBO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 2 of the License.
|
7
|
+
# WATOBO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
8
|
+
# You should have received a copy of the GNU General Public License along with WATOBO; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
9
|
+
|
10
|
+
# @private
|
11
|
+
module Watobo#:nodoc: all
|
12
|
+
class FileSessionStore < SessionStore
|
13
|
+
def num_chats
|
14
|
+
get_file_list(@conversation_path, "*-chat*").length
|
15
|
+
end
|
16
|
+
|
17
|
+
def num_findings
|
18
|
+
get_file_list(@findings_path, "*-finding*").length
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_finding(finding)
|
22
|
+
return false unless finding.respond_to? :request
|
23
|
+
return false unless finding.respond_to? :response
|
24
|
+
|
25
|
+
finding_file = File.join("#{@findings_path}", "#{finding.id}-finding.mrs")
|
26
|
+
unless File.exists?(finding_file)
|
27
|
+
save_finding(finding_file, finding)
|
28
|
+
return true
|
29
|
+
end
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def delete_finding(finding)
|
34
|
+
finding_file = File.join("#{@findings_path}", "#{finding.id}-finding")
|
35
|
+
File.delete finding_file if File.exist? finding_file
|
36
|
+
file = finding_file + ".yml"
|
37
|
+
File.delete file if File.exist? file
|
38
|
+
file = finding_file + ".mrs"
|
39
|
+
File.delete file if File.exist? file
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
def save_finding(fname, finding)
|
44
|
+
File.open(fname, 'wb'){|f|
|
45
|
+
f.print Marshal::dump(finding.to_h)
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def update_finding(finding)
|
50
|
+
finding_file = File.join("#{@findings_path}", "#{finding.id}-finding.mrs")
|
51
|
+
|
52
|
+
if File.exists?(finding_file) then
|
53
|
+
save_finding(finding_file, finding)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
# add_scan_log
|
59
|
+
# adds a chat to a specific log store, e.g. if you want to log scan results.
|
60
|
+
# needs a scan_name (STRING) as its destination which will be created
|
61
|
+
# if the scan name does not exist.
|
62
|
+
def add_scan_log(chat, scan_name = nil)
|
63
|
+
return false unless chat.respond_to? :request
|
64
|
+
return false unless chat.respond_to? :response
|
65
|
+
begin
|
66
|
+
|
67
|
+
return false if scan_name.nil?
|
68
|
+
return false if scan_name.empty?
|
69
|
+
|
70
|
+
scan_name_clean = scan_name.gsub(/[:\\\/\.]*/,"_")
|
71
|
+
# puts ">> scan_name"
|
72
|
+
path = File.join(@scanlog_path, scan_name_clean)
|
73
|
+
|
74
|
+
Dir.mkdir path unless File.exist? path
|
75
|
+
|
76
|
+
file = File.join( path, "log_" + Time.now.to_f.to_s + ".mrs")
|
77
|
+
|
78
|
+
unless File.exists?(file)
|
79
|
+
File.open(file, "wb") { |fh|
|
80
|
+
fh.print Marshal::dump(chat.to_h)
|
81
|
+
}
|
82
|
+
end
|
83
|
+
|
84
|
+
return true
|
85
|
+
rescue => bang
|
86
|
+
puts bang
|
87
|
+
puts bang.backtrace if $DEBUG
|
88
|
+
end
|
89
|
+
return false
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_chat(chat)
|
93
|
+
return false unless chat_valid? chat
|
94
|
+
chat_file = File.join("#{@conversation_path}", "#{chat.id}-chat.mrs")
|
95
|
+
|
96
|
+
unless File.exists?(chat_file)
|
97
|
+
File.open(chat_file, "wb") { |fh|
|
98
|
+
fh.print Marshal::dump(chat.to_h)
|
99
|
+
}
|
100
|
+
chat.file = chat_file
|
101
|
+
return true
|
102
|
+
end
|
103
|
+
return false
|
104
|
+
end
|
105
|
+
|
106
|
+
def each_chat(&block)
|
107
|
+
list = get_file_list(@conversation_path, "*-chat*")
|
108
|
+
list.each do |fname|
|
109
|
+
#puts
|
110
|
+
chat = nil
|
111
|
+
if fname =~ /\.mrs$/
|
112
|
+
chat = Watobo::Utils.loadChatMarshal(fname)
|
113
|
+
elsif fname =~ /\.yml$/
|
114
|
+
chat = Watobo::Utils.loadChatYAML(fname) unless list.include?(fname.gsub(/yml$/,'mrs'))
|
115
|
+
end
|
116
|
+
next if chat.nil?
|
117
|
+
yield chat if block_given?
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def each_finding(&block)
|
122
|
+
list = get_file_list(@findings_path, "*-finding*")
|
123
|
+
list.each do |fname|
|
124
|
+
f = nil
|
125
|
+
if fname =~ /\.mrs$/
|
126
|
+
f = Watobo::Utils.loadFindingMarshal(fname)
|
127
|
+
elsif fname =~ /\.yml$/
|
128
|
+
f = Watobo::Utils.loadFindingYAML(fname) unless list.include?(fname.gsub(/yml$/,'mrs'))
|
129
|
+
end
|
130
|
+
next if f.nil?
|
131
|
+
yield f if block_given?
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def initialize(project_name, session_name)
|
136
|
+
|
137
|
+
wsp = Watobo.workspace_path
|
138
|
+
return false unless File.exist? wsp
|
139
|
+
puts "* using workspace path: #{wsp}" if $DEBUG
|
140
|
+
|
141
|
+
@log_file = nil
|
142
|
+
@log_lock = Mutex.new
|
143
|
+
|
144
|
+
@project_path = File.join(wsp, project_name)
|
145
|
+
unless File.exist? @project_path
|
146
|
+
puts "* create project path: #{@project_path}" if $DEBUG
|
147
|
+
Dir.mkdir(@project_path)
|
148
|
+
end
|
149
|
+
|
150
|
+
@project_config_path = File.join(@project_path, ".config")
|
151
|
+
Dir.mkdir @project_config_path unless File.exist? @project_config_path
|
152
|
+
|
153
|
+
@session_path = File.join(@project_path, session_name)
|
154
|
+
|
155
|
+
unless File.exist? @session_path
|
156
|
+
puts "* create session path: #{@session_path}" if $DEBUG
|
157
|
+
Dir.mkdir(@session_path)
|
158
|
+
end
|
159
|
+
|
160
|
+
@session_config_path = File.join(@session_path, ".config")
|
161
|
+
Dir.mkdir @session_config_path unless File.exist? @session_config_path
|
162
|
+
|
163
|
+
sext = Watobo::Conf::General.session_settings_file_ext
|
164
|
+
|
165
|
+
@session_file = File.join(@session_path, session_name + sext)
|
166
|
+
@project_file = File.join(@project_path, project_name + Watobo::Conf::General.project_settings_file_ext)
|
167
|
+
|
168
|
+
@conversation_path = File.expand_path(File.join(@session_path, Watobo::Conf::Datastore.conversations))
|
169
|
+
|
170
|
+
@findings_path = File.expand_path(File.join(@session_path, Watobo::Conf::Datastore.findings))
|
171
|
+
@log_path = File.expand_path(File.join(@session_path, Watobo::Conf::Datastore.event_logs_dir))
|
172
|
+
@scanlog_path = File.expand_path(File.join(@session_path, Watobo::Conf::Datastore.scan_logs_dir))
|
173
|
+
|
174
|
+
[ @conversation_path, @findings_path, @log_path, @scanlog_path ].each do |folder|
|
175
|
+
if not File.exists?(folder) then
|
176
|
+
puts "create path #{folder}"
|
177
|
+
begin
|
178
|
+
Dir.mkdir(folder)
|
179
|
+
rescue SystemCallError => bang
|
180
|
+
puts "!!!ERROR:"
|
181
|
+
puts bang
|
182
|
+
rescue => bang
|
183
|
+
puts "!!!ERROR:"
|
184
|
+
puts bang
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
@log_file = File.join(@log_path, session_name + ".log")
|
190
|
+
|
191
|
+
# @chat_files = get_file_list(@conversation_path, "*-chat")
|
192
|
+
# @finding_files = get_file_list(@findings_path, "*-finding")
|
193
|
+
end
|
194
|
+
|
195
|
+
def save_session_settings(group, session_settings)
|
196
|
+
# puts ">> save_session_settings <<"
|
197
|
+
file = Watobo::Utils.snakecase group.gsub(/\.yml/,'')
|
198
|
+
file << ".yml"
|
199
|
+
|
200
|
+
session_file = File.join(@session_config_path, file)
|
201
|
+
# puts "Dest.File: #{session_file}"
|
202
|
+
# puts session_settings.to_yaml
|
203
|
+
# puts "---"
|
204
|
+
Watobo::Utils.save_settings(session_file, session_settings)
|
205
|
+
end
|
206
|
+
|
207
|
+
def load_session_settings(group)
|
208
|
+
# puts ">> load_session_settings : #{group}"
|
209
|
+
file = Watobo::Utils.snakecase group.gsub(/\.yml/,'')
|
210
|
+
file << ".yml"
|
211
|
+
|
212
|
+
session_file = File.join(@session_config_path, file)
|
213
|
+
# puts "File: #{session_file}"
|
214
|
+
# puts "---"
|
215
|
+
|
216
|
+
s = Watobo::Utils.load_settings(session_file)
|
217
|
+
s
|
218
|
+
end
|
219
|
+
|
220
|
+
def save_project_settings(group, project_settings)
|
221
|
+
# puts ">> save_project_settings : #{group}"
|
222
|
+
file = Watobo::Utils.snakecase group.gsub(/\.yml/,'')
|
223
|
+
file << ".yml"
|
224
|
+
|
225
|
+
project_file = File.join(@project_config_path, file)
|
226
|
+
# puts "Dest.File: #{project_file}"
|
227
|
+
# puts project_settings.to_yaml
|
228
|
+
# puts "---"
|
229
|
+
Watobo::Utils.save_settings(project_file, project_settings)
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
def load_project_settings(group)
|
234
|
+
# puts ">> load_project_settings : #{group}"
|
235
|
+
file = Watobo::Utils.snakecase group.gsub(/\.yml/,'')
|
236
|
+
file << ".yml"
|
237
|
+
|
238
|
+
project_file = File.join(@project_config_path, file)
|
239
|
+
# puts "File: #{project_file}"
|
240
|
+
# puts "---"
|
241
|
+
|
242
|
+
s = Watobo::Utils.load_settings(project_file)
|
243
|
+
s
|
244
|
+
|
245
|
+
end
|
246
|
+
|
247
|
+
def logs
|
248
|
+
l = ''
|
249
|
+
@log_lock.synchronize do
|
250
|
+
l = File.open(@log_file).read
|
251
|
+
end
|
252
|
+
l
|
253
|
+
end
|
254
|
+
|
255
|
+
def logger( message, prefs = {} )
|
256
|
+
opts = { :sender => "unknown", :level => Watobo::Constants::LOG_INFO }
|
257
|
+
opts.update prefs
|
258
|
+
return false if @log_file.nil?
|
259
|
+
begin
|
260
|
+
t = Time.now
|
261
|
+
now = t.strftime("%m/%d/%Y @ %H:%M:%S")
|
262
|
+
log_message = [ now ]
|
263
|
+
log_message << "#{opts[:sender]}"
|
264
|
+
if message.is_a? Array
|
265
|
+
log_message << message.join("\n| ")
|
266
|
+
log_message << "\n-"
|
267
|
+
else
|
268
|
+
log_message << message
|
269
|
+
end
|
270
|
+
@log_lock.synchronize do
|
271
|
+
File.open(@log_file,"a") do |lfh|
|
272
|
+
lfh.puts log_message.join("|")
|
273
|
+
end
|
274
|
+
end
|
275
|
+
rescue => bang
|
276
|
+
puts bang
|
277
|
+
end
|
278
|
+
|
279
|
+
end
|
280
|
+
|
281
|
+
private
|
282
|
+
|
283
|
+
def chat_valid?(chat)
|
284
|
+
return false unless chat.respond_to? :request
|
285
|
+
return false unless chat.respond_to? :response
|
286
|
+
true
|
287
|
+
end
|
288
|
+
|
289
|
+
def get_file_list(path, pattern)
|
290
|
+
fl = Dir["#{path}/#{pattern}"].sort_by{ |x| File.basename(x).sub(/[^0-9]*/,'').to_i }
|
291
|
+
|
292
|
+
fl
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
|
297
|
+
end
|
data/lib/watobo/adapters.rb
CHANGED
@@ -250,6 +250,10 @@ module Watobo#:nodoc: all
|
|
250
250
|
return false if status.empty?
|
251
251
|
return true, t_request, t_response if status =~ /^403/
|
252
252
|
return false, t_request, t_response if status =~ /^40\d/
|
253
|
+
if status =~ /^50\d/
|
254
|
+
# puts "* ignore server errors #{Watobo::Conf::Scanner.ignore_server_errors.class}"
|
255
|
+
return false, t_request, t_response if Watobo::Conf::Scanner.ignore_server_errors
|
256
|
+
end
|
253
257
|
|
254
258
|
#puts @settings[:custom_error_patterns]
|
255
259
|
|
data/lib/watobo/core/chat.rb
CHANGED
data/lib/watobo/core/chats.rb
CHANGED
@@ -53,7 +53,8 @@ module Watobo#:nodoc: all
|
|
53
53
|
matches = []
|
54
54
|
@chats.each do |c|
|
55
55
|
if c.request.site == site then
|
56
|
-
matches.push c if o[:dir] == c.request.dir
|
56
|
+
matches.push c if o[:dir] == c.request.dir
|
57
|
+
yield c if block_given?
|
57
58
|
end
|
58
59
|
return matches if o[:max_count] > 0 and matches.length >= o[:max_count]
|
59
60
|
end
|