DOM 在此示例中可以使用基于 XSS 的方法吗?
DOM based XSS is possible in this example?
我已经阅读了一堆关于 DOM 基于 XSS 的文档,但我仍然无法弄清楚。来看看我的例子吧
var html = `
<a class="url" href="${untrustedURL}">
<img src="${untrustedSource}">
</a>
<span class="name" data-value="${untrustedValue}">${untrustedText}</span>
`;
document.querySelector('#user').innerHTML = html;
攻击者如何利用此代码的漏洞?解决方案是什么?
通过 url 和图像的来源,不受信任的值将是,例如:
javascript:evilStuff()
在 link 的情况下,代码将在用户单击时 运行,而在图片来源的情况下,浏览器将 运行尝试加载图像。请注意,图像 src 的技术仅适用于旧浏览器,现代浏览器将忽略它。我看到 link 的另一个问题是,例如,您可能会得到一个 link 将您定向到网络钓鱼站点!
仅当您在代码中的其他地方使用该值时,数据值属性才会变得易受攻击,并且以可能有害的方式使用,否则,我看不到其中的危险。
至于 span 的内容,如果不转义 HTML 个字符,几乎所有内容都可以插入其中。脚本标签、iframe、图像等...请注意,这适用于您在任何地方插入的所有不安全值。
恶意人员可以在您无法逃脱 HTML 实体的任何地方插入任何 HTML。
我认为解决方案总是 escape/strip 标签和某些值。例如,为了防止用户在动态 href 中插入危险的 url,您可以应用正则表达式从字符串的开头删除单词 javascript:
,或者检查无效的 urls(不同的域、不寻常的字符、格式错误的 url 等)。
假设 ${untrustedText}
没有被 HTML 转义,尝试将其设置为:
<div style="position:fixed;left:0;right:0;top:0;bottom:0;"
onmousemove="this.style.display='none';alert('XSS');"></div>
虽然我同意@Alfonso 的回答中提出的漏洞,但情况实际上更糟:所有 你的不受信任的变量在这里容易受到 XSS 攻击。
例如,
假设 untrustedURL
包含以下文本
"><img src="http://example.com" onerror=alert(/xss/) data-x="
这将导致呈现以下内容:
<a class="url" href=""><img src="http://example.com" onerror="alert(/xss/)" data-x="">
这将导致 JavaScript 警报立即显示:
由于您的代码已经全部在 JavaScript 上下文中,因此您需要对数据进行 follow Rule #1 of the OWASP XSS cheat sheet 和 HTML 编码。以下字符的简单转换就足够了:
& --> &
< --> <
> --> >
" --> "
' --> ' ' not recommended because its not in the HTML spec (See: section 24.4.1) ' is in the XML and XHTML specs.
/ --> / forward slash is included as it helps end an HTML entity
请注意,OWASP 推荐规则 #2 用于 HTML 属性值,但是如果您引用所有属性,那么以上内容就足够了。规则 #2 适用于任何地方,包括未引用的,所以如果你有混合规则 #2 会更简单。
我读过 关于你说你应该 encode Javascript after escaping HTML entities
。
是的,这适用于值的初始来源(比如来自服务器端),但您应该使用服务器端代码使用的语言进行编码,而不是 JavaScript。此外,首先执行 JavaScript 转义以将服务器端变量放入 JavaScript,然后在 JavaScript 中使用 HTML 转义准备插入 DOM。
例如JavaScript 在 ASP.NET C#:
中转义
<script>
var untrustedURL = "<%=HttpUtility.JavaScriptEncodeString(usersUrl)%>";
</script>
.
然后你需要HTML使用函数编码:
function escapeHTML (unsafe_str) {
return unsafe_str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\"/g, '"')
.replace(/\'/g, ''')
.replace(/\//g, '/')
}
所以你的代码可以是
<script>
var untrustedURL = escapeHTML("<%=HttpUtility.JavaScriptEncodeString(usersUrl)%>");
</script>
untrustedURL
和 untrustedSource
请注意,这些是也应进行验证的特殊情况。您应该在服务器端执行此操作,并确保它们以 http://
、https://
或 //
(protocol relative URL) 开头。白名单方法可确保用户无法输入 javascript:
方案 URL 并且还将防止输入可能对用户的浏览器、操作系统、设备、配置等唯一的不同方案。仅允许 HTTP 更安全。
我已经阅读了一堆关于 DOM 基于 XSS 的文档,但我仍然无法弄清楚。来看看我的例子吧
var html = `
<a class="url" href="${untrustedURL}">
<img src="${untrustedSource}">
</a>
<span class="name" data-value="${untrustedValue}">${untrustedText}</span>
`;
document.querySelector('#user').innerHTML = html;
攻击者如何利用此代码的漏洞?解决方案是什么?
通过 url 和图像的来源,不受信任的值将是,例如:
javascript:evilStuff()
在 link 的情况下,代码将在用户单击时 运行,而在图片来源的情况下,浏览器将 运行尝试加载图像。请注意,图像 src 的技术仅适用于旧浏览器,现代浏览器将忽略它。我看到 link 的另一个问题是,例如,您可能会得到一个 link 将您定向到网络钓鱼站点!
仅当您在代码中的其他地方使用该值时,数据值属性才会变得易受攻击,并且以可能有害的方式使用,否则,我看不到其中的危险。
至于 span 的内容,如果不转义 HTML 个字符,几乎所有内容都可以插入其中。脚本标签、iframe、图像等...请注意,这适用于您在任何地方插入的所有不安全值。
恶意人员可以在您无法逃脱 HTML 实体的任何地方插入任何 HTML。
我认为解决方案总是 escape/strip 标签和某些值。例如,为了防止用户在动态 href 中插入危险的 url,您可以应用正则表达式从字符串的开头删除单词 javascript:
,或者检查无效的 urls(不同的域、不寻常的字符、格式错误的 url 等)。
假设 ${untrustedText}
没有被 HTML 转义,尝试将其设置为:
<div style="position:fixed;left:0;right:0;top:0;bottom:0;"
onmousemove="this.style.display='none';alert('XSS');"></div>
虽然我同意@Alfonso 的回答中提出的漏洞,但情况实际上更糟:所有 你的不受信任的变量在这里容易受到 XSS 攻击。
例如,
假设 untrustedURL
包含以下文本
"><img src="http://example.com" onerror=alert(/xss/) data-x="
这将导致呈现以下内容:
<a class="url" href=""><img src="http://example.com" onerror="alert(/xss/)" data-x="">
这将导致 JavaScript 警报立即显示:
由于您的代码已经全部在 JavaScript 上下文中,因此您需要对数据进行 follow Rule #1 of the OWASP XSS cheat sheet 和 HTML 编码。以下字符的简单转换就足够了:
& --> &
< --> <
> --> >
" --> "
' --> ' ' not recommended because its not in the HTML spec (See: section 24.4.1) ' is in the XML and XHTML specs.
/ --> / forward slash is included as it helps end an HTML entity
请注意,OWASP 推荐规则 #2 用于 HTML 属性值,但是如果您引用所有属性,那么以上内容就足够了。规则 #2 适用于任何地方,包括未引用的,所以如果你有混合规则 #2 会更简单。
我读过 encode Javascript after escaping HTML entities
。
是的,这适用于值的初始来源(比如来自服务器端),但您应该使用服务器端代码使用的语言进行编码,而不是 JavaScript。此外,首先执行 JavaScript 转义以将服务器端变量放入 JavaScript,然后在 JavaScript 中使用 HTML 转义准备插入 DOM。
例如JavaScript 在 ASP.NET C#:
中转义<script>
var untrustedURL = "<%=HttpUtility.JavaScriptEncodeString(usersUrl)%>";
</script>
然后你需要HTML使用函数编码:
function escapeHTML (unsafe_str) {
return unsafe_str
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/\"/g, '"')
.replace(/\'/g, ''')
.replace(/\//g, '/')
}
所以你的代码可以是
<script>
var untrustedURL = escapeHTML("<%=HttpUtility.JavaScriptEncodeString(usersUrl)%>");
</script>
untrustedURL
和 untrustedSource
请注意,这些是也应进行验证的特殊情况。您应该在服务器端执行此操作,并确保它们以 http://
、https://
或 //
(protocol relative URL) 开头。白名单方法可确保用户无法输入 javascript:
方案 URL 并且还将防止输入可能对用户的浏览器、操作系统、设备、配置等唯一的不同方案。仅允许 HTTP 更安全。