c:out nested inside element attribute

11,802

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)}"/>
Share:
11,802

Related videos on Youtube

Ryan
Author by

Ryan

Software Developer

Updated on June 04, 2022

Comments

  • Ryan
    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
    BalusC over 12 years
    This 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
    Ryan over 12 years
    Hmmm, it seems like there is no good reason to ever use c:out then?
  • BalusC
    BalusC over 12 years
    Not 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
    IcedDante almost 12 years
    Is 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
    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
    IcedDante almost 12 years
    Thanks, I'll let @BalusC know now!
  • Stuart Wakefield
    Stuart Wakefield over 8 years
    My 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 function escapeHtmlAttribute would be ideal, ${fn:escapeXml(person.firstname)} is sufficient.
  • RustyTheBoyRobot
    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.