History | Log In     View a printable version of the current page. Get help!  
Issue Details (XML | Word)

Key: JBSEAM-2931
Type: Task Task
Status: Closed Closed
Resolution: Done
Priority: Minor Minor
Assignee: Norman Richards
Reporter: Felix Ho?feld
Votes: 0
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
Seam

Improve the exception thrown by an insecure order by clause

Created: 28/Apr/08 11:02 AM   Updated: Thursday 03:00 PM
Component/s: Framework
Affects Version/s: 2.0.1.GA
Fix Version/s: 2.1.0.BETA1 , 2.0.2.GA

Original Estimate: Unknown Remaining Estimate: Unknown Time Spent: Unknown
Issue Links:
Related
 
This issue is related to:
JBSEAM-2099 Support protection against SQL inject... Critical Closed

JBoss Forum Reference: http://www.jboss.com/index.html?module=bb&op=viewtopic&t=119810


 Description  « Hide
We have an existing application running Seam 1.2. Today I tried upgrading to Seam 2.0.1.GA. In the process I discovered that the fix for JBSEAM-2099 breaks the application because the application uses lots of query objects with an order clause that sorts on the result of an function, namely UPPER(): order="UPPER(p.lastname)".

This used to work under 1.2. So this is a regression that probably does affect a lot of real world applications. I have suggested the original fix and have to say it is not done probably. Even my latest version is not the proper way to fix this as it will not allow functions with multiple arguments, nor concatenations of properties, nor computing the order by-value... To fix this properly it definitly takes an EJBQL-Expert greater than me :-) I'm not even sure if there is an SQL-Injection threat here.

I don't mind implementing an insufficient fix for my special problem myself by extending the Query object and binding that to a custom namespace but I would appreciate if
a.) the regression would be properly documented, and
b.) the error message would tell the user what happened and what is necessary to fix it.

 All   Comments   Work Log   Change History   Subversion Commits      Sort Order:
Felix Ho?feld [28/Apr/08 11:29 AM]
Sorry, I could not reopen JBSEAM-2099 so I have cloned it.

The fix for JBSEAM-2099 does not work as expected because the regular expression is too restrictive.


When I suggested the regex for input filtering I did not think of funtion based order clauses which are quite common in the real world, e.g.



<framework:entity-query name="qry_allPersons"
ejbql="SELECT p FROM Person p" entity-manager="#{entityManager}" order="UPPER(p.lastname)">
</framework:entity-query>

The query will raise an invalid argument exception "invalid order clause" because the order clause does not match the regular expression
"^[\\w\\.,\\s]*$" defined in ORDER_CLAUSE_PATTERN). (http://fisheye.jboss.com/browse/Seam/trunk/src/main/org/jboss/seam/framework/Query.java?r=7173).

I suggest changing this to

^(\\w+\\([\\w\\.\\s]+\\)\\s*,\\s*|[\\w\\.]+\\s*,\\s*)*(\\w+\\([\\w\\.\\s]+\\)|[\\w\\.]+)

which will alo match something like:

UPPER(p.lastname), p.age, LOWER(p.country).



Felix Ho?feld [28/Apr/08 11:29 AM]
The original issue that created the issue

Felix Ho?feld [28/Apr/08 11:30 AM]
Teh original issue that introduced the problem

Norman Richards [28/Apr/08 11:49 AM]
We aren't going to play regexp games with fields that we are supporting direct UI binding for. If you want a complex order clause that can be set from a UI binding, you'll need to subclass and accept responsibility for the SQL injection protection yourself.

Felix Ho?feld [28/Apr/08 11:59 AM]
Fair enough but I think that restriction should be mentioned into the docs because function based sorting is quite common.

And it would also be nice if the error message would be more informative, e.g. "Invalid order clause \" + order +"\". Your order clause must not contain any special charcters."

Pete Muir [28/Apr/08 12:34 PM]
Unscheduling issue, we can't fix for a released version.

Felix, please make this issue describe the problem you want fixed *now*.

Felix Ho?feld [28/Apr/08 02:34 PM]
We have an existing application running Seam 1.2. Today I tried upgrading to Seam 2.0.1.GA. In the process I discovered that the fix for JBSEAM-2099 breaks the application because the application uses lots of query objects with an order clause that sorts on the result of an function, namely UPPER(): order="UPPER(p.lastname)".

This used to work under 1.2. So this is a regression that probably does affect a lot of real world applications. I have suggested the original fix and have to say it is not done probably. Even my latest version is not the proper way to fix this as it will not allow functions with multiple arguments, nor concatenations of properties, nor computing the order by-value... To fix this properly it definitly takes an EJBQL-Expert greater than me :-) I'm not even sure if there is an SQL-Injection threat here.

I don't mind implementing an insufficient fix for my special problem myself by extending the Query object and binding that to a custom namespace but I would appreciate if
a.) the regression would be properly documented, and
b.) the error message would tell the user what happened and what is necessary to fix it.

Pete Muir [28/Apr/08 02:57 PM]
I tidied up the issue for you...

Norman Richards [28/Apr/08 06:34 PM]
Yes, we can improve the message on the exception.

Yes, we should do more to document the huge hole that was in Seam and strongly urge people not to try and do this kind of thing. Please, please please, do not try and pass type of data in from the UI. Bind to properties that you will consult to independently construct a query. The fact that that by breaking the old code we might alert people that they almost certainly already had broken code is a pleasant side effect of this change that I really didn't consider.

Note - unless you are trying to change the order parameter from a UI binding, the santizing code should not be called and there should be no error regardless of how you craft the order by clause.



Felix Ho?feld [29/Apr/08 04:19 AM]
> we should do more to document the huge hole that was in Seam and strongly urge people not to try and do this kind of thing.

I perfectly agree. In the opriginal issue I recommended myself this warrants an official advisory and a backport of the patch to 1.2. Since most people think EJBQL is not SQL they assume that they are safe from any SQL injection.

> Note - unless you are trying to change the order parameter from a UI binding, the santizing code should not be called and there should be no error regardless of how you craft the order by clause.

The check against the regex is in the order-acessor so it is called every time regardless whether the order clause was created by an EL expression or is hardcoded into the query object. The example I already posted above will fail:

<framework:entity-query name="qry_allPersons" ejbql="SELECT p FROM Person p" entity-manager="#{entityManager}" order="UPPER(p.lastname)" />

Now in this case it would be trivial to fix this by rewriting this query as

<framework:entity-query name="qry_allPersons" ejbql="SELECT p FROM Person p ORDER BY UPPER(p.lastname)" entity-manager="#{entityManager}" />

but I assume this does not work if I wish to add restrictions. Is this correct?

IMHO the best solutions would be to add an additional element to the entity-query element called "order" with two attributes "by" and "valid". If this alement is missing the behaviour is exactly as it is now. But if you feel lucky you can do something like this:

<framework:entity-query name="qry_allPersons" ejbql="SELECT p FROM Person p" entity-manager="#{entityManager}" />
   <framework:order by="UPPER(#{TestAction.orderBy})" valid="^UPPER(\w+(\.\w+)*)" />
</framework:entity-query>

Then Seam should for check if the by attribute contains an EL expression and if it does but the valid attribute was not set it would fail with an exception. This would force people to think about security but still allow people to make (more or less) informed choices about what they wish to allow. However, it would still allow stupid people to do stupid things like:

   <framework:order by="#{facesContext.externalContext.requestParameterMap['order']}" valid=".*" />

I have to solve the issue anyway today so I will post what I will come up with.

Pete Muir [30/Apr/08 11:26 AM]
I improved the exception message. Norman, if you want to improve the docs, we can do that before the GA.