watobo 0.9.20 → 0.9.21

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.
Files changed (51) hide show
  1. data/CHANGELOG.md +54 -2
  2. data/README.md +1 -1
  3. data/config/scanner.yml +1 -0
  4. data/custom-views/prettify-json.rb +19 -0
  5. data/lib/watobo/adapters/file/marshal_store.rb +297 -0
  6. data/lib/watobo/adapters.rb +2 -1
  7. data/lib/watobo/core/active_check.rb +4 -0
  8. data/lib/watobo/core/chat.rb +8 -0
  9. data/lib/watobo/core/chats.rb +2 -1
  10. data/lib/watobo/core/cookie.rb +3 -3
  11. data/lib/watobo/core/finding.rb +7 -0
  12. data/lib/watobo/core/request.rb +3 -3
  13. data/lib/watobo/core/session.rb +6 -2
  14. data/lib/watobo/framework/init_modules.rb +18 -16
  15. data/lib/watobo/gui/conversation_table.rb +13 -16
  16. data/lib/watobo/gui/conversation_table_ctrl2.rb +1 -0
  17. data/lib/watobo/gui/custom_viewer.rb +101 -76
  18. data/lib/watobo/gui/define_scope_frame.rb +44 -10
  19. data/lib/watobo/gui/edit_scope_dialog.rb +1 -1
  20. data/lib/watobo/gui/fuzzer_gui.rb +61 -23
  21. data/lib/watobo/gui/main_window.rb +1 -1
  22. data/lib/watobo/gui/scanner_settings_dialog.rb +15 -0
  23. data/lib/watobo/http/data/json.rb +6 -0
  24. data/lib/watobo/interceptor/html/favicon.ico +0 -0
  25. data/lib/watobo/interceptor/html/index.html +13 -0
  26. data/lib/watobo/interceptor/proxy.rb +70 -18
  27. data/lib/watobo/mixins/httpparser.rb +26 -16
  28. data/lib/watobo/mixins/shapers.rb +49 -5
  29. data/lib/watobo/mixins/transcoders.rb +8 -8
  30. data/lib/watobo/sockets/connection.rb +1 -1
  31. data/lib/watobo/utils/load_chat.rb +62 -0
  32. data/lib/watobo/utils/response_hash.rb +3 -3
  33. data/lib/watobo.rb +1 -1
  34. data/modules/active/cq5/cq5_default_selectors.rb +116 -0
  35. data/modules/active/cq5/cqp_user_enumeration.rb +134 -0
  36. data/modules/active/struts2/include_params_ognl.rb +1 -1
  37. data/modules/active/xml/xml_xxe.rb +6 -1
  38. data/modules/passive/disclosure_domino.rb +1 -1
  39. data/modules/passive/in_script_parameter.rb +9 -4
  40. data/plugins/aem/aem.rb +21 -0
  41. data/plugins/aem/gui/main.rb +128 -0
  42. data/plugins/aem/gui/tree_view.rb +180 -0
  43. data/plugins/aem/icons/aem.ico +0 -0
  44. data/plugins/aem/lib/agent.rb +140 -0
  45. data/plugins/aem/lib/dispatcher.rb +53 -0
  46. data/plugins/aem/lib/engine.rb +187 -0
  47. data/plugins/filefinder/dbs/cq5.db +23 -0
  48. data/plugins/filefinder/dbs/subs-big.lst +44 -44
  49. data/plugins/filefinder/filefinder.rb +4 -4
  50. data/plugins/sqlmap/lib/sqlmap_ctrl.rb +11 -10
  51. 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 mihd number of checked ciphers depends on installed ruby version :/
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
- ** General **
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
- WATOBO is a security tool for testing web applications. It is intended to enable security professionals to perform efficient (semi-automated) web application security audits.
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
@@ -1,6 +1,7 @@
1
1
  :logout_signatures:
2
2
  - ^Location.*login
3
3
  :smart_scan: true
4
+ :ignore_server_errors: true
4
5
  :custom_error_patterns: []
5
6
  :excluded_chats: []
6
7
  :max_parallel_checks: 15
@@ -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
@@ -11,4 +11,5 @@
11
11
  require "watobo/adapters/#{lib}"
12
12
  end
13
13
 
14
- require "watobo/adapters/file/file_store"
14
+ #require "watobo/adapters/file/file_store"
15
+ require "watobo/adapters/file/marshal_store"
@@ -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
 
@@ -60,6 +60,14 @@ module Watobo#:nodoc: all
60
60
 
61
61
  def source()
62
62
  @settings[:source]
63
+ end
64
+
65
+ def to_h
66
+ h = {}
67
+ h.update @settings
68
+ h[:request] = @request.to_a
69
+ h[:response] = @response.to_a
70
+ h
63
71
  end
64
72
 
65
73
 
@@ -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