1. 程式人生 > >使用<a>標籤時,你可能會忽略的一個安全問題

使用<a>標籤時,你可能會忽略的一個安全問題

本文首發於公眾號:符合預期的CoyPan

本文章翻譯於:medium.com/front-end-w… 原標題為:Prevent Sending HTTP Referer Headers from Your Website

在一個新視窗中開啟連結是前端開發中一個很常見的邏輯,它可以將使用者引導到一個新的域名。我們可以用target='_blank'來實現這個功能。我敢肯定,每個人都會在他的某個專案中使用過target='_blank,但是我不確定是否每個人都知道這種用法的缺陷。

當一個外部連結使用了target=_blank的方式,這個外部連結會開啟一個新的瀏覽器tab。此時,新頁面會開啟,並且和原始頁面佔用同一個程序。這也意味著,如果這個新頁面有任何效能上的問題,比如有一個很高的載入時間,這也將會影響到原始頁面的表現。如果你開啟的是一個同域的頁面,那麼你將可以在新頁面訪問到原始頁面的所有內容,包括document

物件(window.opener.document)。如果你開啟的是一個跨域的頁面,你雖然無法訪問到document,但是你依然可以訪問到location物件。

這意味著,如果你在你的站點或者文章中,嵌入了通過新視窗開啟一個新頁面的連結,這個新頁面可以使用window.opener,在一定程度上來修改原始頁面

可以參考這個例子:s.codepen.io/adamlaki/de…

(筆者這裡做了一個小gif,方便大家看上面那個例子的效果)

我們來看看上面例子發生了什麼?當你點選了連結(在開啟的document中),瀏覽器會開啟這個頁面。而這個頁面中運行了一段JavaScript

程式碼:通過window.opener來修改原始頁面(你來自的那個頁面)。有點乏味但是這可能是有害的。

那麼問題來了:我們如何阻止這種情況的發生呢?在所有使用target=_blank開啟新頁面的連結上,加上ref="noopener"

<a href="https://niteshsoni.info" rel="noopener"></a>
複製程式碼

使用了ref=noopener以後,當一個新頁面通過一個連結開啟後,新頁面中的惡意JavaScript程式碼將無法通過window.opener來訪問到原始頁面。這將保證新頁面執行在一個單獨的程序裡。

在老瀏覽器中,你可以使用ref=noreferrer屬性,具有同樣的效果。但是,這樣也會阻止Refererheader被髮送到新頁面。

<a href="https://niteshsoni.info" rel="noopener noreferrer"></a>
複製程式碼

在上面的例子中,使用了rel="noreferrer" ,當一個使用者點選了這個超連結進入到新頁面後,新頁面拿不到referrer資訊。這將意味著,新頁面不知道使用者是從哪裡來的。

如果你通過JavaScript中的window.open開啟一個頁面的話,上文所說的都適用,因為你也是打開了一個新的視窗。在這種情況下,你不得不清楚掉opener物件:

var newWindow = window.open();
newWindow.opener = null;
複製程式碼

在我看來,使用第一種解決方案(在每一個target="_blank"的連結中加上ref="noopener")是沒有什麼明顯的壞處的。這個問題表明,在你的網頁安全性中找到漏洞是多麼的容易。

筆者的總結

這是一篇很短的文章,主要介紹了在使用<a target="_blank">標籤開啟一個新視窗過程中的安全問題。新頁面中可以使用window.opener來控制原始頁面。如果新老頁面同域,那麼在新頁面中可以任意操作原始頁面。如果是不同域,新頁面中依然可以通過window.opener.location,訪問到原始頁面的location物件。

試想一下,你在自己的a頁面中,通過<a target="_blank" href="http://b.com">開啟新視窗,跳轉到了b頁面,此刻b頁面中有一段程式碼window.opener.location = 'http://c.com'。這是,a頁面就會自動跳轉到c頁面。如果這個c頁面是一個和a頁面長得一樣的釣魚網站,那麼使用者可能就中招了。

解決方法就是:在帶有target="_blank"<a>標籤中,加上rel="noopener"屬性。如果使用window.open的方式開啟頁面,將opener物件置為空。這樣的副作用是:在某些低版本瀏覽器中,新頁面中拿不到referer資訊。

寫在後面

本文介紹了一種前端開發中容易引發安全問題的情況,問題不大,但是比較容易被忽略。筆者自己也是第一次接觸到這個問題 - -。

符合預期。