diff --git a/collects/web-server/scribblings/templates.scrbl b/collects/web-server/scribblings/templates.scrbl index d52568ad97..f9d3f8ea0f 100644 --- a/collects/web-server/scribblings/templates.scrbl +++ b/collects/web-server/scribblings/templates.scrbl @@ -256,6 +256,84 @@ issue for you called @racket[in]: }| Notice how it also avoids the absurd amount of punctuation on line two. +@section{Escaping} + +@margin-note{Thanks to Michael W. for this section.} + +Because templates are useful for many things (scripts, CSS, HTML, +etc), the Web Server does not assume that the template is for XML-like +content. Therefore when when templates are expanded, no +XML escaping is done by default. Beware of @emph{cross-site scripting} +vulnerabilities! For example, suppose a servlet serves the following +template where @racket[_some-variable] is an input string supplied by +the client: + +@verbatim[#:indent 2]|{ + + Fastest Templates in the West! + + @some-variable + + +}| + +If the servlet contains something like the following: + +@racketblock[ + (let ([some-variable (get-input-from-user)]) + (include-template "static.htm")) +] + +There is nothing to prevent an attacker from entering +@litchar[""] to make the +template expand into: + +@verbatim[#:indent 2]|{ + + Fastest Templates in the West! + + + + +}| + +Now the server will send the attacker's code to millions of innocent +users. To keep this from happening when serving HTML, use the +@racket[xexpr->string] function from the @racketmodname[xml] module. + +This can be done in the servlet: + +@racketblock[ + (require xml) + + (let ([some-variable (xexpr->string (get-input-from-user))]) + (include-template "static.htm")) +] + +Alternatively, make the template responsible for its own escaping: + +@verbatim[#:indent 2]|{ + + Fastest Templates in the West! + + @(xexpr->string some-variable) + + +}| + +The improved version renders as: + +@verbatim[#:indent 2]|{ + + Fastest Templates in the West! + + <script type=\"text/javascript\">...</script> + + +}| + +When writing templates, always remember to escape user-supplied input. + @section{HTTP Responses} The quickest way to generate an HTTP response from a template is using