Cross-site scripting(XSS) 跨網站指令碼
クロスサイトスクリプティング
去年在考IPA的情報セキュリティマネジメント試験時,常常看到這個關鍵字,XSS的中文是跨網站指令碼是一種網路攻擊,攻擊者會利用漏洞將惡意程式碼(HTML或是JavaScript或PHP等等)注入到網頁上,然後利用釣魚郵件或是留言板之類的社群軟件當作媒介,第三者在閱覽這些帶有惡意指令碼的網頁時就有可能受到攻擊。
XSS Attacks (HTML)
HTML的例子(1)
在留言板寫下HTML的程式碼
按下submit後真的會執行html的程式碼讓程式碼變紅色
HTML的例子(2)
在輸入框就算用空一行輸入,得到的結果也是在同一排,也無法顯示為2排。
textContent和innerHTML
innerHTML
目的在於取得在一個節點內的全部樣式textContent
目的在於取得在一個節點內的文字(換行)
innerHTML
首先試看看Javascript用innerHTML的結果
btn.addEventListener("click",function(){
article.innerHTML = article.innerHTML + `
<div class ="article" >
<p>${content.value}</p>
</div>
`;
content.value ="";
})
用留言板的漏洞來注入貓咪圖片
結果會顯示一張貓的圖片
textContent
如果Javascript用textContent的話呢?
btn3.addEventListener("click",function(){
outcome3.textContent = con3.value;
})
則會顯示輸入文字而不會顯示圖片
innerText也是一樣的結果唷
XSS Attacks (Javascript)
如果前端可以輸入<script></script>去執行Javascript的腳本的話,那就可以做更多壞事了..
但HTML5 似乎把<script></script標籤插在innerHTML的這個漏洞給擋掉了
以下輸入起不到任何作用
但我在github看到一個利用加載圖片發生錯誤時執行javascript的方法可以鑽漏洞。onerror 事件
target.innerHTML = “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
target.innerText= “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
target.textContent = “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
接下來用這段來試看看吧。
這次跟剛剛一樣,用textContent和innerHTML,再加上一個innerText來試看看好了。
innerHTML
首先試看看Javascript用在innerHTML的結果
btn.addEventListener("click",function(){
article.innerHTML = article.innerHTML + `
<div class ="article" >
<p>${content.value}</p>
</div>
`;
content.value ="";
})
target.innerHTML = “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
target.innerText= “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
target.textContent = “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
只要輸入以上三條都會出現alert
很有趣的是,就算我下一行輸入其他字串,如圖 你好啊你好啊的字串,按下按鈕後還是會出現一次alert
因為會讀到之前的article.innerHTML而在執行一次,若前面有兩條
target.innerHTML = “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;紀錄的話
則會出現2次alert
btn.addEventListener("click",function(){
article.innerHTML = article.innerHTML + `
<div class ="article" >
<p>${content.value}</p>
</div>
`;
content.value ="";
})
innerText
試看看Javascript用在innerText的結果
function Messagecontent2(){
let con2 = Messagecontentform.content2.value;
let content2_html = document.getElementById("contentdisplay");
content2_html.innerText = con2;
Messagecontentform.content2.value =" ";
}
target.innerHTML = “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
target.innerText= “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
target.textContent = “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
輸入以上三條都沒有出現alert,下面顯示文字訊息
textContent
試看看Javascript用在textContent的結果
btn3.addEventListener("click",function(){
outcome3.textContent = con3.value;
})
target.innerHTML = “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
target.innerText= “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
target.textContent = “<img src=x onerror=”alert(‘XSS Yoy have been hacked’)” >”;
輸入以上三條都沒有出現alert,下面顯示文字訊息
結論
根據上述,我們在寫前端時應該避免使用innerHTML,因為innerHTML有可能會遭收到xss攻擊,我們可以使用textContent或innerText代替innerHTML。
參考 mozilla網站內有關Element.innerHTML安全性的資料
我的測試腳本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Message</h1>
<p>Message content</p>
<textarea id="content" rows="8" ></textarea>
<br>
<br>
<button id="btn"> submit</button>
<div class="article" id="article">
<p>メッセージを入力してください</p>
</div>
<form name="Messagecontentform" >
內容  <input type="text" style="width:200px; height:20px;" name="content2" />
<br/>
<br/>
<input type="button" id="btn2" name="btn2" value="更新" onclick="Messagecontent2()"/>
</form>
<br>
<br>
<div id="contentdisplay"></div>
<br>
<br>
<form name="Messagecontentform_dangerous" >
  <input type="text" style="width:1000px; height:100px;" id="content3" />
<br/>
<br/>
<input type="button" id="btn3" name="btn3" value="更新"/>
</form>
<br>
<br>
<div id="outcome3"></div>
<br>
<br>
<script>
let content = document.getElementById("content");
let btn = document.getElementById("btn");
let article = document.getElementById("article");
btn.addEventListener("click",function(){
article.innerHTML = article.innerHTML + `
<div class ="article" >
<p>${content.value}</p>
</div>
`;
content.value ="";
})
function Messagecontent2(){
let con2 = Messagecontentform.content2.value;
let content2_html = document.getElementById("contentdisplay");
content2_html.innerText = con2;
}
let con3 = document.getElementById("content3");
let btn3 = document.getElementById("btn3");
let outcome3 = document.getElementById("outcome3");
btn3.addEventListener("click",function(){
outcome3.textContent = con3.value;
})
</script>
</body>
</html>