views:

409

answers:

3

How do I make sure I don't escape something twice?

I've heard that its good practice to escape values as you receive them from a form, and also escape when you output. That way you have two chances to catch something.

+2  A: 

You should only html encode when you output something to a browser. This prevents XSS attacks. The kind of escaping that you do when you collect data from a form, before you insert it into a database is not html encoding. It's escaping special database characters (best done using parameterized queries). The purpose of that is to prevent SQL injection attacks. So there is no double encoding going on.

Asaph
+6  A: 

I presume that you're using JSP.

Just escape during display only. There for the JSTL <c:out> tag is perfectly suitable. It escapes HTML entities by default. Use it to display every user-controlled input, such as request URL, request headers and request parameters.

E.g.

<input type="text" name="foo" value="<c:out value="${param.foo}" />">

Escaping during input is not needed. XSS doesn't harm in raw Java code nor in SQL databases. On the other hand, you would also rather save data unmodified in DB so that you can still see what the user actually entered, so that you can if necessary do social actions on mailicious users.

If you'd like to know what to escape during input, it would be SQL injection. In such case just use PreparedStatement instead of regular Statement whenever you want to save any user-controlled input in the database.

E.g.

create = connection.prepareStatement("INSERT INTO user (username, password) VALUES (?, MD5(?))");
create.setString(1, username);
create.setString(2, password);
create.executeUpdate();
BalusC
I'm now convinced to just escape during display. I'm wondering why Spring has the `defaultHtmlEscape` for forms though?
Kyle
@Spines: framework bloat?
Pontus Gagge
Isn't that an option to set "htmlescape" by default... and htmlescape means that it will write values into the final html form escaped? Something like <input type="textbox" value="some extrange chars"...>
helios
The *normal practice* is to escape them during **display/output** only. You don't want to mess with the input data. The Spring's `defaultHtmlEscape` is just a global setting to make all Spring MVC form tags behave like JSTL `c:out` does: escaping HTML entities. I don't do Spring MVC, but I suppose that this is defaulted to "true" like as `escapeXml` attribute of `c:out`.
BalusC
Thanks, I wasn't too sure about the `defaultHtmlEscape`, I had just read about it in http://stackoverflow.com/questions/2147958/how-do-i-prevent-people-from-doing-xss-in-java/2148120#2148120
Kyle
You're welcome :)
BalusC
Let me reiterate: If you always and consistently escape as you are formatting output, you'll avoid trouble. I'm presently working on a system where sometimes they escape at display time, sometimes they escape as they read values off the database, sometimes in the middle of bigger processes, and most of the time never at all. It's a nightmare to figure out. And how do I clean it up? I can't just put in escapes at display time now, because many values are already escaped, and so we'd end up displaying a bunch of ampersands! Arggh!
Jay
Oh, and do HTML escaping as you write to the browser, and SQL escaping -- whether with PreparedStatements or other means -- as you build your SQL. When you try to escape in advance, you may find that a code change means that a value that is SQL-escaped now needs to be written to the screen. I'm sure some insane programmers then write functions to convert SQL escapes to HTML escapes in a work area.
Jay
It's indeed a matter of proper timing. Only escape when you **actually need** to do so (i.e. during passing from one to other context where it can become malicious). That what you were saying is unfortunately recognizeable in poor projects. Best what you can do is to review the entire code and remove any unnecessary/wrong-timed escaping. Good luck.
BalusC
The <c:out> tag is not perfectly suitable. It escapes all of 5 characters, while the OWASP folks list many more than 5 characters that should be escaped. I don't trust c:out, and I don't recommend its use at all.
John O
When receiving input do _input validation_, and when ouputting data to a browser, a database or another subsystem, escape the data for that system. If you escape on input there is no way to know which system (database, browser, ldap, xml etc.) to escape for.
Erlend
+1  A: 

Content that is harmless in one context can be dangerous in another context. The best way to avoid injection attacks is to prepare the content before passing it to another context. In your case html text changes its context when it is passed to the browser. The server doesn't render the html but the browser does. So be sure to pass no malicious html to the browser and mask it before sending.

Another argument to do so is that it could be possible that the attack code is assembled within the application from two ore more inputs. Each of the inputs was harmless but together they can become dangerous.

deamon