| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"/> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"/> |
| <meta name="Date-Revision-yyyymmdd" content="20140918"/> |
| <meta http-equiv="Content-Language" content="en"/> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| |
| <title>Security</title> |
| |
| <link href="//fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,400italic,600italic,700italic" rel="stylesheet" type="text/css"> |
| <link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet"> |
| <link href="/css/main.css" rel="stylesheet"> |
| <link href="/css/custom.css" rel="stylesheet"> |
| <link href="/highlighter/github-theme.css" rel="stylesheet"> |
| |
| <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> |
| <script type="text/javascript" src="/bootstrap/js/bootstrap.js"></script> |
| <script type="text/javascript" src="/js/community.js"></script> |
| </head> |
| <body> |
| |
| <a href="http://github.com/apache/struts" class="github-ribbon"> |
| <img style="position: absolute; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_red_aa0000.png" alt="Fork me on GitHub"> |
| </a> |
| |
| <header> |
| <nav> |
| <div role="navigation" class="navbar navbar-default navbar-fixed-top"> |
| <div class="container"> |
| <div class="navbar-header"> |
| <button type="button" data-toggle="collapse" data-target="#struts-menu" class="navbar-toggle"> |
| Menu |
| <span class="sr-only">Toggle navigation</span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| </button> |
| <a href="/index.html" class="navbar-brand logo"><img src="/img/struts-logo.svg"></a> |
| </div> |
| <div id="struts-menu" class="navbar-collapse collapse"> |
| <ul class="nav navbar-nav"> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Home<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/index.html">Welcome</a></li> |
| <li><a href="/download.cgi">Download</a></li> |
| <li><a href="/releases.html">Releases</a></li> |
| <li><a href="/announce-2021.html">Announcements</a></li> |
| <li><a href="http://www.apache.org/licenses/">License</a></li> |
| <li><a href="https://www.apache.org/foundation/thanks.html">Thanks!</a></li> |
| <li><a href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Support<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/mail.html">User Mailing List</a></li> |
| <li><a href="https://issues.apache.org/jira/browse/WW">Issue Tracker</a></li> |
| <li><a href="/security.html">Reporting Security Issues</a></li> |
| <li class="divider"></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Migration+Guide">Version Notes</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">Security Bulletins</a></li> |
| <li class="divider"></li> |
| <li><a href="/maven/project-info.html">Maven Project Info</a></li> |
| <li><a href="/maven/struts2-core/dependencies.html">Struts Core Dependencies</a></li> |
| <li><a href="/maven/struts2-plugins/modules.html">Plugin Dependencies</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Documentation<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/birdseye.html">Birds Eye</a></li> |
| <li><a href="/primer.html">Key Technologies</a></li> |
| <li><a href="/kickstart.html">Kickstart FAQ</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Home">Wiki</a></li> |
| <li class="divider"></li> |
| <li><a href="/getting-started/">Getting Started</a></li> |
| <li><a href="/security/">Security Guide</a></li> |
| <li><a href="/core-developers/">Core Developers Guide</a></li> |
| <li><a href="/tag-developers/">Tag Developers Guide</a></li> |
| <li><a href="/maven-archetypes/">Maven Archetypes</a></li> |
| <li><a href="/plugins/">Plugins</a></li> |
| <li><a href="/maven/struts2-core/apidocs/index.html">Struts Core API</a></li> |
| <li><a href="/tag-developers/tag-reference.html">Tag reference</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/FAQs">FAQs</a></li> |
| <li><a href="http://cwiki.apache.org/S2PLUGINS/home.html">Plugin registry</a></li> |
| </ul> |
| </li> |
| <li class="dropdown"> |
| <a data-toggle="dropdown" href="#" class="dropdown-toggle"> |
| Contributing<b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <li><a href="/youatstruts.html">You at Struts</a></li> |
| <li><a href="/helping.html">How to Help FAQ</a></li> |
| <li><a href="/dev-mail.html">Development Lists</a></li> |
| <li><a href="/contributors/">Contributors Guide</a></li> |
| <li class="divider"></li> |
| <li><a href="/submitting-patches.html">Submitting patches</a></li> |
| <li><a href="/builds.html">Source Code and Builds</a></li> |
| <li><a href="/coding-standards.html">Coding standards</a></li> |
| <li><a href="https://cwiki.apache.org/confluence/display/WW/Contributors+Guide">Contributors Guide</a></li> |
| <li class="divider"></li> |
| <li><a href="/release-guidelines.html">Release Guidelines</a></li> |
| <li><a href="/bylaws.html">PMC Charter</a></li> |
| <li><a href="/volunteers.html">Volunteers</a></li> |
| <li><a href="https://gitbox.apache.org/repos/asf?p=struts.git">Source Repository</a></li> |
| <li><a href="/updating-website.html">Updating the website</a></li> |
| </ul> |
| </li> |
| <li class="apache"><a href="http://www.apache.org/"><img src="/img/apache.png"></a></li> |
| </ul> |
| </div> |
| </div> |
| </div> |
| </nav> |
| </header> |
| |
| |
| <article class="container"> |
| <section class="col-md-12"> |
| <a class="edit-on-gh" href="https://github.com/apache/struts-site/edit/master/source/security/index.md" title="Edit this page on GitHub">Edit on GitHub</a> |
| |
| <h1 class="no_toc" id="security">Security</h1> |
| <p><a href="https://github.com/apache/struts-site/edit/master/source/security/index.md" class="edit-on-gh" title="Edit this page on GitHub">Edit on GitHub</a></p> |
| |
| <ul id="markdown-toc"> |
| <li><a href="#security-tips" id="markdown-toc-security-tips">Security tips</a> <ul> |
| <li><a href="#restrict-access-to-the-config-browser-plugin" id="markdown-toc-restrict-access-to-the-config-browser-plugin">Restrict access to the Config Browser Plugin</a></li> |
| <li><a href="#dont-mix-different-access-levels-in-the-same-namespace" id="markdown-toc-dont-mix-different-access-levels-in-the-same-namespace">Don’t mix different access levels in the same namespace</a></li> |
| <li><a href="#never-expose-jsp-files-directly" id="markdown-toc-never-expose-jsp-files-directly">Never expose JSP files directly</a></li> |
| <li><a href="#disable-devmode" id="markdown-toc-disable-devmode">Disable devMode</a></li> |
| <li><a href="#reduce-logging-level" id="markdown-toc-reduce-logging-level">Reduce logging level</a></li> |
| <li><a href="#use-utf-8-encoding" id="markdown-toc-use-utf-8-encoding">Use UTF-8 encoding</a></li> |
| <li><a href="#do-not-define-setters-when-not-needed" id="markdown-toc-do-not-define-setters-when-not-needed">Do not define setters when not needed</a></li> |
| <li><a href="#do-not-use-incoming-values-as-an-input-for-localisation-logic" id="markdown-toc-do-not-use-incoming-values-as-an-input-for-localisation-logic">Do not use incoming values as an input for localisation logic</a></li> |
| <li><a href="#do-not-use-incoming-untrusted-user-input-in-forced-expression-evaluation" id="markdown-toc-do-not-use-incoming-untrusted-user-input-in-forced-expression-evaluation">Do not use incoming, untrusted user input in forced expression evaluation</a></li> |
| <li><a href="#use-struts-tags-instead-of-raw-el-expressions" id="markdown-toc-use-struts-tags-instead-of-raw-el-expressions">Use Struts tags instead of raw EL expressions</a></li> |
| <li><a href="#define-custom-error-pages" id="markdown-toc-define-custom-error-pages">Define custom error pages</a></li> |
| <li><a href="#proactively-protect-from-ognl-expression-injections-attacks-if-easily-applicable" id="markdown-toc-proactively-protect-from-ognl-expression-injections-attacks-if-easily-applicable">Proactively protect from OGNL Expression Injections attacks if easily applicable</a> <ul> |
| <li><a href="#run-ognl-expressions-inside-sandbox" id="markdown-toc-run-ognl-expressions-inside-sandbox">Run OGNL expressions inside sandbox</a></li> |
| <li><a href="#apply-a-maximum-allowed-length-on-ognl-expressions" id="markdown-toc-apply-a-maximum-allowed-length-on-ognl-expressions">Apply a maximum allowed length on OGNL expressions</a></li> |
| </ul> |
| </li> |
| </ul> |
| </li> |
| <li><a href="#internal-security-mechanism" id="markdown-toc-internal-security-mechanism">Internal security mechanism</a> <ul> |
| <li><a href="#accessing-static-methods" id="markdown-toc-accessing-static-methods">Accessing static methods</a></li> |
| <li><a href="#ognl-is-used-to-call-actions-methods" id="markdown-toc-ognl-is-used-to-call-actions-methods">OGNL is used to call action’s methods</a></li> |
| <li><a href="#accepted--excluded-patterns" id="markdown-toc-accepted--excluded-patterns">Accepted / Excluded patterns</a></li> |
| <li><a href="#strict-method-invocation" id="markdown-toc-strict-method-invocation">Strict Method Invocation</a></li> |
| <li><a href="#resource-isolation-using-fetch-metadata" id="markdown-toc-resource-isolation-using-fetch-metadata">Resource Isolation Using Fetch Metadata</a></li> |
| <li><a href="#cross-origin-isolation-with-coop-and-coep" id="markdown-toc-cross-origin-isolation-with-coop-and-coep">Cross Origin Isolation with COOP and COEP</a></li> |
| </ul> |
| </li> |
| </ul> |
| |
| <h2 id="security-tips">Security tips</h2> |
| |
| <p>The Apache Struts 2 doesn’t provide any security mechanism - it is just a pure web framework. Below are few tips |
| you should consider during application development with the Apache Struts 2.</p> |
| |
| <h3 id="restrict-access-to-the-config-browser-plugin">Restrict access to the Config Browser Plugin</h3> |
| |
| <p><a href="../plugins/config-browser/">Config Browser Plugin</a> exposes internal configuration and should be used only during |
| development phase. If you must use it on production site, we strictly recommend restricting access to it - you can use<br /> |
| Basic Authentication or any other security mechanism (e.g. <a href="https://shiro.apache.org/">Apache Shiro</a>)</p> |
| |
| <h3 id="dont-mix-different-access-levels-in-the-same-namespace">Don’t mix different access levels in the same namespace</h3> |
| |
| <p>Very often access to different resources is controlled based on URL patterns, see snippet below. Because of that |
| you cannot mix actions with different security levels in the same namespace. Always group actions in one namespace |
| by security level.</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><security-constraint></span> |
| <span class="nt"><web-resource-collection></span> |
| <span class="nt"><web-resource-name></span>admin<span class="nt"></web-resource-name></span> |
| <span class="nt"><url-pattern></span>/secure/*<span class="nt"></url-pattern></span> |
| <span class="nt"></web-resource-collection></span> |
| <span class="nt"><auth-constraint></span> |
| <span class="nt"><role-name></span>admin<span class="nt"></role-name></span> |
| <span class="nt"></auth-constraint></span> |
| <span class="nt"></security-constraint></span> |
| </code></pre></div></div> |
| |
| <h3 id="never-expose-jsp-files-directly">Never expose JSP files directly</h3> |
| |
| <p>You must always hide JSP file behind an action, you cannot allow for direct access to the JSP files as this can leads |
| to unpredictable security vulnerabilities. You can achieve this by putting all your JSP files under the <code class="highlighter-rouge">WEB-INF</code> folder</p> |
| <ul> |
| <li>most of the JEE containers restrict access to files placed under the <code class="highlighter-rouge">WEB-INF</code> folder. Second option is to add security |
| constraint to the <code class="highlighter-rouge">web.xml</code> file:</li> |
| </ul> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"><!-- Restricts access to pure JSP files - access available only via Struts action --></span> |
| <span class="nt"><security-constraint></span> |
| <span class="nt"><display-name></span>No direct JSP access<span class="nt"></display-name></span> |
| <span class="nt"><web-resource-collection></span> |
| <span class="nt"><web-resource-name></span>No-JSP<span class="nt"></web-resource-name></span> |
| <span class="nt"><url-pattern></span>*.jsp<span class="nt"></url-pattern></span> |
| <span class="nt"></web-resource-collection></span> |
| <span class="nt"><auth-constraint></span> |
| <span class="nt"><role-name></span>no-users<span class="nt"></role-name></span> |
| <span class="nt"></auth-constraint></span> |
| <span class="nt"></security-constraint></span> |
| |
| <span class="nt"><security-role></span> |
| <span class="nt"><description></span>Don't assign users to this role<span class="nt"></description></span> |
| <span class="nt"><role-name></span>no-users<span class="nt"></role-name></span> |
| <span class="nt"></security-role></span> |
| </code></pre></div></div> |
| |
| <p>The best approach is to used the both solutions.</p> |
| |
| <h3 id="disable-devmode">Disable devMode</h3> |
| |
| <p>The <code class="highlighter-rouge">devMode</code> is a very useful option during development time, allowing for deep introspection and debugging into you app.</p> |
| |
| <p>However, in production it exposes your application to be presenting too many informations on application’s internals |
| or to evaluating risky parameter expressions. Please <strong>always disable</strong> <code class="highlighter-rouge">devMode</code> before deploying your application |
| to a production environment. While it is disabled by default, your |
| <code class="highlighter-rouge">struts.xml</code> might include a line setting it to <code class="highlighter-rouge">true</code>. The best way is to ensure the following setting is applied |
| to our <code class="highlighter-rouge">struts.xml</code> for production deployment:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><constant</span> <span class="na">name =</span><span class="s">"struts.devMode"</span> <span class="na">value=</span><span class="s">"false"</span> <span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <h3 id="reduce-logging-level">Reduce logging level</h3> |
| |
| <p>It’s a good practice to reduce logging level from <strong>DEBUG</strong> to <strong>INFO</strong> or less. Framework’s classes can produce |
| a lot of logging entries which will pollute the log file. You can even set logging level to <strong>WARN</strong> for classes that |
| belongs to the framework, see example Log4j2 configuration:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span> |
| <span class="nt"><Configuration></span> |
| <span class="nt"><Appenders></span> |
| <span class="nt"><Console</span> <span class="na">name=</span><span class="s">"STDOUT"</span> <span class="na">target=</span><span class="s">"SYSTEM_OUT"</span><span class="nt">></span> |
| <span class="nt"><PatternLayout</span> <span class="na">pattern=</span><span class="s">"%d %-5p [%t] %C{2} (%F:%L) - %m%n"</span><span class="nt">/></span> |
| <span class="nt"></Console></span> |
| <span class="nt"></Appenders></span> |
| <span class="nt"><Loggers></span> |
| <span class="nt"><Logger</span> <span class="na">name=</span><span class="s">"com.opensymphony.xwork2"</span> <span class="na">level=</span><span class="s">"warn"</span><span class="nt">/></span> |
| <span class="nt"><Logger</span> <span class="na">name=</span><span class="s">"org.apache.struts2"</span> <span class="na">level=</span><span class="s">"warn"</span><span class="nt">/></span> |
| <span class="nt"><Root</span> <span class="na">level=</span><span class="s">"info"</span><span class="nt">></span> |
| <span class="nt"><AppenderRef</span> <span class="na">ref=</span><span class="s">"STDOUT"</span><span class="nt">/></span> |
| <span class="nt"></Root></span> |
| <span class="nt"></Loggers></span> |
| <span class="nt"></Configuration></span> |
| </code></pre></div></div> |
| |
| <h3 id="use-utf-8-encoding">Use UTF-8 encoding</h3> |
| |
| <p>Always use <code class="highlighter-rouge">UTF-8</code> encoding when building an application with the Apache Struts 2, when using JSPs please add the following |
| header to each JSP file</p> |
| |
| <pre><code class="language-jsp"><%@ page contentType="text/html; charset=UTF-8" %> |
| </code></pre> |
| |
| <h3 id="do-not-define-setters-when-not-needed">Do not define setters when not needed</h3> |
| |
| <p>You should carefully design your actions without exposing anything via setters and getters, thus can leads to potential |
| security vulnerabilities. Any action’s setter can be used to set incoming untrusted user’s value which can contain |
| suspicious expression. Some Struts <code class="highlighter-rouge">Result</code>s automatically populate params based on values in |
| <code class="highlighter-rouge">ValueStack</code> (action in most cases is the root) which means incoming value will be evaluated as an expression during |
| this process.</p> |
| |
| <h3 id="do-not-use-incoming-values-as-an-input-for-localisation-logic">Do not use incoming values as an input for localisation logic</h3> |
| |
| <p>All <code class="highlighter-rouge">TextProvider</code>’s <code class="highlighter-rouge">getText(...)</code> methods (e.g. in<code class="highlighter-rouge">ActionSupport</code>) perform evaluation of parameters included in a message |
| to properly localize the text. This means using incoming request parameters with <code class="highlighter-rouge">getText(...)</code> methods is potentially |
| dangerous and should be avoided. See example below, assuming that an action implements getter and setter for property |
| <code class="highlighter-rouge">message</code>, the below code allows inject an OGNL expression:</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="n">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span> |
| <span class="n">message</span> <span class="o">=</span> <span class="n">getText</span><span class="o">(</span><span class="n">getMessage</span><span class="o">());</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p><strong>Never use value of incoming request parameter as part of your localization logic.</strong></p> |
| |
| <h3 id="do-not-use-incoming-untrusted-user-input-in-forced-expression-evaluation">Do not use incoming, untrusted user input in forced expression evaluation</h3> |
| |
| <p>You can use a forced expression evalaution in many tags’ attributes by using <code class="highlighter-rouge">%{...}</code> syntax. This is a very powerful option |
| but used with wrong data can lead to the Remote Code Execution. Never use forced expression evalaution if you didn’t verify |
| the input or it can be passed in by a user.</p> |
| |
| <p><strong>Never use value of incoming request parameter as input for forced expression evalaution.</strong></p> |
| |
| <h3 id="use-struts-tags-instead-of-raw-el-expressions">Use Struts tags instead of raw EL expressions</h3> |
| |
| <p>JSP EL doesn’t perform any kind of escaping, you must perform this using a dedicated function, see <a href="https://stackoverflow.com/a/6135001/1805267">this example</a>. |
| Never use a raw <code class="highlighter-rouge">${}</code> EL expression on incoming values as this can lead to injecting a malicious code into the page.</p> |
| |
| <p>The safest option is to use Struts Tags instead.</p> |
| |
| <h3 id="define-custom-error-pages">Define custom error pages</h3> |
| |
| <p>As mentioned in <a href="https://cwiki.apache.org/confluence/display/WW/S2-006">S2-006</a> it’s a good practicse to define your own |
| error pages. This avoids exposing users to XSS attacks as Struts does not escape action’s names in automatically |
| generated error pages.</p> |
| |
| <p>You can eaither disable <a href="../core-developers/action-configuration#dynamic-method-invocation">DMI</a></p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.enable.DynamicMethodInvocation"</span> <span class="na">value=</span><span class="s">"false"</span> <span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <p>or define an error page</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><global-results></span> |
| <span class="nt"><result</span> <span class="na">name=</span><span class="s">"error"</span><span class="nt">></span>/error_page.jsp<span class="nt"></result></span> |
| <span class="nt"></global-results></span> |
| |
| <span class="nt"><global-exception-mappings></span> |
| <span class="nt"><exception-mapping</span> <span class="na">exception=</span><span class="s">"java.lang.Exception"</span> <span class="na">result=</span><span class="s">"error"</span><span class="nt">/></span> |
| <span class="nt"></global-exception-mappings></span> |
| </code></pre></div></div> |
| |
| <h3 id="proactively-protect-from-ognl-expression-injections-attacks-if-easily-applicable">Proactively protect from OGNL Expression Injections attacks if easily applicable</h3> |
| |
| <p>The framework has a history of critical security bugs, many tied to its use of OGNL technology; Due to its ability to |
| create or change executable code, OGNL is capable of introducing critical security flaws to any framework that uses it. |
| Multiple Struts 2 versions have been vulnerable to OGNL security flaws. Consequently, we’ve equipped OGNL and the |
| framework with following proactive optional possibilities since OGNL 3.1.24 and Struts 2.5.22. They’re disabled by |
| default but via enabling them, you can proactively protect from potential still unknown OGNL Expression Injections flaws:</p> |
| |
| <blockquote> |
| <p><strong>NOTE</strong>: These might break your current app functionality. Before using in production environment, you’re recommended to |
| comprehensively test your app UI and functionalities with these enabled.</p> |
| </blockquote> |
| |
| <h4 id="run-ognl-expressions-inside-sandbox">Run OGNL expressions inside sandbox</h4> |
| |
| <p>You can do this simply via adding <code class="highlighter-rouge">-Dognl.security.manager</code> to JVM arguments. OGNL thereupon utilizes Java Security |
| Manager to run OGNL expressions (which includes your actions either!) inside a sandbox with no permission. It is worth |
| noting that it affects only OGNL expression execution and thereafter OGNL reverts Java Security Manager to its previous |
| state.</p> |
| |
| <h4 id="apply-a-maximum-allowed-length-on-ognl-expressions">Apply a maximum allowed length on OGNL expressions</h4> |
| |
| <p>You can enable this via Struts configuration key <code class="highlighter-rouge">struts.ognl.expressionMaxLength</code>. OGNL thereupon doesn’t evaluate any |
| expression longer than specified value. You would choose a value large enough to permit ALL valid OGNL expressions used |
| within the application. Values larger than the 200-400 range have diminishing security value (at which point it is |
| really only a “style guard” for long OGNL expressions in an application).</p> |
| |
| <h2 id="internal-security-mechanism">Internal security mechanism</h2> |
| |
| <p>The Apache Struts 2 contains internal security manager which blocks access to particular classes and Java packages - |
| it’s a OGNL-wide mechanism which means it affects any aspect of the framework ie. incoming parameters, expressions |
| used in JSPs, etc.</p> |
| |
| <p>There are three options that can be used to configure excluded packages and classes:</p> |
| |
| <ul> |
| <li><code class="highlighter-rouge">struts.excludedClasses</code> - comma-separated list of excluded classes</li> |
| <li><code class="highlighter-rouge">struts.excludedPackageNamePatterns</code> - patterns used to exclude packages based on RegEx - this option is slower than |
| simple string comparison but it’s more flexible</li> |
| <li><code class="highlighter-rouge">struts.excludedPackageNames</code> - comma-separated list of excluded packages, it is used with simple string comparison |
| via <code class="highlighter-rouge">startWith</code> and <code class="highlighter-rouge">equals</code></li> |
| </ul> |
| |
| <p>The defaults are as follow:</p> |
| |
| <div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.excludedClasses"</span> |
| <span class="na">value=</span><span class="s">"com.opensymphony.xwork2.ActionContext"</span> <span class="nt">/></span> |
| |
| <span class="c"><!-- this must be valid regex, each '.' in package name must be escaped! --></span> |
| <span class="c"><!-- it's more flexible but slower than simple string comparison --></span> |
| <span class="c"><!-- constant name="struts.excludedPackageNamePatterns" value="^java\.lang\..*,^ognl.*,^(?!javax\.servlet\..+)(javax\..+)" / --></span> |
| |
| <span class="c"><!-- this is simpler version of the above used with string comparison --></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.excludedPackageNames"</span> <span class="na">value=</span><span class="s">"java.lang,ognl,javax"</span> <span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <p>Any expression or target which evaluates to one of these will be blocked and you see a WARN in logs:</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[WARNING] Target class [class example.MyBean] or declaring class of member type [public example.MyBean()] are excluded! |
| </code></pre></div></div> |
| |
| <p>In that case <code class="highlighter-rouge">new MyBean()</code> was used to create a new instance of class (inside JSP) - it’s blocked because <code class="highlighter-rouge">target</code> |
| of such expression is evaluated to <code class="highlighter-rouge">java.lang.Class</code></p> |
| |
| <p>It is possible to redefine the above constants in struts.xml but try to avoid this and rather change design of your application!</p> |
| |
| <h3 id="accessing-static-methods">Accessing static methods</h3> |
| |
| <p>Support for accessing static methods from expression will be disabled soon, please consider re-factoring your application |
| to avoid further problems! Please check <a href="https://issues.apache.org/jira/browse/WW-4348">WW-4348</a>.</p> |
| |
| <h3 id="ognl-is-used-to-call-actions-methods">OGNL is used to call action’s methods</h3> |
| |
| <p>This can impact actions which have large inheritance hierarchy and use the same method’s name throughout the hierarchy, |
| this was reported as an issue <a href="https://issues.apache.org/jira/browse/WW-4405">WW-4405</a>. See the example below:</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">RealAction</span> <span class="kd">extends</span> <span class="n">BaseAction</span> <span class="o">{</span> |
| <span class="nd">@Action</span><span class="o">(</span><span class="s">"save"</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">save</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span> |
| <span class="kd">super</span><span class="o">.</span><span class="na">save</span><span class="o">();</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| |
| <span class="kd">public</span> <span class="kd">class</span> <span class="nc">BaseAction</span> <span class="kd">extends</span> <span class="n">AbstractAction</span> <span class="o">{</span> |
| <span class="kd">public</span> <span class="n">String</span> <span class="nf">save</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span> |
| <span class="n">save</span><span class="o">(</span><span class="n">Double</span><span class="o">.</span><span class="na">MAX_VALUE</span><span class="o">);</span> |
| <span class="k">return</span> <span class="n">SUCCESS</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| |
| <span class="kd">public</span> <span class="kd">abstract</span> <span class="kd">class</span> <span class="nc">AbstractAction</span> <span class="kd">extends</span> <span class="n">ActionSupport</span> <span class="o">{</span> |
| <span class="kd">protected</span> <span class="kt">void</span> <span class="nf">save</span><span class="o">(</span><span class="n">Double</span> <span class="n">val</span><span class="o">)</span> <span class="o">{</span> |
| <span class="c1">// some logic</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>In such case OGNL cannot properly map which method to call when request is coming. This is do the OGNL limitation. |
| To solve the problem don’t use the same method’s names through the hierarchy, you can simply change the action’s method |
| from <code class="highlighter-rouge">save()</code> to <code class="highlighter-rouge">saveAction()</code> and leaving annotation as is to allow call this action via <code class="highlighter-rouge">/save.action</code> request.</p> |
| |
| <h3 id="accepted--excluded-patterns">Accepted / Excluded patterns</h3> |
| |
| <p>As from version 2.3.20 the framework provides two new interfaces which are used to accept / exclude param names |
| and values - <a href="../maven/struts2-core/apidocs/com/opensymphony/xwork2/security/AcceptedPatternsChecker.html">AcceptedPatternsChecker</a> |
| and <a href="../maven/struts2-core/apidocs/com/opensymphony/xwork2/security/ExcludedPatternsChecker.html">ExcludedPatternsChecker</a> |
| with default implementations. These two interfaces are used by <a href="../core-developers/parameters-interceptor.html">Parameters Interceptor</a> |
| and <a href="../core-developers/cookie-interceptor.html">Cookie Interceptor</a> to check if param can be accepted or must be excluded. |
| If you were using <code class="highlighter-rouge">excludeParams</code> previously please compare patterns used by you with these provided by the framework in default implementation.</p> |
| |
| <h3 id="strict-method-invocation">Strict Method Invocation</h3> |
| |
| <p>This mechanism was introduced in version 2.5. It allows control what methods can be accessed with the bang “!” operator |
| via <a href="../core-developers/action-configuration.html#dynamic-method-invocation">Dynamic Method Invocation</a>. Please read |
| more in the Strict Method Invocation section of <a href="../core-developers/action-configuration.html">Action Configuration</a>.</p> |
| |
| <h3 id="resource-isolation-using-fetch-metadata">Resource Isolation Using Fetch Metadata</h3> |
| |
| <p>Fetch Metadata is a mitigation against common cross origin attacks such as Cross-Site Request Forgery (CSRF). It is |
| a web platform security feature designed to help servers defend themselves against cross-origin attacks based |
| on the preferred resource isolation policy. The browser provides information about the context of an HTTP request |
| in a set of <code class="highlighter-rouge">Sec-Fetch-*</code> headers. This allows the server processing the request to make decisions on whether the request |
| should be accepted or rejected based on the available resource isolation policies.</p> |
| |
| <p>A Resource Isolation Policy prevents the resources on a server from being requested by external websites. This policy |
| can be enabled for all endpoints of the application or the endpoints that are meant to be loaded in a cross-site context |
| can be exempted from applying the policy. Read more about Fetch Metadata and resource isolation <a href="https://web.dev/fetch-metadata/">here</a>.</p> |
| |
| <p>This mechanism is implemented in Struts using the <a href="../core-developers/fetch-metadata-interceptor.html">FetchMetadata Interceptor</a>. |
| Refer to the documentation for <a href="../core-developers/fetch-metadata-interceptor.html">FetchMetadata Interceptor</a> |
| instructions on how to enable Fetch Metadata.</p> |
| |
| <h3 id="cross-origin-isolation-with-coop-and-coep">Cross Origin Isolation with COOP and COEP</h3> |
| |
| <blockquote> |
| <p>Note: since Struts 2.6.</p> |
| </blockquote> |
| |
| <p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy">Cross-Origin Opener Policy</a> is |
| a security mitigation that lets developers isolate their resources against side-channel attacks and information leaks. |
| The COOP response header allows a document to request a new browsing context group to better isolate itself from other |
| untrustworthy origins.</p> |
| |
| <p><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy">Cross-Origin Embedder Policy</a> |
| prevents a document from loading any cross-origin resources which don’t explicitly grant the document permission to be loaded.</p> |
| |
| <p>COOP and COEP are independent mechanisms that can be enabled, tested and deployed separately. While enabling one doesn’t |
| require developers to enable the other, when set together COOP and COEP allows developers to use powerful features (such |
| as <code class="highlighter-rouge">SharedArrayBuffer</code>, <code class="highlighter-rouge">performance.measureMemory()</code> and the JS Self-Profiling API) securely, without worrying about |
| side channel attacks like <a href="https://meltdownattack.com/">Spectre</a>. |
| Further reading on <a href="https://docs.google.com/document/d/1zDlfvfTJ_9e8Jdc8ehuV4zMEu9ySMCiTGMS9y0GU92k/edit#bookmark=id.uo6kivyh0ge2">COOP/COEP</a> |
| and <a href="https://web.dev/why-coop-coep/">why you need cross-origin isolation</a>.</p> |
| |
| <p>The recommended configuration for the policies are:</p> |
| |
| <div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Cross-Origin-Embedder-Policy: require-corp; |
| Cross-Origin-Opener-Policy: same-origin; |
| </code></pre></div></div> |
| |
| <p>COOP and COEP are implemented in Struts using <a href="../core-developers/coop-interceptor.html">CoopInterceptor</a> |
| and <a href="../core-developers/coep-interceptor.html">CoepInterceptor</a>.</p> |
| |
| </section> |
| </article> |
| |
| |
| <footer class="container"> |
| <div class="col-md-12"> |
| Copyright © 2000-2018 <a href="http://www.apache.org/">The Apache Software Foundation </a>. |
| All Rights Reserved. |
| </div> |
| <div class="col-md-12"> |
| Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are |
| trademarks of The Apache Software Foundation. |
| </div> |
| <div class="col-md-12">Logo and website design donated by <a href="https://softwaremill.com/">SoftwareMill</a>.</div> |
| </footer> |
| |
| <script>!function (d, s, id) { |
| var js, fjs = d.getElementsByTagName(s)[0]; |
| if (!d.getElementById(id)) { |
| js = d.createElement(s); |
| js.id = id; |
| js.src = "//platform.twitter.com/widgets.js"; |
| fjs.parentNode.insertBefore(js, fjs); |
| } |
| }(document, "script", "twitter-wjs");</script> |
| <script src="https://apis.google.com/js/platform.js" async="async" defer="defer"></script> |
| |
| <div id="fb-root"></div> |
| |
| <script>(function (d, s, id) { |
| var js, fjs = d.getElementsByTagName(s)[0]; |
| if (d.getElementById(id)) return; |
| js = d.createElement(s); |
| js.id = id; |
| js.src = "//connect.facebook.net/en_GB/all.js#xfbml=1"; |
| fjs.parentNode.insertBefore(js, fjs); |
| }(document, 'script', 'facebook-jssdk'));</script> |
| |
| |
| </body> |
| </html> |