M
m4dc4p
Something I've seen in the blogosphere lately has been the
vulnerability of web applications to cross site scripting (XSS)
attacks. I think it was LiveJournal I was reading about which got hit
with a nasty one that compromised quite a few accounts.
This got me thinking about how to protect against this kind of stuff in
an automatic way. Because I've done all of my ruby web apps using
Rails, I thought about modifing view templates so they always
HTML-escape "dangerous" content. ERB templates as rhtml files is the
most common way for Rails to generate content, so that was the first
place I looked.
In erb.rb, the Buffer#compile method actually builds the template which
will get evaluated. I modified the source where it outputs code when a
close tag (i.e. "%>") is found. The code went from (this starts on line
549 for 1.8.3):
case token
when '%>'
case scanner.stag
when '<%'
# snip
when '<%='
out.push("#{@put_cmd}((#{content}).to_s)")
# snip
To:
# snip
when '<%='
out.push("#{@put_cmd}((#{content}).tainted? ?
html_escape((#{content}).to_s) : (#{content}).to_s)")
# snip
I thought it was logical that if a piece of code was tainted, it should
be HTML escaped. Unfortuntately, this was a little too broad and it
ended up escaping some things I didn't want escaped.
I didn't have a chance to take this much further but does it strike a
thought in anyone else?
Justin
vulnerability of web applications to cross site scripting (XSS)
attacks. I think it was LiveJournal I was reading about which got hit
with a nasty one that compromised quite a few accounts.
This got me thinking about how to protect against this kind of stuff in
an automatic way. Because I've done all of my ruby web apps using
Rails, I thought about modifing view templates so they always
HTML-escape "dangerous" content. ERB templates as rhtml files is the
most common way for Rails to generate content, so that was the first
place I looked.
In erb.rb, the Buffer#compile method actually builds the template which
will get evaluated. I modified the source where it outputs code when a
close tag (i.e. "%>") is found. The code went from (this starts on line
549 for 1.8.3):
case token
when '%>'
case scanner.stag
when '<%'
# snip
when '<%='
out.push("#{@put_cmd}((#{content}).to_s)")
# snip
To:
# snip
when '<%='
out.push("#{@put_cmd}((#{content}).tainted? ?
html_escape((#{content}).to_s) : (#{content}).to_s)")
# snip
I thought it was logical that if a piece of code was tainted, it should
be HTML escaped. Unfortuntately, this was a little too broad and it
ended up escaping some things I didn't want escaped.
I didn't have a chance to take this much further but does it strike a
thought in anyone else?
Justin