我有一个功能,用户可以上传html文件,然后我通过PHP读取其内容,并将其作为字符串发送到第三方API。现在,在我把它发送给API之前,我想要生成一个他们上传到用户的HTML预览,这样他们就可以按下确认按钮来发送它。
HTML文件应该主要是字母模板,但用户可以修改HTML和添加一些脚本标签或注入其他恶意代码,可能会损害我的网站,同时显示预览。有什么办法可以避免吗?
我想剥离标签,但如果他们有onclick事件在html元素?
我从这样的东西开始,剥离脚本和注释:
$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,而Regex是在黑暗中拍摄。
实际上,您可以对所有这些使用DOMDocument,而根本不使用Regex。在DOMDocument对象中加载HTML,并遍历树,删除您想要的内容。
这不是100%适合您,但似乎将HTML作为SVG呈现到画布上将限制内容在您的需求范围内(没有脚本,没有加载外部源)。
查看更多文档:https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas
你可能想知道这怎么可能是安全的,考虑到对从画布中读取敏感数据的可能性。的答案是:这个解决方案依赖于这样一个事实SVG图像的实现是非常受限的。SVG图像则不是允许加载任何外部资源,例如,甚至是那些似乎来自同一个地区。光栅图像等资源(如JPEG图像)或s必须内联为data: uri。
此外,您不能在SVG图像中包含脚本,因此没有从其他脚本访问DOM的风险,以及SVG中的DOM元素图像不能接收输入事件,因此无法加载将特权信息放入表单控件中(例如到控件的完整路径)文件元素)并呈现它,然后通过读取像素
我可能已经找到了处理这个问题的库。我还没有完全测试过它,但根据它的描述,它可能是:http://htmlpurifier.org/
使用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>