Security Research
cancel
Showing results for 
Search instead for 
Did you mean: 

Re: Protect your Struts1 applications

alvaro_munoz

Hi,

 

It depends on how do you name your Struts1 servlet. Look for a servlet definition like:

 

    <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
      ....
  </servlet>

 

The servlet name for this particular example is "action".

 

Thanks,

A

0 Kudos
About the Author

alvaro_munoz

Comments
Arturo T

In the original Struts 2 vulnerability documentation, the regular expression also check for the following initial strings followed by a dot:

 

  • dojo
  • struts
  • session
  • request
  • application
  • servletRequest
  • servletResponse
  • parameters
  • action
  • method

Why the regexp for Struts 1 presented here does not include them? Are they relevant?

alvaro_munoz

Hi Arturo,

 

Thanks for your comment. Those keywords are relevant if evaluated in the context of the Struts2 Value Stack via OGNL. Struts1 does not use OGNL and has no access to the anything similar to the Value Stack and so they dont suppose a specific risk.

 

Cheers,

Alvaro

Kishore Kirdat

Is it safe to assume that if I am not using ActionForm, but simple using actions alone, then I am not impacted by this vulnerability?

alvaro_munoz

Hi Kishore,


Thanks for your comment. If there is no ActionForm associated with the action in the action declaration, then Struts will not start the ActionForm binding process and therefore this particular attack vector will not be possible. However we strongly recommend taking all possible mitigation actions to protect your applciations from unknown attack vectors that may be working on the wild.

 

Cheers,

A

Patrick Trainor

Thanks for making this code available. What license  applies to it if any?

Someone123

Here is an improved version of the filter that compiles the pattern only once: https://gist.github.com/anonymous/0045ef4df99b31b43daa

alvaro_munoz

Hi Patrick,

 

Thanks for your comment. The fix is not licensed in any way and its completely open source so that any one is free to use it or modify it.
It is provided as-is with no guarantees nor support and designed as a temporal workaround until a patch is made available.


Cheers,

A

pmulay

Can you tell a sample test URL that we can use to test this logic?

alvaro_munoz

Thanks for the comment pmulay,

 

Any action associated with an actionForm is vulnerable. URL should look like http://myserver.com/myaction.do

 

Cheers,

A

Jamie W

how do you test if the vulnerability is there and then verify the fix addressed the issue? The main problem I have is I don't know how to test it the vulnerability and thus can't verify if the issue is really addressed after incorporating this fix. Thanks for any help you can provide.

alvaro_munoz

Hi Jamie,

 

Thanks for your comment, Im sorry I cannot explain how to verify if the issue has been fixed withouth disclosing the exploit details.

 

All I can say is that the filter has been tested in our labs and verified by the Struts security team.

 

Cheers,

A

William Howard

Thanks for providing the patch!

 

After analysing the regular expression, did you realise that in your regular expression:

 

(.*\.|^|.*|\[('|"))(c|C)lass(\.|('|")]|\[).*

 

the prefix part can be simplified to:

 

(.*)(c|C)lass(\.|('|")]|\[).*

 

Is this still what you intended to do?

 

Regards,

William

 

Reva C
 

I'm using Struts 1.3.10 with Websphere 8. I tried testing the above fix  in my application by providing urls with parameters like "?class.classLoader.defaultAssertionStatus=true", or "class.classLoader.resource.dircontext.docBase=someText" either case all such parameters are permitted into my application. I see those parameters inside the finalParameters returned by the by getParameters(). Am I testing correctly or am I missing something here? I've placed this ParamFilter as the first filter in the chain in my web.xml file. Thanks in advance.

alvaro_munoz

Thanks for the comment William,

 

Yes I realized that and I would suggest removing the .* from the first group since otherwise properties ending on "class" wont be accepted. I chose to stick to Struts2 proposed regex and notify them about the extra ".*"

 

Cheers,

A

alvaro_munoz

Hi Reva,

 

Thanks for your comment. This filter is a temporal fix for this particular vulnerability. Struts 1 uses getParameterNames to loop through parameters that are going to be bound to ActionForm properties. So in order to mitigate this issue, it is enough to prevent dangerous property names from appearing in the return collection of getParameterNames(). Other request methods like getParameters are not intercepted by the filter and so those parameter will still be available for the servlets except that an ActionForm property mapping will be prevented.

 

Cheers,

A

Reva C

Hi Alvaro,

 

Can you give an example url parameter which will be prevented by this Filter? 

 

Thanks!

alvaro_munoz

Hi Reva,

 

The one you posted is an example of a bean property that wont be bound to the actionForm, although a request.getParameters() will return it. The filter will prevent request.getParameterNames() but not request.getParameters(), effectively preventing ActionForm property binding but not other legitimate accesses to the request parameter.

 

Cheers,

A

JFreedom

I have been able to replicate the exploit when using a ActionForm directly, but not when using DynaActionForms. We are using DynaActionForms it appears to use form properties from the struts-config instead of the request.getParameterName during the ActionForm binding process. Is this correct?

alvaro_munoz

Hi JFreedom,

 

Thanks for your comment. DynaActionForms use request.getParameterNames() in the same way that ActionForms do. But the bind process is slightly different, DynaActionForms contains a HashMap where the property name and value are stored instead of using apache commons BeanUtils to set up the beans properties.

 

Cheers,

A

Kristina T

Thanks so much for addressing this.

 

You responded to a comment that the regex given by Struts 2 is slightly incorrect, but I was unsure how to apply your comments.  You said to remove the .* from the first group, so would this change the regex to

 

(.*\.|^|\[('|"))(c|C)lass(\.|('|")]|\[).*

 

or something else?  I was finding that in our application, with the original regex, we were able to set property names that ended in "class" just fine but were also able to deny setting those that would affect the class object directly, but I'm wondering if I'm missing something.  Can you please clarify?

 

Thanks!

 

Kristina

alvaro_munoz

Hi Kristina,

 

Thank you for your comment. The original regex suggested by the struts team is effectively equivalent to

.*(c|C)lass(\.|('|")]|\[).*

That regex will match and prevent setting nested properties like:  somethingclass.prop

But it will allow setting a property like: simpleclass  (no nesting)

 

The regex that you suggest:

(.*\.|^|\[('|"))(c|C)lass(\.|('|")]|\[).*


will allow to set nested and simple properties that end in "class" but will prevent the classloader manipulation.

 

Thanks,

A

ushasingh

Hello ,

 

Is this ok if I use below filter mapping in given solution.

 

    <filter-mapping>

     <filter-name>ParamFilter</filter-name>
       <url-pattern>*.do</url-pattern>    
    </filter-mapping>

Jamie Wang

Hi Alvaro,

 

I understand your comment about not able to detail how to verify the vulnerability. I am wondering if we can discuss this in private. I am working on a product where we need to verify if our product is vulnerable. Not sure if you can reach me via the email address I provided in the form or if possible, I can also be reached at xxx-xxx-xxxx. Thanks in advance.

 

Jamie

 

 

alvaro_munoz

Hi ushasingh,

 

That should work if all your actions use the .do suffix

 

Cheers,

A

alvaro_munoz

Hi Jamie,

 

Im really sorry, but I cannot give any details on the exploit. Please get in contact with the Struts security team to see if they can help you.

 

Cheers,

A

yours

 Hi Team,

       Thank you for your solution.

       But which name I need to configure in servlet-name

<servlet-name>YOUR ACTION SERVLET</servlet-name>
alvaro_munoz

Hi,

 

It depends on how do you name your Struts1 servlet. Look for a servlet definition like:

 

    <servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
      ....
  </servlet>

 

The servlet name for this particular example is "action".

 

Thanks,

A

Nilesh001

Thanks for the solution.

 

I have a question though.

 

If my request has a parameter name like myclass.name, would it not get filtered out as well? I am not good at regular expressions so not sure this regular expression filters only the malecious input parameters and not valid businessnames like myclass.something?

 

Thanks,

Nilesh

alvaro_munoz

Hi Nilesh,

 

Thank you for your comment. The original regex suggested by the struts team will match and prevent setting nested properties like:  myclass.something

But it will allow setting a property like: myclass  (no nesting)

 

The following regex will allow to set nested and simple properties that end in "class" but will prevent the classloader manipulation.

(.*\.|^|\[('|"))(c|C)lass(\.|('|")]|\[).*



Thanks,

A

shigee

Hi,

 

Workarounds of cookie was necessary in Struts2.

In Struts1, is similar Workarounds unnecessary?

 

 

Thanks!

alvaro_munoz

Hi Shigee,

 

No, this particular bug only affects Action Form bindings

 

Cheers,

A

Tomari Rohai

I've coded this, tested it, and I can see the bit of code that lets parameters through is being used, by examining the log.

 

So negatively, I can see this is working, no problemo.

 

How can I test a positive (ie, that somehing is being trapped by the code)? I dont want to know anything about the exploit, but I need a strategy whereby I can show this code is working.

 

Any ideas? Am I missing something glaringly obvious here? Me missing something obvious is always the default position.

 

Cheers,

 

Tom

alvaro_munoz

Hi Tom,

 

Thanks for your comment. If the filter works ok and its correctly deployed, it should be preventing access to certain parameters. The parameters that are going to be intercepted are the ones in that match the regular expression. So for example if you have a Action form with a user field of type "User", then trying to set the nested property "user.class" should be trapped by the filter and logged.

 

Cheers,

A

Martin Gainty
struts.debug=true
1)You *should* see the parameters trapped by your regex with the System.out:
if (!parameterName.matches(regex)) { finalParameterNames.add(parameterName); System.out.println("Param included is : " + parameterName); }
else { System.out.println("Param excluded is : "+parameterName); }
2)Shark your line if you want to see the traffic coming and going

Saludos Cordiales desde EEUU,
Martín

 

SpringUser

Hi Alvaro,

 

Thanks for the post. Its very useful. Also, I'm having some queries. I would like to clear them out. 

 

1. Our application is based upon Spring Framework and is just using the struts tiles framework . So in our case we are having controllers instead of action forms. As we have imported struts 1.3.10 jars, so would like to know if our application comes under the scope of vulnerablility. 

 

2. Also, we are having a custom XSS filter already defined for all the URL's to find below patterns in parameter's.

 

Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),
Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
Pattern.compile("</script>", Pattern.CASE_INSENSITIVE),
// Remove any lonesome <script ...> tag
Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
// eval(...)
Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
// expression(...)
Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
// javascript:...
Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE),
// vbscript:...
Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE),
// onload(...)=...
Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),
//remove <IMG.. > tags
Pattern.compile("<IMG(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL)

 

I would like to know if this servers the same purpose as the ParamFilter.

 

3. My last query is will Param Filter or above XSS filter prevent cookie attacks too?

 

java_developer

Can we define a security policy and secure specific classes? Will this help in solving this?

java_developer

I was able to recreate the issue (Struts 1.1) with url parameters (class.ClassLoader), which resulted in modifying the classloader settings. But could not see any issue with html elements with name class.ClassLoader. Is it sufficient if I only put parameter blacklisting in the filter?

 

Would like to know why the ParamWrapperFilter reads the input stream and check for blacklist pattern.

alvaro_munoz

Hi,

 

Parameter blacklistt should be used to protect query parameters and request body (so it is necessary to read and protect the request input stream)

 

Cheers,

A

Ferozkhan

Hi

 

I would like to know whether struts team will release the Struts1.3 version with this vulnerability been fixed ?

 

Thanks in advance.

 

Feroz

Ferozkhan

Hi Support,

 

Any update for the my earlier query ?

 

In addition, Is this vulnerability impacted If my project is using the DynaActionForm ?

 

Please let me know in details.

 

Thks and Rgds

 

Feroz

Ferozkhan

Hi support ,

 

We are using DynaActionForm in my project.

 

I would like to check with Struts support team to confirm whether the DynaActionForm is really impacted with this vulnerability.

 

Please let us know in details.

 

FYI. I have raised the same type of question last month and the question was not published yet into the portal.

 

Rgds

 

Feroz

alvaro_munoz

Hi Feroz,

 

DynaActionForms are impacted but Im sorry we cannot disclose details.

 

Cheers,

A

nvaslav48

Hi Alvaro,

 

I have applied filter using StrutsFilter1.jar from maven repository and modifying web.xml file by adding this:

<

 

filter>

 

<filter-name>ParamWrapperFilter</filter-name>

 

<filter-class>net.rgielen.struts1.filter.ParamWrapperFilter</filter-class>

</

 

filter>

 

<filter-mapping>

 

<filter-name>ParamWrapperFilter</filter-name>

 

<servlet-name>banking</servlet-name>

</

 

filter-mapping>

 

 

However, when I Analyze project using forify static analyzer it still flags Struts1Classloader issue.

 

Is that supposed to be?

 

Thanks

 

alvaro_munoz

Hi nvaslav48,

 

A bug has been filed and issue will be remove in future releases.

 

Thanks,

A

Bhayani

Hi,

 

I would like to know if we have a solution to above discussed problem yet?

 

Thanks,

Sohil

Bhayani

hi,

 

Also I am trying to Test the ParamWrapperFilter which was last updated on Jan 22. I am providing "][]Class][<>" as a value to parameterName, however pattern.matcher(parameterName).matches() line always returns false. Please can somebody explain me what I am doing wrong here.

 

Thanks,

Sohil

alvaro_munoz
Hi Sohil, Please file an issue in the github repo for further discussion. Thanks, A
Bhayani

 

Hi Alvaro,

As per your suggestion, I have posted issue in github repo. Please let me know if there is a fix for Classloader manipulation issue for Struts1.x.

 

https://github.com/rgielen/struts1filter/issues/4

 

Thanks,

Sohil

alvaro_munoz

Hi Sohil,

 

I have just replied to your comment in github: https://github.com/rgielen/struts1filter/issues/4

 

Also, please check for a different workaround that implies patching Struts 1 code or using an unofficial patched build: https://github.com/rgielen/struts1filter/issues/3

 

Workaround: use patched struts distribution instead of this filter.

Patch link: https://github.com/apache/struts1/pull/1/files

Patched struts 1.3.10 is available for example for Fedora 20 in build "struts-1.3.10-10.fc20" in form of RPM: http://koji.fedoraproject.org/koji/buildinfo?buildID=552377

Labels
Events
June 6 - 8, 2017
Las Vegas, Nevada
Discover 2017 Las Vegas
Join us for HPE Discover 2017 in Las Vegas. The event will be held at the Venetian | Palazzo from June 6-8, 2017.
Read more
Each Month in 2017
Online
Software Expert Days - 2017
Join us online to talk directly with our Software experts during online Expert Days. Find information here about past, current, and upcoming Expert Da...
Read more
View all