| <!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="/css/syntax.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> |
| |
| <!-- Matomo --> |
| <script> |
| var _paq = window._paq = window._paq || []; |
| /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ |
| /* We explicitly disable cookie tracking to avoid privacy issues */ |
| _paq.push(['disableCookies']); |
| _paq.push(['trackPageView']); |
| _paq.push(['enableLinkTracking']); |
| (function() { |
| var u="//analytics.apache.org/"; |
| _paq.push(['setTrackerUrl', u+'matomo.php']); |
| _paq.push(['setSiteId', '41']); |
| var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; |
| g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); |
| })(); |
| </script> |
| <!-- End Matomo Code --> |
| </head> |
| <body> |
| |
| <a href="https://github.com/apache/struts" class="github-ribbon"> |
| <img decoding="async" loading="lazy" style="position: absolute; right: 0; border: 0;" width="149" height="149" src="https://github.blog/wp-content/uploads/2008/12/forkme_right_red_aa0000.png?resize=149%2C149" class="attachment-full size-full" alt="Fork me on GitHub" data-recalc-dims="1"> |
| </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-2023.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> |
| <li><a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy Policy</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><a href="/commercial-support.html">Commercial Support</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 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="/contributors/">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> |
| |
| <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="#defining-and-annotating-your-action-parameters" id="markdown-toc-defining-and-annotating-your-action-parameters">Defining and annotating your Action parameters</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="#ambiguous-action-methods" id="markdown-toc-ambiguous-action-methods">Ambiguous Action 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> |
| <li><a href="#proactively-protecting-against-ognl-expression-injections-attacks" id="markdown-toc-proactively-protecting-against-ognl-expression-injections-attacks">Proactively protecting against OGNL Expression Injections attacks</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="#restricting-access-to-the-struts-context-actioncontext" id="markdown-toc-restricting-access-to-the-struts-context-actioncontext">Restricting access to the Struts Context (ActionContext)</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> |
| <li><a href="#ognl-member-access" id="markdown-toc-ognl-member-access">OGNL Member Access</a></li> |
| <li><a href="#struts-ognl-guard" id="markdown-toc-struts-ognl-guard">Struts OGNL Guard</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="language-plaintext highlighter-rouge">WEB-INF</code> folder</p> |
| <ul> |
| <li>most of the JEE containers restrict access to files placed under the <code class="language-plaintext highlighter-rouge">WEB-INF</code> folder. Second option is to add security |
| constraint to the <code class="language-plaintext 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="language-plaintext 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="language-plaintext highlighter-rouge">devMode</code> before deploying your application |
| to a production environment. While it is disabled by default, your |
| <code class="language-plaintext highlighter-rouge">struts.xml</code> might include a line setting it to <code class="language-plaintext highlighter-rouge">true</code>. The best way is to ensure the following setting is applied |
| to our <code class="language-plaintext 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="language-plaintext 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> |
| |
| <div class="language-jsp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><%@ page </span><span class="na">contentType=</span><span class="s">"text/html; charset=UTF-8"</span> <span class="nt">%></span> |
| </code></pre></div></div> |
| |
| <h3 id="defining-and-annotating-your-action-parameters">Defining and annotating your Action parameters</h3> |
| |
| <blockquote> |
| <p>Note: Since 6.4 using <code class="language-plaintext highlighter-rouge">struts.parameters.requireAnnotations=true</code>. Or by default from 7.0.</p> |
| </blockquote> |
| |
| <p>Request parameters, such as those submitted by a form, can be stored on your Struts Action class by defining getters and |
| setters for them. For example, if you have a form with a field called <code class="language-plaintext highlighter-rouge">name</code>, you can store the value of that field by |
| defining a <code class="language-plaintext highlighter-rouge">public void setName(String name)</code> method on your Action class, and then importantly, annotating this method |
| with <code class="language-plaintext highlighter-rouge">@StrutsParameter</code>. The presence of this annotation indicates that the method is intended for parameter injection |
| and is safe to be invoked by any user who can view the Action.</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">private</span> <span class="nc">String</span> <span class="n">name</span><span class="o">;</span> |
| |
| <span class="nd">@StrutsParameter</span> |
| <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setName</span><span class="o">(</span><span class="nc">String</span> <span class="n">name</span><span class="o">)</span> <span class="o">{</span> |
| <span class="k">this</span><span class="o">.</span><span class="na">name</span> <span class="o">=</span> <span class="n">name</span><span class="o">;</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>If you wish to populate a DTO (Data Transfer Object) instead of setting the parameters directly on the Action class, you |
| can define a getter for the DTO on your Action class instead. For example, define a method <code class="language-plaintext highlighter-rouge">public MyDto getFormData()</code> |
| which is also annotated by <code class="language-plaintext highlighter-rouge">@StrutsParameter(depth = 1)</code>. Then, a parameter with name <code class="language-plaintext highlighter-rouge">formData.fullName</code> will be mapped |
| to the setter <code class="language-plaintext highlighter-rouge">setFullName</code> on that DTO. Note that the <code class="language-plaintext highlighter-rouge">@StrutsParameter</code> annotation has a <code class="language-plaintext highlighter-rouge">depth</code> field which dictates |
| the depth to which parameter injection is permitted. The default value is 0, which only allows setting parameters |
| directly on the Action class as in the first example. A <code class="language-plaintext highlighter-rouge">depth</code> of 1 indicates that the immediate public properties of |
| an object returned by the getter are permitted to be set. If you have further nested objects, you can increase |
| the <code class="language-plaintext highlighter-rouge">depth</code> accordingly. Do not set this <code class="language-plaintext highlighter-rouge">depth</code> field to a value greater than the minimum required for your use case.</p> |
| |
| <div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">private</span> <span class="nc">MyDto</span> <span class="n">formData</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">MyDto</span><span class="o">();</span> |
| |
| <span class="nd">@StrutsParameter</span><span class="o">(</span><span class="n">depth</span> <span class="o">=</span> <span class="mi">1</span><span class="o">)</span> |
| <span class="kd">public</span> <span class="nc">MyDto</span> <span class="nf">getFormData</span><span class="o">()</span> <span class="o">{</span> |
| <span class="k">return</span> <span class="n">formData</span><span class="o">;</span> |
| <span class="o">}</span> |
| |
| <span class="kd">public</span> <span class="kd">static</span> <span class="kd">class</span> <span class="nc">MyDto</span> <span class="o">{</span> |
| <span class="kd">private</span> <span class="nc">String</span> <span class="n">fullName</span><span class="o">;</span> |
| |
| <span class="kd">public</span> <span class="kt">void</span> <span class="nf">setFullName</span><span class="o">(</span><span class="nc">String</span> <span class="n">fullName</span><span class="o">)</span> <span class="o">{</span> |
| <span class="k">this</span><span class="o">.</span><span class="na">fullName</span> <span class="o">=</span> <span class="n">fullName</span><span class="o">;</span> |
| <span class="o">}</span> |
| <span class="o">}</span> |
| </code></pre></div></div> |
| |
| <p>It is critical that any method you annotate with <code class="language-plaintext highlighter-rouge">@StrutsParameter</code> is safe for any user who can view that corresponding |
| action to invoke (including any public methods on objects returned by that method and so forth). Any getters you |
| annotate should only ever return a DTO or a collection/hierarchy of DTOs. Do NOT mix business logic or service |
| references with your parameter injection methods and DTOs. Additionally, any database DTOs should be entirely separate |
| from request parameter/form DTOs.</p> |
| |
| <p>Do NOT, under any circumstance, annotate a method that returns one of the following unsafe objects:</p> |
| <ul> |
| <li>live Hibernate persistent objects</li> |
| <li>container or Spring-managed beans, or any other live components/services</li> |
| <li>objects (or objects that contain references to objects) that contain setter methods that are used for anything other |
| than setting form parameter values</li> |
| </ul> |
| |
| <p>If you are finding updating your application with this new annotation time-consuming, you can temporarily combine the |
| above option with <code class="language-plaintext highlighter-rouge">struts.parameters.requireAnnotations.transitionMode=true</code>. When this mode is enabled, only ‘nested’ |
| parameters, i.e. DTOs or Collections represented by public getters on Action classes, will require annotations. This |
| means public setters will still be exposed for parameter injection. Notably, |
| the <a href="#allowlist-capability">auto-allowlisting capability</a>, which is also supported by these annotations, is not degraded |
| in any way, so it proves a useful transitioning option for applications that wish to enable the OGNL allowlist as soon |
| as possible.</p> |
| |
| <h3 id="do-not-define-setters-when-not-needed">Do not define setters when not needed</h3> |
| |
| <blockquote> |
| <p>Note: Only relevant if you are not using <code class="language-plaintext highlighter-rouge">struts.parameters.requireAnnotations=true</code> as per the previous section.</p> |
| </blockquote> |
| |
| <p>You should carefully design your actions without exposing anything via setters and getters, this can lead 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="language-plaintext highlighter-rouge">Result</code>s automatically populate params based on values in |
| <code class="language-plaintext 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="language-plaintext highlighter-rouge">TextProvider</code>’s <code class="language-plaintext highlighter-rouge">getText(...)</code> methods (e.g. in<code class="language-plaintext 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="language-plaintext 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="language-plaintext 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="nc">String</span> <span class="nf">execute</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">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="no">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="language-plaintext 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="language-plaintext 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 either 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="ambiguous-action-methods">Ambiguous Action 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="nc">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="nc">String</span> <span class="nf">save</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">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="no">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="nc">AbstractAction</span> <span class="o">{</span> |
| <span class="kd">public</span> <span class="nc">String</span> <span class="nf">save</span><span class="o">()</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span> |
| <span class="n">save</span><span class="o">(</span><span class="nc">Double</span><span class="o">.</span><span class="na">MAX_VALUE</span><span class="o">);</span> |
| <span class="k">return</span> <span class="no">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="nc">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="nc">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="language-plaintext highlighter-rouge">save()</code> to <code class="language-plaintext highlighter-rouge">saveAction()</code> and leaving annotation as is to allow call this action via <code class="language-plaintext 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">AcceptedPatternsChecker</a> |
| and <a href="../maven/struts2-core/apidocs/com/opensymphony/xwork2/security/ExcludedPatternsChecker">ExcludedPatternsChecker</a> |
| with default implementations. These two interfaces are used by the <a href="../core-developers/parameters-interceptor">Parameters Interceptor</a> |
| and <a href="../core-developers/cookie-interceptor">Cookie Interceptor</a> to check if param can be accepted or must be excluded. |
| If you were using <code class="language-plaintext 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">Action Configuration</a>.</p> |
| |
| <h3 id="resource-isolation-using-fetch-metadata">Resource Isolation Using Fetch Metadata</h3> |
| |
| <blockquote> |
| <p>Note: since Struts 6.0.0</p> |
| </blockquote> |
| |
| <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="language-plaintext 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">FetchMetadata Interceptor</a>. |
| Refer to the documentation for <a href="../core-developers/fetch-metadata-interceptor">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 6.0.0</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="language-plaintext highlighter-rouge">SharedArrayBuffer</code>, <code class="language-plaintext 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="language-plaintext 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">CoopInterceptor</a> |
| and <a href="../core-developers/coep-interceptor">CoepInterceptor</a>.</p> |
| |
| <h2 id="proactively-protecting-against-ognl-expression-injections-attacks">Proactively protecting against OGNL Expression Injections attacks</h2> |
| |
| <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 a number of additional security capabilities, some of which need to be manually enabled.</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> |
| |
| <h3 id="run-ognl-expressions-inside-sandbox">Run OGNL expressions inside sandbox</h3> |
| |
| <p>You can do this simply via adding <code class="language-plaintext 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> |
| |
| <p>Note: This feature does not work with JDK 21 and above.</p> |
| |
| <h3 id="restricting-access-to-the-struts-context-actioncontext">Restricting access to the Struts Context (ActionContext)</h3> |
| |
| <p>The Struts ActionContext is a core construct of the Struts framework. It is shared and manipulated throughout the |
| codebase. From the ActionContext, it is possible to access application parameters, the OgnlValueStack, the current |
| request/response/session, the servlet context, the Guice container, and a number of other objects either directly or |
| indirectly via the directly exposed objects. The Struts ActionContext enables powerful features and functionality, but |
| it also presents a major security risk if not properly secured.</p> |
| |
| <p>The Struts ActionContext is accessible to OGNL expressions. In the case of an OGNL expression exploit, usually achieved |
| through some form of server-side template injection or parameter injection, the ActionContext is a prime gadget for |
| escalation of the vulnerability, often to remote code execution (RCE). Whilst known harmful capabilities of the |
| ActionContext items are blocked by the OGNL Member Access policy exclusion list (see below), this is not always |
| effective due to the myriad of changing objects available on the ActionContext. The new allowlist capability (also see |
| below) offers much stronger protection. However, for the strongest level of protection, we recommend disabling access |
| to the ActionContext from OGNL expressions entirely.</p> |
| |
| <p>Note that before disabling access to the ActionContext from OGNL expressions, you should ensure that your application |
| does not rely on this capability. OGNL expressions may access the context directly using the <code class="language-plaintext highlighter-rouge">#</code> operator, or indirectly |
| using the OgnlValueStack’s fallback to context lookup capability. As of Struts 6.4.0, the Set, Iterator and Action |
| Struts components require ActionContext access from OGNL expressions.</p> |
| |
| <p>To disable access to the ActionContext from OGNL expressions, set the following constants in your <code class="language-plaintext highlighter-rouge">struts.xml</code> or |
| <code class="language-plaintext highlighter-rouge">struts.properties</code> file. The option <code class="language-plaintext highlighter-rouge">struts.ognl.excludedNodeTypes</code> is an <a href="#Struts-OGNL-Guard">OGNL Guard</a> setting |
| which completely forbids the context accessing syntax node. The <code class="language-plaintext highlighter-rouge">struts.ognl.valueStackFallbackToContext</code> option |
| disables ValueStack behaviour which allows the context to be accessed indirectly via a fallback behaviour triggered when |
| an OGNL expression does not evaluate to a valid value.</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.ognl.valueStackFallbackToContext"</span> <span class="na">value=</span><span class="s">"false"</span><span class="nt">/></span> |
| <span class="nt"><constant</span> <span class="na">name=</span><span class="s">"struts.ognl.excludedNodeTypes"</span> <span class="na">value=</span><span class="s">" |
| ognl.ASTThisVarRef, |
| ognl.ASTVarRef |
| "</span><span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <h3 id="apply-a-maximum-allowed-length-on-ognl-expressions">Apply a maximum allowed length on OGNL expressions</h3> |
| |
| <p>You can enable this via Struts configuration key <code class="language-plaintext highlighter-rouge">struts.ognl.expressionMaxLength</code> (defaults to 256). 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> |
| |
| <h3 id="ognl-member-access">OGNL Member Access</h3> |
| |
| <p>Struts 2 implements an OGNL internal security mechanism which blocks access to particular classes and Java packages - |
| it’s an OGNL-wide mechanism which means it affects any aspect of the framework i.e. incoming parameters, expressions |
| used in JSPs, etc. Matching is done based on both the target and member class of all components of an OGNL expression.</p> |
| |
| <p>There are 4 options that can be used to configure excluded packages and classes:</p> |
| |
| <ul> |
| <li><code class="language-plaintext highlighter-rouge">struts.excludedClasses</code>: comma-separated list of excluded classes.</li> |
| <li><code class="language-plaintext highlighter-rouge">struts.excludedPackageNames</code>: comma-separated list of excluded packages, matched using string comparison via |
| <code class="language-plaintext highlighter-rouge">startWith</code>. Note that classes in subpackages are also excluded.</li> |
| <li><code class="language-plaintext highlighter-rouge">struts.excludedPackageNamePatterns</code> - comma-separated list of RegEx patterns used to exclude packages. Note that this |
| option is more flexible than <code class="language-plaintext highlighter-rouge">struts.excludedPackageNames</code> but will have a greater impact on performance and page |
| latency.</li> |
| <li><code class="language-plaintext highlighter-rouge">struts.excludedPackageExemptClasses</code> - comma-separated list of classes to exempt from any of the excluded packages or |
| package name patterns. An exact exemption must exist for each exclusion match (target or member or both).</li> |
| </ul> |
| |
| <p>The defaults are defined <a href="https://github.com/apache/struts/blob/master/core/src/main/resources/struts-excluded-classes.xml">here</a>.</p> |
| |
| <p>Any expression or target which does not pass this criteria will be blocked, and you will see a warning in the logs:</p> |
| |
| <div class="language-plaintext 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="language-plaintext highlighter-rouge">new MyBean()</code> was used to create a new instance of class (inside JSP) - it’s blocked because the <code class="language-plaintext highlighter-rouge">target</code> |
| of such expression is <code class="language-plaintext highlighter-rouge">java.lang.Class</code> which is excluded.</p> |
| |
| <p>It is possible to redefine the above constants in <code class="language-plaintext highlighter-rouge">struts.xml</code>, but avoid reducing the list, instead extending the list |
| with other known dangerous classes or packages in your application.</p> |
| |
| <h4 id="additional-options">Additional Options</h4> |
| |
| <p>We additionally recommend enabling the following options (enabled by default in 7.0).</p> |
| |
| <ul> |
| <li><code class="language-plaintext highlighter-rouge">struts.ognl.allowStaticFieldAccess=false</code> - static methods are always blocked, but static fields can also optionally be blocked</li> |
| <li><code class="language-plaintext highlighter-rouge">struts.disallowProxyMemberAccess=true</code> - disallow proxied objects from being used in OGNL expressions as they may present a security risk</li> |
| <li><code class="language-plaintext highlighter-rouge">struts.disallowDefaultPackageAccess=true</code> - disallow access to classes in the default package which should not be used in production</li> |
| <li><code class="language-plaintext highlighter-rouge">struts.ognl.disallowCustomOgnlMap=true</code> - disallow construction of custom OGNL maps which can be used to bypass the SecurityMemberAccess policy</li> |
| </ul> |
| |
| <h4 id="allowlist-capability">Allowlist Capability</h4> |
| |
| <blockquote> |
| <p>Note: Since Struts 6.4. Or by default from 7.0.</p> |
| </blockquote> |
| |
| <p>For the most stringent OGNL protection, we recommend enabling the allowlist capability with <code class="language-plaintext highlighter-rouge">struts.allowlist.enable</code>.</p> |
| |
| <p>Now, in addition to enforcing the exclusion list, classes involved in OGNL expression must also belong to a list of |
| allowlisted classes and packages. By default, all required Struts classes are allowlisted as well as any classes that |
| are defined in your <code class="language-plaintext highlighter-rouge">struts.xml</code> package configurations.</p> |
| |
| <p>We highly recommend enabling the <a href="#defining-and-annotating-your-action-parameters">parameter annotation</a> capability to |
| ensure any necessary parameter injection types are allowlisted, in addition to its other benefits.</p> |
| |
| <p>You can add additional classes and packages to the allowlist with:</p> |
| |
| <ul> |
| <li><code class="language-plaintext highlighter-rouge">struts.allowlist.classes</code>: comma-separated list of allowlisted classes.</li> |
| <li><code class="language-plaintext highlighter-rouge">struts.allowlist.packages</code>: comma-separated list of allowlisted packages, matched using string comparison via |
| <code class="language-plaintext highlighter-rouge">startsWith</code>. Note that classes in subpackages are also allowlisted.</li> |
| </ul> |
| |
| <p>Depending on the functionality of your application, you may not need to manually allowlist any classes. Please monitor |
| your application logs for any warnings about blocked classes and add them to the allowlist as necessary.</p> |
| |
| <h4 id="extensibility">Extensibility</h4> |
| |
| <blockquote> |
| <p>Note: since Struts 6.4.</p> |
| </blockquote> |
| |
| <p>The OGNL Member Access mechanism is extensible, allowing you to define your own rules for blocking access to OGNL |
| expression evaluations. To do so, you may use the <code class="language-plaintext highlighter-rouge">struts.securityMemberAccess</code> extension point. Please be vigilant when |
| overriding methods as not to reduce protections offered by the default implementation.</p> |
| |
| <h3 id="struts-ognl-guard">Struts OGNL Guard</h3> |
| |
| <blockquote> |
| <p>Note: since Struts 6.4.</p> |
| </blockquote> |
| |
| <p>The Struts OGNL Guard allows applications to completely disable certain OGNL expression features/capabilities. This |
| feature is disabled by default but can be enabled and configured with <code class="language-plaintext highlighter-rouge">struts.ognl.excludedNodeTypes</code>.</p> |
| |
| <p>It is recommended to disable any OGNL feature you are not leveraging in your application.</p> |
| |
| <p>For example, if you do not need to use the addition operation in any OGNL expressions, you can add <code class="language-plaintext highlighter-rouge">ognl.ASTAdd</code> to your |
| excluded node types. This will mitigate against a host of String concatenation attacks.</p> |
| |
| <p>For applications using a minimal number of Struts features, you may find the following list a good starting point. |
| Please be aware that this list WILL break certain Struts features.</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.ognl.excludedNodeTypes"</span> |
| <span class="na">value=</span><span class="s">" |
| ognl.ASTAdd, |
| ognl.ASTAssign, |
| ognl.ASTBitAnd, |
| ognl.ASTBitNegate, |
| ognl.ASTBitOr, |
| ognl.ASTCtor, |
| ognl.ASTDivide, |
| ognl.ASTEval, |
| ognl.ASTIn, |
| ognl.ASTInstanceof, |
| ognl.ASTKeyValue, |
| ognl.ASTList, |
| ognl.ASTMap, |
| ognl.ASTMultiply, |
| ognl.ASTNegate, |
| ognl.ASTNotIn, |
| ognl.ASTProject, |
| ognl.ASTRootVarRef, |
| ognl.ASTSelect, |
| ognl.ASTSelectFirst, |
| ognl.ASTSelectLast, |
| ognl.ASTSequence, |
| ognl.ASTShiftLeft, |
| ognl.ASTShiftRight, |
| ognl.ASTStaticField, |
| ognl.ASTStaticMethod, |
| ognl.ASTThisVarRef, |
| ognl.ASTUnsignedShiftRight, |
| ognl.ASTVarRef, |
| ognl.ASTXor |
| "</span><span class="nt">/></span> |
| </code></pre></div></div> |
| |
| <h4 id="extensibility-1">Extensibility</h4> |
| |
| <p>The Struts OGNL Guard mechanism is extensible, allowing you to define your own rules for blocking access to both raw |
| OGNL expressions and compiled syntax trees. To do so, you may use the <code class="language-plaintext highlighter-rouge">struts.ognlGuard</code> extension point. You may choose |
| to override the default implementation or implement the <code class="language-plaintext highlighter-rouge">OgnlGuard</code> interface directly.</p> |
| |
| </section> |
| </article> |
| |
| |
| <footer class="container"> |
| <div class="col-md-12"> |
| Copyright © 2000-2022 <a href="https://www.apache.org/">The Apache Software Foundation</a>. |
| Apache Struts, Struts, Apache, the Apache feather logo, and the Apache Struts project logos are |
| trademarks of The Apache Software Foundation. All Rights Reserved. |
| </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> |