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
@@ -75,7 +75,7 @@ EOD
75
75
  tparam = Watobo::UrlParameter.new( :name => "watobo", :value => CGI::escape(test_value) )
76
76
 
77
77
  test_request.url.set tparam
78
- puts test_request.first
78
+ #puts test_request.first
79
79
 
80
80
  request, response = doRequest(test_request)
81
81
 
@@ -18,7 +18,12 @@ module Watobo#:nodoc: all
18
18
  # if the result is the same, chances are good that XXE attacks will work
19
19
  #
20
20
  # Links:
21
- # http://www.w3.org/TR/2004/REC-xml-20040204/#sec-external-ent
21
+ # http://www.w3.org/TR/2004/REC-xml-20040204/#sec-external-ent
22
+
23
+ # Exploitation notes:
24
+ # https://www.christian-schneider.net/GenericXxeDetection.html
25
+ # <!ENTITY % three SYSTEM "file:///etc/passwd">
26
+ # <!ENTITY % two "<!ENTITY % four SYSTEM 'file:///%three;'>">
22
27
 
23
28
  @info.update(
24
29
  :check_name => 'XML-XXE', # name of check which briefly describes functionality, will be used for tree and progress views
@@ -33,7 +33,7 @@ module Watobo#:nodoc: all
33
33
  )
34
34
 
35
35
 
36
- @pattern = '([\w\/\-0-9\.:]+\.nsf)'
36
+ @pattern = '([a-zA-Z\/\-0-9\.:]+\.nsf)'
37
37
  @dbs = []
38
38
  end
39
39
 
@@ -35,9 +35,11 @@ module Watobo#:nodoc: all
35
35
 
36
36
  end
37
37
 
38
- def showError(chatid, message)
39
- puts "!!! Error #{Module.nesting[0].name}"
40
- puts "Chat: [#{chatid}]"
38
+ def showError(chat, message)
39
+ puts "!!! Error in module #{Module.nesting[0].name}"
40
+ puts "Chat: [#{chat.id}]"
41
+ puts "URL: #{chat.request.url}"
42
+ puts "-- Error --"
41
43
  puts message
42
44
  end
43
45
 
@@ -78,7 +80,10 @@ module Watobo#:nodoc: all
78
80
  end
79
81
  rescue => bang
80
82
  # raise
81
- showError(chat.id, bang)
83
+
84
+ showError(chat, bang)
85
+ puts bang
86
+ puts "-- trace --"
82
87
  puts bang.backtrace
83
88
 
84
89
  end
@@ -0,0 +1,21 @@
1
+ #.
2
+ # aem.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::Plugin
12
+ module Plugin
13
+ class AEM < Watobo::PluginBase
14
+ plugin_name "AEM"
15
+ description "Adobe Experience Manager Enumerator"
16
+ load_libs
17
+ load_gui :main, :tree_view
18
+ end
19
+ end
20
+ end
21
+
@@ -0,0 +1,128 @@
1
+ #.
2
+ # main.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
+ module Plugin
13
+ class AEM
14
+ class Gui < Watobo::PluginGui
15
+
16
+ window_title "Adobe Experience Manager Enumerator"
17
+ icon_file "aem.ico"
18
+ def start
19
+ @results = []
20
+ @tree_view.clear
21
+ @tree_view.set_base_dir @url.text
22
+ Watobo::Plugin::CQ5.reset
23
+ # Watobo::Plugin::CQ5.use_relative_path = @relative_path_cb.checked?
24
+ Watobo::Plugin::CQ5.ignore_patterns = @ignore_cb.checked? ? @ignore_patterns_list.to_a : []
25
+ Watobo::Plugin::CQ5.run( @url.text , @results_queue)
26
+ end
27
+
28
+ def stop
29
+ Watobo::Plugin::CQ5.stop
30
+ end
31
+
32
+ def initialize()
33
+ @results = []
34
+ @export_path = Watobo.workspace_path
35
+ @results_queue = Queue.new
36
+
37
+ super()
38
+
39
+ main_frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
40
+
41
+ url_frame = FXHorizontalFrame.new(main_frame, :opts => LAYOUT_FILL_X)
42
+ @url = FXTextField.new(url_frame, 25, nil, 0, :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_X|LAYOUT_LEFT)
43
+
44
+ @url.setFocus()
45
+ @url.setDefault()
46
+
47
+ @start_btn = FXButton.new(url_frame, "start")
48
+
49
+ @url.connect(SEL_COMMAND){ start }
50
+ @start_btn.connect(SEL_COMMAND){ start }
51
+
52
+ @stop_btn = FXButton.new(url_frame, "stop")
53
+ @stop_btn.connect(SEL_COMMAND){ stop }
54
+
55
+ splitter = FXSplitter.new(main_frame, LAYOUT_FILL_X|SPLITTER_HORIZONTAL|LAYOUT_FILL_Y|SPLITTER_TRACKING)
56
+ opts_frame = FXVerticalFrame.new(splitter, :opts => LAYOUT_SIDE_BOTTOM|LAYOUT_FIX_WIDTH, :width => 450)
57
+
58
+
59
+ gbframe = FXGroupBox.new(opts_frame, "Ignore Path Patterns", FRAME_GROOVE|LAYOUT_FILL_Y, 0, 0, 0, 0)
60
+ iframe = FXVerticalFrame.new(gbframe, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
61
+ @ignore_cb = FXCheckButton.new(iframe, "enable", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
62
+ @ignore_cb.checkState = true
63
+
64
+ @invert_cb = FXCheckButton.new(iframe, "invert", nil, 0, JUSTIFY_LEFT|JUSTIFY_TOP|ICON_BEFORE_TEXT|LAYOUT_SIDE_TOP)
65
+ @invert_cb.checkState = false
66
+ @invert_cb.disable
67
+
68
+ FXLabel.new(iframe, "Ignore if url matches one of the following patterns (regex):")
69
+ @ignore_patterns_list = Watobo::Gui::ListBox.new(iframe)
70
+ @ignore_patterns_list.set %w( replication\/data jcr.*versionstorage workflow\/instances audit\/com.day.cq.replication\/content )
71
+ #@scope_only_cb.connect(SEL_COMMAND) { }
72
+
73
+ #mr_splitter = FXSplitter.new(main_frame, LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_HORIZONTAL|SPLITTER_REVERSED|SPLITTER_TRACKING)
74
+ # top = FXHorizontalFrame.new(mr_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_SIDE_BOTTOM)
75
+ top_frame = FXVerticalFrame.new(splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FIX_HEIGHT|FRAME_SUNKEN,:height => 500)
76
+ @tree_view = TreeView.new top_frame
77
+
78
+
79
+ frame = FXHorizontalFrame.new(main_frame, :opts => LAYOUT_FILL_X)
80
+ @counter = FXLabel.new(frame, "")
81
+ @queue_size = FXLabel.new(frame, "")
82
+ update_counter
83
+
84
+ @tree_view.subscribe(:show_info){|item|
85
+ puts "Item clicked"
86
+ puts item[:url]
87
+ }
88
+
89
+ @save_btn = FXButton.new(frame, "save", :opts => BUTTON_NORMAL|LAYOUT_RIGHT)
90
+ @save_btn.connect(SEL_COMMAND){ save_results }
91
+
92
+ update_timer(500){
93
+ max = 100
94
+ count = 0
95
+ while @results_queue.size > 0 and count < max
96
+ r = @results_queue.deq
97
+ @results << r
98
+ #puts @results.length
99
+ @tree_view.add r
100
+ count += 1
101
+ end
102
+ update_counter
103
+ }
104
+ end
105
+
106
+ private
107
+
108
+ def update_counter
109
+ @counter.text = "Total: #{@results.length}"
110
+ @queue_size.text = "Queue: #{Watobo::Plugin::CQ5.queue_size}"
111
+ end
112
+
113
+ def save_results
114
+ fname = "cq5_" + Time.now.to_i.to_s + ".json"
115
+ dst_file = File.join(@export_path, fname)
116
+ filename = FXFileDialog.getSaveFilename(self, "Select Export File", dst_file)
117
+ if filename != "" then
118
+ @export_path = File.dirname filename
119
+ Thread.new(filename){|fn|
120
+ File.open(fn,"wb"){|fh| fh.print JSON.pretty_generate(@results) }
121
+ }
122
+ end
123
+ end
124
+
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,180 @@
1
+ #.
2
+ # tree_view.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
+ #require 'qcustomize.rb'
11
+
12
+ # @private
13
+ module Watobo#:nodoc: all
14
+ module Plugin
15
+ class AEM
16
+ class Gui
17
+ class TreeView < FXTreeList
18
+
19
+ include Watobo::Constants
20
+ include Watobo::Gui::Icons
21
+
22
+ def subscribe(event, &callback)
23
+ (@event_dispatcher_listeners[event] ||= []) << callback
24
+ end
25
+
26
+ def clear()
27
+ @results = []
28
+ self.clearItems
29
+ end
30
+
31
+ #def refresh_tree()
32
+ # self.clearItems
33
+
34
+ #Watobo::Chats.each do |chat|
35
+ # addChat(chat)
36
+ #end
37
+
38
+ # @interface.updateRequestTable(@project)
39
+ #end
40
+
41
+ def expandFullTree(item)
42
+ self.expandTree(item)
43
+ item.each do |c|
44
+ expandFullTree(c) if !self.itemLeaf?(c)
45
+ end
46
+ end
47
+
48
+ def collapseFullTree(item)
49
+ self.collapseTree(item)
50
+ item.each do |c|
51
+ collapseFullTree(c) if !self.itemLeaf?(c)
52
+ end
53
+ end
54
+
55
+
56
+
57
+ def add(result)
58
+ addItem(result)
59
+ end
60
+
61
+ def set_base_dir(url)
62
+ url.gsub!(/^.*\/\//,'')
63
+ subdirs = url.split '/'
64
+ subdirs.shift
65
+ item = nil
66
+ subdirs.each do |d|
67
+ # puts "* append #{d}"
68
+ nxt = self.appendItem(item, d)#, @folderIcon, @folderIcon)
69
+ self.setItemData(nxt, :base_dir)
70
+ # puts nxt.class
71
+ item = nxt
72
+ end
73
+
74
+ # @base_dir = subdirs.join '/'
75
+ end
76
+
77
+ # end
78
+ def addItem(result)
79
+ #puts result
80
+ url = "#{result[:url].to_s}"
81
+ url.gsub!(/^.*\/\//,'')
82
+ subdirs = url.split '/'
83
+ subdirs.shift
84
+
85
+ puts subdirs.join ' | '
86
+
87
+ item = nil
88
+ subdirs.each do |d|
89
+ nxt = self.findItem(d, item, SEARCH_FORWARD)
90
+ break if nxt.nil?
91
+ item = nxt
92
+ end
93
+
94
+ unless item.nil?
95
+ unless subdirs.last == item.text
96
+ new_item = self.appendItem(item, subdirs.last)#, @folderIcon, @folderIcon)
97
+ self.setItemData(new_item, result)
98
+ end
99
+ end
100
+
101
+ end
102
+
103
+ def initialize(parent)
104
+
105
+ @parent = parent
106
+ @quick_filter = Hash.new
107
+ @show_scope_only = false
108
+
109
+ @results = []
110
+
111
+ super(parent, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_TOP|LAYOUT_RIGHT|TREELIST_SHOWS_LINES|TREELIST_SHOWS_BOXES|TREELIST_ROOT_BOXES|TREELIST_EXTENDEDSELECT)
112
+
113
+ @event_dispatcher_listeners = Hash.new
114
+
115
+ @projectIcon = ICON_PROJECT
116
+
117
+ @folderIcon = ICON_FOLDER
118
+ @reqIcon = ICON_REQUEST
119
+ @siteIcon= ICON_SITE
120
+
121
+ @filtered_domains = Hash.new # domains which already have been filtered
122
+
123
+ @tree_filters = {
124
+ :response_status => []
125
+ }
126
+
127
+ # session_leaf = self.appendItem(nil, @session_name, @projectIcon, @projectIcon)
128
+
129
+ self.connect(SEL_COMMAND) do |sender, sel, item|
130
+ url_parts = []
131
+ begin
132
+ if item.data.is_a? Hash
133
+ #if item.data.class.to_s =~ /Qchat/
134
+ #@interface.show_chat(item.data)
135
+ notify(:show_info, item.data)
136
+ end
137
+
138
+ rescue => bang
139
+ # puts bang
140
+ # puts bang.backtrace if $DEBUG
141
+ #puts "!!! Error: could not show selected tree item"
142
+ end
143
+
144
+ getApp().beginWaitCursor do
145
+ notify(:show_conversation, @quick_filter[item.object_id]) if @quick_filter[item.object_id]
146
+ end
147
+ end
148
+
149
+ self.connect(SEL_RIGHTBUTTONRELEASE) do |sender, sel, event|
150
+ exclude_site = nil
151
+ unless event.moved?
152
+ FXMenuPane.new(self) do |menu_pane|
153
+
154
+ target = FXMenuCheck.new(menu_pane, "test" )
155
+
156
+ menu_pane.create
157
+ menu_pane.popup(nil, event.root_x, event.root_y)
158
+ app.runModalWhileShown(menu_pane)
159
+
160
+ end
161
+ end
162
+ end
163
+ end
164
+
165
+ private
166
+
167
+ def notify(event, *args)
168
+ if @event_dispatcher_listeners[event]
169
+ @event_dispatcher_listeners[event].each do |m|
170
+ m.call(*args) if m.respond_to? :call
171
+ end
172
+ end
173
+ end
174
+
175
+ end
176
+ # namespace end
177
+ end
178
+ end
179
+ end
180
+ end
Binary file
@@ -0,0 +1,140 @@
1
+ #.
2
+ # agent.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
+ module Plugin
13
+ class CQ5
14
+ class Agent < Watobo::Session
15
+ def initialize(base_request, in_queue, out_queue )
16
+ @work_queue = in_queue
17
+ @disp_queue = out_queue
18
+ @request = base_request
19
+
20
+
21
+ super(@request.object_id, Watobo::Conf::Scanner.to_h )
22
+
23
+ end
24
+
25
+ def stop
26
+ @agent_thread.kill
27
+ end
28
+
29
+ def run
30
+ return nil if @work_queue.nil? or @disp_queue.nil?
31
+
32
+ @agent_thread = Thread.new(){
33
+ puts "#{self} running ..."
34
+ loop do
35
+ begin
36
+
37
+ item = @work_queue.deq
38
+ # not interested in jcr:content ... skip ...
39
+ next if item[:url] =~ /jcr%3acontent$/
40
+
41
+ get_pages item
42
+ file_info item
43
+
44
+ rescue => bang
45
+ puts bang
46
+ puts bang.backtrace
47
+ exit
48
+ end
49
+ end
50
+ }
51
+ @agent_thread
52
+ end
53
+
54
+ def get_pages(item)
55
+ test = @request.copy
56
+ # puts item
57
+ url = item[:url].gsub(/\/$/,'') + '/.pages.json'
58
+ test.replaceURL( url )
59
+
60
+ request, response = sendRequest test
61
+
62
+ return false unless response.respond_to? :status
63
+ item[:pages_status] = response.status
64
+ # @disp_queue << item
65
+
66
+
67
+ if response.content_type =~ /json/i
68
+ begin
69
+ ntpages = JSON.parse response.body.to_s
70
+
71
+ if ntpages['pages']
72
+
73
+ ntpages['pages'].each do |p|
74
+ #unless @use_relative_path
75
+ ep = p['escapedPath']
76
+ next if ep.nil?
77
+ next if ep.empty?
78
+
79
+ purl = ''
80
+
81
+ purl = @request.url.to_s.gsub(/\/$/, '') + p['escapedPath']
82
+ puts "+ #{purl}"
83
+
84
+ next if purl.empty?
85
+
86
+ item = {
87
+ :url => purl,
88
+ :page_info => p,
89
+ :file_info => nil,
90
+ :status => nil
91
+ }
92
+
93
+ @disp_queue << item
94
+ end
95
+ end
96
+
97
+ rescue => bang
98
+ puts bang
99
+ puts ntpages
100
+ puts "---"
101
+ end
102
+ end
103
+ #puts response.body.to_s
104
+ true
105
+ end
106
+
107
+ def file_info(item)
108
+ #url = item[:url]
109
+ #@request.replaceURL "#{url}/.json"
110
+ test = @request.copy
111
+ test.set_file_extension "json"
112
+ # puts "\n>> #{@request.url}"
113
+ request, response = sendRequest test
114
+
115
+ return false unless response.respond_to? :status
116
+ item[:info_status] = response.status
117
+
118
+ if response.content_type =~ /json/i
119
+ info = JSON.parse response.body.to_s
120
+ item[:file_info] = info
121
+ end
122
+ #@disp_queue << item
123
+ true
124
+ end
125
+
126
+ def sendRequest(request, prefs={})
127
+ begin
128
+ test_req, test_resp = self.doRequest(request, prefs)
129
+ return test_req, test_resp
130
+ rescue => bang
131
+ puts bang
132
+ puts bang.backtrace if $DEBUG
133
+ end
134
+ return nil, nil
135
+ end
136
+ end
137
+
138
+ end
139
+ end
140
+ end