将此 "code playground" 添加到我的 WordPress 网站是否存在安全风险?
Is adding this "code playground" to my WordPress website a security risk?
所以我打算将这种“代码游乐场”类的交互式代码片段演示添加到我网站上的一些教程中。
我想知道这里是否存在安全隐患
代码字段是可编辑的。
显然人们可以轻松地注射 JavaScript。
但是,这与我们从控制台选项卡注入 JS 时有什么不同吗?这里有任何安全问题吗?
感谢您对此的任何帮助。
PS。您可以 运行 下面的代码片段,或在此处查看代码笔:https://codepen.io/elementhow/pen/dyJKYoB
let examples = document.querySelectorAll(".prog-example");
examples.forEach((example, i, arr) => {
let pres = example.querySelectorAll(".examples pre");
if (pres.length < 1) document.querySelector('.examples').remove();
let htmlOfPreview = example.querySelector(".preview-parent pre");
let preview = example.querySelector(".preview");
htmlOfPreview.innerHTML = escapeHTML(preview.innerHTML);
htmlOfPreview.addEventListener('input',function(){
preview.innerHTML = htmlOfPreview.textContent;
});
let CSSdiv = document.createElement("style");
document.getElementsByTagName("head")[0].appendChild(CSSdiv);
pres.forEach((pre, i, arr) => {
pre.addEventListener("click", function () {
arr.forEach((e) => e.classList.remove("label-active"));
pre.classList.add("label-active");
CSSdiv.innerHTML = pre.textContent;
});
pre.setAttribute('contenteditable',"");
if (pre.hasAttribute("contenteditable")){
pre.addEventListener('input', function(){
CSSdiv.innerHTML = pre.textContent;
});
}
});
if (pres[0]) pres[0].click();
});
function escapeHTML(html) {
return document.createElement("div").appendChild(document.createTextNode(html)).parentNode.innerHTML;
}
*, *::after {
box-sizing: border-box;
}
.prog-example {
display: flex;
width: 100%;
background:#cecece;
}
.prog-example .examples {
max-height: 440px;
overflow-y: auto;
padding: 0 10px;
background-color:#eee8ab;
min-width:170px;
position:relative;
}
.prog-example .preview-parent {
margin: 10px;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.prog-example .examples pre {
font-size: 12px;
padding: 6px;
border: 1px solid #999;
margin: 14px 0;
border-radius: 8px;
cursor: pointer;
background-color:#fff;
min-width:170px;
}
.prog-example .examples pre[contenteditable]{
/* cursor: text; */
}
.prog-example .examples pre.label-active {
outline: 2px solid #333;
}
.prog-example .preview-parent pre {
background-color: #eee;
margin: 0 0 10px;
padding: 0 10px;
position:relative;
}
.prog-example .preview-parent .preview {
border: 1px solid #999;
flex-grow: 1;
position:relative;
min-height:130px;
background-color:#fff;
}
.prog-example .preview-parent > pre::after,.prog-example .preview-parent .preview::after, .prog-example .examples::after {
content:'HTML';
position:absolute;
background-color:#777;
font-family:monospace;
font-size:13px;
color:#fff;
padding:4px;
border-bottom-left-radius:6px;
top:0;
right:0;
}
.prog-example .preview-parent .preview::after {
content:'PREVIEW';
}
.prog-example .examples::after {
content:'CSS';
}
/* scroll bar if there is overflow */
.prog-example .examples::-webkit-scrollbar-track {
background-color: #f4f4f4;
}
.prog-example .examples::-webkit-scrollbar {
width: 6px;
background-color: #f4f4f4;
}
.prog-example .examples::-webkit-scrollbar-thumb {
background-color: #00000044;
}
<div class="prog-example">
<div class="examples">
<pre>
.test-button{
font-size:16px;
}</pre>
<pre>
.test-button{
font-size:21px;
} </pre>
<pre>
.test-button{
font-size:44px;
} </pre>
<pre>
.test-button{
font-size:16px;
}</pre>
<pre>
.test-button{
font-size:21px;
} </pre>
<pre>
.test-button{
font-size:44px;
} </pre>
<pre>
.test-button{
font-size:16px;
}</pre>
<pre>
.test-button{
font-size:21px;
} </pre>
<pre>
.test-button{
font-size:44px;
} </pre>
<pre>
.test-button{
font-size:16px;
}</pre>
<pre>
.test-button{
font-size:21px;
} </pre>
<pre contenteditable>
.test-button{
font-size:44px;
} </pre>
</div>
<div class="preview-parent">
<pre contenteditable></pre>
<div class="preview">
<div class="wrapper">
<button class='test-button'>click me</button>
</div>
</div>
</div>
</div>
简答:只要没有可以向您的服务器发送 http 请求的输入,都是客户端并且安全的。
长:
在攻击面的 HTTP 世界中,您需要一个“输入字段”(不是 UI 元素),您可以在其中发送一些将由服务器解析的数据。这是通过 http 请求完成的,您将一些数据放在 header 和 body 中,将它们发送到服务器,然后您期望从服务器得到某种响应。如果您不为服务器可接受的数据形式创建策略,则可能会注入使服务器行为不同于业务逻辑的代码。
在您的情况下,您从服务器获取游乐场,并在您的浏览器 javascript 引擎(客户端)上获取游乐场 运行s 中的脚本,但没有任何内容被发送回服务器。
例如,一个大问题是,如果没有任何安全措施,您可以将恶意游乐场发送回服务器以保存它(如 codepen)。通过这种方式,您可以在不同级别注入代码:服务器框架、数据库(SQL 注入)。如果其他人能够打开您的恶意游乐场,那么危险脚本将 运行 在他们的客户端(XSS 和 CSRF 攻击)。
因此,每个输入都可能是您必须在 server-side 上安全处理的威胁,方法是 input sanitization and output escaping。
所以我打算将这种“代码游乐场”类的交互式代码片段演示添加到我网站上的一些教程中。
我想知道这里是否存在安全隐患
代码字段是可编辑的。
显然人们可以轻松地注射 JavaScript。
但是,这与我们从控制台选项卡注入 JS 时有什么不同吗?这里有任何安全问题吗?
感谢您对此的任何帮助。
PS。您可以 运行 下面的代码片段,或在此处查看代码笔:https://codepen.io/elementhow/pen/dyJKYoB
let examples = document.querySelectorAll(".prog-example");
examples.forEach((example, i, arr) => {
let pres = example.querySelectorAll(".examples pre");
if (pres.length < 1) document.querySelector('.examples').remove();
let htmlOfPreview = example.querySelector(".preview-parent pre");
let preview = example.querySelector(".preview");
htmlOfPreview.innerHTML = escapeHTML(preview.innerHTML);
htmlOfPreview.addEventListener('input',function(){
preview.innerHTML = htmlOfPreview.textContent;
});
let CSSdiv = document.createElement("style");
document.getElementsByTagName("head")[0].appendChild(CSSdiv);
pres.forEach((pre, i, arr) => {
pre.addEventListener("click", function () {
arr.forEach((e) => e.classList.remove("label-active"));
pre.classList.add("label-active");
CSSdiv.innerHTML = pre.textContent;
});
pre.setAttribute('contenteditable',"");
if (pre.hasAttribute("contenteditable")){
pre.addEventListener('input', function(){
CSSdiv.innerHTML = pre.textContent;
});
}
});
if (pres[0]) pres[0].click();
});
function escapeHTML(html) {
return document.createElement("div").appendChild(document.createTextNode(html)).parentNode.innerHTML;
}
*, *::after {
box-sizing: border-box;
}
.prog-example {
display: flex;
width: 100%;
background:#cecece;
}
.prog-example .examples {
max-height: 440px;
overflow-y: auto;
padding: 0 10px;
background-color:#eee8ab;
min-width:170px;
position:relative;
}
.prog-example .preview-parent {
margin: 10px;
display: flex;
flex-direction: column;
flex-grow: 1;
}
.prog-example .examples pre {
font-size: 12px;
padding: 6px;
border: 1px solid #999;
margin: 14px 0;
border-radius: 8px;
cursor: pointer;
background-color:#fff;
min-width:170px;
}
.prog-example .examples pre[contenteditable]{
/* cursor: text; */
}
.prog-example .examples pre.label-active {
outline: 2px solid #333;
}
.prog-example .preview-parent pre {
background-color: #eee;
margin: 0 0 10px;
padding: 0 10px;
position:relative;
}
.prog-example .preview-parent .preview {
border: 1px solid #999;
flex-grow: 1;
position:relative;
min-height:130px;
background-color:#fff;
}
.prog-example .preview-parent > pre::after,.prog-example .preview-parent .preview::after, .prog-example .examples::after {
content:'HTML';
position:absolute;
background-color:#777;
font-family:monospace;
font-size:13px;
color:#fff;
padding:4px;
border-bottom-left-radius:6px;
top:0;
right:0;
}
.prog-example .preview-parent .preview::after {
content:'PREVIEW';
}
.prog-example .examples::after {
content:'CSS';
}
/* scroll bar if there is overflow */
.prog-example .examples::-webkit-scrollbar-track {
background-color: #f4f4f4;
}
.prog-example .examples::-webkit-scrollbar {
width: 6px;
background-color: #f4f4f4;
}
.prog-example .examples::-webkit-scrollbar-thumb {
background-color: #00000044;
}
<div class="prog-example">
<div class="examples">
<pre>
.test-button{
font-size:16px;
}</pre>
<pre>
.test-button{
font-size:21px;
} </pre>
<pre>
.test-button{
font-size:44px;
} </pre>
<pre>
.test-button{
font-size:16px;
}</pre>
<pre>
.test-button{
font-size:21px;
} </pre>
<pre>
.test-button{
font-size:44px;
} </pre>
<pre>
.test-button{
font-size:16px;
}</pre>
<pre>
.test-button{
font-size:21px;
} </pre>
<pre>
.test-button{
font-size:44px;
} </pre>
<pre>
.test-button{
font-size:16px;
}</pre>
<pre>
.test-button{
font-size:21px;
} </pre>
<pre contenteditable>
.test-button{
font-size:44px;
} </pre>
</div>
<div class="preview-parent">
<pre contenteditable></pre>
<div class="preview">
<div class="wrapper">
<button class='test-button'>click me</button>
</div>
</div>
</div>
</div>
简答:只要没有可以向您的服务器发送 http 请求的输入,都是客户端并且安全的。
长:
在攻击面的 HTTP 世界中,您需要一个“输入字段”(不是 UI 元素),您可以在其中发送一些将由服务器解析的数据。这是通过 http 请求完成的,您将一些数据放在 header 和 body 中,将它们发送到服务器,然后您期望从服务器得到某种响应。如果您不为服务器可接受的数据形式创建策略,则可能会注入使服务器行为不同于业务逻辑的代码。
在您的情况下,您从服务器获取游乐场,并在您的浏览器 javascript 引擎(客户端)上获取游乐场 运行s 中的脚本,但没有任何内容被发送回服务器。
例如,一个大问题是,如果没有任何安全措施,您可以将恶意游乐场发送回服务器以保存它(如 codepen)。通过这种方式,您可以在不同级别注入代码:服务器框架、数据库(SQL 注入)。如果其他人能够打开您的恶意游乐场,那么危险脚本将 运行 在他们的客户端(XSS 和 CSRF 攻击)。
因此,每个输入都可能是您必须在 server-side 上安全处理的威胁,方法是 input sanitization and output escaping。