Implementing CSRF in webapp - java

I am following this for prevent CSRF in my webapp.
I could implement the same, but I have a minor doubt regarding how it exactly secures my webapp. We are creating an encrypted String along with the form with input type="hidden". So far so good. The user is not aware of the attribute that is passed along when submitting a form.
But, if the attacker is keen and finds the input element (document.getElementById/Name), and uses JS to get the value out of the form and use it in the malicious request, How is it exactly helping here? My server would still keep allowing the request to go through since the malicious request also might be having the same encrypted String as hidden input.

A CSRF token is a random, hard-to-guess string. On a page with a form you want to protect, the server would generate a random string, the CSRF token, add it to the form as a hidden field and also remember it somehow, either by storing it in the session or by setting a cookie containing the value.
When the user submits the form, the server simply has to compare the value of the posted field csrf-token (the name doesn’t matter) with the CSRF token remembered by the server. If both strings are equal, the server may continue to process the form. Otherwise, the server should immediately stop processing the form and respond with an error.
For More detailed Info: https://cloudunder.io/blog/csrf-token

Related

How to defend against xss when saving data and when displaying it

Let's say I have a simple CRUD application with a form to add new object and edit an existing one. From a security point of view I want to defend against cross-site scripting. Fist I would validate the input of submitted data on the server. But after that, I would escape the values being displayed in the view because maybe I have more than one application writing in my database (some developer by mistake inserts unvalidated data in the DB in the future). So I will have this jsp:
<%# taglib prefix="esapi" uri="http://www.owasp.org/index.php/Category:OWASP_Enterprise_Security_API" %>
<form ...>
<input name="myField" value="<esapi:encodeForHTMLAttribute>${myField}</esapi:encodeForHTMLAttribute>" />
</form>
<esapi:encodeForHTMLAttribute> does almost the same thing as <c:out>, it HTML escapes sensitive characters like < > " etc
Now, if I load an object that somehow was saved in the database with myfield=abc<def the input will display correctly the value abc<def while the value in the html behind will be abc<def.
The problem is when the user submits this form without changing the values, the server receives the value abc<def instead of what is visible in the page abc<def. So this is not correct. How should I implement the protection in this case?
The problem is when the user submits this form without changing the values, the server receives the value abc<def instead of what is visible in the page abc
Easy. In this case HTML decode the value, and then validate.
Though as noted in a few comments, you should see how we operate with the OWASP ESAPI-Java project. By default we always canonicalize the data which means we run a series of decoders to detect multiple/mixed encoding as well as to create a string safe to validate against with regex.
For the part that really guarantees you protection however, you normally want to have raw text stored on the server--not anything that contains HTML characters, so you may wish to store the unescaped string, if only that you can safely encode it when you send it back to the user.
Encoding is the best protection for XSS, and I would in fact recommend it BEFORE input validation if for some reason you had to choose.
I say may because in general I think its a bad practice to store altered data. It can make troubleshooting a chore. This can be even more complicated if you're using a technology like TinyMCE, a rich-text editor in the browser. It also renders html so its like dealing with a browser within a browser.

Process password within servlet securely

I am transmitting a password through HTTP(S) to a HttpServlet as parameter. To get the password I am using the Servlets getParameter(String) method, which returns a String. But passwords should be handled with char[] like mentioned here.
Well, what I want to know is: How can I process a password securely within a Java Servlet? Is my solution with getParameter(String) the only one or are there better options?
Please keep in mind that I am NOT interested in how to transmit a password securely (I am expecting that the transmit is secure - maybe with SSL or something else).
Thanks in advance :)
Edit:
I forgot to mention that I am not using the password myself (for some kind of access restrictions for my application). I am just forwarding the password (so you could say my WebApp is something like a remote control).
If your login parameter is sent in a POST request and contained in the request content you could parse the content yourself and put the password in a char array.
You need to do this before any call to request.getParameter(String)is made since this will make the container read and parse the content. This only works if the servlet container lazily initializes its parameter map.
"Teleporter" approach:
Have Javascript break the password into parameters of 1 character each. Reassemble directly into char array at server side.

How to allow specific characters with OWASP HTML Sanitizer?

I am using the OWASP Html Sanitizer to prevent XSS attacks on my web app. For many fields that should be plain text the Sanitizer is doing more than I expect.
For example:
HtmlPolicyBuilder htmlPolicyBuilder = new HtmlPolicyBuilder();
stripAllTagsPolicy = htmlPolicyBuilder.toFactory();
stripAllTagsPolicy.sanitize('a+b'); // return a+b
stripAllTagsPolicy.sanitize('foo#example.com'); // return foo#example.com
When I have fields such as email address that have a + in it such as foo+bar#gmail.com I end up with the wrong data in the the database. So two questions:
Are characters such as + - # dangerous on their own do they really need to be encoded?
How do I configure the OWASP html sanitizer to allow specific characters such as + - #?
Question 2 is the more important one for me to get an answer to.
You may want to use ESAPI API to filter specific characters. Although if you like to allow specific HTML element or attribute you can use following allowElements and allowAttributes.
// Define the policy.
Function<HtmlStreamEventReceiver, HtmlSanitizer.Policy> policy
= new HtmlPolicyBuilder()
.allowElements("a", "p")
.allowAttributes("href").onElements("a")
.toFactory();
// Sanitize your output.
HtmlSanitizer.sanitize(myHtml, policy.apply(myHtmlStreamRenderer));
I know I am answering question after 7 years, but maybe it will be useful for someone.
So, basically I agree with you guys, we should not allow specific character for security reasons (you covered this topic, thanks).
However I was working on legacy internal project which requried escaping html characters but "#" for reason I cannot tell (but it does not matter). My workaround for this was simple:
private static final PolicyFactory PLAIN_TEXT_SANITIZER_POLICY = new HtmlPolicyBuilder().toFactory();
public static String toString(Object stringValue) {
if (stringValue != null && stringValue.getClass() == String.class) {
return HTMLSanitizerUtils.PLAIN_TEXT_SANITIZER_POLICY.sanitize((String) stringValue).replace("#", "#");
} else {
return null;
}
}
I know it is not clean, creates additional String, but we badly need this.
So, if you need to allow specific characters you can use this workaround. But if you need to do this your application is probably incorrectly designed.
The danger in XSS is that one user may insert html code in his input data that you later inserts in a web page that is sent to another user.
There are in principle two strategies you can follow if you want to protect against this. You can either remove all dangerous characters from user input when they enter your system or you can html-encode the dangerous characters when you later on write them back to the browser.
Example of the first strategy:
User enter data (with html code)
Server remove all dangerous characters
Modified data is stored in database
Some time later, server reads modified data from database
Server inserts modified data in a web page to another user
Example of second strategy:
User enter data (with html code)
Unmodified data, with dangerous characters, is stored in database
Some time later, server reads unmodified data from database
Server html-encodes dangerous data and insert them into a web page to another user
The first strategy is simpler, since you usually reads data less often that you use them. However, it is also more difficult because it potentially destroys the data. It is particulary difficult if you needs the data for something other than sending them back to the browser later on (like using an email address to actually send an email). It makes it more difficult to i.e. make a search in the database, include data in an pdf report, insert data in an email and so on.
The other strategy has the advantage of not destroying the input data, so you have a greater freedom in how you want to use the data later on. However, it may be more difficult to actually check that you html-encode all user submitted data that is sent to the browser. A solution to your particular problem would be to html-encode the email address when (or if) you ever put that email address on a web page.
The XSS problem is an example of a more general problem that arise when you mix user submitted data and control code. SQL injection is another example of the same problem. The problem is that the user submitted data is interpreted as instructions and not data. A third, less well known example is if you mix user submitted data in an email. The user submitted data may contain strings that the email server interprets as instructions. The "dangerous character" in this scenario is a line break followed by "From:".
It would be impossible to validate all input data against all possible control characters or sequences of characters that may in some way be interpreted as instructions in some potential application in the future. The only permanent solution to this is to actually sanitize all data that is potentially unsafe when you actually use that data.
To be honest you should really be doing a whitelist against all user supplied input. If it's an email address, just use the OWASP ESAPI or something to validate the input against their Validator and email regular expressions.
If the input passes the whitelist, you should go ahead and store it in the DB. When displaying the text back to a user, you should always HTML encode it.
Your blacklist approach is not recommended by OWASP and could be bypassed by someone who is committed to attacking your users.
You should decode after sanitising your input:
System.out.println(StringEscapeUtils.unescapeHtml("<br />foo'example.com"));

Do you always REDIRECT after POST? If yes, How do you manage it?

Say, you are submitting a form, which affects your database (adding records/ deleting them/ updating them) and this is how your request looks like:
POST /application/action=update
Now, say, you are done with your update, so you would like to take the user to the home page.
Response.sendRedirect /application/action=home
This works wonderfully well. User is sent a redirect after POST, so even if the user tries to refresh the page by hitting F5, you are good. However, this will not work if you did this:
requestDispatcher.forward(/application/action=home)
Given that there is a scenario where you have to display different kinds of error / success messages after you are done with your update, you are most likely doing a forward after POST. In such a scenario, how do you avoid update actions from happening twice?
I find it rather amusing that many secure sites (banks) / payment gateways tend to inform the user by placing text on screen, such as "Please don't press back / refresh buttons".
Is there no better way to handling this? Other than requesting the user not to press these buttons? When I last checked, there was something called the 'Vertical Response Cache'. A Filter that would identify uniqueness of your request in a session and tries to send a cached response if the request is duplicate. Are there any simpler ways to solving this classic problem?
Here is a link to the vertical response cache solution I was talking about: http://www.fingo.info/en/articles/_1.html. I am, However, not sure as to how well this really works.
Yes, I believe that you should redirect after a POST, with the exception of API requests. Without doing this not only do you have to worry about getting duplicate POSTs when the user uses the back button, but the browser will also give the user annoying dialogs when they try to use the back button.
Response.sendRedirect works in practice, but tecnically speaking this is sending the wrong HTTP response code for this purpose. sendRedirect sends a 302, but the correct code to use to transform a POST into a GET is 303. (most browsers will treat a 302 just like a 303 if they get it in response to a POST, however)
In general you want the redirect to send the user to whatever view will display the effect of their change. For example, if they edit a widget, they should be redirected to the view of that widget. If they delete a widget, they should be redirected to the view that the widget would have appeared in when it existed (perhaps the widget list).
Sometimes it's nice to have a status message to further drive home the fact that an action occurred. A simple way to do this is to have a common parameter to your views that, when set, will display an action completed message. eg:
/widget?id=12345&msg=Widget+modified.
Here the "msg" parameter contains the message "Widget modified". The one downside to this approach is that it may be possible for malicious sites to give your users confusing/misleading messages. eg:
/account?msg=Foo+Corp.+hates+you.
If you're really worried about this you could include an expiring signature for the message as an additional parameter. If the signature is invalid or has expired, simply don't display the message.
The best solution to solve the problem of showing status messages to the users after a POST to GET redirect is to use user sessions.
How
Add attributes to user session with value as set of messages to be displayed. for eg.
userSession.put("success_messages", new HashSet<String>(){"Success", "Check your account balance"});
userSession.put("warning_messages", new HashSet<String>(){"Your account balance is low. Recharge immediately"});
And have a filter which scans the user session for these particular attributes and outputs the messages. The filter should delete the attributes after reading once, as the status messages are generally displayed only once.
One thought that I've had is to embed a unique ID (probably a random string) as a hidden form field in the form that is being POST-submitted. The ID string can be put in the database as a "transaction ID". Now, when you go to update the database, first check whether there's an existing record with the submitted transaction ID, and if so, assume it's a duplicate and don't change the database.
Of course, as I said, this is just a thought. I don't know what methods are actually used in practice. (I suspect that a lot of less-critical sites just ignore the problem and hope their users will be smart... a losing proposition if I ever saw one ;-)
EDIT: as pointed out in the comments, storing transaction IDs in the database might take up a lot of space, but if that's an issue, you could keep an in-memory cache of all transaction IDs processed in the last 5 minutes/1 hour/1 day/whatever. That should work unless you're up against a determined hacker...
I find it rather amusing that many secure sites (banks) / payment gateways tend to inform the user by placing text on screen, such as "Please don't press back / refresh buttons".
some people find its better to "disable all Back, Refresh event on this critical pages";
I'm not sure if this is good or not.
But your addressed solution "vertical response cache" sounds nice
Its a little non-obvious but:
create a keyed-object in the user session.
the value is a Request + java Future for the result
return immediately with a client-side redirect.
while the client-side redirect is being handled, have a worker thread work on producing the answer.
So by the time the client browser completes the redirect, getting the new page's images, etc... the results are waiting for the user.
The alternative is to make the user painfully aware of how long the database is taking.
Security Update (2011 Jan 24 ) :
The key is vulnerable to attack since it is part of the response to the client, so
Generate a random key
Use user's session id as a salt to create a SHA-1
Store both the random key and the SHA-1 in the database with (, ) as the primary key. (no separate indexing on the RANDOMKEY.
Use both RANDOMKEY and the SHA-1 as the db lookup.
Do not store the Session Id (avoid privacy issues with being able to corollate many entries to the same user)
Expire the results after 2-3 days. ( Allows a daily batch job to do the clean up and avoids creating problems for user sessions that are semi-long lasting )
This method requires any hacker to know both the session id and the random key.
This approach may seem overkill, but a redirect-hardened mechanism can be used for situations like password resets.
If you are working with java server side scripting and also using struts 2 then you refer this link which talks about on using token .
http://www.xinotes.org/notes/note/369/
A token should be generated and kept in session for the initial page render, when the request is submitted along with the token for the first time , in struts action run a thread with thread name as the token id and run the logic whatever the client has requested for , when client submit again the same request, check whether the thread is still running(thread.getcurrentthread().interrupted) if still running then send a client redirect 503.
Please look at the ExecuteAndWaitInterceptor of struts 2code, the logic of this combined with token will help out fast click

Multiple questions in Java (Validating URLs, adding applications to startup, etc.)

I have an application to build in Java, and I've got some questions to put.
Is there some way to know if one URL of a webpage is real? The user enters the URL and I have to test if it's real, or not.
How can I konw if one webpage has changes since one date, or what is the date of the last update?
In java how can I put an application running on pc boot, the application must run since the user turns on the computer.
I'm not sure what kind of application you want to build. I'll assume it's a desktop application. In order to check if a URL exists, you should make a HTTP HEAD Request, and parse the results. HEAD can be used to check if the page has been modified. In order for an application to start when the PC boots, you have to add a registry entry under Windows; this process is explained here
To check whether a url is valid you could try using a regular expression (regex for urls).
To know if a webpage has changed you can take a look at the http headers (reading http headers in java).
You can't make the program startup automatically on boot, the user must do that. However, you can write code to help the user set the program as startup app; this however depends on the operating system.
I'm not sure what you mean by "real". If you mean "valid", then you can just construct a java.net.URL from a String and catch the resulting MalformedURLException if it's not valid. If you mean that there's actually something there, you could issue an HTTP HEAD request like Geo says, or you could just retrieve the content. HTTPUnit is particularly handy for retrieving web content.
HTTP headers may indicate when the content has changed, as nan suggested above. If you don't want to count on that you can just retrieve the page and store it, or even better, store a hash of the page content. See DigestOutputStream for generating a hash. On a subsequent check for changes you would simply compare the new hash with the the one you stored last time.
Nan is right about start on boot. What OS are you targeting?

Categories