有更好的方法吗?(递归解析HTML unicode实体)

Is there a better way to do this? (recursively resolving HTML unicode entities)

本文关键字:HTML unicode 实体 递归 更好 方法      更新时间:2023-09-26

我正在解析一个不受信任的URI,但必须遵守它的URI引擎盖。我正在努力防止javascript:链接,但我觉得我需要重复使用它,因为你可以:

javascriptjavascript::

并且在剥离了CCD_ 3的所有实例之后,再次取回我们的老朋友CCD_。

我关心的另一个问题是类似的嵌套unicode实体。例如,我们可以有:

"j&#X41vascript:alert('pwnt')"

但我们也可以有:

"j&#&#X5841vascript:alert('pwnt')"

尽管我似乎做错了(而一个成功的攻击者显然不会。)

function resolveEntities(uri) {
  var s = document.createElement('span')
    , nestTally = uri.match(/&/) ? 0 : 1
    , limitReached = false;
  s.innerHTML = uri;
  while (s.textContent.match(/&/)) {
    s.innerHTML = s.textContent;
    if(nestTally++ >= 5) {
      limitReached = true;
      break;
    }
  }
  return encodeURI(s.textContent);
}

你以前不是已经问过几乎相同的问题吗?不管怎样,我的建议还是一样的:使用合适的HTML消毒剂。

我链接到的特定消毒剂会自动剥离javascript: URL,但您也可以将其设置为只允许某些白名单URL方案,如Thomas建议的那样。正如他所指出的,这是一个好主意,因为只允许像httphttps这样你知道是安全的方案会安全得多。

(特别是,给定的模糊URL方案是否安全,可能不仅取决于用户的浏览器,还取决于他们的操作系统和他们可能安装的第三方软件,许多程序喜欢将自己注册为自己URL方案的处理程序。)

与其指定要将哪些内容列入黑名单(例如javascript: URI),不如指定要将什么内容列入白名单(例如仅限httphttps)。像这样的东西怎么样:

function sanitizeUri(uri) {
  if (!uri.match(/^https?:'/'//)) {
    uri = "http://" + uri;
  }
  return uri;
}