如何安全地处理Scala中的unicode用户输入(esp XML实体)

时间:2010-01-09 15:25:32

标签: xml scala xml-serialization

在我的网站上,我有一个表单,其中包含一些文本用户输入。一切都适用于“普通”字符。但是当输入unicode字符时......好吧,情节会变粗。

用户输入类似

的内容
やっぱ死にかけてる

这作为包含XML实体引用

的文本进入服务器
やっぱ死にかけてる?

现在,当我想以HTML格式回复客户端时,我该怎么做?

如果我只是按原样输出字符串,则可能存在脚本攻击的可能性。如果我尝试使用scala.xml.Text对其进行编码,则会转换为:

やっぱ死にかけてる?

Scala中是否有更好的现成解决方案,可以检测实体引用,转义它们,但是转义XML标记?

4 个答案:

答案 0 :(得分:5)

将包含实体引用的字符串解析为XML片段。要安全地在XML中输出Unicode字符,您可以偏执并使用XML实体引用,根据函数escape

scala>import xml.parsing.ConstructingParser                                                             
import xml.parsing.ConstructingParser

scala>import io.Source                                                                                  
import io.Source

scala> val d = ConstructingParser.fromSource(Source.fromString("<dummy>&#12420;</dummy>"), true).documnent
d: scala.xml.Document = <dummy>や</dummy>

scala>val t = d(0).text                                                                                         
res0: String = や

scala> import xml._
import xml._

scala> def escape(xmlText: String): NodeSeq = {
     |   def escapeChar(c: Char): xml.Node =
     |     if (c > 0x7F || Character.isISOControl(c))
     |       xml.EntityRef("#" + Integer.toString(c, 10))
     |     else
     |       xml.Text(c.toString)
     | 
     |   new xml.Group(xmlText.map(escapeChar(_)))
     | }
escape: (xmlText: String)scala.xml.NodeSeq

scala> <foo>{escape(t)}</foo>                            
res3: scala.xml.Elem = <foo>&#12420;</foo>

答案 1 :(得分:1)

好的,我正在尝试这个简单的黑客攻击。欢迎评论:

def secureEscape(text: String) = {
  val s = new StringBuilder()
  for (c <- text.elements) c match {
   case '<' => s.append("&lt;")
   case '>' => s.append("&gt;")
   case _   => s.append(c)
  }
  s.toString
}

这基本上会逃脱<>

然后我使用此函数来解析传入的表单输入,然后将其输出,而无需进一步处理客户端。

答案 2 :(得分:0)

实际上,浏览器应该负责正确的UTF-8编码和字符转义(这似乎正在发生)。然后,您的Web框架应该处理unescaping和解码。

这可能是一个棘手的业务,涉及几个步骤,所有这些都可能必须明确配置为正确的UTF-8操作。特别是在使用旧框架和服务器,缓存代理,内容交付网络等时

关键是,在内部,您希望看到预期的unicode字符 - 而不是实体引用。同样,您应该在系统边界输出本机unicode和句柄以及所需的编码,最好由您选择的Web框架自动处理。

为了给您正确的解决方案,有必要知道您正在使用的软件堆栈以及表单的提交方式(即GET / POST / AJAX + JSON)

答案 3 :(得分:0)

当字符位于提供页面的字符集之外时,浏览器仅将输入字符编码为数字字符引用实体。节省很多麻烦,并以UTF-8正确标记为UTF-8的方式提供页面。 Scala,Java和Javascript字符串处理全部使用Unicode,并且限制为网页的iso-8859-1会在所有方向上引发这样的转换问题。如果您现有的内容是ASCII,那么转换应该是轻松的。