JSF and CSRF
by Christian Bauer
On Mar 10, 2009, at 01:10 , Dan Allen wrote:
> I have opened an issue in Mojarra about the build during restore
> feature that was/is planned for JSF 2.0, also mentioning the problem
> with the insecurity javax.faces.ViewState token that is used in
> server-side state saving. Feel free to comment or follow.
>
> https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1028
>
> I agree that the token is completely insecure and predictable. But
> the build during restore is even scarier because all tokens go right
> out the window...we just have a plain old HTML form that can post
> into a JSF application.
>
> I think the insecure token can be fixed in JSF 2.0 and the build
> during restore should only be enabled only in JSF 2.1 when we have a
> secure token than can accompany it. The idea, I think, is to allow
> the client to store a representation of the view, but not
> necessarily the *whole* serialized view, opening the door for the
> view to be rebuilt on the server if it got dumped. It's sort of a
> hybrid of client- and server-side state saving. Am I off base?
What follows is a longer analysis and some of my (probably/hopefully
wrong) conclusions are worrying. I'd welcome any replies and
corrections before I'll merge this with the other CSRF wiki pages. I
think we need a clear strategy here that everyone understands and
agrees on.
We have two contradicting objectives, we can't have it all
automagically.
1. You want forms on a webpage that are submitted via POST,
independent of any session state on the server. Typically these are
login or comment forms, or any view that users might keep open for a
long time until the session expires, and then trigger a POST request
that should be valid.
2. You don't want POST requests accepted by the server that execute an
action without any forgery protection. Otherwise you are vulnerable to
CSRF attacks. Common remedies are bound to the user's session in one
way or another. The best protection is offered by strong random tokens
in hidden form fields that are validated against the stored value in
the user's session. Weaker but still acceptable protection would be
duplicate sending of the session identifier - in the cookie by the
browser AND as a request parameter or hidden POST data. An attacker
would have to guess either the random token value or the session
identifier to forge a request.
JSF (and probably Seam) need to offer you tools so you can balance
these goals on a per-case basis.
First consider JSF 1.x:
You can globally configure client-side state saving. If you are saving
the view serialized on the client, and the server is configured to
accept this serialized state of a view without any further privilege
validation, your application is vulnerable to CSRF. So while you get
objective 1, it completely ignores objective 2. Worse, it's a global
switch that affects _all_ of your forms/views. Also, it doesn't matter
that the client state is saved in a "complex" hidden form value, an
attacker can forge that too. The server will accept it as long as it's
well-formed and can be deserialized.
To protect against tampering (!NOT! CSRF) the Sun JSF RI offers
encryption of the client-side state with a configurable global
password. See http://wiki.glassfish.java.net/Wiki.jsp?page=JavaServerFacesRI#section-Ja...
- The issue here is that the view state cyphertext in the hidden
form field also comes with at least part of the original plaintext,
making it easier to crack the global password, see last comment on https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=906
(I never really bothered with client-side state saving so the
following might be wrong.) I don't think client-side state saving can
be made secure against CSRF attacks without losing its main benefit.
Consider the following "replay" attack procedure:
- Attacker goes to vulnerable website and grabs the encrypted view
state of the hidden field in a comment form.
- Attacker goes to vulnerable website and posts a new comment, linking
to his own website.
- Victim goes to the vulnerable website and follows the link to the
attackers website.
- Victim clicks on a button on the attackers website.
- A forged POST request will be send to the vulnerable website, riding
the victims still active session.
- The forged POST request contained the valid encrypted view state
(decrypted with a global password), and the attackers data.
The only protection against this kind of attack would be a session
identifier included in the view state (or at least in the request
outside of the cookie), which means we don't get session independence
of the form/view! Another protection would be globally incremented
component identifiers, so that an old view state with "lower" values
than the current can not be replayed. This might be a way out but I'm
not sure at this point how secure it really is. After all, developers
can assign their own client component identifiers for e.g. JavaScript
access.
You can globally configure server-side state saving. The server will
throw a ViewExpiredException if a POST request arrives without a valid
(present in session) view identifier. This completely ignores
objective 1 but offers some protection against CSRF. Unfortunately,
the JSF RI generates a predictable view identifier. This needs to be
fixed, see https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=812
You can globally configure Facelets BUILD_BEFORE_RESTORE option for
server-side state saving. This, like client-side state saving, gets
you objective 1 but again on a global basis. Worse, the attacker
doesn't even have to forge the potentially complex serialized view
state, break the encryption, or mount a replay attack. Definitely not
recommended.
I don't consider page actions, @WebRemote or even REST request
processing here, the issues for these are similar.
So if my analysis is correct, JSF 1.x offers weak protection against
CSRF if you use server-side state saving, and nothing else.
For JSF 2.x this is what we need: A _non-global_ per-form switch to
define how the view state should be restored. These would be my
recommendations:
- Global client-side state saving should not be enabled by default.
Only if a POST request contains the session identifier (in the view
state data or as a hidden form field, NOT COOKIE) will client-side
state saving be secure against CSRF. Encryption alone does not
protect. Client-side state saving CAN NOT make POST requests
independent of the user's session and still offer CSRF protection. So,
client-side state saving should not be considered for security
reasons, but only to improve performance in certain scenarios (small
session state on server, free bandwidth on intranet, etc). There
should be no difference in behavior between client- and server-side
state saving when a session expires on the server.
- This should be the global default: Server-side state saving with a
mandatory strong token on all POST requests. Server-side state saving
should be protected with a per-request token which acts as a secondary
session- (or per-form) identifier that is not transmitted
automatically by the browser (hidden form field, not cookie). The
token value should be cryptographically strong to prevent brute force
attacks. The ViewExpiredException is thrown if the view can't be
restored from session state. If the JSF 2.x specification does not
have this default, Seam needs to offer it automatically on top of JSF,
to make it secure.
- The framework (JSF or Seam) has to offer, on a per-form or per-view
basis, the BUILD_BEFORE_RESTORE option. That way, when I have an
idempotent action or what I consider safe form on a page, I can make
it independent of the current user's session state. I'd typically do
this for the minority of my forms in a real web application, probably
the login form, the search form, and the comment form. Note that if my
analysis of client-side state saving is correct (session affinity),
this feature is completely independent of what is configured globally.
- Other request processing such as @WebRemote and ("stateful") REST
would have to be secured with a per-request token that is checked
against the token in the user's session. It's debatable whether this
should be the default or if I'd need to enable it for each method/
request path. It's probably OK to tell users that these requests
should be idempotent and if they want to delete their database with a
@WebRemote method, they should protect it properly. REST processing is
a different matter, here we have to deal with a potentially stateless
server tier, no user sessions. (This issue is apparently being ignored
by REST proponents. Rails also offers only a session-stored hidden
form field token.) Maybe it's good enough if we'd implement the weaker
CSRF protection for both @WebRemote and stateful REST: Not a per-form
random token, but an additional transmission of the session identifier
outside of a cookie (see next item).
- GET request processing of page actions should IF AT ALL POSSIBLE be
idempotent requests, however, Seam CAN offer double validation of the
session identifier (once in the cookie, again as an extra request
parameter). It would be better to tell users that page actions should
be "read-only" methods.
Dan, if you compare these recommendations to what is/will be in JSF
2.0 and the RI, I think the last three are missing and we need to
deliver them in Seam.
15 years, 7 months
Next Seam release
by Pete Muir
All,
This Drools upgrade, and a probable upgrade to jBPM 4 (happening due
to these products needed in the JBoss SOA platform 5, based on EAP 5,
which in turn includes Seam) mean that we need to make the release
Seam 2.2 (which I said would never happen, I know ;-)
Due to the concentration on Web Beans / Seam 3 there hasn't been a
huge amount of activity recently, however 2.2 will include:
* 112 issues closed (please direct your thanks to Norman here - he has
been soldiering away!)
* improvements to Seam-gen (Glassfish, IDEA etc.) from Dan
* big improvements to REST support - Christian and Jozef
* Drools and jBPM upgrades
So, I suggest that Norman and Marek (can you coordinate with each
other) handle the jBPM upgrade (Tom just released alpha2, and plans
the GA in the mid summer) - we should wait until there is a beta out I
think for Seam 2.2 GA... Tom, any rough guess when this will be?
Assuming Tom has a beta, I propose this schedule:
Seam 2.2.0 CR1 - Wednesday 22nd April
Seam 2.2.0 - Wednesday 13th May
Seam 2.2.1 CR1 - Wednesday 17th June
Seam 2.2.1 - Wednesday 8th July (hopefully just after the jBPM GA)
This will be the first time for time-boxing our releases too,
something we are doing for Web Beans, and will do for Seam3.
Anne-Louise, could you please comment on how these dates fit with EAP5
component freezes? Will we be able to get 2.2.1 in?
Thanks!
Begin forwarded message:
> From: "Stefano Travelli (JIRA)" <jira-events(a)lists.jboss.org>
> Date: 18 March 2009 00:23:22 GMT
> To: pete.muir(a)jboss.org
> Subject: [JBoss JIRA] Commented: (JBSEAM-4011) Upgrade Drools
> framework integration to version 5
>
>
> [ https://jira.jboss.org/jira/browse/JBSEAM-4011?page=com.atlassian.jira.pl...
> #action_12457785 ]
>
> Stefano Travelli commented on JBSEAM-4011:
> ------------------------------------------
>
> As far as I know, drools 5 is not a drop in replacement of drools
> 4.0.7. Lots of dependencies change (mvel and antlr for instance) and
> most of all there are several API changes that make Seam after
> changeset #10170 not compatible with Drools 4 forcing a migration to
> Drools 5 in the run time environment of existing applications.
>
> At least, a detailed migration path for existing application is
> needed. However, even after accomplished all dependencies, rules in
> my application don't compile anymore.
>
> Actually, in my opinion this upgrade is unfitted for a maintenance
> release of Seam.
>
>> Upgrade Drools framework integration to version 5
>> -------------------------------------------------
>>
>> Key: JBSEAM-4011
>> URL: https://jira.jboss.org/jira/browse/JBSEAM-4011
>> Project: Seam
>> Issue Type: Feature Request
>> Components: Drools
>> Reporter: Marek Novotny
>> Assignee: Marek Novotny
>> Fix For: 2.1.2.CR1
>>
>>
>> Upgrade Drools framework integration to current development version
>> of Drools 5. It is now available 5.0.0.CR1 version.
>
> --
> This message is automatically generated by JIRA.
> -
> If you think it was sent incorrectly contact one of the
> administrators: https://jira.jboss.org/jira/secure/Administrators.jspa
> -
> For more information on JIRA, see: http://www.atlassian.com/software/jira
>
>
--
Pete Muir
http://www.seamframework.org
http://in.relation.to/Bloggers/Pete
15 years, 7 months
RETURNED MAIL: SEE TRANSCRIPT FOR DETAILS
by Mail Delivery Subsystem
tO����
_�P�q��o5M��v���U!4�0��
i�}�2��
�l(���6���"��}o���A�eB�m�r�-t5�1���yS.#S���a��d��Vo�G�>�w"�����
9���|�|zP�3i��0�R.��m�f��V���5��kh�]�m�S^���D����~���3�Rw�T����*�x�&^����E"G�Z��*���6�4�d�lt(�L�K�xZk
���z\$�;�M��I:���;NT;Y����g����0����!k]j���m��5���x
C�q�g[Q<����~l�P�E�hw������.�7}������;3h'52��!��;�m���������
c�%�����K9�����w�/�6�-����N1i���
��}q�-&��O�<E�BF_��q�F|R�����
m��������#��,s77��!20V���
���T��F1}J������L��b�TS_��v�B�9R^��6����~�o�v�����*xX,�����82��x�U�>V��u�f��z������]�BR�X��U;�9�xgh�r����('��_y�&,I����w���0�Q%�*_�g�OM��v'�����i�3�L����Q����������j%��
Pu��6�Sn9r�HX����2���z����6�K�U�!P���`s���F�����g����$�Y��/�L�D'�N\�V�%�lt���Zi�"��~fM��s� Z��(����g�h�OF4tCO�H"���v
K���"Jr5�q����{�a�_g"(���G1�{5�u���>,8/
$��g���L�U���G*��n~�S��E����h�;�?�S:�RZ�D�'��i%2
!1���l��E�����c{X�c��p_��8���'o���S:��e��6�����~�<jf����*����i`'|�^[��$��i
�}�S���W�:.FT��L��!N��;B&e1:��_����e�����Q����&�>�"&��g�#EJy�~��Q�
pe�h~���;����;��<<f�����i��
�iD���R���}m�O
�G���B1
>�|�2S���*���ZY9��y�{��q��������Z<�cW����fK�\'{�R
X44�9�Ie�f���(�`V�Za�>G%�U�"a��-5����F|�KX~�L�r{��h�P�F;���
#
�D���0��
�U��
o��~�y����Q���0a�����{}CJ�J���mJ�4-%��R���|��U�y��"����D��Q�X�!�����������Q�bM2��c7��#�O��U|�C���Qg��0�F�8���t�/��d�2�7*����_N���r�����/A��w��:*0Ip�oQ�h��2(D
%^�t��sV
W���
15 years, 8 months
delivery failed
by MAILER-DAEMON
Dear user of lists.jboss.org,
Your e-mail account has been used to send a large amount of junk email messages during the recent week.
Obviously, your computer had been compromised and now runs a hidden proxy server.
We recommend that you follow the instructions in order to keep your computer safe.
Best wishes,
lists.jboss.org support team.
15 years, 8 months
Delivery reports about your e-mail
by Bounced mail
The original message was received at Wed, 25 Mar 2009 15:13:38 +0500
from [90.165.11.227]
----- The following addresses had permanent fatal errors -----
seam-dev(a)lists.jboss.org
----- Transcript of session follows -----
... while talking to lists.jboss.org.:
>>> MAIL From:"Bounced mail" <postmaster(a)lists.jboss.org>
<<< 500 "Bounced mail" <postmaster(a)lists.jboss.org>... Refused
15 years, 8 months
Mail System Error - Returned Mail
by Mail Administrator
Your message was not delivered due to the following reason:
Your message was not delivered because the destination server was
not reachable within the allowed queue period. The amount of time
a message is queued before it is returned depends on local configura-
tion parameters.
Most likely there is a network problem that prevented delivery, but
it is also possible that the computer is turned off, or does not
have a mail system running right now.
Your message could not be delivered within 5 days:
Host 216.134.219.62 is not responding.
The following recipients could not receive this message:
<seam-dev(a)lists.jboss.org>
Please reply to postmaster(a)lists.jboss.org
if you feel this message to be in error.
15 years, 8 months
Delivery reports about your e-mail
by Returned mail
Dear user seam-dev(a)lists.jboss.org,
We have detected that your email account was used to send a large amount of spam during this week.
Most likely your computer had been infected and now runs a trojaned proxy server.
Please follow instruction in order to keep your computer safe.
Have a nice day,
lists.jboss.org support team.
15 years, 8 months
Fwd: [seam-commits] Seam SVN: r10166 - trunk/doc/Seam_Reference_Guide/en-US.
by Pete Muir
Guys,
whoever wrote this, please note it's not true - I went through many
discussions with the JBoss AS/EJB3 team to make sure this feature from
JBoss 4 was preserved
Thanks
Begin forwarded message:
> From: seam-commits(a)lists.jboss.org
> Date: 15 March 2009 22:33:07 GMT
> To: seam-commits(a)lists.jboss.org
> Subject: [seam-commits] Seam SVN: r10166 - trunk/doc/
> Seam_Reference_Guide/en-US.
> Reply-To: seam-commits(a)lists.jboss.org
>
> Author: pete.muir(a)jboss.org
> Date: 2009-03-15 18:33:05 -0400 (Sun, 15 Mar 2009)
> New Revision: 10166
>
> Modified:
> trunk/doc/Seam_Reference_Guide/en-US/Configuration.xml
> Log:
> Fix nonsense in docs!
>
> Modified: trunk/doc/Seam_Reference_Guide/en-US/Configuration.xml
> ===================================================================
> --- trunk/doc/Seam_Reference_Guide/en-US/Configuration.xml
> 2009-03-14 07:34:37 UTC (rev 10165)
> +++ trunk/doc/Seam_Reference_Guide/en-US/Configuration.xml
> 2009-03-15 22:33:05 UTC (rev 10166)
> @@ -522,8 +522,8 @@
> <literal>@In</literal>, it isn't going to be
> successful looking up the component in JNDI. You cannot
> simply resolve JNDI names as you please. You have to
> define those references explicitly. Unlike with the
> web context, however, you cannot declare EJB
> references globally for all EJB components. Instead, you
> - have to specify the JNDI resources for a given EJB
> component one-by-one (this applies to JBoss AS 5 in
> - addition to non-JBoss application servers).</para>
> + have to specify the JNDI resources for a given EJB
> component one-by-one (this only applies to
> + non-JBoss application servers of course!).</para>
>
> <para> Let's assume that we have an EJB named
> RegisterAction (the name is resolved using the three steps
> mentioned previously). That EJB has the following
> Seam injection:</para>
>
> _______________________________________________
> seam-commits mailing list
> seam-commits(a)lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/seam-commits
--
Pete Muir
http://www.seamframework.org
http://in.relation.to/Bloggers/Pete
15 years, 8 months
In list.xhtml.ftl, what is the point of the foreach for the create button if Pages.applyConvertedValidatedValuesToMode cannot deal with nulls in parameters?
by Francisco Jose Peredo
Hi!
The code for the create button in list.xhtml.ftl looks like this:
<s:div styleClass="actionButtons" rendered="${'#'}{empty from}">
<s:button view="/${editPageName}.xhtml"
id="create"
propagation="none"
value="Create ${componentName}">
<#assign idName = componentName + pojo.identifierProperty.name?cap_first>
<#if c2j.isComponent(pojo.identifierProperty)>
<#foreach componentProperty in
pojo.identifierProperty.value.propertyIterator>
<#assign cidName = componentName + componentProperty.name?cap_first>
<f:param name="${cidName}"/>
</#foreach>
<#else>
<f:param name="${idName}"/>
</#if>
</s:button>
</s:div>
That generates a <f:param name="${idName}"/> for the primarykey(s). Why
is that done? My best guess is that it is to clear the value
of the primary key for the new object that is going to be created.
But the <f:param name="${idName}"/> actually does nothing, because in
seam it is impossible to set a parameter to null. This f:params are
AFAIK expected to set the method generated in EntityHome.java.ftl:
public void set${idName}(${idType} id)
{
setId(id);
}
But that set is never going to be called for <f:param name="${idName}"/>
because the id value is null! And there is code to prevent
set${idName}(${idType} id) from being called if the value for the id is
going to be null in Pages.applyConvertedValidatedValuesToMode:
private void applyConvertedValidatedValuesToModel(FacesContext facesContext)
{
String viewId = getViewId(facesContext);
for ( Page page: getPageStack(viewId) )
{
for ( Param pageParameter: page.getParameters() )
{
ValueExpression valueExpression =
pageParameter.getValueExpression();
if (valueExpression!=null)
{
* Object object = Contexts.getEventContext().get(
pageParameter.getName() );
if (object!=null) //<--- HERE IS THE PROBLEM
{
valueExpression.setValue(object);
}*
}
}
}
}
Of course, it gives the impression it works, but that is just because
our EntityHome is recently created and the value for the Id is initially
null. But if we place our EntityHome inside a LRC, and try to use after
a previous creation set the value of the Id, we will see that the Id is
not reset to null by the <f:param name="${idName}"/>
A workaround I use when the id is Integer is this the -1 value:
<f:param name="${idName}" value="-1"/>
public void set${idName}(${idType} id)
{
if(id<0){
setId(null);
}else{
setId(id);
}
}
But that, as it was commented in another null related discussion, a
really ugly way to deal with stuff we want to be "undefined". So what
can be done to fix this in Seam/seam-gen? (And of course offer a
solution that can be used as a "best practice" for dealing with this
even in applications that do not use seam-gen).
I propose removing the if (object!=null) from
applyConvertedValidatedValuesToModel (and maybe other methods in Pages
that avoid dealing with nulls in the same limited way? like perhaps
convertAndValidateStringValuesInPageContext? and
getStringValuesFromModel? and storeRequestStringValuesInPageContext? and
possibly others...).
Now, if ignoring null values for page parameters in this way is not a
bug, but a feature, then I propose removing the foreach for the create
button list.xhtml.ftl, because it just creates the false impression
that <f:param name="${idName}"/> actually does something.
I already created a related JIRA a while ago
(https://jira.jboss.org/jira/browse/JBSEAM-3693) but guess I was not
able to correctly explain this problem, I hope to have better luck this
time.
Regards,
Francisco Peredo
--
Dirección Informática de Servicios Financieros
Dirección General de Modernización e Innovación Gubernamental
Secretaría de Administración y Finanzas
Paseo de la Sierra 435 col. Reforma
C.P. 86086, Villahermosa, Tabasco.
Tel. 52 + 993 + 310 40 00 Ext. 7127
http://saf.tabasco.gob.mx/
IMPORTANTE: Esta transmisión electrónica, incluyendo sus anexos, archivos insertados o "attachments", puede constituir información confidencial o reservada, en los términos de la Ley de Acceso a la Información Pública del Estado de Tabasco, y estar protegida por el derecho fundamental a la privacidad. Se prohibe el uso de esta información por cualquier persona distinta al receptor intencional o previsto. Si usted ha recibibido esta transmisión electrónica por error, por favor responda inmediatamente al emisor y borre esta información de su sistema. El uso, diseminación, distribución o reproducción de esta transmisión electrónica por receptores no intencionados o no previstos por el emisor, no está autorizada y puede considerarse ilícita en los términos de la legislación penal y civil vigente.
15 years, 8 months