blob: 366f68383ed57bab3440746d8b62ad88dbce190f [file] [log] [blame]
<!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">&lt;security-constraint&gt;</span>
<span class="nt">&lt;web-resource-collection&gt;</span>
<span class="nt">&lt;web-resource-name&gt;</span>admin<span class="nt">&lt;/web-resource-name&gt;</span>
<span class="nt">&lt;url-pattern&gt;</span>/secure/*<span class="nt">&lt;/url-pattern&gt;</span>
<span class="nt">&lt;/web-resource-collection&gt;</span>
<span class="nt">&lt;auth-constraint&gt;</span>
<span class="nt">&lt;role-name&gt;</span>admin<span class="nt">&lt;/role-name&gt;</span>
<span class="nt">&lt;/auth-constraint&gt;</span>
<span class="nt">&lt;/security-constraint&gt;</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">&lt;!-- Restricts access to pure JSP files - access available only via Struts action --&gt;</span>
<span class="nt">&lt;security-constraint&gt;</span>
<span class="nt">&lt;display-name&gt;</span>No direct JSP access<span class="nt">&lt;/display-name&gt;</span>
<span class="nt">&lt;web-resource-collection&gt;</span>
<span class="nt">&lt;web-resource-name&gt;</span>No-JSP<span class="nt">&lt;/web-resource-name&gt;</span>
<span class="nt">&lt;url-pattern&gt;</span>*.jsp<span class="nt">&lt;/url-pattern&gt;</span>
<span class="nt">&lt;/web-resource-collection&gt;</span>
<span class="nt">&lt;auth-constraint&gt;</span>
<span class="nt">&lt;role-name&gt;</span>no-users<span class="nt">&lt;/role-name&gt;</span>
<span class="nt">&lt;/auth-constraint&gt;</span>
<span class="nt">&lt;/security-constraint&gt;</span>
<span class="nt">&lt;security-role&gt;</span>
<span class="nt">&lt;description&gt;</span>Don't assign users to this role<span class="nt">&lt;/description&gt;</span>
<span class="nt">&lt;role-name&gt;</span>no-users<span class="nt">&lt;/role-name&gt;</span>
<span class="nt">&lt;/security-role&gt;</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">&lt;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">/&gt;</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">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
<span class="nt">&lt;Configuration&gt;</span>
<span class="nt">&lt;Appenders&gt;</span>
<span class="nt">&lt;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">&gt;</span>
<span class="nt">&lt;PatternLayout</span> <span class="na">pattern=</span><span class="s">"%d %-5p [%t] %C{2} (%F:%L) - %m%n"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/Console&gt;</span>
<span class="nt">&lt;/Appenders&gt;</span>
<span class="nt">&lt;Loggers&gt;</span>
<span class="nt">&lt;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">/&gt;</span>
<span class="nt">&lt;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">/&gt;</span>
<span class="nt">&lt;Root</span> <span class="na">level=</span><span class="s">"info"</span><span class="nt">&gt;</span>
<span class="nt">&lt;AppenderRef</span> <span class="na">ref=</span><span class="s">"STDOUT"</span><span class="nt">/&gt;</span>
<span class="nt">&lt;/Root&gt;</span>
<span class="nt">&lt;/Loggers&gt;</span>
<span class="nt">&lt;/Configuration&gt;</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">&lt;%@ page contentType="text/html; charset=UTF-8" %&gt;
</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">&lt;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">/&gt;</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">&lt;global-results&gt;</span>
<span class="nt">&lt;result</span> <span class="na">name=</span><span class="s">"error"</span><span class="nt">&gt;</span>/error_page.jsp<span class="nt">&lt;/result&gt;</span>
<span class="nt">&lt;/global-results&gt;</span>
<span class="nt">&lt;global-exception-mappings&gt;</span>
<span class="nt">&lt;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">/&gt;</span>
<span class="nt">&lt;/global-exception-mappings&gt;</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">&lt;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">/&gt;</span>
<span class="c">&lt;!-- this must be valid regex, each '.' in package name must be escaped! --&gt;</span>
<span class="c">&lt;!-- it's more flexible but slower than simple string comparison --&gt;</span>
<span class="c">&lt;!-- constant name="struts.excludedPackageNamePatterns" value="^java\.lang\..*,^ognl.*,^(?!javax\.servlet\..+)(javax\..+)" / --&gt;</span>
<span class="c">&lt;!-- this is simpler version of the above used with string comparison --&gt;</span>
<span class="nt">&lt;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">/&gt;</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 &copy; 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>