c:out nested inside element attribute
Solution 1
The common practice to prevent XSS attacks in HTML element attributes without disturbing the well formed XML syntax by a nested <c:out>
tag is using fn:escapeXml()
function instead:
<input type="text" name="firstname" value="${fn:escapeXml(param.firstname)}"/>
Solution 2
I usually use the ${}
everywhere that I can. It's simple and more readable. I use <c:out>
when I need the extra functionality, such as the escapeXml
function.
In your example, you could actually get away with no <c:out>
:
<input type="text" name="firstname" value="${param.firstname}"/>
Edit: XSS issues
My answer does not address the XSS holes that BalusC and StuartWakefield mention. Although my answer is simplistically correct, you really should always mitigate XSS holes. I prefer to use the OWASP taglib.
<span>${esc:forHtml(sketchyText)}</span>
<span><esc:forHtml(sketchyText)/></span>
<input value="${esc:forHtmlAttribute(sketchyText)}"/>
Related videos on Youtube
Comments
-
Ryan almost 2 years
Is nesting a c:out JSTL tag inside an element attribute a good practice or is using the var attribute of c:out generally preferred? It seems to work either way, but I suspect nesting it might not work in some application servers or versions of JSP (and it just looks wrong).
For example, an input element which has its value restored on validation failure, and with special character escaping:
<input type="text" name="firstname" value="<c:out value="${param.firstname}"/>"/>
versus:
<c:out value="${param.firstname}" var="firstname"/> <input type="text" name="firstname" value="${firstname}"/>
-
BalusC over 12 yearsThis only works in JSP 2.0 and newer, which should be no problem nowadays, but this only puts a wide XSS attack hole open...
-
Ryan over 12 yearsHmmm, it seems like there is no good reason to ever use c:out then?
-
BalusC over 12 yearsNot in HTML element attributes, no. Outside it, that depends. The
<c:out value="${bean.foo}" />
is for some developers more readable than${fn:escapeXml(bean.foo)}
. Alternatively, you can also go ahead with a MVC framework like JSF so that you never need to worry about this (and all other repeated boilerplate in servlets). -
IcedDante almost 12 yearsIs that documented somewhere? I would like to read more about it and I cannot conceive why using ${} directly in an HTML attribute would lead to an XSS attack...
-
RustyTheBoyRobot almost 12 years@IcedDante - If you use the '@{username}' in your comment, it'll send a notification to BalusC. Otherwise, he'll probably miss your comment.
-
IcedDante almost 12 yearsThanks, I'll let @BalusC know now!
-
Stuart Wakefield over 8 yearsMy friend's firstname is
"/><script>/*xss here*/</script><img src="lolcatz.jpg"
... Some other security measure may capture this case before we get to the input but it is conceivable to get around it. In any case, with the code above any errant double quote in the firstname will "break out" of the HTML attribute. You should escape it for the context you are outputting it, i.e. a functionescapeHtmlAttribute
would be ideal,${fn:escapeXml(person.firstname)}
is sufficient. -
RustyTheBoyRobot over 8 years@StuartWakefield - Please tell me you actually know someone with that name. I thought it was only myth. Thankfully, I've learned a lot more about XSS since posting this answer.