I have a basic question about JSF ManagedBeans for which I can't find a answer.
Suppose I have a bean MyBean with two methods method1 and method2 and a JSF page with a command link
<h:commandLink action="#{myBean.method1}">
</h:commandLink>
Is it possible for someone to analyse the source code of the page and call method2 instead of method1?
Answer
No, this is not possible by design.
Reasoning
Technically the client can only tell the server "The user clicked a html element with a certain id".
This event is then processed by JSF on the server-side, the component with the corresponding id is looked up and in this case the method "#{myBean.method1}" is executed.
As you can see, the client can not[!] tell the server what to do with this event.
Sources
JSF 2.2 Spec - 3.4 Event and Listener Model
Caveat
JSF is stateful and there are multiple ways to hold this state. The default is to hold state information server-side (e.g. in the users HttpSession).
Another option is to transfer (encrypted) state to and from the client. This is still conceptionally secure, but there *might* be bugs with client side state saving. Such a bug *could* be exploitable to do something like you described.
Yes, it is always possible to modify code (or markup-language) on the client-side. Your "action" will be called through some forms and/or Javascript-Methods - everything visible to experienced users.
But that's not an issue of JSF-2 only - this applies for every language which allows insights from the client side.
You shouldn't apply "security through obscurity" (https://en.wikipedia.org/wiki/Security_through_obscurity) but rather make sure, that you can handle this on the server-side.
If a user, who has access to two urls modifies url1 to url2 - that's fine, why not? (Could be bookmarked) - But YOU should take care of the modified request, if he is not allowed to access url2.
Related
We have been securing our backing bean methods using a custom #Secure interceptor to prevent forged invocations of the method.
But recently, it hit me that these methods are not reachable if the component invoking the action is not rendered. It is my understanding that JSF will generate the view, and if the component is not rendered based on permissions (e.g. EL with isUserInRole), then any forged POST with that component as the source will not fire because the component will not be found in the restored view. Is this correct?
Essentially, any forgery would have to have a compromised and current JSESSIONID and perhaps even ViewState depending on whether they needed the same view.
Can someone please confirm that my assumptions are correct and, if possible, point me to a place in the spec?
Thanks
Ok,I think I have confirmation that actions for non-rendered components are indeed not reachable according to the spec.
Section 2.2.2 of the specification states:
During the Apply Request Values phase, the JSF implementation must
call the processDecodes() method of the UIViewRoot of the component
tree.[P1-end] This will normally cause the processDecodes() method of
each component in the tree to be called recursively, as described in
the Javadocs for the UIComponent.processDecodes() method.
It also states:
During the decoding of request values, some components perform special
processing, including: Components that implement ActionSource (such as
UICommand), which recognize that they were activated, will queue an
ActionEvent. The event will be delivered at the end of Apply Request
Values phase if the immediate property of the component is true, or at
the end of Invoke Application phase if it is false.
So ActionSource components will only queue an action if they are processed according to processDecodes. Looking at the javadoc for that:
Perform the component tree processing required by the Apply Request
Values phase of the request processing lifecycle for all facets of
this component, all children of this component, and this component
itself, as follows.
If the rendered property of this UIComponent is false, skip further
processing.
So the first check must be whether or not the component is rendered, and if not, skip the rest. The ActionSource is never queued and the action never invoked.
One more note, it does appear that ViewState is only reliable for CSFR prevention as of JSF 2.2 per the spec:
https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-869
Previous implementations were apparently too predictable and didn't cover GET requests. The spec now requires this.
So, while it may still be a good practice to secure the server side as well, it does appear it is sufficient to control rendering of the ActionSource component.
JSESSIONID is definitely needed. but that can be easily accessed if a user logged in - I am talking about a case when the user is logged in, but supposedly doesn't have access to the specific method.
The other part is more tricky. If the state is stored on client side, then that can be forged. Beside, there is mechanisms to provide direct link to the actions and pages - like pretty or simple link. If the method is exposed in any of those ways, it should be restricted.
I would secure them to prevent future headaches of constantly monitoring which method is exposed in what way - just imagine if you wanted to add a REST or SOA interface for the application.
I am very new to xPages and have been reading about xAgents. I need to write one but am a bit puzzled how to begin. Things like how to call it once it's written. Where do I put the code, can I use library code, java code. . .
Does anyone have a complete sample I could see so I can get started with this? I have most of my code written in an xPage but for security reasons need to put it into an xAgent with sessionAsSigner to access other data.
Thanks!
Your first stop would be the original article that coined the term XAgent (also check the links at the end of the article). Depending on your output the XMl Helper class might be useful too.
Update/Clarification: An XAgent is a front-end programming technique, not a back-end tool. XAgents get called from browsers (or other devices using HTTP(s)) and need thus be accessible to end-users (ACL applies of course). For functionality your program is calling you use beans and/or SSJS libraries
But taking one step back:
An XAgent is first and foremost an XPage. So all rules for XPages apply:
You call it via an URL, there is no scheduling or event facility. An XAgent is a replacement for the ?OpenAgent URL command, not for the other agent use cases
The XAgent is always accessible from the outside, that is its sole purpose, not a device for back-end calls
since your access to an XAgent is via URL, it isn't an approach for security, security is done using ACL, Readers and Authors. Be careful with using sessionAsSigner, if that is your default you need to revisit your access control ideas
Since you render all of the XAgent output yourself a typical use case is to obtain the XPages outputstream only and hand this into a function call of a Java (managed) bean
What you might want to look at (again: revisit your security model) is to run an agent from an XPage (comes with a performance penalty) or simply have a managed bean for your sensitive parts
Using sessionAsSigner in a xAgent could cause a serious security issue. When an anonymous user knows the url of your xagent he can use it to retrieve data from users who are not allowed to do so.
The xAgent is retrieving the data, displaying the data in json or xml structure of some sort ( probably ) and your calling website is then parsing this data. Because of this a user who knows the url of your xagent can use this agent to retrieve data he is not allowed to see. (what If I wrote a php script which calls your agent a couple 100 times to with different parameters? )
I think the best approach would be to have a simple onclick method bound to a button or maybe an onchange which does a partial refresh on a panel where you display the result of the verification.
For ages I've been puzzled about why after login I sometimes don't directed to the application welcome page. I've finally figured it out (years after everyone else):
I login successfully via j_security_check and go to the welcome page
wait for session timeout
click on h:link which sends a GET request
because it's a GET and not a POST my custom ViewExpiredException
handler doesn't kick in
container security redirects to the login page because the session
has timed out. Because of the session timeout+container security the
get request (from h:link) isn't seen by the application, in either a phase listener
or filter.
I successfully login again
j_security_check redirects me to the page which triggered the
authentication, in this case the target of the GET request.
The last bit I'd not understood, I assumed it would always go to the welcome page.
My problem is that my current design requires that after login I always show the welcome page. The welcome page has a preRenderView event which sets up some context information in a session scoped bean after login and increments a few counters etc...
This context information is required by backing bean code for other pages, and presently if I don't go through the welcome page first there'll be an exception.
In terms of fixing it I've looked at the following options:
Ideally there'd be an #PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.
I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.
I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.
Write a Server Authentication Module for glassfish to override j_security_check behavior.
How is this normally handled? I've started hitting this problem after moving to GETs for simple navigation cases after years of abusing POSTs, and the custom exception handler doesn't work. If anyone has any guidance on this issue I'd appreciate it, at least I know what's going on now. Hopefully I've missed something obvious!
Thanks
O/S
Ideally there'd be an #PostLogin method that could be called, which would cleanly solve all my problems. I use JSF (Mojarra) with Myfaces CODI but I don't see anything which does what I want.
There is indeed no such thing.
I could add some more code to my filter, but I need to persist some data (i.e. login count), it doesn't look like a nice option. Maybe I'm wrong.
That would indeed be the "easiest" way. Basically:
UserPrincipal user = request.getUserPrincipal();
HttpSession session = request.getSession();
if (user != null && session.getAttribute("user") == null) {
session.setAttribute("user", user);
// First-time login. You can do your intercepting thing here.
response.sendRedirect(request.getContextPath() + "/welcome.xhtml");
}
I make all the preRenderView methods of potential targets of j_security_check (pages called with GET) handle the case where they are called directly from j_seecurity_check. I can see this being what I have to do but it seems like a lot of hassle.
That's not DRY.
Write a Server Authentication Module for glassfish to override j_security_check behavior.
Can't answer that as I've never done that.
In a jsf application I have a table with summarized data. If I'm interested in the details I can click on a row an see the details in another page.
If the managed bean of the 'master' page is ion view scope it is re-created every time I return back from the 'detail' page and I don't think it is a good idea if the user is supposed to check the details more times. I can solve putting the bean in sessions cope but this way the bean (and the data) are kept in memory also when the user is interacting with the application in a completely different section. Probably I would need a custom scope but:
the documentation about custom scope is poor and I'm a bit frightened about people complaining it has bugs and doesn't work well.
the scenario I'm dealing with seems to me quite general, so I wonder why there is no ready solution for it.
Thanks
Filippo
If the detail page has to be idempotent (i.e. it's permalinkable, bookmarkable, searchbot-crawlable), just use two request or view scoped beans and use a GET link with the entity ID as request parameter to go from master page to detail page. See also Creating master-detail pages for entities, how to link them and which bean scope to choose for a concrete example.
If the detail page does not need to be idempotent, then you can always conditionally render the master and detail in the very same view or even display the detail in some modal dialog from the master page on. This way you can continue with a single view scoped bean.
In JSF side you must not be too much worried about the DB performance cost. Rather configure and finetune it in the persistence layer. In JPA for example you can setup a second level cache. If you've much more than 500~1000 items, then consider database-level pagination.
It may be valid to reload the master page each time e.g. if the data could have changed after viewing the details page. However, if you want to keep the data available for longer than #ViewScoped your options are:
You should be using JEE6 of which JSF 2.0 is a part of, so look at Conversation Scope (part of CDI)
Some additional scopes for JEE6 CDI is available through the MyFaces CODI
Potentially use Session Scope and make sure you tidy up when a Request hits which is not for the Master or Details page
Rework your design to use Ajax, so if clicking a record on the Master page its details load in the same view. You could then use #ViewScoped
My preference would be to look at the Conversation Scope. You don't mention which JSF implementation you are running or in which environment.
I am a beginner in JSF. I am building an application where on loggin on user details from the database are to be displayed in another JSP. I use a managed bean each for all of my jsp pages (JSF) I have defined thier scope as request in my faces-config XML. On logging in the details are verified by an actionListener method in my login page. Before leaving this method I am attempting to set attributes of the managed bean of the next page. But the state that I have set is not preserved in the second page. What am I missing out.
P.S. Please redirect me if this question was asked before and answered.
Thank you
The boundary between the two requests is when you return the navigation outcome from your managed bean action. Then a redirect (if configured so) is triggered to that outcome.
You have three options:
don't use <redirect /> in your navigation rules - thus you'll stay within the same request even when you show another page after submit. The downside is that this hurts user experience - if refresh is pressed, the ugly 'resubmit' dialog appears
use session scope - this is not harmful in small doses, but be careful not to have too many session-scoped beans.
use a conversation framework (like MyFaces Orchestra) - defines a custom scope called "conversation.access" - your data is accessible as long as it is needed.
use <a4j:keepAlive> from richfaces - preferred for ajax-requests.