[jsr-314-open-mirror] [jsr-314-open] [Spec-869-Specify CSRF Solution] PROPOSAL
Roger Kitain
roger.kitain at oracle.com
Fri Oct 1 13:31:38 EDT 2010
Hey Alexander -
Thanks for the late feedback.
Comments inline..
On 10/1/10 1:22 PM, Alexander Smirnov wrote:
> I disagree with suggested proposal. There are two pitfalls:
> a) additional parameter just increases size of generated html code and
> number of request parameters. JSF forms always contain viewId parameter,
> so adding encoded token to that field will have minimal side effects.
> That token should be checked by StateManager before restoring view.
True - that JSF includes View state that at a bare minimum provides basic
CSRF protection. It is harder to guess the view state to get into a JSF app
if client side state saving is chosen. For server side state saving -
it's a bit easier.
Adding the extra field (which by the way is how Seam does it) enhances
the protection.
> b) URL parameter does not make sense for forms, but more important for
> 'GET' access. To make this parameter compatible with portal environment,
> it can be passed trough ExternalContext.encodeNamespace method ( while I
> think that it should be portal vendor concern, where secure token has to
> protect whole portal page ).
No - it does not make sense for forms. This proposal allows various
configuration options.
> c) For token encoded as url parameter this proposal protects whole
> application, so no one can either got logged in to protected site
> because of circular dependencies: to open login page, visitor has to
> have secure token, which one he can get only from JSF login page...
> There should be per-page security configuration.
True, it does. But we chose this option to have it implicitly done.
> On 09/30/2010 07:59 PM, Roger Kitain wrote:
>> Folks -
>>
>> I have combined the previous two proposals into one based on valuable
>> feed back from
>> Kito Mann and Neil Griffin:
>>
>> On 9/27/10 5:12 PM, Kito Mann wrote:
>>> On Tue, Sep 21, 2010 at 1:15 PM, Roger Kitain<roger.kitain at oracle.com
>>> <mailto:roger.kitain at oracle.com>> wrote:
>>>
>>>
>>> There are two proposals for enhancing CSRF attacks in JSF. We
>>> need to pick one.
>>>
>>>
>>> Why? I think it's actually safer to allow both:
>>> http://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#Disclosure_of_Token_in_URL.
>>> According to this, appending the token works better when you can't
>>> guarantee that a server-side operation is occurring only through POST.
>>> Especially with the new capabilities of JSF 2 for parsing view
>>> parameters, I don't think we can make this guarantee.
>>>
>>> Also, the rewriting approach is what they're using for the generic
>>> filter in Tomcat 7:
>>> http://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet#Disclosure_of_Token_in_URL.
>>> I was talking to Mark Thomas, the guy working on this feature, about
>>> this at JavaOne. As you can see, it doesn't even look like they're
>>> using the hidden field approach (probably because it'd be very hard to
>>> implement in a generic fashion).
>>>
>>> So, I think we should provide both features, but give the users to
>>> turn off either algorithm, with a context parameter such as:
>>>
>>> javax.faces.CSRF_ALGORITHM=NONE | FORM | URL | BOTH (or ALL)
>>>
>> On 9/21/10 4:20 PM, Neil Griffin wrote:
>>> #1 is probably not compatible with portlets. Portals are in full
>>> control of creation of URLs in general, and it is not possible to
>>> simply append "&javax.faces.Token=XYZ" to a portal's ActionURL and
>>> expect it to work.
>>>
>>> #2 is compatible with portlets, but it would be best to have the
>>> hidden field namespaced. Otherwise it would be like
>>> javax.faces.VIEW_ID which is not namespaced, and can cause problems in
>>> portals.
>>> Neil
>> ==============================================
>>
>> This proposal does the following:
>>
>> - Token is generated on the server consisting (minimally) of a randomly
>> generated "secret key" (stored in session). The token can be generated
>> upon session creation, or, at the time the token hidden field and/or
>> token Url parameter is produced.
>>
>> - Standard context parameter javax.faces.CSRF_ALGORITHM controls where the
>> token is produced by the following values:
>> a. "form" : token is produced as the value of the hidden field with the name
>> <form client id>:javax.faces.Token where<form client id> is the
>> enclosing form's client identifier (produced with getClientId) - i.e.
>> the hidden field is namespaced using the form's client identifier.
>> b. "url" : token is produced and appended as a parameter to the form's
>> action Url with the same name as in [a].
>> c. "all" : token is produced as in [a] *and* [b]
>> d. "none" : no token is produced
>> The default is [a] "form".
>>
>> - After render time, a subsequent action will send the token to the server.
>> - Restore View Phase processing compares the incoming token request parameter
>> value with the token value generated from the secret key in the session.
>>
>> Spec Document Modifications:
>>
>> Section 7.5.1:
>>
>> getActionURL:
>>
>> The returned URL must contain the
>> parameter with a name consisting of the form's fully namespaced
>> client identifier, the NamingContainer.SEPARATOR_CHAR and the constant
>> defined by ResponseStateManager.VIEW_TOKEN_PARAM,
>> if the configuration option javax.faces.CSRF_ALGORITHM
>> is set to "url" or "all". The value of this parameter, known
>> as the "token value" must be a cryptographically produced random generated
>> value (known as the "secret key") retrieved from the session. If the
>> "secret key" does not already exist in the session, create the random value
>> and store it in the session. Implementations may choose to produce a more
>> complex token value by combining the random "secret key" with other values.
>>
>>
>> Section 2.2.1
>>
>> "If the value of the configuration option javax.faces.CSRF_ALGORITHM
>> is not "none" verify the "javax.faces.Token" request parameter value is
>> the same as the token value generated from the "secret key" stored in the
>> session. If the values do not match, throw a meaningful exception.
>> The exception message must not include the token value."
>>
>> Standard RenderKit Docs
>>
>> - Form Rendering
>>
>> Render a hidden field named javax.faces.Token using the
>> ResponseStateManager.VIEW_TOKEN_PARAM constant if the configuration option
>> javax.faces.CSRF_ALGORITHM is set to the key words "form" or "all".
>> The name must be namespaced with the enclosing form's client identifier. Render
>> the value of this hidden field, known as the "token value", as a cryptographically
>> produced random generated value (known as the "secret key") retrieved from the
>> session. If the "secret key" does not already exist in the session, create the random value and
>> store it in the session. Implementations may choose to produce a more complex token value by
>> combining the random "secret key" with other values.
>>
>> Implementation Changes are attached to this issue:
>>
>> [1] https://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=869
>>
>>
>> -roger
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> --
>> roger.kitain at oracle.com
>> https://twitter.com/rogerk09
>> http://www.java.net/blogs/rogerk
>>
--
roger.kitain at oracle.com
https://twitter.com/rogerk09
http://www.java.net/blogs/rogerk
More information about the jsr-314-open-mirror
mailing list