常見網路攻擊:XSS 篇

劉zx發表於2018-05-03

提起防禦網路攻擊,很多同學只知道需要轉義,編碼。但是這個話題實際上博大精深,不止這四個字這麼簡單。

文章目錄:

  • 常見的 XSS 攻擊型別
  • 不止如此
  • 談談防禦
  • 總結

常見的 XSS 攻擊型別

某天前端打雜小劉和後端同學在給現有業務加搜尋功能,前端同學在展示模糊搜尋結果的同時,需要展示使用者當前搜尋的欄位,比如『沒有關於 *** 的搜尋內容』。在沒有任何防禦措施的時候,使用者輸入<script>alert(1)</script>,就__有可能__直接彈出在頁面上。這就是__反射型 XSS 攻擊__。還是這個搜尋功能,如果有一天產品心血來潮要加一個『朋友們的最近搜尋』功能,依然是在沒有任何防禦的時候,某個使用者還是搜尋<script>alert(1)</script>,那麼其他使用者訪問時就__有可能__彈框,這就是__儲存型(持久型)XSS 攻擊__。 從上面這個例子可以看出,所謂反射型,是發生在當前使用者的某些請求或者頁面訪問的 url 中攜帶的某些欄位,回顯到頁面或者影響到當前頁面的一些執行過程。但是並沒有儲存到資料庫中,意味著不會影響到其他訪問這個頁面的使用者。 儲存型則不同,像剛才的例子,我們把使用者最近輸入的內容儲存到資料庫,以在他的關聯使用者訪問時可以展示。這種攻擊會影響到其他的使用者。 DOM-based XSS 又是什麼?很多文章指出DOM-based是反射型 XSS 的一種,但是我個人認為不太對,下面附上 mediawiki 的解釋:

DOM-based XSS (or type-0 XSS) is a type of Cross-site scripting attack that occurs when client-side scripts (such as JavaScript) manipulate the page's DOM, allowing an attacker to run JavaScript in the victim's browser. This class of XSS is distinct from Reflective XSS (type-1 XSS) and Stored XSS (type-2 XSS), since the server is not returning executable JavaScript to the browser. Instead, data that has been sanitized by the server, or possibly never sent to the server, is converted to executable JavaScript by the existing code running on the page.

只要是在客戶端指令碼操作頁面 DOM 時執行了攻擊者的 javascript 指令碼,都歸類於 DOM-based XSS。也就是說他概括的維度更貼近於觸發的出口,而不是方式。所以他其實和反射型,儲存型是有交叉的。DOM-based XSS 甚至不依賴於請求,只在客戶端本身就具備發生此類攻擊的條件。

不止如此

繼續回到前端打雜小劉的故事。測試同學在安全測試的過程中,反饋了 bug。前端同學和後端同學兩個人開始商量怎麼處理。轉義!兩人一拍即合。後端同學針對字串型別的資料進行__實體化轉義__ [圖片上傳失敗...(image-16800d-1524309858885)] 小劉在自己呼叫 innerHTML 方法的引數前也加了一層轉義。大功告成! 沒高興幾個小時,測試又提過來一個 bug 。小劉當時偷懶,直接在標籤上寫了dom 0級事件。如下寫法:

<button onclick=`alert(${name})`></button>
複製程式碼

而 name 是依賴於使用者輸入的。如果使用者輸入的 name 為:);alert(document.cookie 你看會發生什麼?小劉驚訝於還有這種操作的同時,也深刻意識到了防範 XSS 攻擊遠遠不止簡單實體化轉義 HTML 程式碼這麼簡單。我們需要對不同的應用場景,和你的程式碼,來做不同的轉義。在這個例子裡,我們需要對拼接進事件中的使用者字串進行一次 javascript 編碼(這裡科普一下 javascript 編碼指的就是 unicode 編碼)即:

<h1 class="title" onclick="alert('\u0027\u0029\u003b\u0061\u006c\u0065\u0072\u0074\u0028\u0027\u0053\u0052\u0043')">點選彈出</h1>
複製程式碼

類似的場景還有很多,最近還有針對 css 攻擊防禦的文章,大家有時間可以瞭解一下。但是萬變不離其宗,我們要秉持懷疑所有使用者輸入的態度,有針對性的轉義和編碼,而不是隻是知道需要轉義這麼簡單。

談談防禦

在上面一個小節已經講過轉義的基本用法和針對的場景。下面來說一些老生常談的話題:哪些是前端不能做的雷區。 new functionechoinnerHTML、dom 0 級事件等等。尤其是當他們的內容和使用者輸入有關聯的時候,都有可能形成漏洞。

總結

  1. XSS 防範是需要我們在養成好的寫碼習慣的同時,還要對所有使用者輸入保持警惕。
  2. 不能把自己的安全建立在其他介面是否返回正確的基礎上,所以最好在前端也要加一層校驗,而不能完全依賴後端。
  3. 現代瀏覽器很多都對類似的情況有過濾和處理,但是並不完備。大多數的模板引擎和框架內部也多有針對 XSS 的防範。

推薦閱讀: 淺談XSS—字元編碼和瀏覽器解析原理 如何讓前端更安全?——XSS 攻擊和防禦詳解 DOM-based XSS 與儲存性 XSS、反射型 XSS 有什麼區別?

相關文章