将脚本标记代码附加到 dom 元素以执行,替代 document.write
Attach script tag code to dom element for execution , alternate for document.write
var str = '<script>alert(1)</script>';
var decoded = $("<div/>").html(str).text();
//document.write(decoded); THIS WORKS, but I want to avoid using document.write
var para = document.createElement("script");
var node = document.createTextNode(decoded);
para.appendChild(node);
var element = document.getElementById("div1");
element.appendChild(para);
问题是由于存在脚本标记,此 createElement 方法将不起作用。在编码的 str 中关闭脚本标签将导致语法错误(未捕获的语法错误:意外的标记“<”)。
Document.write 工作完美,但我想避免由于其解析器块等缺点
在实际使用案例中,编码字符串将是用户输入的一些广告。请注意,我们无法从他们输入的代码中删除脚本标签,而是使用 htmlentities($adcode).
将其保存在数据库中
用户输入是可信的,因此没有任何 xss 漏洞的问题,这可能会通过所提出的解决方案发生。
示例用户输入之一:
<script async="async" src="someURL.js"></script>
<script>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
</script>
<div id="xyzid">
<script type="text/javascript">
googletag.cmd.push(function() {
googletag.pubads().display("Mobile_ATF_300x250", [300,250],"div-gpt-ad-0");
});
</script>
</div>
可以有各种不同版本的广告集,模式未知。
其他不太相关的信息:我们将进一步使用类似 <script>
if(var==1) { codeblock1 } else { codeblock2} </script>
的东西(这里的 codeblock 是第一个代码块集) .因此,任何包含直接使用解码用户输入的解决方案都不会有用,因为脚本块将在 if-else 中中断。
因此,为了回答这个问题,我必须首先更改 ad2,因为它位于脚本标记内,不再需要它,您可以做的是创建一个名为 Script 的元素,类型为 text/javascript并插入文本,然后将其插入正文。
var ad2 = `alert(12)`;
var decoded = decodeHtml(ad2);
decoded = decoded.replace(/(<([^>]+)>)/ig,'')
var para = document.createElement("script");
para.type = "text/javascript";
para.text = decoded
var element = document.getElementById("div12")
element.appendChild(para)
这是 jsfiddle 中关于如何操作的工作演示。
https://jsfiddle.net/59g24do1/
编辑
对于多个脚本,请改用它;我们在这里做的是首先我们创建一个标签数组,然后我们用前面的函数一个一个地创建,做一个 for 循环以执行它们。 = >
function getParagraphs(htmlString) {
const div = document.createElement("div");
div.insertAdjacentHTML("beforeend", htmlString);
return Array.from(div.querySelectorAll("script"))
.map(script => script.outerHTML);
}
for(let i = 0;i<decoded.length;i++){
if(decoded[i].includes("src")){
let srcString = decoded[i].match('src="(.*)"')
var para = document.createElement("script");
let aux = decoded[i].replace(/(<([^>]+)>)/ig,'')
para.type = "text/javascript";
para.src = srcString[1]
para.text = aux
var element = document.getElementById("div12")
element.appendChild(para)
}else{
let aux = decoded[i].replace(/(<([^>]+)>)/ig,'')
let para = document.createElement("script");
para.type = "text/javascript";
para.text = aux
let element = document.getElementById("div12")
element.appendChild(para)
}
}
对于完整的示例,请使用 jsfiddle
https://jsfiddle.net/f2Leu74g/2/
我能够通过下面的代码解决它,如果将来有人遇到同样的问题,我想更新。
var ad = "whatever encoded here script code";
function decodeHtml(html) {
return $("<textarea/>").html(html).text();
}
function fetch(id, html) {
var elm = document.getElementById(id);
elm.innerHTML = html;
var scripts = elm.getElementsByTagName("script");
var scriptsClone = [];
for (var i = 0; i < scripts.length; i++) {
scriptsClone.push(scripts[i]);
}
for (var i = 0; i < scriptsClone.length; i++) {
var currentScript = scriptsClone[i];
var s = document.createElement("script");
// Copy all the attributes from the original script
for (var j = 0; j < currentScript.attributes.length; j++) {
var a = currentScript.attributes[j];
s.setAttribute(a.name, a.value);
}
s.appendChild(document.createTextNode(currentScript.innerHTML));
currentScript.parentNode.replaceChild(s, currentScript);
}
}
var decoded = decodeHtml(ad);
fetch('YourDivID',decoded);
var str = '<script>alert(1)</script>';
var decoded = $("<div/>").html(str).text();
//document.write(decoded); THIS WORKS, but I want to avoid using document.write
var para = document.createElement("script");
var node = document.createTextNode(decoded);
para.appendChild(node);
var element = document.getElementById("div1");
element.appendChild(para);
问题是由于存在脚本标记,此 createElement 方法将不起作用。在编码的 str 中关闭脚本标签将导致语法错误(未捕获的语法错误:意外的标记“<”)。 Document.write 工作完美,但我想避免由于其解析器块等缺点
在实际使用案例中,编码字符串将是用户输入的一些广告。请注意,我们无法从他们输入的代码中删除脚本标签,而是使用 htmlentities($adcode).
将其保存在数据库中用户输入是可信的,因此没有任何 xss 漏洞的问题,这可能会通过所提出的解决方案发生。
示例用户输入之一:
<script async="async" src="someURL.js"></script>
<script>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
</script>
<div id="xyzid">
<script type="text/javascript">
googletag.cmd.push(function() {
googletag.pubads().display("Mobile_ATF_300x250", [300,250],"div-gpt-ad-0");
});
</script>
</div>
可以有各种不同版本的广告集,模式未知。
其他不太相关的信息:我们将进一步使用类似 <script>
if(var==1) { codeblock1 } else { codeblock2} </script>
的东西(这里的 codeblock 是第一个代码块集) .因此,任何包含直接使用解码用户输入的解决方案都不会有用,因为脚本块将在 if-else 中中断。
因此,为了回答这个问题,我必须首先更改 ad2,因为它位于脚本标记内,不再需要它,您可以做的是创建一个名为 Script 的元素,类型为 text/javascript并插入文本,然后将其插入正文。
var ad2 = `alert(12)`;
var decoded = decodeHtml(ad2);
decoded = decoded.replace(/(<([^>]+)>)/ig,'')
var para = document.createElement("script");
para.type = "text/javascript";
para.text = decoded
var element = document.getElementById("div12")
element.appendChild(para)
这是 jsfiddle 中关于如何操作的工作演示。
https://jsfiddle.net/59g24do1/
编辑 对于多个脚本,请改用它;我们在这里做的是首先我们创建一个标签数组,然后我们用前面的函数一个一个地创建,做一个 for 循环以执行它们。 = >
function getParagraphs(htmlString) {
const div = document.createElement("div");
div.insertAdjacentHTML("beforeend", htmlString);
return Array.from(div.querySelectorAll("script"))
.map(script => script.outerHTML);
}
for(let i = 0;i<decoded.length;i++){
if(decoded[i].includes("src")){
let srcString = decoded[i].match('src="(.*)"')
var para = document.createElement("script");
let aux = decoded[i].replace(/(<([^>]+)>)/ig,'')
para.type = "text/javascript";
para.src = srcString[1]
para.text = aux
var element = document.getElementById("div12")
element.appendChild(para)
}else{
let aux = decoded[i].replace(/(<([^>]+)>)/ig,'')
let para = document.createElement("script");
para.type = "text/javascript";
para.text = aux
let element = document.getElementById("div12")
element.appendChild(para)
}
}
对于完整的示例,请使用 jsfiddle https://jsfiddle.net/f2Leu74g/2/
我能够通过下面的代码解决它,如果将来有人遇到同样的问题,我想更新。
var ad = "whatever encoded here script code";
function decodeHtml(html) {
return $("<textarea/>").html(html).text();
}
function fetch(id, html) {
var elm = document.getElementById(id);
elm.innerHTML = html;
var scripts = elm.getElementsByTagName("script");
var scriptsClone = [];
for (var i = 0; i < scripts.length; i++) {
scriptsClone.push(scripts[i]);
}
for (var i = 0; i < scriptsClone.length; i++) {
var currentScript = scriptsClone[i];
var s = document.createElement("script");
// Copy all the attributes from the original script
for (var j = 0; j < currentScript.attributes.length; j++) {
var a = currentScript.attributes[j];
s.setAttribute(a.name, a.value);
}
s.appendChild(document.createTextNode(currentScript.innerHTML));
currentScript.parentNode.replaceChild(s, currentScript);
}
}
var decoded = decodeHtml(ad);
fetch('YourDivID',decoded);