1. 程式人生 > >Django—XSS及CSRF

Django—XSS及CSRF

awr BE var 請求頭 item 應用 腳本 views div

綜合編程 Python_博客園 (源鏈) 2017-06-28

一、XSS

跨站腳本攻擊 (Cross Site Scripting),為不和 層疊樣式表 (Cascading Style Sheets, CSS )的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。惡意攻擊者往Web頁面裏插入惡意Script代碼,當用戶瀏覽該頁之時,嵌入其中Web裏面的Script代碼會被執行,從而達到惡意攻擊用戶的目的。

1. 工作流程

a. 惡意用戶,在一些公共區域(例如,建議提交表單或消息公共板的輸入表單)輸入一些文本,這些文本被其它用戶看到,但這些文本不僅僅是他們要輸入的文本,同時還包括一些可以在客戶端執行的腳本。如:


   this.document = "*********"; 
  alert(‘Not Safe‘);

b. 惡意提交這個表單

c. 其他用戶看到這個包括惡意腳本的頁面並執行,獲取用戶的cookie等敏感信息。

技術分享圖片

2. 實例-未防範XSS攻擊


 1 pinglu = []     # 評論列表
 2 
 3 #提交表單
 4 def commit(request):
 5     if request.method == ‘GET‘:
 6         return render(request, ‘commit.html‘)
 7     else:
 8         com = request.POST.get(‘commit‘)
 9         pinglu.append(com)
10         return redirect(‘/index.html/‘)
11 
12 
13 #查看評論頁面
14 def index(request):
15     return render(request, ‘index.html‘, {‘commit‘: pinglu})

view.py

 1 
 2 
 3 
 4     
 5     
 6 
 7 
 8

評論


 9
10 11 {{ error }} 12 13 14 commit.html

 1 
 2 
 3 
 4     
 5     
 6 
 7 
 8

評論


 9 {% for item in commit %}
10
{{ item|safe }}

11 {#    item後加safe,默認數據安全,django不會做特殊處理#}
12 {% endfor %}
13 
14 

index.html

以上實例中,若在commit.html頁面輸入以下內容並提交:

 alert(123) 

則會在index頁面執行此行代碼,彈出警告框(若包含惡意代碼,則會執行)

技術分享圖片

3. 防範XSS攻擊

  • 最直接的方法就是對於無法控制的輸入在html頁面內不要使用safe
{#
{{ item|safe }}
#}
{{ item }}
  • 也可以在views裏進行過濾,防止特殊字符提交到數據庫或網頁內
def commit(request):
    if request.method == ‘GET‘:
        return render(request, ‘commit.html‘)
    else:
        com = request.POST.get(‘commit‘)
        if ‘‘ in com:    # 過濾“”關鍵字,防止惡意代碼的提交
            return render(request, ‘commit.html‘, {‘error‘: ‘此條評論有毒,已被和諧‘})
        else:
            pinglu.append(com)
            return redirect(‘/index.html/‘)

技術分享圖片

二、CSRF

CSRF(Cross-site request forgery)跨站請求偽造,也被稱為“One Click Attack”或者Session Riding,通常縮寫為CSRF或者XSRF,是一種對網站的惡意利用。盡管聽起來像跨站腳本( XSS ),但它與XSS非常不同,XSS利用站點內的信任用戶,而CSRF則通過偽裝來自受信任用戶的請求來利用受信任的網站。與 XSS 攻擊相比,CSRF攻擊往往不大流行(因此對其進行防範的資源也相當稀少)和難以防範,所以被認為比 XSS 更具危險性。

1. 工作流程

攻擊通過在授權用戶訪問的頁面中包含鏈接或者腳本的方式工作:

技術分享圖片

2. django中如何防範

django為用戶實現防止跨站請求偽造的功能,通過中間件 django.middleware.csrf.CsrfViewMiddleware 來完成。而對於django中設置防跨站請求偽造功能有分為全局和局部。

全局:

  • 啟用中間件 django.middleware.csrf.CsrfViewMiddleware

技術分享圖片

局部:

from django.views.decorators.csrf import csrf_exempt,csrf_protect
  • @csrf_protect,為當前函數強制設置防跨站請求偽造功能,即便settings中沒有設置全局中間件
  • @csrf_exempt,取消當前函數防跨站請求偽造功能,即便settings中設置了全局中間件。

3. django中的具體應用方法

  • form表單中添加 { % csrf_token % }

若form表單中未添加 { % csrf_token % },則會報403錯誤。

#settings.py中打開MIDDLEWARE設置
‘django.middleware.csrf.CsrfViewMiddleware‘,

1 from django.shortcuts import render, HttpResponse, redirect
2 
3 def csrf_test(request):
4     if request.method == ‘GET‘:
5         return render(request, ‘csrf_test.html‘)
6     else:
7         return HttpResponse(‘ok‘)

views.py

 1 
 2 
 3 
 4     
 5     
 6 
 7 
 8
9 10 11 12 13 14 csef_test.html

技術分享圖片

修改csef_test.html:


 1 
 2 
 3 
 4     
 5     
 6 
 7 
 8
9 {% csrf_token %} 10 11 12 13 14 15 form表單中添加{% csrf_token %}

技術分享圖片

  • 全站禁用,即將settings.py中的 ‘django.middleware.csrf.CsrfViewMiddleware’ 註釋掉即可
  • 基於FBV視圖的局部禁用和使用

 1 #settings.py
 2 #啟用 ‘django.middleware.csrf.CsrfViewMiddleware‘,
 3 
 4 
 5 from django.views.decorators.csrf import csrf_exempt
 6 
 7 
 8 @csrf_exempt
 9 def csrf_test(request):
10     if request.method == ‘GET‘:
11         return render(request, ‘csrf_test.html‘)
12     else:
13         return HttpResponse(‘ok‘)

局部禁用

 1 #settings.py
 2 #禁用 #‘django.middleware.csrf.CsrfViewMiddleware‘,
 3 
 4 
 5 from django.views.decorators.csrf import csrf_protect
 6 
 7 
 8 @csrf_protect
 9 def csrf_test(request):
10     if request.method == ‘GET‘:
11         return render(request, ‘csrf_test.html‘)
12     else:
13         return HttpResponse(‘ok‘)

局部使用
  • 基於CBV視圖的(只能局部使用或禁用類,不能在類方法裏局部使用或禁用

 1 #settings.py
 2 #禁用    ‘django.middleware.csrf.CsrfViewMiddleware‘,
 3 
 4 
 5 from django.views import View
 6 from django.views.decorators.csrf import csrf_protect
 7 from django.utils.decorators import method_decorator
 8 
 9 
10 @method_decorator(csrf_protect, name=‘dispatch‘)
11 class Foo(View):
12     def get(self, request):
13         pass
14 
15     def post(self, request):
16         pass

局部使用

 1 #settings.py
 2 #啟用    ‘django.middleware.csrf.CsrfViewMiddleware‘,
 3 
 4 
 5 from django.views import View
 6 from django.views.decorators.csrf import csrf_exempt
 7 from django.utils.decorators import method_decorator
 8 
 9 
10 @method_decorator(csrf_exempt, name=‘dispatch‘)
11 class Foo(View):
12     def get(self, request):
13         pass
14 
15     def post(self, request):
16         pass

局部禁用
  • Ajax提交數據時,攜帶CSRF

 1 
 2 
 3 
 4     
 5     
 6 
 7 
 8
9 {% csrf_token %} 10 11 {# #} 12 Ajax提交表單 13 14 15 16 17 function submitForm() { 18 var csrf = $("input[name=‘csrfmiddlewaretoken‘]").val() 19 var user = $("#user").val() 20 $.ajax({ 21 url: ‘/csrf_test.html/‘, 22 type: ‘POST‘, 23 data: {"user": user, "csrfmiddlewaretoken": csrf}, 24 success: function (arg) { 25 console.log(arg); 26 } 27 }) 28 } 29 30 31 Ajax重寫csrf_test,htmlcsrf數據存放於data

 1 
 2 
 3 
 4     
 5     
 6 
 7 
 8
9 {% csrf_token %} 10 11 {# #} 12 Ajax提交表單 13 14 15 16 {#專門處理cookie的插件,提取cookie字符串#} 17 18 19 {#csrf數據放於data中#} 20 {##} 21 {# function submitForm() {#} 22 {# var csrf = $("input[name=‘csrfmiddlewaretoken‘]").val();#} 23 {# var user = $("#user").val();#} 24 {# $.ajax({#} 25 {# url: ‘/csrf_test.html/‘,#} 26 {# type: ‘POST‘,#} 27 {# data: {"user": user, "csrfmiddlewaretoken": csrf},#} 28 {# success: function (arg) {#} 29 {# console.log(arg);#} 30 {# }#} 31 {# })#} 32 {# }#} 33 {##} 34 35 {#csrf數據放於請求頭中#} 36 37 function submitForm() { 38 var csrf = $.cookie(‘csrftoken‘); 39 var user = $("#user").val(); 40 $.ajax({ 41 url: ‘/csrf_test.html/‘, 42 type: ‘POST‘, 43 headers: {‘X-CSRFToken‘: csrf}, 44 data: {"user": user}, 45 success: function (arg) { 46 console.log(arg); 47 } 48 }) 49 } 50 51 52 53 54 55 Ajax重寫csrf_test.htmlcsrf數據存放於headers

註意: { % csrf_token % }和cookie中的csrftoken值不一樣。

form表單中的隱藏csrf_token

技術分享圖片

cookie中

技術分享圖片

Django—XSS及CSRF