UTF-8的 multibyte特性:
1个文字是由复数个字节组成的.
Shift_JIS情况下,一个"あ"占2个字节.
"あ".tosjis.bytes.to_a #=>[130, 160]
utf-8情况下,一个"あ"占3个字节.
"あ".toutf8.bytes.to_a #=>[227, 129, 130]
攻击例:
ruby代码
<%= f.text_area :memo, :size =>"100x10" %>
1.http://example.com/...?memo=%c0%3c%2ftextarea%20%c0%3e%c0%3cimg%20src=1%20onerror=alert(0)//
[decode值 http://example.com/...?memo=�</textarea �>�<img src=1 onerror=alert(0)//]
解析后HTML代码
<textarea cols="100" id="memo" name="object[memo]" rows="10">�</textarea �>�<img src=1 onerror=alert(0)//</textarea>
原因:
output_safety.rb#html_escape方法处理不了utf-8 multibyte数据.
html_escape中的String.gsub(/[&"><]/)把�<当成一个字符处理,所以不会转义<
对策:
def html_escape(s)
s = s.to_s
if s.html_safe?
s
else
- s.gsub(/[&"><]/) { |special| HTML_ESCAPE[special] }.html_safe
+ s.to_s.gsub(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/</, "<").html_safe
end
end
参考文章:
http://groups.google.com/group/rubyonrails-security/browse_thread/thread/56bffb5923ab1195
http://gihyo.jp/admin/serial/01/charcode/0006
http://d.hatena.ne.jp/IwamotoTakashi/20090922/p1
http://dev1.slideshare.com/ockeghem/ss-5620584