getclassloader vulnerability exploitation of struts2 framework

Posted by trammel at 2020-02-26

By: Weibo:


In 2012, in my "attack Java Web", I mentioned more about "Dos vulnerability caused by classloader under specific environment". At that time, there was no more in-depth explanation. In recent days, struts officially fixed this vulnerability. This paper is an in-depth study of this vulnerability.


All of this starts from the fact that we have controlled classloader. We once wrote an article that mentioned a small technical detail, which is very inconspicuous. Refer to the spring framework (cve-2010-1622) vulnerability utilization Guide: In fact, Struts2 is supposed to cause a remote code execution vulnerability. It's only because of its field mapping problem. It only maps the basic type and is not responsible for mapping other types by default. Therefore, when an attacker submits URLs [0] = XXX directly, the field type conversion error is directly exploded, and the result is a lucky escape. -

After Tomcat 8.0 came out, this problem broke out, which is a backattack of vulnerability.

Before any action of struts 2 runs, once the user submits the parameter XX = ZZZZZ, ognl is responsible for calling the corresponding setXXX method of the current action. As for what the set method does, it doesn't matter in fact, and the logic in it is not important. We only focus on the method call and parameter passing. This kind of change to attributes can sometimes greatly affect the subsequent complex logic.

A little popularization

Object is the basic class of Java. All the objects generated by class inherit all the properties and methods of object. Therefore, no matter what the code of the current action is, there must be a getClass method that comes with the object. This method will return a class object, and the class object must have a getclassloader method, which can be used in every action finally

Get the current classloader.

I studied this problem. A few years ago, it was not easy to understand this thing, especially the different web containers. At that time, there was an Alibaba internal training on "classloader loading principle of Tomcat and other containers", which was very fruitful. This article is limited in length. Let's talk about it briefly.

In JRE startup, each class will have its own classloader. Web container, in order to facilitate the management of the start-up process, usually has the implementation of custom classloader. Spring framework's vulnerability utilization scenario is really lucky. It takes advantage of the geturls method of the web container's features. All servlet's classloaders of the container will get the geturls method by inheriting the parent urlclassloader, so the vulnerability can not be affected by the container. In fact, each container's classloader is implemented by itself, and the environment will inevitably be different. That time, struts 2 narrowly escaped a disaster, so one of my concerns was to focus on the classloader code changes of several web containers. One day I saw that tomcat8 put resources into classloader, and ServletContext happened to hang on resources, and I knew that the game was coming.

Research on the possibility of uploading webshell

Many times of Remote Code Execution Vulnerability baptism, I have been simulating in my mind "ServletContext is under control, what can I do this time", which routes can lead to the field of code execution. For example: Struts2 will go to ServletContext to get a value, and then execute it as ognl. This is too simple. I don't believe it myself.

The context tree structure of ognl:

ServletContext has been converted into map, which has become the application sub item in the figure. This address is awkward. If it is a node of the upper layer, it is possible to find value stack from the top to the bottom, but now it seems that this path is broken, and it does not support finding the parent node. After many searches, we can only start from the web container itself to confirm that ognl is out.

The struts running under tomcat8, in any action code, insert this section, the next breakpoint,

The classloader of any action is org.apache.catalina.loader.webappclassloader, which is the source of the vulnerability.

My idea is to give context the initialization parameter readonly = false. Because on tomcat, all requests will be processed by default on the defaultservlet or by jspservet. As long as readonly = false when context is initialized, then defaultservlet will really handle put request, delete request and other powerful requests, so we can directly put the file.

The premise of this idea is that the default servlet is initialized again. The reality is cruel, and this idea has not been implemented at last, because the servlet will only be initialized once, and the readonly attribute will really assign a value to the readonly attribute of the Servet only when the servlet is initialized. This breakthrough is a failure.

Some debugging tips for this vulnerability:

1. It is not accurate to only view the assignment of ognl from debug. Debug can only see the variables defined by this class.

If there is a code like this:

But this property has not been defined. Debug cannot see this thing at this time, but in fact, ognl can be called directly through name = ZZZZZ, and ZZZZZ can be passed.

2. If there is only one private property, but there is no set method, in fact, it cannot be assigned by ognl.

This debug, when observing this vulnerability, is only a reference. Only when you really go deep into the code can you keep the same view with ognl.

3. A final object, or just an object returned by the get method, looks like it is read-only. In fact, the properties of the object can be changed. This is just a reference to the object.

You can understand that the address that the pointer points to cannot be changed, but the properties of the object that it points to can be modified.

Give an example:

These two codes, in fact, are all user objects returned to ognl. As long as there is a set method for the properties of the object, they can also be modified. It can still pass

Assign a value to the name of the user.

Arbitrary file read vulnerability of struts 2 running in Tomcat 8.0.1rc5 (before November 2013)

In Tomcat's environment, classloader will mount a resource named "standardroot", which is related to Tomcat's resource file management. The first attribute seen by debug is the very dangerous attribute "allowlinking".

This matter, from a long time ago, struts patched an arbitrary file read vulnerability.


This is a directory list + file reading vulnerability. The patching scheme is very insidious. Instead of using formal means to solve the vulnerability in the framework layer, it takes advantage of a convention feature of the web container. The web container of JSP complies with a rule.

When a path is called "/ var / www / Tomcat / webapps / demo / struts /...", the

The return path is:

Will remove / / and go directly to the destination directory.

This is called web container characteristics, which has the final say of web container. Web container is angry and web is not allowed to speak. In fact, I always like to talk about framework security. One of the principles is that "framework should not rely on the features of Web containers for defense". Of course, today, we will not discuss this topic, just make a little preparation.

The patch code was:

When the user submits "struts /...", pathending = "struts /...".


So it doesn't end with pathending. This kind of lewd practice was effective at that time.

This version of Tomcat 8 suddenly took off. After rewriting this method, it really returned

Declare the fall. But in the actual operation of the code, there is a requirement that "standardroot. Allowlinking" must be true (the default must be false). Here comes the chance. First submit:

Debug can see that it is already true. Then follow the previous attack method:

Can easily read any file, get database password and so on.

This is the result of the combination of two vulnerabilities. Unfortunately, after RC5, someone submitted a requirement to Tomcat. About November 2013, among the unimportant requirements of Tomcat (which happened to involve the code related to the resource file), the maintenance personnel of Tomcat may not realize the threat of reading the resource file. They just put The function of reading resources has been re abstracted and planned once, and this loophole has been mended. The reason for this problem is very grievance, and the reason for mending is very grievance. The most depressing thing is that I, living, have lost 0day. Originally, I thought I could kill all directions, but God sneezed.

Finally, by the way, this vulnerability is only normal under windows, and the unknown reason is blowing under Linux.

Blackout the home page of struts 2 application under Tomcat 8

But don't worry. Tomcat can't solve the fundamental problem for struts. Standard root can be exposed and affect many things. Is this DDoS? In fact, I can write "hacked by kxlzx" on your application homepage.

The cause of formation is very "normal", because this context attribute represents the configuration of Tomcat's / conf / context.xml file. Now I have changed the path to you. When struts processes the result, it will use the path splicing to read the file. Now the directory name has been changed, so naturally it can't read the file. Unfortunately, it can't be truncated at 00, otherwise it is an arbitrary file reading vulnerability.

Here is the website that was killed. Visiting any action will have the following effects:

Take a look at debug:

The current action is called T1, t1.jsp will be found, but now the directory name has been modified, so an error is reported.

This problem can affect all versions of Tomcat 8 running struts 2, by the way, you have to design your own exp ha, do not mess in.

Jetty7 shutdown command

Since we mentioned web containers, only Tomcat can't cover the concerns of everyone, so I chose another lightweight web container, jetty, which is open-source, free and widely used.

Now let's see if jetty has a breakthrough. On the other hand, we should first find a loophole that has "little impact" and that you "are not" very concerned about. ".

Let's first look at the web structure and use the old method breakpoint:

See a class:

The vulnerability of jetty is not as implicit as Tomcat. It is very direct. Context is mounted on classloader.

During the operation of jetty, it will check the shutdown attribute in contexthandler in real time (webappcontext inherits this class through several layers of inheritance relationship, actually the relationship is eight Zhangs away). Once it finds true, it will not work directly, which is typical. It uses a state to judge whether the business is in the same line. Based on this principle, as long as you visit below, there will be only 404 left for this application in the future.

No matter what action it is, it will only return this error. For subsequent execution, jetty thinks it's really shutdown. And there is no remedy for this process. The administrator has to restart it manually. Dear SA, are you ready?

Jetty any file download

Let's make 404 serve this vulnerability to the end.

As a matter of fact, the following problem happened on jetty, and Tomcat really escaped by coincidence.

Let's take a look at jetty's configuration process for custom error files:

For this configuration file, you can customize the 404 error file. Here, you can specify the file under the / WEB-INF / directory. Once configured, the errorpageerrorhandler is responsible for adding a corresponding relationship to the errorpages (this is also a map). This class will eventually be hung in the context, so according to the principle of this vulnerability, we can call it layer by layer, and finally make an error, such as 404 error.

Jetty mounts errorhandler to context. Errorhandler has an errorpages attribute, which is actually a map, representing the error page. Key is a return code number, and value is the file displayed after the error.

So open:

After visiting the URL in the picture, the effect is as follows, any page that does not exist

The contents of web.xml are displayed:

With this problem, you can read database files, view database passwords, read code files, and find hidden business logic vulnerabilities. Note that anyone can see this page when they encounter 404. It's better to use it when it's quiet at night. You have to restore it when you're finished.

Bug fix:

This loophole has been fixed by the official. The old problem that came out in 2012 is just not submitted to the official alone, but it can also be delayed until now. I suggest you make up your mind to change the framework. By: Weibo: