【发布时间】:2020-03-17 14:10:36
【问题描述】:
我很好奇是否有人可以告诉我在用户提供的图像上使用 toDataURL 有多安全。基本思想是用户 A 将在其浏览器中上传图像并将其转换为 URL,然后忽略其间的步骤,最终用户 B(以及其他用户)将检索将转换的 URL 格式返回图片并显示在用户 B 的浏览器中。
所以我的问题围绕着是否有人可以滥用系统将代码注入用户 B 的浏览器,或者以其他方式造成严重破坏。一般来说,在使用 toDataURL 然后再将其转换回来时,有哪些安全注意事项?
我知道跨源图像会污染画布,它不允许任何涉及数据的方法,但我不知道这是多少一揽子解决方案。我读过一些浏览器没有此限制,而其他浏览器(甚至同一浏览器的其他版本)根据跨源图像的内容以不同方式实现此限制。
到目前为止我在研究中的发现:
- this question 答案指向一篇很棒的文章,从将上传的图像存储在服务器上的角度来看。
- this question 答案指出了一种有趣的方式来隐藏我以前从未见过的图像中的脚本,但我不确定如果我不尝试从该图像中提取脚本并运行它会产生什么漏洞它。
- 和this link 详细说明了浏览器选择限制对跨源图像的图像数据的访问的一个重要原因。我一直认为它只是为了防止恶意图像,但现在意识到它还可以防止更多。
从一个用户通过上传图像(不会保持上传状态而是转换为数据 url)攻击另一个用户的角度来看,以上都没有充分接近它,另一个用户稍后会下载和查看(使用 img src 设置为数据 url,而不是恶意用户的原始上传)。 2 接近回答我的问题,但据我了解,如果恶意用户也将一些脚本注入查看用户的浏览器,详细方法将无法正常工作。
解决这个问题是我想做的一个示例,包括文件上传/转换为数据 url 以及示例数据 url 以尝试导入(此示例 url 可以安全导入并且很小所以它可以快速导入):
window.onload = function() {
document.getElementById("convert").onclick = convert;
document.getElementById("import").onclick = importF;
let imageLoader = document.getElementById("imageLoader");
let canvas = document.getElementById("imageCanvas");
let ctx = canvas.getContext("2d");
imageLoader.addEventListener('change', e => {
let reader = new FileReader();
reader.onload = (ee) => {
loadImage("imageCanvas", ee.target.result);
}
reader.readAsDataURL(e.target.files[0]);
}, false);
};
function loadImage(id, src) {
let canvas = document.getElementById(id);
let ctx = canvas.getContext("2d");
let img = new Image();
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
}
img.src = src;
}
function convert() {
let canvas = document.getElementById("imageCanvas");
console.log(canvas.toDataURL());
}
function importF() {
let imageImport = document.getElementById("imageImport");
let url = imageImport.value;
loadImage("imageCanvas", url);
}
<label>Upload Image:</label>
<input type="file" id="imageLoader" name="imageLoader"/>
<br/>
<label>Import Image:</label>
<input type="text" id="imageImport" name="imageImport"/>
<br/>
<label>Sample URL:</label>
<code style="user-select: all;"> data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAOCAYAAAAmL5yKAAAApUlEQVQ4T2NkQALyKu5GjP8Z01kZ/1n/+s+kjSyHi80Ik1BQdvf4z8C4nYPx/z819t9M+py/GRj+MzAwgFTgocEGyCl75DEyMEz04f3OEC34lUGY+R8xloPVMMopeTgzMjLsMeb8xdAu8YFojTCFjPJKblNlWf+lTpV5z8rBCHIraYBRQ9Xtoi3XL70S0U+k6YSqZpRX9vgfK/CVIVbw66gBIzcMAHB4Ryt6jeYXAAAAAElFTkSuQmCC </code>
<br/>
<button id="import"> Import from URL </button>
<button id="convert"> Convert to URL </button>
<br/>
<canvas id="imageCanvas"></canvas>
【问题讨论】:
-
我会说浏览器坏了,如果这真的是一个问题,需要修复,只要你在图像标签中使用数据 url,只有。因为否则显然我可以制作图像来创建恶意网站。对于 SVG(可能包含脚本)作为图像标签中的数据 url,它们将在“沙箱”中执行。
-
很高兴了解沙盒,让我感觉更安全。我同意任何问题都可能更多地出在浏览器上而不是我身上,但听到其他人也有同样的感觉会很有帮助。
-
当然,在您将其内联到您的页面之前,请确保它是一个有效的 URL!否则像这样的未转义的“URL”将是一个问题:
data:image/png;base64,iVBORw"><script>console.log("Hello")</script><img src=" -
是的,不用担心,从我的问题中提供的 sn-p 可以看出,我没有计划将其内联到我的页面中。感谢所有有用的信息:)
-
@Sebastian svg in an img 不会执行任何脚本,甚至不会被沙盒化。
标签: javascript html security canvas