watobo 0.9.21 → 0.9.23
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +46 -1
- data/bin/nfq_server.rb +0 -9
- data/bin/watobo_gui.rb +3 -13
- data/custom-views/prettify-json.rb +9 -18
- data/icons/watobo.ico +0 -0
- data/icons/watobo.ico.old +0 -0
- data/lib/watobo.rb +10 -19
- data/lib/watobo/adapters.rb +5 -14
- data/lib/watobo/adapters/data_store.rb +50 -59
- data/lib/watobo/adapters/file/file_store.rb +287 -296
- data/lib/watobo/adapters/file/marshal_store.rb +293 -296
- data/lib/watobo/adapters/session_store.rb +5 -14
- data/lib/watobo/ca.rb +1 -10
- data/lib/watobo/config.rb +197 -206
- data/lib/watobo/constants.rb +0 -9
- data/lib/watobo/core.rb +3 -12
- data/lib/watobo/core/active_check.rb +72 -135
- data/lib/watobo/core/active_checks.rb +49 -58
- data/lib/watobo/core/ca.rb +369 -389
- data/lib/watobo/core/cert_store.rb +34 -43
- data/lib/watobo/core/chat.rb +92 -101
- data/lib/watobo/core/chats.rb +271 -280
- data/lib/watobo/core/client_cert_store.rb +106 -35
- data/lib/watobo/core/conversation.rb +48 -57
- data/lib/watobo/core/cookie.rb +23 -32
- data/lib/watobo/core/egress_handlers.rb +98 -0
- data/lib/watobo/core/finding.rb +66 -75
- data/lib/watobo/core/findings.rb +107 -114
- data/lib/watobo/core/forwarding_proxy.rb +13 -22
- data/lib/watobo/core/fuzz_gen.rb +0 -9
- data/lib/watobo/core/intercept_carver.rb +166 -177
- data/lib/watobo/core/intercept_filter.rb +235 -244
- data/lib/watobo/core/interceptor.rb +98 -107
- data/lib/watobo/core/min_class.rb +4 -13
- data/lib/watobo/core/netfilter_queue.rb +170 -179
- data/lib/watobo/core/ott_cache.rb +132 -141
- data/lib/watobo/core/parameter.rb +43 -52
- data/lib/watobo/core/passive_check.rb +103 -102
- data/lib/watobo/core/passive_checks.rb +48 -57
- data/lib/watobo/core/passive_scanner.rb +54 -55
- data/lib/watobo/core/plugin.rb +11 -20
- data/lib/watobo/core/project.rb +3 -9
- data/lib/watobo/core/proxy.rb +43 -52
- data/lib/watobo/core/request.rb +125 -123
- data/lib/watobo/core/response.rb +44 -53
- data/lib/watobo/core/scanner.rb +0 -9
- data/lib/watobo/core/scanner3.rb +405 -414
- data/lib/watobo/core/scope.rb +83 -92
- data/lib/watobo/core/session.rb +1043 -1026
- data/lib/watobo/core/sid_cache.rb +98 -107
- data/lib/watobo/core/subscriber.rb +25 -34
- data/lib/watobo/defaults.rb +21 -30
- data/lib/watobo/external/diff/lcs.rb +0 -9
- data/lib/watobo/external/diff/lcs/array.rb +0 -9
- data/lib/watobo/external/diff/lcs/block.rb +0 -9
- data/lib/watobo/external/diff/lcs/callbacks.rb +0 -9
- data/lib/watobo/external/diff/lcs/change.rb +0 -9
- data/lib/watobo/external/diff/lcs/hunk.rb +0 -9
- data/lib/watobo/external/diff/lcs/ldiff.rb +0 -9
- data/lib/watobo/external/diff/lcs/string.rb +0 -9
- data/lib/watobo/externals.rb +6 -15
- data/lib/watobo/framework.rb +4 -13
- data/lib/watobo/framework/create_project.rb +60 -69
- data/lib/watobo/framework/init.rb +0 -9
- data/lib/watobo/framework/init_modules.rb +0 -9
- data/lib/watobo/framework/license_text.rb +28 -37
- data/lib/watobo/framework/load_chat.rb +13 -22
- data/lib/watobo/gui.rb +132 -123
- data/lib/watobo/gui/about_watobo.rb +0 -9
- data/lib/watobo/gui/browser_preview.rb +0 -9
- data/lib/watobo/gui/certificate_dialog.rb +0 -9
- data/lib/watobo/gui/chat_diff.rb +0 -9
- data/lib/watobo/gui/chatviewer_frame.rb +73 -72
- data/lib/watobo/gui/checkboxtree.rb +0 -9
- data/lib/watobo/gui/checks_policy_frame.rb +0 -9
- data/lib/watobo/gui/client_cert_dialog.rb +96 -87
- data/lib/watobo/gui/confirm_scan_dialog.rb +0 -9
- data/lib/watobo/gui/conversation_table.rb +158 -164
- data/lib/watobo/gui/conversation_table_ctrl.rb +207 -216
- data/lib/watobo/gui/conversation_table_ctrl2.rb +373 -382
- data/lib/watobo/gui/csrf_token_dialog.rb +0 -9
- data/lib/watobo/gui/custom_viewer.rb +374 -383
- data/lib/watobo/gui/dashboard.rb +296 -303
- data/lib/watobo/gui/define_scope_frame.rb +0 -9
- data/lib/watobo/gui/differ_frame.rb +215 -224
- data/lib/watobo/gui/edit_comment.rb +0 -9
- data/lib/watobo/gui/edit_scope_dialog.rb +0 -9
- data/lib/watobo/gui/export_dialog.rb +104 -113
- data/lib/watobo/gui/finding_info.rb +0 -9
- data/lib/watobo/gui/findings_tree.rb +210 -217
- data/lib/watobo/gui/full_scan_dialog.rb +0 -9
- data/lib/watobo/gui/fuzzer_gui.rb +1295 -1313
- data/lib/watobo/gui/fxsave_thread.rb +14 -0
- data/lib/watobo/gui/goto_url_dialog.rb +70 -79
- data/lib/watobo/gui/hex_viewer.rb +0 -9
- data/lib/watobo/gui/html_viewer.rb +287 -296
- data/lib/watobo/gui/intercept_filter_dialog.rb +188 -197
- data/lib/watobo/gui/interceptor_gui.rb +1041 -1051
- data/lib/watobo/gui/interceptor_settings_dialog.rb +0 -9
- data/lib/watobo/gui/json_viewer.rb +287 -0
- data/lib/watobo/gui/list_box.rb +101 -110
- data/lib/watobo/gui/log_file_viewer.rb +32 -41
- data/lib/watobo/gui/log_viewer.rb +83 -88
- data/lib/watobo/gui/login_wizzard.rb +0 -9
- data/lib/watobo/gui/main_window.rb +587 -618
- data/lib/watobo/gui/manual_request_editor.rb +620 -565
- data/lib/watobo/gui/master_pw_dialog.rb +0 -9
- data/lib/watobo/gui/mixins/gui_settings.rb +29 -38
- data/lib/watobo/gui/page_tree.rb +217 -226
- data/lib/watobo/gui/password_policy_dialog.rb +0 -9
- data/lib/watobo/gui/plugin_board.rb +0 -9
- data/lib/watobo/gui/preferences_dialog.rb +0 -9
- data/lib/watobo/gui/progress_window.rb +17 -27
- data/lib/watobo/gui/project_wizzard.rb +0 -9
- data/lib/watobo/gui/proxy_dialog.rb +1 -10
- data/lib/watobo/gui/quick_scan_dialog.rb +0 -9
- data/lib/watobo/gui/request_builder_frame.rb +102 -111
- data/lib/watobo/gui/request_editor.rb +181 -137
- data/lib/watobo/gui/rewrite_filters_dialog.rb +394 -403
- data/lib/watobo/gui/rewrite_rules_dialog.rb +372 -381
- data/lib/watobo/gui/save_chat_dialog.rb +140 -149
- data/lib/watobo/gui/scanner_settings_dialog.rb +0 -9
- data/lib/watobo/gui/select_chat_dialog.rb +0 -9
- data/lib/watobo/gui/session_management_dialog.rb +0 -9
- data/lib/watobo/gui/sites_tree.rb +0 -9
- data/lib/watobo/gui/status_bar.rb +0 -9
- data/lib/watobo/gui/table_editor.rb +0 -9
- data/lib/watobo/gui/tagless_viewer.rb +0 -9
- data/lib/watobo/gui/templates/plugin.rb +0 -9
- data/lib/watobo/gui/templates/plugin2.rb +92 -100
- data/lib/watobo/gui/templates/plugin_base.rb +144 -153
- data/lib/watobo/gui/text_viewer.rb +0 -9
- data/lib/watobo/gui/transcoder_window.rb +0 -9
- data/lib/watobo/gui/utils/gui_utils.rb +0 -9
- data/lib/watobo/gui/utils/init_icons.rb +86 -95
- data/lib/watobo/gui/utils/load_icons.rb +33 -42
- data/lib/watobo/gui/utils/load_plugins.rb +116 -119
- data/lib/watobo/gui/utils/master_password.rb +68 -77
- data/lib/watobo/gui/utils/save_default_settings.rb +113 -122
- data/lib/watobo/gui/utils/save_project_settings.rb +0 -9
- data/lib/watobo/gui/utils/save_proxy_settings.rb +41 -50
- data/lib/watobo/gui/utils/save_scanner_settings.rb +18 -27
- data/lib/watobo/gui/utils/session_history.rb +112 -121
- data/lib/watobo/gui/workspace_dialog.rb +0 -9
- data/lib/watobo/gui/www_auth_dialog.rb +0 -9
- data/lib/watobo/gui/xml_viewer_frame.rb +0 -9
- data/lib/watobo/http.rb +4 -13
- data/lib/watobo/http/cookies/cookies.rb +26 -35
- data/lib/watobo/http/data/data.rb +45 -54
- data/lib/watobo/http/data/json.rb +47 -55
- data/lib/watobo/http/url/url.rb +38 -47
- data/lib/watobo/http/xml/xml.rb +124 -130
- data/lib/watobo/interceptor.rb +3 -12
- data/lib/watobo/interceptor/proxy.rb +742 -739
- data/lib/watobo/interceptor/transparent.rb +22 -24
- data/lib/watobo/mixins.rb +10 -19
- data/lib/watobo/mixins/check_info.rb +27 -36
- data/lib/watobo/mixins/httpparser.rb +613 -637
- data/lib/watobo/mixins/request_parser.rb +88 -97
- data/lib/watobo/mixins/shapers.rb +515 -529
- data/lib/watobo/mixins/transcoders.rb +3 -11
- data/lib/watobo/parser.rb +1 -10
- data/lib/watobo/parser/html.rb +83 -92
- data/lib/watobo/patch_fxruby_setfocus.rb +26 -0
- data/lib/watobo/sockets.rb +3 -12
- data/lib/watobo/sockets/agent.rb +828 -837
- data/lib/watobo/sockets/client_socket.rb +308 -312
- data/lib/watobo/sockets/connection.rb +401 -410
- data/lib/watobo/sockets/http_socket.rb +11 -13
- data/lib/watobo/sockets/ntlm_auth.rb +129 -138
- data/lib/watobo/utils.rb +10 -19
- data/lib/watobo/utils/check_regex.rb +0 -9
- data/lib/watobo/utils/copy_object.rb +0 -9
- data/lib/watobo/utils/crypto.rb +0 -9
- data/lib/watobo/utils/expand_range.rb +23 -32
- data/lib/watobo/utils/export_xml.rb +97 -106
- data/lib/watobo/utils/file_management.rb +9 -11
- data/lib/watobo/utils/hexprint.rb +9 -18
- data/lib/watobo/utils/load_chat.rb +0 -9
- data/lib/watobo/utils/load_icon.rb +0 -9
- data/lib/watobo/utils/ntlm.rb +866 -875
- data/lib/watobo/utils/print_debug.rb +12 -21
- data/lib/watobo/utils/response_builder.rb +90 -99
- data/lib/watobo/utils/response_hash.rb +0 -9
- data/lib/watobo/utils/secure_eval.rb +0 -9
- data/lib/watobo/utils/strings.rb +10 -19
- data/lib/watobo/utils/text2request.rb +0 -9
- data/lib/watobo/utils/url.rb +23 -32
- data/lib/watobo/utils/utf16.rb +11 -20
- data/modules/active/Apache/mod_status.rb +0 -9
- data/modules/active/Apache/multiview.rb +151 -160
- data/modules/active/Flash/crossdomain.rb +0 -9
- data/modules/active/JWT/jwt_oauth2_none.rb +111 -0
- data/modules/active/cq5/cq5_default_selectors.rb +106 -115
- data/modules/active/cq5/cqp_user_enumeration.rb +125 -134
- data/modules/active/directories/dirwalker.rb +0 -9
- data/modules/active/discovery/fileextensions.rb +0 -9
- data/modules/active/discovery/http_methods.rb +0 -9
- data/modules/active/discovery/jsmapfiles.rb +79 -0
- data/modules/active/domino/domino_db.rb +68 -76
- data/modules/active/dotNET/custom_errors.rb +102 -111
- data/modules/active/dotNET/dotnet_files.rb +90 -99
- data/modules/active/fileinclusion/lfi_simple.rb +0 -9
- data/modules/active/jboss/jboss_basic.rb +0 -9
- data/modules/active/sap/business_objects.rb +51 -60
- data/modules/active/sap/its_commands.rb +0 -9
- data/modules/active/sap/its_service_parameter.rb +0 -9
- data/modules/active/sap/its_services.rb +0 -9
- data/modules/active/sap/its_xss.rb +0 -9
- data/modules/active/shell_shock/shell_shock.rb +139 -148
- data/modules/active/siebel/siebel_apps.rb +160 -169
- data/modules/active/sqlinjection/sql_boolean.rb +0 -9
- data/modules/active/sqlinjection/sql_numerical.rb +198 -0
- data/modules/active/sqlinjection/sqli_error.rb +0 -9
- data/modules/active/sqlinjection/sqli_timing.rb +220 -229
- data/modules/active/struts2/default_handler_ognl.rb +106 -115
- data/modules/active/struts2/include_params_ognl.rb +105 -114
- data/modules/active/xml/xml_xxe.rb +112 -123
- data/modules/active/xss/xss_ng.rb +214 -223
- data/modules/active/xss/xss_simple.rb +0 -9
- data/modules/passive/ajax.rb +68 -77
- data/modules/passive/autocomplete.rb +56 -65
- data/modules/passive/cookie_options.rb +0 -9
- data/modules/passive/cookie_xss.rb +0 -9
- data/modules/passive/detect_code.rb +0 -9
- data/modules/passive/detect_fileupload.rb +0 -9
- data/modules/passive/detect_infrastructure.rb +0 -9
- data/modules/passive/detect_one_time_tokens.rb +0 -9
- data/modules/passive/dirindexing.rb +0 -9
- data/modules/passive/disclosure_domino.rb +55 -64
- data/modules/passive/disclosure_emails.rb +0 -9
- data/modules/passive/disclosure_ipaddr.rb +55 -53
- data/modules/passive/filename_as_parameter.rb +0 -9
- data/modules/passive/form_spotter.rb +0 -9
- data/modules/passive/hidden_fields.rb +50 -59
- data/modules/passive/hotspots.rb +0 -9
- data/modules/passive/in_script_parameter.rb +0 -9
- data/modules/passive/json_web_token.rb +93 -0
- data/modules/passive/multiple_server_headers.rb +0 -9
- data/modules/passive/possible_login.rb +0 -9
- data/modules/passive/redirect_url.rb +0 -9
- data/modules/passive/redirectionz.rb +0 -9
- data/modules/passive/sap-headers.rb +56 -65
- data/modules/passive/xss_dom.rb +0 -9
- data/plugins/aem/aem.rb +11 -20
- data/plugins/aem/gui/main.rb +118 -127
- data/plugins/aem/gui/tree_view.rb +171 -180
- data/plugins/aem/lib/agent.rb +130 -138
- data/plugins/aem/lib/dispatcher.rb +45 -51
- data/plugins/aem/lib/engine.rb +177 -186
- data/plugins/catalog/catalog.rb +345 -355
- data/plugins/crawler/crawler.rb +4 -13
- data/plugins/crawler/gui.rb +5 -14
- data/plugins/crawler/gui/auth_frame.rb +270 -279
- data/plugins/crawler/gui/crawler_gui.rb +271 -276
- data/plugins/crawler/gui/general_settings_frame.rb +96 -105
- data/plugins/crawler/gui/hooks_frame.rb +80 -89
- data/plugins/crawler/gui/scope_frame.rb +50 -59
- data/plugins/crawler/gui/settings_tabbook.rb +38 -47
- data/plugins/crawler/gui/status_frame.rb +59 -68
- data/plugins/crawler/lib/bags.rb +18 -27
- data/plugins/crawler/lib/constants.rb +11 -20
- data/plugins/crawler/lib/engine.rb +488 -497
- data/plugins/crawler/lib/grabber.rb +68 -77
- data/plugins/crawler/lib/status.rb +71 -80
- data/plugins/crawler/lib/uri_mp.rb +12 -21
- data/plugins/filefinder/filefinder.rb +326 -333
- data/plugins/sqlmap/bin/test.rb +78 -87
- data/plugins/sqlmap/gui.rb +4 -13
- data/plugins/sqlmap/gui/main.rb +218 -227
- data/plugins/sqlmap/gui/options_frame.rb +97 -106
- data/plugins/sqlmap/lib/sqlmap_ctrl.rb +90 -100
- data/plugins/sqlmap/sqlmap.rb +2 -11
- data/plugins/sslchecker/cli/sslchecker_cli.rb +0 -9
- data/plugins/sslchecker/gui/cipher_table.rb +246 -254
- data/plugins/sslchecker/gui/gui.rb +258 -264
- data/plugins/sslchecker/gui/sslchecker.rb +4 -13
- data/plugins/sslchecker/lib/check.rb +127 -133
- data/plugins/wshell/gui/main.rb +119 -117
- data/plugins/wshell/lib/core.rb +38 -88
- data/plugins/wshell/wshell.rb +11 -20
- metadata +170 -164
data/plugins/catalog/catalog.rb
CHANGED
|
@@ -1,69 +1,60 @@
|
|
|
1
|
-
#.
|
|
2
|
-
# catalog.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
1
|
# @private
|
|
11
|
-
module Watobo#:nodoc: all
|
|
2
|
+
module Watobo #:nodoc: all
|
|
12
3
|
module Plugin
|
|
13
4
|
module Catalog
|
|
14
|
-
|
|
5
|
+
|
|
15
6
|
class About < FXDialogBox
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
7
|
+
def initialize(owner, text)
|
|
8
|
+
super(owner, "About Catalog-Scanner", :opts => DECOR_TITLE|DECOR_BORDER|DECOR_CLOSE|DECOR_RESIZE, :width => 400, :height => 300)
|
|
9
|
+
self.icon = Watobo::Gui::Icons::ICON_WATOBO
|
|
10
|
+
|
|
11
|
+
main = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_GROOVE, :padding => 0)
|
|
12
|
+
main.backColor = FXColor::White
|
|
13
|
+
|
|
14
|
+
about_txt = FXText.new(main, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP)
|
|
15
|
+
about_txt.editable = false
|
|
16
|
+
about_txt.disable
|
|
17
|
+
about_txt.setText text
|
|
18
|
+
about_txt.font = FXFont.new(getApp(), "courier", 12, FONTWEIGHT_BOLD)
|
|
19
|
+
about_txt.backColor = FXColor::White
|
|
20
|
+
|
|
21
|
+
bottom = FXHorizontalFrame.new(main, :opts => LAYOUT_FILL_X)
|
|
22
|
+
FXButton.new(bottom, "OK", :target => self, :selector => FXDialogBox::ID_ACCEPT, :opts => BUTTON_NORMAL|LAYOUT_RIGHT)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
35
26
|
class Check < Watobo::ActiveCheck
|
|
36
27
|
attr_writer :db_files
|
|
37
28
|
attr_writer :var_files
|
|
38
29
|
attr_writer :path
|
|
39
|
-
|
|
30
|
+
|
|
40
31
|
@info.update(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
32
|
+
:check_name => 'Catalog-Scan', # name of check which briefly describes functionality, will be used for tree and progress views
|
|
33
|
+
:description => "Using catalog databases for testing the web application.", # description of checkfunction
|
|
34
|
+
:author => "Andreas Schmidt", # author of check
|
|
35
|
+
:version => "1.0" # check version
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
@finding.update(
|
|
39
|
+
:threat => 'catalog db finding', # thread of vulnerability, e.g. loss of information
|
|
40
|
+
:class => "Catalog", # vulnerability class, e.g. Stored XSS, SQL-Injection, ...
|
|
41
|
+
:type => FINDING_TYPE_VULN, # FINDING_TYPE_HINT, FINDING_TYPE_INFO, FINDING_TYPE_VULN
|
|
42
|
+
:rating => VULN_RATING_LOW
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
55
46
|
def loadVars(path)
|
|
56
47
|
dbpath = Dir.getwd
|
|
57
48
|
dbpath = path if not path.nil?
|
|
58
49
|
@dbvars.clear
|
|
59
50
|
@var_files.each do |file|
|
|
60
51
|
# puts "* loading var-file #{file}"
|
|
61
|
-
fname = File.join(
|
|
52
|
+
fname = File.join(dbpath, file)
|
|
62
53
|
if File.exists?(fname)
|
|
63
54
|
File.open(fname) { |fh|
|
|
64
55
|
fh.each do |line|
|
|
65
56
|
if line.strip =~ /^[^#]/ and line =~ /=/
|
|
66
|
-
key,vars = line.split("=")
|
|
57
|
+
key, vars = line.split("=")
|
|
67
58
|
key.strip!
|
|
68
59
|
|
|
69
60
|
@dbvars[key] = vars.strip.split(" ")
|
|
@@ -75,7 +66,7 @@ module Watobo#:nodoc: all
|
|
|
75
66
|
end
|
|
76
67
|
# puts "* db vars total: #{@dbvars.length}"
|
|
77
68
|
end
|
|
78
|
-
@dbvars["@RFIURL"] = [
|
|
69
|
+
@dbvars["@RFIURL"] = ["http://cirt.net/rfiinc.txt"] unless @dbvars.has_key? "@RFIURL"
|
|
79
70
|
end
|
|
80
71
|
|
|
81
72
|
def loadDBFiles(path, *opts)
|
|
@@ -85,19 +76,19 @@ module Watobo#:nodoc: all
|
|
|
85
76
|
|
|
86
77
|
@db_files.each do |file|
|
|
87
78
|
# puts "* loading db file #{file}.."
|
|
88
|
-
fname = File.join(
|
|
79
|
+
fname = File.join(dbpath, file)
|
|
89
80
|
if File.exists?(fname)
|
|
90
81
|
File.open(fname) { |fh|
|
|
91
82
|
fh.each do |line|
|
|
92
|
-
next if line.strip =~ /^#/
|
|
83
|
+
next if line.strip =~ /^#/
|
|
93
84
|
fields = line.split("\",")
|
|
94
|
-
fields.map!{ |f| f.gsub!(/^"/,'') }
|
|
95
|
-
fields.first.gsub!(/^\"/,"")
|
|
96
|
-
fields.last.gsub!(/\"?/,"")
|
|
85
|
+
fields.map! { |f| f.gsub!(/^"/, '') }
|
|
86
|
+
fields.first.gsub!(/^\"/, "")
|
|
87
|
+
fields.last.gsub!(/\"?/, "")
|
|
97
88
|
@catalog_checks.push fields
|
|
98
89
|
end
|
|
99
90
|
}
|
|
100
|
-
|
|
91
|
+
else
|
|
101
92
|
puts "* file (#{fname}) does not exist. Please check path and name."
|
|
102
93
|
end
|
|
103
94
|
end
|
|
@@ -112,24 +103,26 @@ module Watobo#:nodoc: all
|
|
|
112
103
|
dummy = []
|
|
113
104
|
pattern = nil
|
|
114
105
|
count = 0
|
|
115
|
-
@dbvars.each_key do |k|
|
|
106
|
+
@dbvars.each_key do |k|
|
|
107
|
+
dummy << k;
|
|
108
|
+
end
|
|
116
109
|
pattern = "(#{dummy.join("|")})" if dummy.length > 0
|
|
117
110
|
@catalog_checks.each do |dbid, osvdb, threat, uri, method, match, or_match, and_match, fail, or_fail, summary, post_data, headers|
|
|
118
|
-
|
|
119
|
-
|
|
111
|
+
next if uri =~ /\/$/
|
|
112
|
+
@catalog_checks << [dbid, osvdb, threat, "#{uri}/", method, match, or_match, and_match, fail, or_fail, summary, post_data, headers]
|
|
120
113
|
end
|
|
121
114
|
@catalog_checks.each do |dbid, osvdb, threat, uri, method, match, or_match, and_match, fail, or_fail, summary, post_data, headers|
|
|
122
115
|
|
|
123
116
|
if pattern and uri =~ /(#{pattern})/
|
|
124
117
|
key = $1
|
|
125
118
|
@dbvars[key].each do |v|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
119
|
+
new_uri = uri.gsub(/#{key}/, v)
|
|
120
|
+
if new_uri =~ /#{pattern}/
|
|
121
|
+
@catalog_checks << [dbid, osvdb, threat, new_uri, method, match, or_match, and_match, fail, or_fail, summary, post_data, headers]
|
|
122
|
+
else
|
|
123
|
+
yield dbid, osvdb, threat, new_uri, method, match, or_match, and_match, fail, or_fail, summary, post_data, headers
|
|
124
|
+
end
|
|
125
|
+
|
|
133
126
|
end
|
|
134
127
|
else
|
|
135
128
|
yield dbid, osvdb, threat, uri, method, match, or_match, and_match, fail, or_fail, summary, post_data, headers
|
|
@@ -141,12 +134,10 @@ module Watobo#:nodoc: all
|
|
|
141
134
|
end
|
|
142
135
|
end
|
|
143
136
|
|
|
144
|
-
|
|
145
137
|
|
|
146
138
|
def initialize(project)
|
|
147
139
|
super(project, project.getScanPreferences())
|
|
148
140
|
|
|
149
|
-
|
|
150
141
|
|
|
151
142
|
@path = nil
|
|
152
143
|
|
|
@@ -157,9 +148,9 @@ module Watobo#:nodoc: all
|
|
|
157
148
|
@db_files = %w( db_tests )
|
|
158
149
|
@var_files = %w( db_variables )
|
|
159
150
|
|
|
160
|
-
@threat_list = [
|
|
161
|
-
|
|
162
|
-
|
|
151
|
+
@threat_list = ["File Upload", "Interesting File", "Misconfiguration", "Information Disclosure", "Injection (XSS/Script/HTML)",
|
|
152
|
+
"Remote File Retrieval", "Denial of Service", "Remote File Retrieval", "Command Execution", "SQL Injection",
|
|
153
|
+
"Authentication Bypass", "Software Identification", "Remote source inclusion"]
|
|
163
154
|
|
|
164
155
|
end
|
|
165
156
|
|
|
@@ -174,9 +165,9 @@ module Watobo#:nodoc: all
|
|
|
174
165
|
checker = proc {
|
|
175
166
|
test_request = nil
|
|
176
167
|
test_response = nil
|
|
177
|
-
|
|
168
|
+
|
|
178
169
|
test = chat.copyRequest
|
|
179
|
-
test.replaceFileExt(uri.gsub(/^\//,''))
|
|
170
|
+
test.replaceFileExt(uri.gsub(/^\//, ''))
|
|
180
171
|
|
|
181
172
|
if method !~ /get/i then
|
|
182
173
|
test.replaceMethod(method)
|
|
@@ -185,16 +176,16 @@ module Watobo#:nodoc: all
|
|
|
185
176
|
if method =~ /post/i then
|
|
186
177
|
test.addHeader("Content-Length", "0")
|
|
187
178
|
end
|
|
188
|
-
|
|
179
|
+
|
|
189
180
|
status, test_request, test_response = fileExists?(test, :default => true)
|
|
190
|
-
|
|
191
|
-
|
|
181
|
+
|
|
182
|
+
|
|
192
183
|
unless test_request.nil? or test_response.nil? then
|
|
193
184
|
test_result = false
|
|
194
185
|
response = test_response.join
|
|
195
186
|
if status == true
|
|
196
|
-
|
|
197
|
-
if (
|
|
187
|
+
|
|
188
|
+
if ((match.empty? and or_match.empty?) or (match != "" and response =~ /#{Regexp.quote(match)}/i) or (or_match != "" and response =~ /#{Regexp.quote(or_match)}/i)) then
|
|
198
189
|
test_result = true
|
|
199
190
|
# if match contains only 3 numbers we assume that the response code should be checked
|
|
200
191
|
if match.strip =~ /^\d{3}$/
|
|
@@ -211,19 +202,19 @@ module Watobo#:nodoc: all
|
|
|
211
202
|
|
|
212
203
|
if test_result then
|
|
213
204
|
path = test_request.path
|
|
214
|
-
addFinding(
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
205
|
+
addFinding(test_request, test_response,
|
|
206
|
+
:test_item => uri,
|
|
207
|
+
:proof_pattern => "#{Regexp.quote(match)}",
|
|
208
|
+
:check_pattern => "#{Regexp.quote(uri)}",
|
|
209
|
+
:chat => chat,
|
|
210
|
+
:threat => "#{summary}",
|
|
211
|
+
:title => "[#{uri}] - #{path}"
|
|
221
212
|
|
|
222
213
|
)
|
|
223
214
|
end
|
|
224
215
|
end
|
|
225
216
|
end
|
|
226
|
-
[
|
|
217
|
+
[test_request, test_response]
|
|
227
218
|
}
|
|
228
219
|
yield checker
|
|
229
220
|
end
|
|
@@ -235,85 +226,85 @@ module Watobo#:nodoc: all
|
|
|
235
226
|
end
|
|
236
227
|
|
|
237
228
|
class Catalog < Watobo::Template::Plugin
|
|
238
|
-
|
|
229
|
+
|
|
239
230
|
include Watobo::Constants
|
|
240
|
-
|
|
231
|
+
|
|
241
232
|
def updateView()
|
|
242
233
|
@sites_combo.clearItems()
|
|
243
234
|
@dir_combo.clearItems()
|
|
244
235
|
@dir_combo.disable
|
|
245
236
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
end
|
|
261
|
-
@sites_combo.appendItem(site_string, site)
|
|
237
|
+
|
|
238
|
+
@sites_combo.appendItem("no site selected", nil)
|
|
239
|
+
scope_only = Watobo::Scope.exist?
|
|
240
|
+
sites = Watobo::Chats.sites(:in_scope => Watobo::Scope.exist?)
|
|
241
|
+
if sites.empty?
|
|
242
|
+
scope_only = false
|
|
243
|
+
@log_viewer.log(LOG_INFO, "Defined scope does not match one site. Using all sites.")
|
|
244
|
+
end
|
|
245
|
+
Watobo::Chats.sites(:in_scope => scope_only).each do |site|
|
|
246
|
+
site_string = site
|
|
247
|
+
if site.length > 60
|
|
248
|
+
site_string = site.slice(0..55)
|
|
249
|
+
site_string << "...:"
|
|
250
|
+
site_string << site.gsub(/.*:/, '')
|
|
262
251
|
end
|
|
263
|
-
@sites_combo.
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
@dir_combo.enable
|
|
272
|
-
Watobo::Chats.dirs(site) do |dir|
|
|
273
|
-
puts dir
|
|
274
|
-
@dir_combo.appendItem(dir.slice(0..35), dir)
|
|
275
|
-
end
|
|
276
|
-
@dir_combo.setCurrentItem(0, true) if @dir_combo.numItems > 0
|
|
252
|
+
@sites_combo.appendItem(site_string, site)
|
|
253
|
+
end
|
|
254
|
+
@sites_combo.numVisible = @sites_combo.numItems >= 20 ? 20 : @sites_combo.numItems
|
|
255
|
+
@sites_combo.setCurrentItem(0) if @sites_combo.numItems > 0
|
|
256
|
+
ci = @sites_combo.currentItem
|
|
257
|
+
site = (ci >= 0) ? @sites_combo.getItemData(ci) : nil
|
|
258
|
+
puts site
|
|
259
|
+
puts site.class
|
|
277
260
|
|
|
261
|
+
unless site.nil?
|
|
262
|
+
@dir_combo.enable
|
|
263
|
+
Watobo::Chats.dirs(site) do |dir|
|
|
264
|
+
puts dir
|
|
265
|
+
@dir_combo.appendItem(dir.slice(0..35), dir)
|
|
278
266
|
end
|
|
279
|
-
|
|
267
|
+
@dir_combo.setCurrentItem(0, true) if @dir_combo.numItems > 0
|
|
268
|
+
|
|
269
|
+
end
|
|
270
|
+
|
|
280
271
|
end
|
|
281
272
|
|
|
282
273
|
def initialize(owner, project)
|
|
283
|
-
|
|
284
|
-
super(owner, "Catalog Scanner", project, :opts => DECOR_ALL, :width=>800, :height=>600)
|
|
274
|
+
|
|
275
|
+
super(owner, "Catalog Scanner", project, :opts => DECOR_ALL, :width => 800, :height => 600)
|
|
285
276
|
menu_bar = FXMenuBar.new(self, :opts => LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_GROOVE)
|
|
286
277
|
menu_pane = FXMenuPane.new(self)
|
|
287
|
-
|
|
278
|
+
|
|
288
279
|
text = "Catalog-Scanner will test the web application for known directories and/or files.\nYou need two files (db_tests and db_variables) in the DB folder. "
|
|
289
280
|
text << "These files must have the same format as nikto DB files (http://cirt.net/nikto2).\nSo, if you have your own DB files, you"
|
|
290
281
|
text << " can use them with this plugin."
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
282
|
+
|
|
283
|
+
load_icon(__FILE__)
|
|
284
|
+
|
|
285
|
+
FXMenuTitle.new(menu_bar, "Help", :popupMenu => menu_pane)
|
|
286
|
+
menu = FXMenuCommand.new(menu_pane, "About")
|
|
287
|
+
menu.connect(SEL_COMMAND) {
|
|
288
|
+
dlg = Watobo::Plugin::Catalog::About.new(self, text)
|
|
289
|
+
dlg.execute
|
|
299
290
|
}
|
|
300
291
|
|
|
301
292
|
@event_dispatcher_listeners = Hash.new
|
|
302
293
|
@scanner = nil
|
|
303
294
|
@plugin_name = "Catalog-Scan"
|
|
304
|
-
|
|
295
|
+
|
|
305
296
|
@site = nil
|
|
306
297
|
@dir = nil
|
|
307
298
|
|
|
308
299
|
begin
|
|
309
300
|
hs_green = FXHiliteStyle.new
|
|
310
|
-
hs_green.normalForeColor = FXRGBA(255,255,255,255) #FXColor::Red
|
|
311
|
-
hs_green.normalBackColor = FXRGBA(0,255,0,1)
|
|
301
|
+
hs_green.normalForeColor = FXRGBA(255, 255, 255, 255) #FXColor::Red
|
|
302
|
+
hs_green.normalBackColor = FXRGBA(0, 255, 0, 1) # FXColor::White
|
|
312
303
|
hs_green.style = FXText::STYLE_BOLD
|
|
313
304
|
|
|
314
305
|
hs_red = FXHiliteStyle.new
|
|
315
|
-
hs_red.normalForeColor = FXRGBA(255,255,255,255) # FXColor::Red
|
|
316
|
-
hs_red.normalBackColor = FXRGBA(255,0,0,1)
|
|
306
|
+
hs_red.normalForeColor = FXRGBA(255, 255, 255, 255) # FXColor::Red
|
|
307
|
+
hs_red.normalBackColor = FXRGBA(255, 0, 0, 1) # FXColor::White
|
|
317
308
|
hs_red.style = FXText::STYLE_BOLD
|
|
318
309
|
|
|
319
310
|
path = Dir.getwd
|
|
@@ -321,36 +312,36 @@ module Watobo#:nodoc: all
|
|
|
321
312
|
mr_splitter = FXSplitter.new(self, LAYOUT_FILL_X|LAYOUT_FILL_Y|SPLITTER_VERTICAL|SPLITTER_REVERSED|SPLITTER_TRACKING)
|
|
322
313
|
# top = FXHorizontalFrame.new(mr_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_SIDE_BOTTOM)
|
|
323
314
|
top_frame = FXVerticalFrame.new(mr_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_FIX_HEIGHT|LAYOUT_BOTTOM, :height => 500)
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
315
|
+
# info_frame = FXGroupBox.new(top_frame, "Info", LAYOUT_SIDE_TOP|FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 0)
|
|
316
|
+
# info = FXText.new(info_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP)
|
|
317
|
+
# info.setText text
|
|
318
|
+
# info.backColor = info.parent.backColor
|
|
319
|
+
# info.disable
|
|
329
320
|
top_splitter = FXSplitter.new(top_frame, LAYOUT_FILL_X|SPLITTER_HORIZONTAL|LAYOUT_FILL_Y|SPLITTER_TRACKING)
|
|
330
|
-
log_frame = FXVerticalFrame.new(mr_splitter, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM
|
|
321
|
+
log_frame = FXVerticalFrame.new(mr_splitter, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_BOTTOM, :height => 100)
|
|
331
322
|
|
|
332
323
|
@settings_frame = FXVerticalFrame.new(top_splitter, :opts => LAYOUT_FILL_Y, :padding => 0)
|
|
333
324
|
#request_frame = FXVerticalFrame.new(top_splitter, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
334
|
-
|
|
335
|
-
|
|
325
|
+
request_frame = FXGroupBox.new(top_splitter, "Request Template", LAYOUT_SIDE_TOP|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
326
|
+
FXLabel.new(request_frame, "Select a request template from drop-down list or enter manually.")
|
|
336
327
|
@requestCombo = FXComboBox.new(request_frame, 5, nil, 0,
|
|
337
|
-
|
|
328
|
+
COMBOBOX_STATIC|FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
|
|
338
329
|
|
|
339
330
|
@requestCombo.numVisible = 0
|
|
340
331
|
@requestCombo.numColumns = 50
|
|
341
332
|
@requestCombo.editable = false
|
|
342
333
|
@requestCombo.connect(SEL_COMMAND, method(:onSelectRequest))
|
|
343
334
|
|
|
344
|
-
@request_editor = RequestEditor.new(request_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding=>0)
|
|
335
|
+
@request_editor = RequestEditor.new(request_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
|
|
345
336
|
|
|
346
337
|
ts_frame = FXGroupBox.new(@settings_frame, "Scan Settings", LAYOUT_SIDE_TOP|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
347
338
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
339
|
+
# @scope_only_cb = FXCheckButton.new(@settings_frame, "target scope only", nil, 0, ICON_BEFORE_TEXT|LAYOUT_SIDE_LEFT)
|
|
340
|
+
# @scope_only_cb.setCheck(false)
|
|
341
|
+
# @scope_only_cb.connect(SEL_COMMAND) { updateView() }
|
|
351
342
|
|
|
352
343
|
@sites_combo = FXComboBox.new(ts_frame, 5, nil, 0,
|
|
353
|
-
|
|
344
|
+
COMBOBOX_STATIC|FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
|
|
354
345
|
|
|
355
346
|
@sites_combo.numVisible = @sites_combo.numItems >= 20 ? 20 : @sites_combo.numItems
|
|
356
347
|
@sites_combo.numColumns = 35
|
|
@@ -359,7 +350,7 @@ module Watobo#:nodoc: all
|
|
|
359
350
|
|
|
360
351
|
FXLabel.new(ts_frame, "Root Directory:")
|
|
361
352
|
@dir_combo = FXComboBox.new(ts_frame, 5, nil, 0,
|
|
362
|
-
|
|
353
|
+
COMBOBOX_STATIC|FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
|
|
363
354
|
@dir_combo.numVisible = 20
|
|
364
355
|
@dir_combo.numColumns = 35
|
|
365
356
|
@dir_combo.editable = false
|
|
@@ -383,119 +374,119 @@ module Watobo#:nodoc: all
|
|
|
383
374
|
@scanlog_dir_text.backColor = FXColor::White
|
|
384
375
|
else
|
|
385
376
|
@scanlog_dir_text.enabled = false
|
|
386
|
-
@scanlog_dir_text.backColor = @scanlog_dir_text.parent.backColor
|
|
377
|
+
@scanlog_dir_text.backColor = @scanlog_dir_text.parent.backColor
|
|
387
378
|
end
|
|
388
379
|
end
|
|
389
380
|
|
|
390
381
|
@scanlog_dir_dt = FXDataTarget.new('')
|
|
391
|
-
|
|
392
|
-
@scanlog_dir_label = FXLabel.new(frame, "Scan Name:"
|
|
393
|
-
scanlog_frame = FXHorizontalFrame.new(frame
|
|
382
|
+
# @scanlog_dir_dt.value = @project.scanLogDirectory() if File.exist?(@project.scanLogDirectory())
|
|
383
|
+
@scanlog_dir_label = FXLabel.new(frame, "Scan Name:")
|
|
384
|
+
scanlog_frame = FXHorizontalFrame.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_TOP)
|
|
394
385
|
@scanlog_dir_text = FXTextField.new(scanlog_frame, 20,
|
|
395
|
-
|
|
396
|
-
|
|
386
|
+
:target => @scanlog_dir_dt, :selector => FXDataTarget::ID_VALUE,
|
|
387
|
+
:opts => TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X)
|
|
397
388
|
@scanlog_dir_text.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
398
389
|
unless @logScanChats.checked?
|
|
399
390
|
@scanlog_dir_text.enabled = false
|
|
400
391
|
@scanlog_dir_text.backColor = @scanlog_dir_text.parent.backColor
|
|
401
|
-
end
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
@db_files = %w( db_tests db_variables )
|
|
395
|
+
|
|
396
|
+
@path = File.expand_path(File.dirname(__FILE__))
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
@known_db_paths = [
|
|
400
|
+
# File.expand_path(File.dirname(__FILE__)),
|
|
401
|
+
# "/pentest/web/nikto/plugins" # BackTrack
|
|
402
|
+
@path
|
|
403
|
+
]
|
|
404
|
+
config = load_config
|
|
405
|
+
unless config.nil?
|
|
406
|
+
if config.has_key? :path_history
|
|
407
|
+
begin
|
|
408
|
+
config[:path_history].each do |p|
|
|
409
|
+
@known_db_paths << p unless @known_db_paths.include? p
|
|
410
|
+
end
|
|
411
|
+
rescue => bang
|
|
412
|
+
puts "!Broken Path History"
|
|
413
|
+
end
|
|
422
414
|
end
|
|
415
|
+
@path = config[:db_path] if config.has_key? :db_path
|
|
416
|
+
|
|
423
417
|
end
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
end
|
|
427
|
-
|
|
428
|
-
frame = FXGroupBox.new(@settings_frame, "DB Path", LAYOUT_SIDE_TOP|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
418
|
+
|
|
419
|
+
frame = FXGroupBox.new(@settings_frame, "DB Path", LAYOUT_SIDE_TOP|FRAME_GROOVE|LAYOUT_FILL_X, 0, 0, 0, 0)
|
|
429
420
|
#FXLabel.new(frame, "Path:" )
|
|
430
|
-
db_frame = FXHorizontalFrame.new(frame
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
421
|
+
db_frame = FXHorizontalFrame.new(frame, :opts => LAYOUT_FILL_X|LAYOUT_SIDE_TOP)
|
|
422
|
+
@db_path_combo = FXComboBox.new(db_frame, 5, nil, 0,
|
|
423
|
+
COMBOBOX_STATIC|FRAME_SUNKEN|FRAME_THICK|LAYOUT_SIDE_TOP|LAYOUT_FILL_X)
|
|
424
|
+
|
|
434
425
|
@db_path_combo.numVisible = 3
|
|
435
426
|
@db_path_combo.numColumns = 8
|
|
436
|
-
|
|
427
|
+
|
|
437
428
|
@db_path_combo.editable = false
|
|
438
|
-
@db_path_combo.connect(SEL_COMMAND){
|
|
429
|
+
@db_path_combo.connect(SEL_COMMAND) {
|
|
439
430
|
path = @db_path_combo.getItemData(@db_path_combo.currentItem)
|
|
440
431
|
set_db_path path
|
|
441
432
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
433
|
+
# @db_path_txt = FXTextField.new(db_frame, 20, nil, 0, :opts => TEXTFIELD_NORMAL|LAYOUT_FILL_COLUMN|LAYOUT_FILL_X)
|
|
434
|
+
# @db_path_txt.text = @path
|
|
435
|
+
# @db_path_txt.handle(self, FXSEL(SEL_UPDATE, 0), nil)
|
|
445
436
|
@db_path_btn = FXButton.new(db_frame, "add")
|
|
446
|
-
@db_path_btn.connect(SEL_COMMAND){
|
|
437
|
+
@db_path_btn.connect(SEL_COMMAND) {
|
|
447
438
|
select_db_path
|
|
448
439
|
# @db_path_txt.text = @path
|
|
449
|
-
|
|
440
|
+
}
|
|
450
441
|
#@check_buttons = Hash.new
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
path_index = 0
|
|
445
|
+
@known_db_paths.each_with_index do |dbp, i|
|
|
446
|
+
if File.exist? dbp
|
|
447
|
+
item = @db_path_combo.appendItem(dbp)
|
|
448
|
+
@db_path_combo.setItemData(item, dbp)
|
|
449
|
+
path_index = i if dbp == @path
|
|
450
|
+
end
|
|
451
|
+
end
|
|
452
|
+
|
|
462
453
|
#@db_path_combo.currentItem = path_index if @db_path_combo.numItems > 0
|
|
463
|
-
|
|
454
|
+
|
|
464
455
|
@pbar = FXProgressBar.new(@settings_frame, nil, 0, LAYOUT_FILL_X|FRAME_SUNKEN|FRAME_THICK|PROGRESSBAR_HORIZONTAL)
|
|
465
|
-
|
|
456
|
+
|
|
466
457
|
reset_pbar
|
|
467
|
-
|
|
458
|
+
|
|
468
459
|
@speed = FXLabel.new(@settings_frame, "Requests per second: 0")
|
|
469
460
|
|
|
470
461
|
@start_button = FXButton.new(@settings_frame, "start")
|
|
471
462
|
@start_button.connect(SEL_COMMAND, method(:start))
|
|
472
463
|
@start_button.disable
|
|
473
464
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
465
|
+
# gbox = FXGroupBox.new(@settings_frame, "Info", LAYOUT_SIDE_LEFT|FRAME_GROOVE|LAYOUT_FILL_X|LAYOUT_FILL_Y, 0, 0, 0, 150)
|
|
466
|
+
# gbframe = FXVerticalFrame.new(gbox, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0)
|
|
467
|
+
# fxtext = FXText.new(gbframe, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_WORDWRAP)
|
|
468
|
+
# fxtext.backColor = fxtext.parent.backColor
|
|
469
|
+
# fxtext.disable
|
|
470
|
+
# text = "Catalog-Scanner will test the web application for known directories and/or files. There must be two files in the appropriate plugin folder:\n"
|
|
471
|
+
# text << "- db_tests\n- db_variables\n\nThe format of these files is very similar to the format nikto (http://cirt.net/nikto2) is using. So if you have your own nikto.db-files, you"
|
|
472
|
+
# text << " can use them with this plugin."
|
|
473
|
+
# text << "\n\nCatalog Directory:\n#{File.dirname(__FILE__)}"
|
|
474
|
+
# fxtext.setText(text)
|
|
484
475
|
|
|
485
476
|
@check = nil
|
|
486
477
|
|
|
487
478
|
log_frame_header = FXHorizontalFrame.new(log_frame, :opts => LAYOUT_FILL_X)
|
|
488
|
-
FXLabel.new(log_frame_header, "Logs:"
|
|
489
|
-
|
|
479
|
+
FXLabel.new(log_frame_header, "Logs:")
|
|
480
|
+
|
|
490
481
|
puts "* create logviewer in catalog..."
|
|
491
482
|
|
|
492
483
|
#log_text_frame = FXHorizontalFrame.new(bottom_frame, :opts => LAYOUT_FILL_X|FRAME_SUNKEN|LAYOUT_BOTTOM)
|
|
493
|
-
log_text_frame = FXVerticalFrame.new(log_frame, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding=>0)
|
|
484
|
+
log_text_frame = FXVerticalFrame.new(log_frame, LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN|FRAME_THICK, :padding => 0)
|
|
494
485
|
@log_viewer = LogViewer.new(log_text_frame, nil, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y)
|
|
495
|
-
|
|
486
|
+
|
|
496
487
|
updateView()
|
|
497
488
|
start_update_timer()
|
|
498
|
-
|
|
489
|
+
|
|
499
490
|
rescue => bang
|
|
500
491
|
puts bang
|
|
501
492
|
puts bang.backtrace #if $DEBUG
|
|
@@ -503,7 +494,7 @@ module Watobo#:nodoc: all
|
|
|
503
494
|
end
|
|
504
495
|
|
|
505
496
|
def create
|
|
506
|
-
super
|
|
497
|
+
super # Create the windows
|
|
507
498
|
@log_viewer.purge_logs
|
|
508
499
|
@request_editor.setText('')
|
|
509
500
|
@requestCombo.clearItems()
|
|
@@ -513,17 +504,17 @@ module Watobo#:nodoc: all
|
|
|
513
504
|
show(PLACEMENT_SCREEN) # Make the main window appear
|
|
514
505
|
disableOptions()
|
|
515
506
|
@start_button.disable
|
|
516
|
-
|
|
507
|
+
|
|
517
508
|
updateView()
|
|
518
509
|
end
|
|
519
510
|
|
|
520
|
-
|
|
511
|
+
|
|
521
512
|
private
|
|
522
|
-
|
|
513
|
+
|
|
523
514
|
def reset_pbar
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
515
|
+
@pbar.progress = 0
|
|
516
|
+
@pbar.total = 0
|
|
517
|
+
@pbar.barColor = 'grey' #FXRGB(255,0,0)
|
|
527
518
|
end
|
|
528
519
|
|
|
529
520
|
def updateRequestEditor(chat=nil)
|
|
@@ -533,13 +524,13 @@ module Watobo#:nodoc: all
|
|
|
533
524
|
#@request_box.setText(chat)
|
|
534
525
|
request = chat.copyRequest
|
|
535
526
|
# request.replaceFileExt('')
|
|
536
|
-
@request_editor.setText(request.join.gsub(/\r/,""))
|
|
527
|
+
@request_editor.setText(request.join.gsub(/\r/, ""))
|
|
537
528
|
end
|
|
538
529
|
|
|
539
530
|
def createChat()
|
|
540
531
|
request = @request_editor.parseRequest()
|
|
541
|
-
|
|
542
|
-
|
|
532
|
+
# puts "[#{self}] - createChat:"
|
|
533
|
+
# puts request
|
|
543
534
|
chat = Watobo::Chat.new(request, [], :id => 0)
|
|
544
535
|
end
|
|
545
536
|
|
|
@@ -586,14 +577,14 @@ module Watobo#:nodoc: all
|
|
|
586
577
|
chats = Watobo::Chats.select(@site, :method => "GET")
|
|
587
578
|
updateRequestCombo(chats)
|
|
588
579
|
updateRequestEditor(chats.first)
|
|
589
|
-
|
|
580
|
+
|
|
590
581
|
Watobo::Chats.dirs(@site) do |dir|
|
|
591
582
|
text = "/" + dir #.slice(0..35)
|
|
592
583
|
text.gsub!(/\/+/, '/')
|
|
593
584
|
@dir_combo.appendItem(text, dir)
|
|
594
585
|
end
|
|
595
586
|
@dir_combo.setCurrentItem(0, true) if @dir_combo.numItems > 0
|
|
596
|
-
|
|
587
|
+
|
|
597
588
|
end
|
|
598
589
|
enableOptions()
|
|
599
590
|
@dir_combo.enable
|
|
@@ -627,7 +618,7 @@ module Watobo#:nodoc: all
|
|
|
627
618
|
end
|
|
628
619
|
end
|
|
629
620
|
end
|
|
630
|
-
|
|
621
|
+
|
|
631
622
|
def select_db_path(start_path = nil)
|
|
632
623
|
s_path = start_path.nil? ? @path : start_path
|
|
633
624
|
path = FXFileDialog.getOpenDirectory(self, "Select DB Path", s_path)
|
|
@@ -635,31 +626,31 @@ module Watobo#:nodoc: all
|
|
|
635
626
|
set_db_path(path)
|
|
636
627
|
end
|
|
637
628
|
end
|
|
638
|
-
|
|
629
|
+
|
|
639
630
|
def set_db_path(dbpath)
|
|
640
631
|
path = File.expand_path(dbpath)
|
|
641
632
|
if db_path?(path)
|
|
642
|
-
|
|
643
|
-
|
|
633
|
+
puts "New DB Path >> #{path}"
|
|
634
|
+
@path = path
|
|
644
635
|
@known_db_paths << @path unless @known_db_paths.include? @path
|
|
645
636
|
@start_button.enable
|
|
646
|
-
|
|
637
|
+
|
|
647
638
|
@db_path_combo.clearItems
|
|
648
|
-
@known_db_paths.each_with_index do |dbp,i|
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
639
|
+
@known_db_paths.each_with_index do |dbp, i|
|
|
640
|
+
if File.exist? dbp
|
|
641
|
+
item = @db_path_combo.appendItem(dbp)
|
|
642
|
+
@db_path_combo.setItemData(item, dbp)
|
|
643
|
+
path_index = i if dbp == @path
|
|
644
|
+
end
|
|
654
645
|
end
|
|
655
|
-
|
|
646
|
+
|
|
656
647
|
@db_path_combo.currentItem = @db_path_combo.numItems - 1
|
|
657
648
|
@db_path_combo.numVisible = @db_path_combo.numItems
|
|
658
|
-
|
|
649
|
+
|
|
659
650
|
save_config
|
|
660
651
|
else
|
|
661
|
-
|
|
662
|
-
|
|
652
|
+
@catalog_ready = false
|
|
653
|
+
@start_button.disable
|
|
663
654
|
end
|
|
664
655
|
end
|
|
665
656
|
|
|
@@ -676,7 +667,7 @@ module Watobo#:nodoc: all
|
|
|
676
667
|
|
|
677
668
|
ci = @dir_combo.currentItem
|
|
678
669
|
|
|
679
|
-
if ci > 0
|
|
670
|
+
if ci > 0 then
|
|
680
671
|
@dir = @dir_combo.getItemData(ci)
|
|
681
672
|
else
|
|
682
673
|
@dir = ""
|
|
@@ -691,74 +682,74 @@ module Watobo#:nodoc: all
|
|
|
691
682
|
@scanner.cancel() if @scanner
|
|
692
683
|
@scanner = nil
|
|
693
684
|
|
|
694
|
-
|
|
685
|
+
super
|
|
695
686
|
|
|
696
687
|
end
|
|
697
|
-
|
|
688
|
+
|
|
698
689
|
def db_path?(path)
|
|
699
690
|
@db_files.each do |file|
|
|
700
|
-
fname = File.join(
|
|
691
|
+
fname = File.join(path, file)
|
|
701
692
|
unless File.exists?(fname)
|
|
702
693
|
m = "WARNING: Missing catalog db file: #{fname}"
|
|
703
694
|
puts m
|
|
704
|
-
@log_viewer.log(
|
|
695
|
+
@log_viewer.log(LOG_INFO, m)
|
|
705
696
|
return false
|
|
706
697
|
end
|
|
707
|
-
|
|
698
|
+
|
|
708
699
|
end
|
|
709
|
-
|
|
700
|
+
|
|
710
701
|
return true
|
|
711
702
|
end
|
|
712
|
-
|
|
703
|
+
|
|
713
704
|
def save_config()
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
705
|
+
wd = Watobo.working_directory
|
|
706
|
+
|
|
707
|
+
dir_name = Watobo::Utils.snakecase self.class.to_s.gsub(/.*::/, '')
|
|
708
|
+
path = File.join(wd, "conf", "plugins")
|
|
709
|
+
Dir.mkdir path unless File.exist? path
|
|
710
|
+
conf_dir = File.join(path, dir_name)
|
|
711
|
+
Dir.mkdir conf_dir unless File.exist? conf_dir
|
|
712
|
+
file = File.join(conf_dir, dir_name + "_config.yml")
|
|
713
|
+
config = {
|
|
714
|
+
:db_path => @path,
|
|
715
|
+
:path_history => @known_db_paths
|
|
716
|
+
}
|
|
717
|
+
Watobo::Utils.save_settings(file, config)
|
|
718
|
+
end
|
|
728
719
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
720
|
+
def load_config()
|
|
721
|
+
wd = Watobo.working_directory
|
|
722
|
+
dir_name = Watobo::Utils.snakecase self.class.to_s.gsub(/.*::/, '')
|
|
723
|
+
path = File.join(wd, "conf", "plugins")
|
|
724
|
+
Dir.mkdir path unless File.exist? path
|
|
725
|
+
conf_dir = File.join(path, dir_name)
|
|
726
|
+
Dir.mkdir conf_dir unless File.exist? conf_dir
|
|
727
|
+
file = File.join(conf_dir, dir_name + "_config.yml")
|
|
728
|
+
config = Watobo::Utils.load_settings(file)
|
|
729
|
+
end
|
|
730
|
+
|
|
731
|
+
def start_update_timer
|
|
732
|
+
Watobo.save_thread {
|
|
733
|
+
unless @scanner.nil?
|
|
734
|
+
progress = @scanner.progress
|
|
735
|
+
sum_progress = progress.values.inject(0) { |i, v| i += v[:progress] }
|
|
736
|
+
@speed.text = "Checks per second: #{sum_progress - @pbar.progress}"
|
|
737
|
+
@pbar.progress = sum_progress
|
|
738
|
+
|
|
739
|
+
if @scanner.finished?
|
|
740
|
+
msg = "Scan Finished!"
|
|
741
|
+
@log_viewer.log(LOG_INFO, msg)
|
|
742
|
+
Watobo.log(msg, :sender => "Catalog")
|
|
743
|
+
@scanner.stop
|
|
744
|
+
@scanner = nil
|
|
745
|
+
reset_pbar()
|
|
746
|
+
|
|
747
|
+
@speed.text = "Requests per second: -"
|
|
748
|
+
@start_button.text = "Start"
|
|
749
|
+
end
|
|
758
750
|
end
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
end
|
|
751
|
+
}
|
|
752
|
+
end
|
|
762
753
|
|
|
763
754
|
def start(sender, sel, item)
|
|
764
755
|
if @start_button.text =~ /cancel/i then
|
|
@@ -766,83 +757,82 @@ module Watobo#:nodoc: all
|
|
|
766
757
|
@start_button.text = "Start"
|
|
767
758
|
reset_pbar
|
|
768
759
|
msg = "Scan Canceled By User"
|
|
769
|
-
|
|
770
|
-
|
|
760
|
+
Watobo.log(msg, :sender => "Catalog")
|
|
761
|
+
@log_viewer.log(LOG_INFO, msg)
|
|
771
762
|
return
|
|
772
763
|
end
|
|
773
764
|
|
|
774
765
|
if @logScanChats.checked?
|
|
775
766
|
if @scanlog_dir_dt.value.empty?
|
|
776
|
-
FXMessageBox.information(self,MBOX_OK,"Need Scan-Name", "Please provide a scan name!")
|
|
767
|
+
FXMessageBox.information(self, MBOX_OK, "Need Scan-Name", "Please provide a scan name!")
|
|
777
768
|
return false
|
|
778
769
|
end
|
|
779
|
-
end
|
|
780
|
-
|
|
770
|
+
end
|
|
771
|
+
|
|
781
772
|
@start_button.text = "Cancel"
|
|
782
773
|
|
|
783
774
|
|
|
784
775
|
@check = Check.new(Watobo.project)
|
|
785
|
-
|
|
776
|
+
|
|
786
777
|
@check.path = @path
|
|
787
778
|
|
|
788
779
|
chatlist = []
|
|
789
780
|
checklist = []
|
|
790
781
|
checklist.push @check
|
|
791
782
|
@check.resetCounters()
|
|
792
|
-
|
|
793
|
-
|
|
794
783
|
|
|
795
|
-
|
|
784
|
+
|
|
785
|
+
@log_viewer.log(LOG_INFO, "Starting ...")
|
|
796
786
|
puts "Site: #{@site}"
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
chat = createChat()
|
|
811
|
-
chat.request.replaceFileExt('')
|
|
812
|
-
chat.request.setDir(dir)
|
|
813
|
-
chatlist.push chat
|
|
814
|
-
|
|
815
|
-
@check.updateCounters(chat)
|
|
816
|
-
|
|
817
|
-
end
|
|
818
|
-
else
|
|
819
|
-
|
|
787
|
+
progressWindow = nil
|
|
788
|
+
# Thread.new(progressWindow){ |pw|
|
|
789
|
+
begin
|
|
790
|
+
c=1
|
|
791
|
+
if @test_all_dirs.checked? then
|
|
792
|
+
c = 0
|
|
793
|
+
Watobo::Chats.dirs(@site, :base_dir => @dir, :include_subdirs => @test_all_dirs.checked?) { c += 1 }
|
|
794
|
+
|
|
795
|
+
Watobo::Chats.dirs(@site, :base_dir => @dir, :include_subdirs => @test_all_dirs.checked?) do |dir|
|
|
796
|
+
msg = "running checks in #{@path} on #{@site} for /#{dir}"
|
|
797
|
+
puts msg
|
|
798
|
+
Watobo.log(msg, :sender => "Catalog")
|
|
799
|
+
@log_viewer.log(LOG_INFO, msg)
|
|
820
800
|
chat = createChat()
|
|
821
801
|
chat.request.replaceFileExt('')
|
|
822
|
-
|
|
802
|
+
chat.request.setDir(dir)
|
|
823
803
|
chatlist.push chat
|
|
804
|
+
|
|
824
805
|
@check.updateCounters(chat)
|
|
825
|
-
|
|
826
|
-
msg = "running checks in #{@path} on #{@site} for /#{chat.request.dir}"
|
|
827
|
-
puts msg
|
|
828
|
-
Watobo.log(msg, :sender => "Catalog")
|
|
829
|
-
@log_viewer.log(LOG_INFO, msg)
|
|
806
|
+
|
|
830
807
|
end
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
808
|
+
else
|
|
809
|
+
|
|
810
|
+
chat = createChat()
|
|
811
|
+
chat.request.replaceFileExt('')
|
|
812
|
+
|
|
813
|
+
chatlist.push chat
|
|
814
|
+
@check.updateCounters(chat)
|
|
815
|
+
|
|
816
|
+
msg = "running checks in #{@path} on #{@site} for /#{chat.request.dir}"
|
|
817
|
+
puts msg
|
|
818
|
+
Watobo.log(msg, :sender => "Catalog")
|
|
819
|
+
@log_viewer.log(LOG_INFO, msg)
|
|
836
820
|
end
|
|
821
|
+
rescue => bang
|
|
822
|
+
puts bang
|
|
823
|
+
puts bang.backtrace if $DEBUG
|
|
824
|
+
ensure
|
|
825
|
+
|
|
826
|
+
end
|
|
837
827
|
#scan_prefs = @project.getScanPreferences
|
|
838
828
|
scan_prefs = Watobo::Conf::Scanner.to_h
|
|
839
829
|
#scan_prefs[:scanlog_name] = ""
|
|
840
830
|
if @logScanChats.checked?
|
|
841
831
|
scan_prefs[:scanlog_name] = @scanlog_dir_dt.value unless @scanlog_dir_dt.value.empty?
|
|
842
832
|
end
|
|
843
|
-
|
|
833
|
+
|
|
844
834
|
@scanner = Watobo::Scanner3.new(chatlist, checklist, Watobo::PassiveModules.to_a, scan_prefs)
|
|
845
|
-
@pbar.total = @scanner.progress.values.inject(0){|i,v| i += v[:total]}
|
|
835
|
+
@pbar.total = @scanner.progress.values.inject(0) { |i, v| i += v[:total] }
|
|
846
836
|
@pbar.progress = 0
|
|
847
837
|
@pbar.barColor = 'red'
|
|
848
838
|
|
|
@@ -852,15 +842,15 @@ module Watobo#:nodoc: all
|
|
|
852
842
|
|
|
853
843
|
msg= "Total Requests: #{@pbar.total}"
|
|
854
844
|
@log_viewer.log(LOG_INFO, msg)
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
845
|
+
begin
|
|
846
|
+
msg = "start scanning..."
|
|
847
|
+
@log_viewer.log(LOG_INFO, msg)
|
|
848
|
+
@scanner.run(:run_passive_checks => false)
|
|
849
|
+
rescue => bang
|
|
850
|
+
puts bang
|
|
851
|
+
puts bang.backtrace if $DEBUG
|
|
852
|
+
end
|
|
853
|
+
|
|
864
854
|
end
|
|
865
855
|
|
|
866
856
|
end
|