iT邦幫忙

2

[不做怎麼知道系列之Android開發者的30天後端養成故事 Day28] - 你的Django安全嗎?(上篇) #SecurityInDjango #XSS #CSRF

Sam 2020-03-11 23:03:583724 瀏覽

https://ithelp.ithome.com.tw/upload/images/20200311/20124548gdJ4N9xK2P.png

哈囉,我們又見面了,到了這系列的尾聲,就讓我們用 網路安全 議題來結束這系列吧 !

本篇內容主要是參考 Security in Django 官方文件作為文章大綱,再結合大神們對於各項攻擊防禦的文章,所產出的一篇綜觀 Django 的安全議題文章。

1. XSS (Cross-site scripting)

詳細可以參考 【網頁安全】給網頁開發新人的 XSS 攻擊 介紹與防範 | 巴哈程設版,這篇解釋得蠻簡單易懂的。

1.1 XSS 是什麼 ?

簡單來說,就是攻擊者透過一些方式,能夠在你的網站上,執行攻擊者自己寫的程式碼,這件事可輕可重,輕可變成整人的彈跳視窗,重可變成我也不知道 XD

直接來看一下簡單的 XSS 範例

HTML 頁面中,想要輸出一行帶有使用者名字的字串

Hello, {{ name }}

如果使用者名字是一般的名字的話,那沒什麼問題

但如果有人的名字長 "<script>alert("You've been hacked")</script>" 的話,沒有經過檢查就 render 出來就會變成

Hello, <script>alert("You've been hacked")</script>

使用者端就會跳出一個 You've been hacked 的視窗。

1.2 DjangoXSS 的解決方法

Django 的 Templates 有提供防護 XSS 的方法

Django 事先想到了這一點,所以 Django 提出了一個 automatic HTML escaping,像是 < 會被轉成 &lt;,而 > 會被轉成 &gt;' 會被轉成 &#x27;" 會被轉成 &quot;& 會被轉成 &amp;

這些轉換都是 Django 預設的,也就是說,就算你不知道 Django 有 automatic HTML escaping 的機制,你還是會受到保護,防止惡意的 injection。

如果你在某些欄位要關掉這一層的防護機制,只要加上 |safe 就可以關掉 escaping。

This can disable HTML escaping: {{ data|safe }}

但,這只是最基本的保護機制,還是會有漏洞,漏洞的舉例可以參考官方文件,只不過 Django 的 automatic HTML escaping 機制,已經能防止很大部分的 XSS 攻擊了,剩下的防禦就看開發者的實力如何了。

2. CSRF (Cross-site request forgery)

Django 也有防禦 CSRF 的機制,光是一個 CSRF 的防禦機制,在官方文件就已經是一大篇了XD,對於想更深入瞭解 Django 安全機制的人們,就很值得好好 K 這篇文件。

2.1 什麼是 CSRF 攻擊?

詳細可以參考 讓我們來談談 CSRF | TechBridge 技術共筆部落格,這篇講的是真的很詳細,文章寫得也很不錯,很漸進式的帶入 CSRF 攻擊的影響程度。

簡單來說,CSRF 就是由攻擊者 "代替" 不知情的使用者,執行了一次按鈕,影響程度就要看這個按鈕是什麼按鈕了,如果這個按鈕是對網頁連結到下一頁,那沒什麼問題,那如果是轉帳的按鈕呢 ? 不過目前大部分大型的金融機構,對於轉帳都有基本的防護機制,不用怕 CSRF 就不使用網站轉帳了 XD

這種攻擊方式是利用了瀏覽器順帶 Cookie 的機制,進而仿造使用者曾經做過的行為。

舉例

借用一下 讓我們來談談 CSRF | TechBridge 技術共筆部落格 的一個範例

今天假設小黑是一個邪惡的壞蛋,想要讓小明在不知情的情況下就把自己的文章刪掉,該怎麼做呢?
他知道小明很喜歡心理測驗,於是就做了一個心理測驗網站,並且發給小明。
但這個心理測驗網站跟其他網站不同的點在於,「開始測驗」的按鈕長得像這樣:
開始測驗
小明收到網頁之後很開心,就點擊「開始測驗」。點擊之後瀏覽器就會發送一個 GET 請求給https://small-min.blog.com/delete?id=3 ,並且因為瀏覽器的運行機制,一併把 small-min.blog.com 的 cookie 都一起帶上去。
Server 端收到之後檢查了一下 session,發現是小明,而且這篇文章也真的是小明發的,於是就把這篇文章給刪除了。
這就是 CSRF,你現在明明在心理測驗網站,假設是 https://test.com 好了,但是卻在不知情的狀況下刪除了 https://small-min.blog.com 的文章,你說這可不可怕?超可怕!

2.2 Django 怎麼擋 CSRF 攻擊?

詳細可以參考官方文件,簡單來說,Django 會透過 CsrfViewMiddleware,來檢查每個 POST request 裡面的 csrfmiddlewaretoken (這個 token 不是只是一個值這麼簡單),還有檢查 referrer 欄位是不是同一個 domain。

3. SQL injection

3.1 什麼是 SQL injection ?

詳細可以參考 一次看懂 SQL Injection 的攻擊原理 | Medium,這篇舉了很多有趣的例子,不會一開始就丟語法進來跟你解釋。

概念很像是 XSS,都是看準伺服器端偷懶,沒有檢查接收進來的內容,簡單來說,攻擊者透過輸入一串值,而伺服器端收到這串值之後,放到 SQL 語法中,卻會是一個合法的 SQL 語法,這就是 SQL injection,我知道聽起來有點繞口,所以需要一個範例。

再次借用 一次看懂 SQL Injection 的攻擊原理 | Medium 這篇的範例,假設現在要透過 SQL 語法進行使用者帳號密碼的判斷,如果使用者的名稱 和 密碼 都正確,才可以讀取使用者資料,但攻擊者在只知道使用者帳號、不知道密碼的情況之下,可能可以透過 SQL injection,"繞過" 密碼的判斷。

正常情況下的使用者帳號密碼判斷,需要帳號和密碼都正確才行

https://miro.medium.com/max/2076/1*RuSy8MFLuhng_3_P5x3CWg.png

而,攻擊者可以把密碼的欄位,改成 abc' or '1'='1 (這邊注意一下單引號的位置),也就是下圖中黃色的密碼欄位所呈現的

https://miro.medium.com/max/2079/1*ugn2ANSq_Ep_-8oa-PTz3A.png

如果伺服器端沒有對欄位進行檢查,直接把欄位帶入到 SQL 語法去執行的話,就會成為另一段合法的 SQL 語法,可是卻不是伺服器端所設計的邏輯,藉由這樣的方法,攻擊者就達成了目的。

3.2 Django 怎麼防止 SQL injection ?

Django 採用 MVT Pattern (Model-View-Template),開發者只要寫 Model 部分,而 Model 到 DB 之間會透過 database driver 來轉換,所以 Django 開發者通常不需要寫 Raw SQL 語法,自然就比較難發生 SQL injection 的攻擊。

4. Clickjacking

Django 的官方文件有提到 Clickjacking 的防禦機制,Clickjacking 就是 Click + Hijacking(劫持/劫機),你可以把它想成,按鈕是飛機的機長,而攻擊者利用 Clickjacking 的技術,強迫機長改飛另一個方向( 強迫按鈕改作另一件事情 )的感覺。

4.1 什麼是 Clickjacking ?

詳細可以參考 淺談IFrame式Clickjacking攻擊與防護 | 黑暗執行緒,這篇一開頭就有個範例: 在我們自己的網頁中內嵌一個 google 搜尋首頁,利用的是 HTMLframe 標籤,而在實作上,可以在我們的網頁內嵌一個 Youtube 頁面,這樣就不用自己實作播放器了,這麼做是省事,可是卻容易造成漏洞。

簡單來說,ClickJacking 就是 你以為的按鈕 不是 你以為的按鈕,你以為你點了一個下一頁的按鈕,可是它可能是一個打開筆電前鏡頭的按鈕,也可能是一個載入木馬程式的按鈕,利用的是把 frame 設為透明的,變成在頁面顯示你以為的網頁,但背後卻隱藏真實的網頁。現在的瀏覽器會有 x-frame-options 的防禦機制,來保護使用者意外執行惡意的 frame。

4.2 Django 怎麼防止 Clickjacking ?

Django 透過 X-Frame-Options middleware,把 X-Frame-Options 的 header 改成 DENY,也就是不給嵌入 frame,直接杜絕 Clickjacking 的機會。

如果在某個頁面想要允許 X-Frame 的話,那就使用 @xframe_options_exempt 的 decorator

from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_exempt
    
@xframe_options_exempt
def ok_to_load_in_a_frame(request):
    return HttpResponse("This page is safe to load in a frame on any site.")

單日心得總結

經過這一系列的文章,我深深感覺到了有框架的幫忙,真的對開發後端非常有幫助,框架幫開發者做的事情太多了,即使是開發新手,不要手賤把一些保護機制取消掉的話,都能受到基本的保護。要瞭解一個框架,需要花一段時間的相處、深讀文件,才能知道一個框架的設計精神。

覺得最近我的心已經開始飄飄的,沒辦法好好靜下來寫文章,很急著想要趕快進行到下一個階段,恨不得趕快把這系列終結 XD,在寫最後這幾篇的時候,就會感覺特別難寫,寫到一半的時候,想到其他有趣的東西,就很想要趕快去 survey,但時間又沒那麼多,只好把這樣的慾望給壓下來,好難受 QQ,希望趕快度過這幾天!!

我是 RS,這是我的 不做怎麼知道系列 文章,我們 明天見。


https://ithelp.ithome.com.tw/upload/images/20200219/20124548meDsnCPamL.png


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Robin
iT邦新手 2 級 ‧ 2020-03-13 09:45:38

Django 事先想到了這一點,所以 Django 提出了一個 automatic HTML escaping,像是 < 會被轉成 <,而 > 會被轉成 >,' 會被轉成 '," 會被轉成 ",& 會被轉成 &。

不好意思想問一下xDD
這個轉換是型態轉換還是什麼方式?
轉換有點看不懂他轉了什麼看起來都一樣Orz (是不是我便便吃不夠

Sam iT邦新手 4 級 ‧ 2020-03-13 10:12:49 檢舉

啊~~~~
我竟然沒注意到,被編輯器轉碼了QQ
感謝你看得這麼仔細哈哈

應該是要這樣:

Django 事先想到了這一點,所以 Django 提出了一個 automatic HTML escaping,像是 < 會被轉成 &lt;,而 > 會被轉成 &gt;' 會被轉成 &#x27;" 會被轉成 &quot;& 會被轉成 &amp;

Robin iT邦新手 2 級 ‧ 2020-03-13 12:39:21 檢舉

了解了解~
感謝xDD
/images/emoticon/emoticon12.gif

我要留言

立即登入留言