一、XSS 跨站腳本攻擊(Cross Site Scripting),為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。惡意攻擊者往Web頁面里插入惡意Script代碼,當用戶瀏覽該頁之時,嵌入其中Web裡面的Script代碼會被執行 ...
一、XSS
跨站腳本攻擊(Cross Site Scripting),為不和層疊樣式表(Cascading Style Sheets, CSS)的縮寫混淆,故將跨站腳本攻擊縮寫為XSS。惡意攻擊者往Web頁面里插入惡意Script代碼,當用戶瀏覽該頁之時,嵌入其中Web裡面的Script代碼會被執行,從而達到惡意攻擊用戶的目的。
1. 工作流程
a. 惡意用戶,在一些公共區域(例如,建議提交表單或消息公共板的輸入表單)輸入一些文本,這些文本被其它用戶看到,但這些文本不僅僅是他們要輸入的文本,同時還包括一些可以在客戶端執行的腳本。如:
<script> this.document = "*********";
alert('Not Safe'); </script>
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 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>評論</h1> 9 <form action="/commit.html/" method="post"> 10 <input type="text" name="commit"> 11 <input type="submit" value="sumbit"> {{ error }} 12 </form> 13 </body> 14 </html>commit.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h1>評論</h1> 9 {% for item in commit %} 10 <div>{{ item|safe }}</div> 11 {# item後加safe,預設數據安全,django不會做特殊處理#} 12 {% endfor %} 13 </body> 14 </html>index.html
以上實例中,若在commit.html頁面輸入以下內容並提交:
<script> alert('惡意腳本') </script>
則會在index頁面執行此行代碼,彈出警告框(若包含惡意代碼,則會執行)
3. 防範XSS攻擊
- 最直接的方法就是對於無法控制的輸入在html頁面內不要使用safe
{# <div>{{ item|safe }}</div>#} <div>{{ item }}</div>
- 也可以在views里進行過濾,防止特殊字元提交到資料庫或網頁內
def commit(request): if request.method == 'GET': return render(request, 'commit.html') else: com = request.POST.get('commit') if '<script>' in com: # 過濾“<script>”關鍵字,防止惡意代碼的提交 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 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>csef_test</title> 6 </head> 7 <body> 8 <form action="/csrf_test.html/" method="post"> 9 <input type="text" name="user" id="user"> 10 <input type="submit" value="submit"> 11 </form> 12 13 </body> 14 </html>csef_test.html
修改csef_test.html:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>csef_test</title> 6 </head> 7 <body> 8 <form action="/csrf_test.html/" method="post"> 9 {% csrf_token %} 10 <input type="text" name="user" id="user"> 11 <input type="submit" value="submit"> 12 </form> 13 14 </body> 15 </html>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 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>csef_test</title> 6 </head> 7 <body> 8 <form action="/csrf_test.html/" method="post"> 9 {% csrf_token %} 10 <input type="text" name="user" id="user"> 11 {# <input type="submit" value="submit">#} 12 <a onclick="submitForm();">Ajax提交表單</a> 13 </form> 14 15 <script src="/static/jquery-3.2.1.js"></script> 16 <script> 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 </script> 30 </body> 31 </html>Ajax重寫csrf_test,html,csrf數據存放於data中
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>csef_test</title> 6 </head> 7 <body> 8 <form action="/csrf_test.html/" method="post"> 9 {% csrf_token %} 10 <input type="text" name="user" id="user"> 11 {# <input type="submit" value="submit">#} 12 <a onclick="submitForm();">Ajax提交表單</a> 13 </form> 14 15 <script src="/static/jquery-3.2.1.js"></script> 16 {#專門處理cookie的插件,提取cookie字元串#} 17 <script src="/static/jquery.cookie.js"></script> 18 19 {#csrf數據放於data中#} 20 {#<script>#} 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 {#</script>#} 34 35 {#csrf數據放於請求頭中#} 36 <script> 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 </script> 51 52 53 54 </body> 55 </html>Ajax重寫csrf_test.html,csrf數據存放於headers中
註意:{
%
csrf_token
%
}和cookie中的csrftoken值不一樣。
form表單中的隱藏csrf_token
cookie中
參考資料:
1. http://www.cnblogs.com/wupeiqi/articles/5246483.html