Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
日在公眾號(hào)中挖掘到了一個(gè) XSS 安全漏洞,具體復(fù)現(xiàn)流程如下:
以下是復(fù)現(xiàn)漏洞的視頻
視頻鏈接
如果視頻又打不開了,可以去我公眾號(hào)的文章里看。
現(xiàn)在我們來分析下這個(gè)漏洞的產(chǎn)生過程。
首先標(biāo)題中存在 HTML <input onfocus="alert('1')">,在網(wǎng)頁中如果不對(duì)這部分文本做轉(zhuǎn)義的話,就會(huì)正常渲染為 HTML。
在文章詳情中其實(shí)我們并沒有發(fā)現(xiàn)這個(gè)問題,也就說明了在該頁面中開發(fā)者是做了文本轉(zhuǎn)義的。
但是在留言頁面中卻出現(xiàn)了該問題,也就是說開發(fā)者并沒有做標(biāo)題的轉(zhuǎn)義,因此導(dǎo)致了這個(gè)問題的發(fā)生。
雖然這個(gè)問題觸發(fā)條件不是那么容易,但是對(duì)于微信這樣億級(jí)日活的產(chǎn)品出現(xiàn)這樣低級(jí)的安全問題實(shí)屬?zèng)]想到。
我們把這樣的安全問題稱之為 XSS 攻擊。根據(jù)攻擊的來源,我們可以將此類攻擊分為三種,分別為:
在這個(gè)案例中我們遇到的是存儲(chǔ)型 XSS 攻擊。此類攻擊是攻擊者將惡意代碼提交至服務(wù)器并保存在數(shù)據(jù)庫中,用戶訪問該頁面觸發(fā)攻擊行為。這種類型的攻擊常見于保存用戶編輯數(shù)據(jù)的場景下,比如案例中的發(fā)表文章,亦或者評(píng)論場景等等。
防范存儲(chǔ)型 XSS 攻擊的策略就是不相信一切用戶提交的信息,比如說用戶的評(píng)論、發(fā)表的文章等等。對(duì)于這些信息一律進(jìn)行字符串轉(zhuǎn)義,主要是引號(hào)、尖括號(hào)、斜杠
function escape(str) { str = str.replace(/&/g, '&') str = str.replace(/</g, '<') str = str.replace(/>/g, '>') str = str.replace(/"/g, '&quto;') str = str.replace(/'/g, ''') str = str.replace(/`/g, '`') str = str.replace(/\//g, '/') return str } // "<script>alert(1)</script>" escape('<script>alert(1)</script>') 復(fù)制代碼
但是在顯示富文本的場景下其實(shí)不能把所有的內(nèi)容都轉(zhuǎn)義了,因?yàn)檫@樣會(huì)把需要的格式也過濾掉。對(duì)于這種情況,通常考慮采用白名單過濾的辦法。
// 使用 js-xss 開源項(xiàng)目 const xss = require('xss') let html = xss('<h1 id="title">XSS</h1><script>alert("xss");</script>') // -> <h1>XSS</h1><script>alert("xss");</script> console.log(html) 復(fù)制代碼
在白名單的情況下,h1 標(biāo)簽不會(huì)被轉(zhuǎn)義,但是 script 能被正常轉(zhuǎn)義。
日常開發(fā)中,為了方便數(shù)據(jù)的輸入和輸出,JavaScript提供了一些常用的輸入輸出語句,具體如表1-3所示。
表1常用的輸入輸出語句
類型 | 語句 | 說明 |
輸入 | prompt() | 用于在瀏覽器中彈出輸入框,用戶可以輸入內(nèi)容 |
輸出 | alert() | 用于在瀏覽器中彈出警告框 |
document.write() | 用于在網(wǎng)頁中輸出內(nèi)容 | |
console.log() | 用于在控制臺(tái)中輸出信息 |
接下來將分別演示document.write0、console.log0和promptO的使用。
1. document.write()
document.write0的輸出內(nèi)容中如果含有HTML標(biāo)簽,會(huì)被瀏覽器解析。下面利用documenL.write0在頁面中輸出“我是document.write0語句!”,示例代碼如下。
document.write('我是document.write()語句!');
2. console.log()
利用console.log0語句在控制臺(tái)輸出“我是console.log0語句!”,示例代碼如下。
console.log('我是console.log()語句!');
console:.log0的輸出結(jié)果需要在瀏覽器的控制臺(tái)中查看。在Chrome 瀏覽器中按“F12”鍵(或在網(wǎng)頁空白區(qū)域右擊,在彈出的菜單中選擇“檢查”)啟動(dòng)開發(fā)者工具,然后切換到“Console”(控制臺(tái))面板,即可看到console.log0的輸出結(jié)果。
3.prompt()
利用prompt0語句實(shí)現(xiàn)在頁面中彈出一個(gè)帶有提示信息的輸入框,示例代碼如下。
prompt(請(qǐng)輸入姓名:');
上述示例代碼運(yùn)行后,將在頁面中彈出一個(gè)輸人框并提示用戶“請(qǐng)輸人姓名:”提示框。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="Generator" content="EditPlus?"> <meta name="Author" content=""> <meta name="Keywords" content=""> <meta name="Description" content=""> <title>細(xì)說JavaScript中常用的幾種對(duì)話框</title> <script type="text/javascript">javascript> //第一種 最簡單的提示框alert(彈出對(duì)話框輸出自定義的提示信息) alert("此處填寫自定義的提示信息!!"); //第二種 帶確認(rèn)和取消的詢問提示框confirm 它的返回值為真true/假false if(confirm("請(qǐng)問您確認(rèn)提交嗎")) { alert("您點(diǎn)擊了確定按鈕"); }else { alert("您點(diǎn)擊了取消按鈕"); } //第三種帶輸入的提示對(duì)話框prompt,返回值為 對(duì)話框中輸入的內(nèi)容 //這里需要注意的是,prompt有兩個(gè)參數(shù),前面是提示的話,后面是當(dāng)對(duì)話框出來后,在對(duì)話框里的默認(rèn)值 var name = prompt("請(qǐng)輸入您的名字", ""); //將輸入的內(nèi)容賦給變量 name , if (name)//如果返回的有內(nèi)容 { alert("歡迎您:" + name) } </script> </head> <body> </body> </html>
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。