Extjs Hidden Iframe requests are missing OWASP CSRF token - java

Recently we have implemented OWASP CSRF security token concept to handle CSRF attacks. I used below links as reference to implement
https://www.owasp.org/index.php/Category:OWASP_CSRFGuard_Project
https://github.com/aramrami/OWASP-CSRFGuard
pom.xml
<dependency>
<groupId>org.owasp</groupId>
<artifactId>csrfguard</artifactId>
<version>3.0.0.590</version>
</dependency>
I made all the mandatory changes to my project. Now i could able to see OWASP_CSRFTOKEN as part of request headers.
Problem:
In my project we are using Extjs 4. after implementing the change all ajax calls are successfully carrying OWASP_CSRFTOKEN token.
We do have one Hidden Iframe being used to download some excel files from server. when i inspect this request it's not carrying OWASP_CSRFTOKEN token and in server logs i can see the below message.
Logs:
Nov 21, 2017 2:53:47 PM org.owasp.csrfguard.log.JavaLogger log
WARNING: potential cross-site request forgery (CSRF) attack thwarted (user:<anonymous>,
ip:0:0:0:0:0:0:0:1, method:%request_method%, uri:/aaa/template/onDemandTemplate.action,
error:required token is missing from the request)
Iframe code:
var body = Ext.getBody(),
frame = body.createChild({
tag:'iframe',
cls:'x-hidden',
id:'hiddenform-iframe',
name:'iframe'
}),
form = body.createChild({
tag:'form',
cls:'x-hidden',
id:'hiddenform-form',
action: url,
method: POST,
target:'iframe'
});
var hiddenItem = document.createElement('input');
Ext.fly(hiddenItem).set({
type: 'hidden',
value: Ext.encode(params),
name: 'reportingParams'
});
form.appendChild(hiddenItem);
form.dom.submit();
Does Hidden Iframes internally use ajax or not ?
How can i inject CSRF token manually in Iframe reqeusts?
If any one have better approach/option to handle this situation. please share your ideas.
Thanks

No Iframes do not use ajax. However Iframe like functionality can be achieved by ajax.
If you are going to use Iframes then add a 2nd hidden input for CSRF token.
Code:
var csrf= document.createElement('input');
Ext.fly(hiddenItem).set({
type: 'hidden',
value: getCsrf,// method to get csrf token from the cookie
name: 'csrf'
});
form.appendChild(csrf);
Since you are using Extjs, you are assuming that the client browser is java script enabled, so avoid Iframes and use ajax to download the Excel files.

Related

Implementing a token style security when doing GET requests

I'm implementing a temporary and very simple token-style authentication mechanism for an application.
The idea is very simple. Whenever a user logs in to the application, a token is returned to the client, which stores it in the sessionStorage data structure of the browser.
Now, whenever I do a request through AJAX I can send the token with the request and the server can verify if this token is associated with an authentication or username. If it is, it parses the request normally, if not, a error page or the initial page is returned or displayed.
I'm not sure if this is the way that token-style authentication and authorization is implemented in real or serious applications, but I've now no idea how to send the token when doing GET requests by just clicking on the link of a view.
My only idea would be to intercept the get requests so that I can fill them with the token, but this all seems to be quite odd, and I've already a lot of links and views.
Search for Json Web Tokens and for implementations on java. This is exactly what you need.
If you want to send to the user some sensitive data inside the jwt, use Json Web Encryption.
You can send that token on each request header or as a request parameter
You can set a cookie, ensure to set it httponly (ans secure if you are on an https site) and read the cookie on every request that reach the server.
You can use JWT token (see https://jwt.io/introduction/). JWT is basically a JSON data structure. Usually, the token is passed along in the authorization http header.

Browsers Back button Issues with CSRF Prevention Mechanisam

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.

Check that login is successful into a website using java

I am using a code to login to a website. I am making a Get call first, to get the form parameters.
Then i am sending my login credentials, in the form, by a post call to the website.
I am getting a result like this:
Sending 'POST' request to URL : https://abc.ef.edu/login.asp
Post parameters : userName=xyz&password=xyz&Login=Sign+In
Response Code : 200
Does this result mean that i have logged into the website?
if yes, how can i check?
if no, then how can i login?
No, it doesn't mean you've logged in, it just means you pulled back a page over the web.
To test for login, you would need to "decorate" the page with some token of data (on successful login), then parse the response and look for it.
For example < !-- YOU_LOGGED_IN -->
Then search for that string.
That or create a trimmed down test version of the page that just returns the token.
That code is an HTTP response code which means that your login page was found (agais a 404 that you get when a page is not found). It has no bearing on the status of authentication. Even if the login fails, you'll still receive the HTTP code 200 only.

Preventing login attacks from curl/http post in spring app

I have a spring web app hosted on amazon and I am facing login attacks from some automated machines. From my logs, it is clear that they are bypassing login page, and are using something like :
curl --data "j_username=xxx&j_password=yyy" http://www.mysecureurl.com/j_spring_security_check
My question is how to prevent such attacks. Is there a way I can block such logins which are not coming directly from login page via some spring configuration ?
I will then implement further security measures like captcha, lockout-after-3-wrong-attempts etc when user tries from login page.
You can implement the a Cross-site Request Forgery (CSRF)- Nonce-Token Pattern.
In other words,
generate a random token (for every user an different).
put this token in the user session
an add it as a hidden field in the user login form
if you receive a login request than the check if the submitted token matches the token form the session - if not then send them a access denid
BTW:
you can use this pattern not only for your login page, but for all requests that change the server state. (to prevent CSRF-Attacs)
Spring Security >= 3.2 has a build in CSRF-Prevetion
If all requests coming from the same IP address you can use hasIpAddress expression:
<security:intercept-url pattern="/secure" access="isAuthenticated() and !hasIpAddress('11.11.111.11')" />
It is more temporary hack, because attackers can change their IP.
Here is how I solved my problem, thanks to all the answers above.
1.Added a custom filter to my spring security :
<custom-filter position="FORM_LOGIN_FILTER" ref="loginFilter" />
2.In the login controller, generated a random string and put that in http session
String random = UUID.randomUUID().toString().toLowerCase().replaceAll("-", "");
request.getSession().setAttribute("userKeyInSession", random);
3.Also passed this random key to login page so that the login jsp can submit this as hidden parameter along with form submit.
model.addAttribute("userKey", random);
return "login";
4.In the LoginFilter, I now do a simple string comparison between the request parameter and the random value in the session. If they do not match, I reject and do not proceed with authentication.
More to do: Captcha etc for preventing attacks from UI now..
Looks like you are using the default request login parameters provided by Spring-Security.
The default name attribute and password attribute value is j_username and j_password.
So if you change your login page's username and password parameters name attribute to something specific to you app , then you will be able to avoid such attacks , because in that case only you will be knowing the actual values attribute name and password and no one else and thus no one will be able be able to send http hack request to you app.

Who's Calling my HttpServletRequest?

I have a jsp containing a jquery post to a servlet on my tomcat server which creates a HttpServletRequest. I would like to ensure that only my jsp's calls to my servlet are processed and any requests originating from a source other than my jsp are ignored.
Is there a guaranteed way to see what is the referring page calling my server? I have read that using request.getHeader("referer") can be spoofed so I know I can't rely on that.
Generate an unique string as token, store it in the session and embed it as a hidden input value in the POST form of the JSP and finally check in the servlet if the token is valid.
Basically:
On session creation (in HttpSessionListener#sessionCreated(), for example):
Set<String> tokens = new HashSet<String>();
event.getSession().setAttribute("tokens", tokens);
On preprocessing of the JSP request (in HttpServlet#doGet(), for example):
String token = UUID.randomUUID().toString();
Set<String> tokens = (Set<String>) request.getSession().getAttribute("tokens");
tokens.add(token);
request.setAttribute("token", token);
On processing the JSP itself:
<input type="hidden" name="token" value="${token}" />
On postprocessing of the form submit (in HttpServlet#doPost(), for example):
String token = request.getParameter("token");
Set<String> tokens = (Set<String>) request.getSession().getAttribute("tokens");
if (!tokens.remove(token)) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST);
return;
}
// ...
I of course assume that your jQuery.post() functions are written in an unobtrusive way as in $.post(form.action, form.serialize(), callback) so that it simulates exactly the normal synchronous request (in other words, your forms works perfectly fine with JS disabled).
You can create a random cookie for your jsp, then append it to your POST form, and accept only requests with correct cookie value.
You could render a secure token to your JSP and include it in your Ajax call to the Servlet where you could verify it. This also doesn't guarantee that the Ajax call is made using a browser and your Javascript but it at least requires someone to get the secure token from the JSP before making the call.
A similar concept is recommended to mitigate CSRF.
Just a bit of semantics. Requests are created usually from the browser which displays your JSP. You can not stop another program from requesting your JSP and using whatever information you give them to request again.
You CAN stop another webpage that is being viewed in a user's browser from executing a request to your site. This is called Cross-site request forgery. You can mitigate this scenario.
So depending on what you are trying to prevent, CSRF solutions might work for you. You can find a premade solution from your web server. For example, here is Tomcat's

Categories