We have a JSF2.1.7 application ,our IT security found an issue as below
In Browser:
1) Get login Page.
2) Post Login Page with UserName/Password & submit&JSFViewStateId_1&JSessionID_1
3)Successful login.
Within minutes , if we make the same http request as below with old ViewState and new JSession.
1) Post Login page with UserName/Password & submit&JSFViewStateId_1&JSessionID_2
2) Successful Login
Wondering ,how the old view state is accepted by the server ,when the second request is made ,should it not report view expired?
Does the server validate the ViewSTate and JSession ID as the combined authentication.
That's only possible if the javax.faces.STATE_SAVING_METHOD is set to client. The javax.faces.ViewState does then not represent the unique view state identifier referencing a view state which is stored in the user session, but it represents instead the whole view state itself, in serialized flavor. The session ID is then not relevant anymore.
The webapp being tested has apparently client side state saving enabled. Whether that's a security problem is a second. It would only be possible to extract and send the view state to a malicious server when there's a XSS hole. JSF has by itself very strong builtin XSS prevention which the developer can only disable by explicitly using escape="false" while redisplaying user-controlled data. Even if there was a XSS hole, then it would also be possible to send the session ID along. It wouldn't have been more secure with server side state saving.
Related
My application consists of a client side html/javascript, a web server, and an API (a "regular web app", as auth0 calls it). On the Authorization Code Grant doc page on Auth0, it says to create a URL like this:
https://ygctest.auth0.com/authorize?
audience=YOUR_API_AUDIENCE&
scope=YOUR_SCOPE&
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://YOUR_APP/callback&
state=YOUR_OPAQUE_VALUE
The doc says the state (apparently a nonce to prevent CSRF) returned from the auth0 server via query parameter to /callback needs to be compared to the originally generated state.
My question is: Where should the "state" variable be generated? And, does the state variable need to be verified on the client, server, or both?
Should I generate it on the server and pass it to the client somehow? If so, is it better to do it as a cookie, or can I just generate the entire URL serverside and stick it in the html?
If the state variable should be generated on the client side, how should the server know what the client thinks the state is? The browser is redirected from the login page to /callback (in the example), so the client doesn't have a chance to check the state. Should the client set a cookie so that the GET to /callback includes the state?
Create the session state on the server-side, store its value in session (encrypted cookie or server-side storage cache (eg. Redis). Then during the code authorization grant flow, check its value as a first action in your callback. Some libraries might handle the check for you, or else you will have to do the ceremony of pulling the state value explicitly out of session storage in your code, and comparing that explicitly against the value of state that was returned to your callback endpoint.
If you are using Auth0 Hosted Login Page, and making a call to authorize endpoint, then you can just do it all server-side - see here. If you need to render a form on UI with state value then your Controller can pass the value of your state to the view layer as a value that gets interpolated. The key takeaway is that it is recommended to generate the value server-side, store it in secured session storage, and do the comparison server-side (in the callback) for code authorization grant flow (regular web app).
We are integrating Form Runner/Builder into a project with a custom persistence layer.
Right now we have emptySessionPath="true" set to keep Orbeon and our Java app on the same session.
Orbeon is passing the jsessionid cookie in the persistence CRUD calls... except for the following instance....
User connects to our Java app and logs in, jsessionid cookie is set
User visits an existing form instance at /fr/OurApp/formtest/edit/3eb4ddcf03f2410084e5578adb1e2a7b (Session Cookie is present)
Persistence call is made to our custom persistence layer, but cookie is not forwarded
But, if the user was to first edit the form itself with a call to /fr/orbeon/builder/edit/f40efbe298204d16b6474fcdfea4c9fd which does pass the cookie to the persistence layer
At this point the user can go visit step 2 to complete the form instance and the cookie will persist. It seems that for some reason starting form builder is required to get the cookie to forward to the persistence layer when completing the form?
Any ideas on why the cookie isn't getting passed on step 2?
FYI this is on Orbeon 3.9 CE, also same behavior in 3.8. Using VMWare TC Server (Tomcat). Our java app is a Spring/Grails app.
I am wondering if this might be what's described in this bug (see in particular the comments). Basically, it doesn't seem like you can always reliably produce a JSESSIONID cookie. And as the bug says, we don't have a solution right now.
Do you think the bug corresponds to your case?
If I receive a request to the url host.com/site-directory/page-slug.html?session={someValidNonExpiredSessionGuid} and I detect a session cookie with the value: {someOtherValidNonExpiredSessionGuid}, then
Which session is the correct session to associate with the request?
Here's some background:
The pattern I am using for maintaining state across HTTP requests is to store a unique ID in the querystring, form collection and/or cookie. Then, on each request, I locate the unique Id and pull date from a database table. If the id is not valid, or the session is expired, a new session will be created (with a new id, a new cookie, etc).
The default behavior is that all forms will have a field:
<input type="hidden" name="session" value="{someGuid}" />
All links to other pages on the site will have an appended querystring parameter
a sample link
And, if the user's browsing device supports cookies, a cookie will be set having the session's value.
If I have validated that the user's browsing device supports cookies, then my form and querystring will no longer require the the session id field/parameter.
However, I am having a conceptual issue in deciding whether the session parameter of the querystring should take precedence over the cookie value or vice-versa. It seems like I could potentially get bad data in either circumstance. I could get data with a bad querystring parameter if the user bookmarked a page with the session parameter included in the URL. I could also get bad data from the cookie, if a user closes the browser without terminating the session, and the session expire-window has not yet closed. It also seems like both options could be vulnerable to a malicious user intercepting the request and sending a request with the same session information.
So, once again, my question is
If I receive a request to the url host.com/site-directory/page-slug.html?session={someValidNonExpiredSessionGuid} and I detect a session cookie with the value: {someOtherValidNonExpiredSessionGuid}, then Which session is the correct session to associate with the request?
I am leaning towards the cookie session, because it seems like the most common scenario will be a bookmark with the session included. I've already decided that the form post data should take the greatest precedence, because a page will always render the form with the correct ID, and the only possible situation with a wrong, non-expired ID is a very quickly implemented XSS attack, which is circumvented by including a request-scoped anti-forgery token field.
In addition to the primary question I appreciate any insight to any security-related or logical oversights I have expressed in this description. I apologize for the long post, but felt it was necessary to explain the situation. Thank you very much for your input.
Also, it is not necessarily relevant to the question, but I am using ASP.NET MVC in most situations, and setting my cookies manually with Response.Cookies.
From a security standpoint sessions should not be stored in query strings.
For example:
If sessions are stored in queries and you link to a remote host on the same page, the users valid session could be sent to the remote host via the referer header.
Sessions should always be stored in cookies.
You should try to store it in the cookie (looking the the browser caps to see if the browser supports cookies) and then have a fall back for query string.
I too would lean towards using the cookie session ID in case of ambiguity. This primarily because I'd trust the cookie implementation to be more well baked, more well tested, and more idiot-proof than my own home brewed session tracking implementation. For e.g. there are cases where ASP.NET automatically knows to clear the session cookies, renew them etc.
Also, I would design it so the cookies aren't persistent to minimize the edge cases. If the user closes the browser, then the session is closed.
The other simplification I would consider is to have either cookies or URL based tracking and not both. If the browser supports cookies, there is really no reason to also track the session through a URL.
Thoughts?
Curious ... What were your reason to rule out using the stock ASP.NET cookieless session implementation? - http://msdn.microsoft.com/en-us/library/aa479314.aspx#cookieless_topic2
If I receive a request to the url
host.com/site-directory/page-slug.html?session={someValidNonExpiredSessionGuid}
and I detect a session cookie with the
value:
{someOtherValidNonExpiredSessionGuid},
then Which session is the correct
session to associate with the request?
To answer your specific question, I'd recommend putting session management in the cookies as opposed to the querystring. As has been mentioned, cookies can be set to expire whereas the querystring cannot. This allows your thin-clients to assist in their own session maintenance by removing their own expired cookies. Moreover, since cookies are dropped to specific browsers, you reduce the chances of another browser spoofing the original browser session.
The only way I would use the querystring to pass session information would be as a backup method to re-establish a browser session onto a new browser instance. Here's a scenario: you have an active session using browser A on machine A which suffers some catastrophic error. You want a way to re-establish that same session on another browser instance on either the same machine or on another machine. If your code-behind can recognize that the session cookie doesn't exist, but that a valid session id exists in the querystring, you could initiate a challenge-response to verify the integrity of that session id and then drop a new session cookie on the new machine. Kinda extreme in my humble opinion, but the functionality might be useful in certain situations.
ADDED: I understand that you may want to accommodate users who have turned cookies off on their browsers, and while you can use the querystring to hold the session id I'd recommend against it. But if you must, encrypt that sucker using browser-machine specific information.
I use chrome as debugging browser.
When I start my MVC (Razor) website, click the stop button and the website keeps running in chrome ,while I can make changes in VS ... perfect.
But sometimes (due to I don't know what changes), when I refresh a page, I'm still logged in, but I looses all my session vars.
How can I catch if session vars is cleared, so I can take my users back to login page? (I need a kinde global.asax page_request method.
I do have the .. <forms loginUrl="~/Account/LogOn" timeout="2880" /> ... but Im not logged out - only session vars are cleared.
It's because your login state is persisted in a client cookie. The session state is persisted on the server in memory (or whatever). When your app restarts the session is cleared but the user still has a valid forms authentication token (assuming forms authentication here) on their machine. Forms authentication does't use session in any way by default.
So, at the beginning of the request, you can either reload the user session from the database when it's null (I think this is the preferred approach if possible) or redirect the user to the login screen with a message saying "ooops, sorry we've lost your session" (which is not good!)
If you use the built-in Authorization functionality, you can just add the [Authorize] attribute. There's some info on using custom authentication here:
ASP.NET MVC Authorization
Lee Gunn explained it well. One solution would be to create a custom filter attribute similar to Authorize that verifies the session has the values you're expecting and decorate the appropriate controllers/actions.
We are attempting to integrate an ASP.NET MVC site with our client's SSO system using PingFederate. I would like to use the built in FormsAuthentication framework to do this. The way I've gone about it so far is:
Set up my Web.config so that my FormsAuthentication LoginURL goes to my site's "BeginAuthentication" action on a "Security" controller. From this action, I set up some session variables (what URL was being accessed, for example, since Ping won't send this info back to me), and then redirect to our client's login page on an external site (www.client.com/Login for example).
From here, the authentication takes place and a cookie is generated on the same domain as the one that our application is running on which contains the unique identifier of the authenticated user, I've set it up so that once this happens, the Ping server will redirect to my "EndAuthentication" action on my "Security" controller.
In this action, I call my membership class's "ValidateUser" method which takes this unique identifier from the cookie and loads in the user on our application that this ID refers to. I save that logged in user in our Session (Session["LoggedInAs"], for example) and expire the cookie that contains the id of the authenticated user that the SSO system provided for me.
All of this works well. The issue I'm wondering about is what happens after our user has already authenticated and manually goes back to our client's login page (www.client.com/login) and logs in as another user. If they do that, then the flow from #2 above to number 3 happens as normal - but since there already exists an authenticated user on our site, it seems as though the FormsAuthentication system doesn't bother kicking off anything so I don't get a chance to check for the cookie I'm looking for to login as this new user. What I'd like to do is, somewhere in my Global.asax file (probably FormsAuthenticate_OnAuthenticate), check to see if the cookie that the SSO system sends to me exists, and if so, sign out of the application using FormsAuthentication.SignOut().
Another issue that seems to be related is that if I let my Session expire, the FormsAuthentication still seems to think I am authenticated and it lets me access a page even though no currently logged in user exists in my Session, so the page doesn't render correctly. Should I tap into the Session_End event and do FormsAuthentication.SignOut() here as well?
Basically, I want to know when the authentication ticket created by
System.Web.Security.FormsAuthentication.SetAuthCookie(..) gets checked in the flow of a request so that I can determine whether I need to SignOut() and force revalidation or not.
Thanks for any help. Sorry for the length of this message, trying to be as detailed as possible.
Mustafa
Welcome to the small section of Hades that is mixing session with formsauth.
If your needs are as complex as presented, you would get more sleep if you implement a full provider stack to share amongst the participating sites. Easier said than done, I know.
But to address your question:
from http://www.codeproject.com/Articles/39026/Exploring-Web-config-system-web-httpModules.aspx
On the way in....Check ticket and set identity #
app.AuthenticateRequest += System.Web.Security.FormsAuthenticationModule.OnEnter-->OnAuthenticate
On the way out... set the ticket and redirect as necessary
app.EndRequest += System.Web.Security.FormsAuthenticationModule.OnLeave
Reflector is your friend. ;-)
I don't know about a specific event for when the cookie is checked, but you could place the appropriate logic in Application_BeginRequest() and check the user's authentication state there.
Another issue that seems to be related
is that if I let my Session expire,
the FormsAuthentication still seems to
think I am authenticated and it lets
me access a page even though no
currently logged in user exists in my
Session, so the page doesn't render
correctly.
The life of the cookie (how long until ASP.NET feels it needs to ask for a password again) and how you are managing state are unrelated. The ASP.NET authentication is cookie based so that, should a developer want to, he could turn off viewstate, session, use no query strings or hidden fields and authentication still works.
If you want to tie the interval at which you request the password to how you are persisting data, then you will want your session expiration to be roughly the same as the cookie expiration, but they will never quite match up. It would be better to have two policies (one for how fast you throw away a users session data and one for how long you are willing to wait before you need to reask for a password)