我有一个功能,用户可以上传html文件然后通过PHP读取其内容并将其作为字符串发送到第三方API。在我将其发送到API之前,我想生成他们上传到用户的HTML的预览,以便他们可以按“确认”按钮发送它。
HTML文件应该主要是字母模板,但是用户可以在显示预览时修改html并添加一些脚本标签或注入可能损害我网站的其他恶意代码。有没有办法可以避免这种情况?
我考虑过剥离标签,但是如果他们在html元素中有onclick事件呢?
答案 0 :(得分:2)
我从这样的东西开始剥离脚本和评论:
$htmlblacklist[] = '@<script[^>]*?>.*?</script>@si'; //bye bye javascript
$htmlblacklist[] = '@<![\s\S]*?--[ \t\n\r]*>@'; //goodbye comments
//now apply blacklist
$value = preg_replace($htmlblacklist, '', $value);
对于内联事件,您应该使用DOMDocument,因为它理解HTML而正则表达式在黑暗中拍摄。
实际上,你可以将DOMDocument用于所有这些,而根本不使用Regex。在DOMDocument对象中加载HTML,并遍历树,删除您想要的内容。
答案 1 :(得分:0)
不是100%这对你有用,但似乎将HTML作为SVG渲染到画布上会将内容限制在你的要求范围内(没有脚本,没有外部加载)。
请在此处查看更多文档:https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas
鉴于您的担忧,您可能想知道这是如何安全的 从画布中读取敏感数据的可能性。该 答案是这样的:这个解决方案依赖于这个事实 SVG图像的实现非常严格。 SVG图像不是 允许加载任何外部资源,例如,甚至是那些 似乎来自同一个域。光栅图像等资源 (例如JPEG图像)或s必须作为数据内联:URI。
此外,您不能在SVG图像中包含脚本,因此没有 从其他脚本和SVG中的DOM元素访问DOM的风险 图像无法接收输入事件,因此无法加载 将特权信息转换为表单控件(例如完整路径转换为表单控件) 文件元素)并渲染它,然后拉出那些信息 读取像素。
答案 2 :(得分:0)
我可能找到了处理此问题的库。尚未对其进行全面测试,但根据其描述可能是:http://htmlpurifier.org/
答案 3 :(得分:0)
使用FileReader
读取文件内容,使用iframe
安全(或不)查看文件:
document.querySelector("button").addEventListener(
'click',
function() {
let iframe = document.createElement("iframe"),
holder = document.querySelector("#iframeholder"),
sandboxFlags = [
...document.querySelectorAll('.sandbox-flags:checked')
].map(_ => _.value).join(','),
file = document.querySelector('input[type=file]').files[0],
reader = new FileReader();
reader.addEventListener("load", function() {
iframe.setAttribute("scrolling", "no");
iframe.setAttribute("frameborder", "0");
iframe.setAttribute("srcdoc", this.result);
/*
* Sandboxing is not allowed in code snippets
* iframe.setAttribute("sandbox", sandboxFlags);
*
*/
console.log(`sandbox=${sandboxFlags}`);
while (holder.firstChild)
holder.removeChild(holder.firstChild);
holder.appendChild(iframe);
}, false);
reader.readAsText(file);
},
false);
label {
display: block
}
#iframeholder>iframe {
border:1px solid black;
height:400px;
width:400px;
}
<div>
<input id="browse" type="file" >
</div>
<label>
<input type="checkbox" class="sandbox-flags" value='allow-script' />allow-scripts
</label>
<label>
<input type="checkbox" class="sandbox-flags" value='allow-popups-to-escape-sandbox' />allow-popups-to-escape-sandbox
</label>
<label>
<input type="checkbox" class="sandbox-flags" value='allow-forms' />allow-forms
</label>
<label>
<input type="checkbox" class="sandbox-flags" value='allow-modals' />allow-modals
</label>
<div>
<button type="button">Preview</button>
</div>
<div id="iframeholder"></div>