Referer
header with the incorrect spelling 🙂org.alfresco.web.site.servlet.CSRFFilter
that reads a config section in share-security-config.xml
named CSRFPolicy
which will describe how and when the filter shall mitigate CSRF, summarized as:Alfresco-CSRF-Token
.POST
, PUT
or DELETE
http request against Alfresco Share the token MUST be passed in the request using one of the following methods:Alfresco-CSRF-Token
Alfresco-CSRF-Token
.Content-Type
header starts with multipart/
.Referer
and Original
http request headers matches the current domain (if present in the request).Alfresco.util.Ajax
, alfresco/core/CoreXhr
or Alfresco.forms.Form
javascript classes when creating/updating/deleting data you will also not have to do anything. Everything will be handled for you by:Alfresco.util.Ajax & alfresco/core/CoreXhr
- will automatically take the token from the cookie and add it as a request header for every request.Alfresco.forms.Form
- will automatically take the token from the cookie and add it as a url parameter to when submitting an multipart/form-data
request.Alfresco.util.Ajax
will be used internally)Alfresco.util.CSRFPolicy.getToken()
.XmlHttpRequest
object or a 3rd party library such as jQuery. If that is the case you will need to add code looking something like this to pass the token:if (Alfresco.util.CSRFPolicy && Alfresco.util.CSRFPolicy.isFilterEnabled())
{
xhrHeadersObject[Alfresco.util.CSRFPolicy.getHeader()] = Alfresco.util.CSRFPolicy.getToken();
}
if (Alfresco.util.CSRFPolicy && Alfresco.util.CSRFPolicy.isFilterEnabled())
{
yuiDataSource.connMgr.initHeader(Alfresco.util.CSRFPolicy.getHeader(), Alfresco.util.CSRFPolicy.getToken(), false);
}
multipart/form-data
it is not possible to set a header on the request, the reason is not because of the enctype specifically but due to the fact that its not possible to set a header on any form submission in the browser. Therefor you need to pass the token as a url parameter instead. If you are using the Alfresco.forms.Form
class this will be handled for you automatically but otherwise you have to add the token as a url parameter using code looking something like this:if (Alfresco.util.CSRFPolicy && Alfresco.util.CSRFPolicy.isFilterEnabled())
{
url += '?' + Alfresco.util.CSRFPolicy.getParameter() + '=' + encodeURIComponent(Alfresco.util.CSRFPolicy.getToken());
}
flash.net.FileReference
ActionScript class which will perform a multipart/form-data
request) make sure to add the token as a url parameter in your Javascript before passing in the url to the flash movie. If your Flash movie is performing application/json
or other text based POST
requests (it uses the flash.net.URLRequest
and/or flash.net.navigateToURL
ActionScript classes and methods) then make sure to pass in the token and the name of the header so it can be set from the flash movie.flash.external.ExternalInterface
ActionScript class to call a custom javascript method you have included on the page.CSRFPolicy
config in your share-config-custom.xml
file to not check for a token or a Referer
or Origin
header. To do so simply:CSRFPolicy
config in share-security-config.xml
share-config-custom.xml
file and make sure it is replacing the old config section:<config evaluator='string-compare' condition='CSRFPolicy' replace='true'>
<filter>
element:<rule>
<request>
<method>POST</method>
<path>/page/trusted/call/1|/page/trusted/call/2</path>
</request>
<action name='assertReferer'>
<param name='always'>false</param>
<param name='referer'>https://www.trustedserver.com/.*</param>
</action>
<action name='assertOrigin'>
<param name='always'>false</param>
<param name='origin'>https://www.trustedserver.com</param>
</action>
</rule>
POST
:ing to /page/trusted/call/1
or /page/trusted/call/2
this (and no other) rule will be used and its actions will run. The first action will assert that full page url in the Referer
header (if present) equals https://www.trustedserver.com/.*
and that the protocol and domain in the Origin
header (if present) equals https://www.trustedserver.com
.http://www.my-proxy-server.com.evil-server.se/csrf.html
obviously starts with http://www.my-proxy-server.com
but not http://www.my-proxy-server.com/
.CSRFPolicy
config in share-security-config.xml
share-config-custom.xml
file and make sure it is replacing the old config section:<config evaluator='string-compare' condition='CSRFPolicy' replace='true'>
<action name='assertReferer'>
<param name='always'>false</param>
</action>
<action name='assertReferer'>
<param name='always'>false</param>
<param name='referer'>https://www.proxyserver1.com/.*|https://www.proxyserver2.com/.*</param>
</action>
<action name='assertOrigin'>
<param name='always'>false</param>
</action>
<action name='assertOrigin'>
<param name='always'>false</param>
<param name='origin'>https://www.proxyserver1.com|https://www.proxyserver2.com</param>
</action>
Referer
will contain the entire url from which the request was submitted but the Origin
will only include the protocol and domain (hence the .*
wildcard at the end of the referer
parameter).XMLHttpRequest
s or submitting forms you should contact the plugin developer and ask him to read this blog post so he/she can update the plugin. You will then have to make a decision to either uninstall your plugin OR lower the security level in the filter and not check for tokens anymore (at least until a new version of the plugin has been released). To stop checking for tokens, but continuing to check the Origin and Referer headers when available for logged in users, just add the following code snippet in your share-config-custom.xml
file:<config evaluator='string-compare' condition='CSRFPolicy' replace='true'>
<filter>
<rule>
<request>
<method>POST|PUT|DELETE</method>
<session>
<attribute name='_alf_USER_ID'>.*</attribute>
</session>
</request>
<action name='assertReferer'>
<param name='always'>false</param>
</action>
<action name='assertOrigin'>
<param name='always'>false</param>
</action>
</rule>
</filter>
</config>
share-config-custom.xml
file:<config evaluator='string-compare' condition='CSRFPolicy' replace='true'>
<filter/>
</config>
CSRFPolicy
config in share-security-config.xml
share-config-custom.xml
file and make sure it is replacing the old config section:<config evaluator='string-compare' condition='CSRFPolicy' replace='true'>
<rule>
<request>
<path>/proxy/alfresco/acme/special/services/.*</path>
</request>
<action name='throwError'>
<param name='message'>It is not allowed to access this url from your browser</param>
</action>
</rule>
CSRFPolicy
configuration. It is probably only worth reading in case you're really interested or have run into trouble.<config evaluator='string-compare' condition='CSRFPolicy'>
<!--
(Mandatory) Only 1 client element is allowed.
Describes what names are used to communicate the token back and forth
between the server and the client.
-->
<client>
<!--
(Mandatory) A client element must have exactly 1 cookie element.
Name of the cookie that will hold the token, used by the client side to
grab the value.
-->
<cookie>
<!--
(Mandatory) A client element must have exactly 1 header element.
Name of the custom Http header to place the token in when sending a request
-->
<header/>
<!--
(Mandatory) A client element must have exactly 1 parameter element.
Name of the parameter to place the token in when sending a request
-->
<parameter/>
</client>
<!--
(Mandatory) Only 1 filter element is allowed.
The filter will look for 1 rule with a matching request and execute its
actions (if any). An empty filter element means the CSRF filter is disabled,
in other words will allow all requests to pass.
-->
<filter>
<!--
(Optional) Zero or more rule elements are allowed.
A rule contains a description of a request and a set of actions to execute.
-->
<rule>
<!-- (Mandatory) A rule element must have exactly 1 request element -->
<request>
<!--
(Optional) A request element may have exactly 1 method element.
Holds a regular expression that will be matched against the request's
method.
-->
<method/>
<!--
(Optional) A request element may have exactly 1 path element.
Holds a regular expression that will be matched against the request's
'share path', i.e. /page/start-workflow or /proxy/alfresco/api/people
-->
<path/>
<!--
(Optional) A request element may have any number of header elements.
Holds a regular expression that will be matched by the header specified
by the name attribute.
-->
<header name=''/>
<!-- (Optional) A request element may have exactly 1 session element -->
<session>
<!--
(Optional) A session may have multipe attribute elements.
Holds a regular expression that will be matched by the session
attribute specified by the name attribute. A closed attribute element
indicates that the session attribute does not exist.
I.e. <attribute name='Alfresco-CSRFToken'/> means that the token has
not yet been created.
-->
<attribute name=''/>
</session>
</request>
<!--
(Optional) A rule element may have multiple action elements.
Below is a list of all available actions:
-->
<!-- Generate the token -->
<action name='generateToken'>
<!--
(Mandatory) An 'generateToken' action may have exactly 1 'session'
param.
Holds the name of the session attribute in which to place the token,
shall match the client element's session element above.
-->
<param name='session'/>
<!--
(Mandatory) A 'generateToken' action may have exactly 1 'cookie' param.
Holds the name of the cookie in which to place the token, shall match
the client element's cookie element above.
-->
<param name='cookie'/>
</action>
<!-- Clear the token value -->
<action name='clearToken'>
<!--
(Mandatory) A 'clearToken' action may have exactly 1 'session' param.
Holds the name of the session attribute which value shall be cleared,
shall match the client element's session element above.
-->
<param name='session'/>
<!--
(Mandatory) A 'clearToken' action may have exactly 1 'session' param.
Holds the name of the cookie which value shall be cleared, shall match
the client element's cookie element above.
-->
<param name='cookie'/>
</action>
<!--
Assert the request's Referer header matches the current domain.
If not an error will be thrown.
-->
<action name='assertReferer'>
<!--
(Mandatory) An 'assertReferer' action may have exactly 1 'always' param.
Decides when to compare the incoming requests Referer header to the
current domain, if set to:
- true: Always compare, even when no Referer header was provided in the
request.
- false: Only compare if a Referer header was provided in the request
-->
<param name='always'/>
<!--
(Optional) An 'assertReferer' action may have 0 or 1 'referer' param.
Holds a regular expression that will be matched against the incoming
Referer header if the incoming Referer header does not match Share's domain.
-->
<param name='referer'/>
</action>
<!--
Assert the requets's Origin header matches the current domain.
If not an error will be thrown.
-->
<action name='assertOrigin'>
<!--
(Mandatory) An 'assertOrigin' action may have exactly 1 'always' param.
Decides when to compare the incoming requests Origin header to the
current domain, if set to:
- true: Always compare, even when no Origin header was provided in the
request.
- false: only compare if a Origin header was provided in the request
-->
<param name='always'/>
<!--
(Optional) An 'assertOrigin' action may have 0 or 1 'origin' param.
Holds a regular expression that will be matched against the incoming
Origin header if the incoming Origin header does not match Share's
domain.
-->
<param name='origin'/>
</action>
<!-- Will throw an error -->
<action name='throwError'>
<!--
(Optional) A 'throwError' action may have exactly 1 'message' param.
Holds the error message that will be used when throwing the error.
-->
<param name='message'/>
</action>
</rule>
</filter>
</config>
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.