Browsers Back button Issues with CSRF Prevention Mechanisam - java

I tried using OWASAP mechanism to protect my legacy application form CSRF, but i got issues with navigation and back button. I then tried using struts-1 token mechanism but faced the same issue. The problem i think with token injection mechanism is initially we will generate a token in jsp and store it in session and perform some action.
Consider A.jsp. lets take token value 1 in the jsp and we will store the same in the session.
Now we will validate it in the filter/Action class.
After that we will do some other operation in B.jsp and we will have token new value 2 in the jsp and in session.After validation form server we will be having value 2 in session.
Now if we navigate using browsers back button and move to page 1 and submit it, it will load the values from cache and the A.jsp will have the value 1 as token,
After submitting A.jsp at this point it will show CSRF error as it contradicts the value in session.
Is there a way to implement the CSRF prevention mechanism without actually disturbing the application?

So if I understand your problem correctly, pressing back button you get page from cache with old token? If I'm correct, then there is an easy way how to solve this problem - do not cache your pages, and load them from server all the time.
It can be achieved by setting following response headers
Cache-Control: max-age=0, no-cache, must-revalidate
Other, more difficult way, is to implement single page application, in that case you'll always have actual token in browser memory.

Related

On refresh browser go to last finished step using cookies(java + react)

Ok, so I have simple website which force user to start from last finished step. Whenever user refresh page he needs to call at application initialization to:
REST /user/{id}/step
This endpoint will tell where user finished. The problem is I am using http only cookie. So I cannot get this {ID} from cookie in javascript.
At the moment I have added additional cookie(NOT http only) named clientId. So application can get his id from cookie, and call to this particular endpoint.
It is working but I feel that it is kinda not best approach. It has few side effects like taking care of clearing this stupid cookie on logout, etc situations.
What is best practice ? I've been thinking about creating additional endpoint which will be used on every application initialization
REST /user/status
// I want to be restfull, so I dont want REST user/logged/step
which will return setCookie clientId="" or setCookie clientId={ID} whenever user is logged or not, in this case I even don't need to care about clearing cookies on frontend side, any ideas?
The problem is I am using http only cookie.
So this http only cookie contains what? I presume a user's session? Then why do you need to specify this user ID in the URL if you should be able to get the ID from the session token?
I believe you should just have the following endpoint REST /user/step which returns the step number for a current user (defined by the session token in the http only cookie) or it returns 401 code (Unauthorised) if the user is not logged in..

Redirected to j_spring_security_check via GET method

I have a strange re-occurring problem with requests being made to j_spring_security_check via GET method.
All my login forms use POST to j_spring_security check for posting login credentials. Yet, application users reported on several occasions that sometimes they get an error page when trying to log in. I tracked those situations in the logs and it looks like people visit the login page and then next request is GET to j_spring_security_check.
It happend to me once too, but I cannot reproduce it.
Do you have any ideas why this may happen? Could spring security redirect to j_spring_security for some reason?
I double checked html and javascript there are no mentions of j_spring_security_check except in the action field of form elements which all have method set as POST.
Any help or ideas would be appreciated.
EDIT: additional information:
WebApp is served by Tomcat. There is Apache reverse proxy in front of it. Pages that contain login forms pass w3c validations.
After almost a month, we have finally figured out why this thing happens in google Chrome.
Apparently, if you submit a form using SHIFT+ENTER Chrome will open a new window and make a GET request instead of a POST request. Since some users have uppercase characters / special characters as a last letter of the password they type in the last letter with shift pressed and the press enter to log in while not yet releasing shift key. And the result is GET request to j_spring_security check. We will fix this by intercepting shift + enter in javascript.

CSRF Protection: Methods to send CSRF token for each request

My initial code generated tokens for the requests that could alter state of my database, like CRUD operations. The token was generated for each request. Sent to client side in JSON-format along with other data and I expected this token to be returned with the request and changed it after completion of the request. But, as I implemented it to only parts of my code (CRUD operations), I was told to redo it and make it web-app wide. I think the best way to do this is with filters.
My problem is, how do I make the client send "the token" for each request? Do I set it in cookies? What are my options? Please advice.
best way is , all links should be GET request, and within get requests no modification should be made to application state. So for GET requests there will be no need for CSRF tokens.
For POST request s which make modifications in application state you have to generate, csrf hidden fields in your forms and validate the token in server during form submit.

Servlet request blocking

I have a Filter which scans all the request going through my application. I want to block a request if it requests for a specific url. I can able to check this and if the condition matches I am NOT doing chain.doFilter, but still the request moves to a black page. How can I block this request from going any further and stay in the current page - meaning user should not see any change to the screen that he clicked?
The HTTP status code 204 might work, but it is not guaranteed to work with all browsers:
204 No Content
The server has fulfilled the request
but does not need to return an
entity-body, and might want to return
updated metainformation. The response
MAY include new or updated
metainformation in the form of
entity-headers, which if present
SHOULD be associated with the
requested variant.
If the client is a user agent, it
SHOULD NOT change its document view
from that which caused the request to
be sent. This response is primarily
intended to allow input for actions to
take place without causing a change to
the user agent's active document view,
although any new or updated
metainformation SHOULD be applied to
the document currently in the user
agent's active view.
The 204 response MUST NOT include a
message-body, and thus is always
terminated by the first empty line
after the header fields.
(emphasis mine)
Alternatively, you can try one of these strategies:
Have the servlet return 307 (temporary redirect) back to the previous page using the HTTP Referer field. This approach might cause problems with caches and proxies.
Use ajax to load contents from your servlet. You will have to substitute direct links with JavaScript calls that initiate ajax calls to substitute part of your page. The URL in the browser will not change when you load contents this way, which may or may not be desirable. Many sites use a mix, including StackOverflow. Anything that should be "permalink-able" is navigated to via a regular link, but parts of each page is fetched lazily via ajax.
Finally, what's wrong with telling the user a link is off limits? Have the servlet return 403 (forbidden).
You can't. The browser has already made the request and it's out of its hands. You might be able to hack something where you return a little bit of javascript that silently "hits" the browsers "back" button, but that no doubt has all sorts of nasty issues with it.
But once the browser is has sent the request, the current page is "dead".

Java: Session attribute is only in next operation

I'm posting some strings in my Session with the call
request.getSession().setAttribute(key, value);
And making the redirect with
response.sendRedirect(urlRedirect);
In almost all cases the values is there after the redirect.
But sometimes I can only read this value in the next page view, not in the redirect. There is no common behavior.
Someone has faced the same problem?
Sessions are backed by a HTTP cookie. On first-time session creation, a cookie will be set in the response header. By default, cookies are bound to a specific context only.
So, if you redirect while the cookie hasn't been set yet, the session will get lost. To go around this, you need to encode the redirect URL.
response.sendRedirect(response.encodeRedirectURL(url));
This appends the jsessionid identifier to the URL which allows the servletcontainer to locate the right session without help of a cookie.
If you don't like the jsessionid thing, then consider implementing a filter like this which ensures that the client is aware of the session cookie before the request enters your controller wherein you fire the redirect.
Also, if you redirect to a different context, it won't be able to access the same session. To go around this, you need to configure the servletcontainer to share the session among the contexts. In for example Tomcat, check the emptySessionPath attribute of the <Connector> element in /conf/server.xml.
Such a behaviour can be caused by caching.
If the page you are redirecting to is retrieved from the browser cache, you obviously can't see the result of setAttribute() on it. So make sure it's actually requested by the browser.
Are you sure you need to do redirect through browser (response.sendRedirect()) and not on the server side (RequestDispatcher.forward())? Latter is faster as there are no network round trip.
The problem was solve by changing the way of submit.
The page was submitting the data only changing the value of location.href to the Servlet Action.
We only call the submit function from the page form, and the session attributes works fine!

Categories