Django自身安全機制-XSS和CSRF

XSS攻擊

什麼是XSS攻擊

XSS是一種常常出如今web應用中的計算機安全漏洞,它容許惡意web用戶將代碼植入到提供給其它用戶使用的頁面中。好比這些代碼包括HTML代碼和客戶端腳本。攻擊者利用XSS漏洞旁路掉訪問控制——例如 同源策略(same origin policy)。這種類型的漏洞因爲被黑客用來編寫危害性更大的 網絡釣魚(Phishing)攻擊而變得廣爲人知。對於 跨站腳本攻擊,黑客界共識是:跨站腳本攻擊是新型的「 緩衝區溢出攻擊「,而JavaScript是新型的「ShellCode」。
 

實施XSS攻擊須要具有兩個條件:

  1、須要向web頁面注入惡意代碼;javascript

  2、這些惡意代碼可以被瀏覽器成功的執行。html

解決辦法:前端

  一、一種方法是在表單提交或者url參數傳遞前,對須要的參數進行過濾。
  二、在後臺對從數據庫獲取的字符串數據進行過濾,判斷關鍵字。
  三、設置安全機制。
  django框架:內部機制默認阻止了。它會斷定傳入的字符串是不安全的,就不會渲染而以字符串的形式顯示。若是手賤寫了safe,那就危險了,若想使用safe,那就必須在後臺對要渲染的字符串作過濾了。因此在開發的時候,必定要慎用安全機制。尤爲是對用戶能夠提交的並能渲染的內容!!!java

- 示例:web

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title></title>
 6 </head>
 7 <body>
 8     <form method="POST" action="/comment/">
 9         <h4>評論</h4>
10         <input type="text" name="content"/>
11         <input type="submit" value="提交" />{{ error }}
12     </form>
13 </body>
14 </html>
評論提交頁面
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title></title>
 6 </head>
 7 <body>
 8     <h1>評論內容</h1>
 9     {% for item in msg %}
10         <div>{{ item|safe }}</div>
11     {% endfor %}
12 </body>
13 </html>
評論顯示頁面
 1 from django.shortcuts import render
 2 msg = []
 3 def comment(request):
 4         if request.method == "GET":
 5         return render(request,'comment.html')
 6     else:
 7         v = request.POST.get('content')
 8         if "script" in v:
 9             return render(request,'comment.html',{'error': '小比崽子還黑我'})
10         else:
11             msg.append(v)
12             return render(request,'comment.html')
13 
14 def index(request):
15     return render(request,'index.html',{'msg':msg})
16 
17 def test(request):
18     from django.utils.safestring import mark_safe
19     temp = "<a href='http://www.baidu.com'>百度</a>"
20     newtemp = mark_safe(temp)
21     return render(request,'test.html',{'temp':newtemp}
後臺處理

CSRF跨站請求僞造

什麼是 CSRFajax

  CSRF, Cross Site Request Forgery, 跨站點請求僞造。舉例來說,某個惡意的網站上有一個指向你的網站的連接,若是某個用戶已經登陸到你的網站上了,那麼當這個用戶點擊這個惡意網站上的那個連接時,就會向你的網站發來一個請求,你的網站會覺得這個請求是用戶本身發來的,其實呢,這個請求是那個惡意網站僞造的。數據庫

 

csrf攻擊過程

1.用戶C打開瀏覽器,訪問受信任網站A,輸入用戶名和密碼請求登陸網站A;django

2.在用戶信息經過驗證後,網站A產生Cookie信息並返回給瀏覽器,此時用戶登陸網站A成功,能夠正常發送請求到網站A;json

3.用戶未退出網站A以前,在同一瀏覽器中,打開一個TAB頁訪問網站B;後端

4.網站B接收到用戶請求後,返回一些攻擊性代碼,併發出一個請求要求訪問第三方站點A;

5.瀏覽器在接收到這些攻擊性代碼後,根據網站B的請求,在用戶不知情的狀況下攜帶Cookie信息,向網站A發出請求。網站A並不知道該請求實際上是由B發起的,因此會根據用戶C的Cookie信息以C的權限處理該請求,致使來自網站B的惡意代碼被執行。

csrf的攻擊之因此會成功是由於服務器端身份驗證機制能夠經過Cookie保證一個請求是來自於某個用戶的瀏覽器,但沒法保證該請求是用戶容許的。所以,預防csrf攻擊簡單可行的方法就是在客戶端網頁上添加隨機數,在服務器端進行隨機數驗證,以確保該請求是用戶容許的。Django也是經過這個方法來防護csrf攻擊的。

在django防護csrf攻擊

原理

在客戶端頁面上添加csrftoken, 服務器端進行驗證,服務器端驗證的工做經過'django.middleware.csrf.CsrfViewMiddleware'這個中間層來完成。在django當中防護csrf攻擊的方式有兩種, 1.在表單當中附加csrftoken 2.經過request請求中添加X-CSRFToken請求頭。注意:Django默認對全部的POST請求都進行csrftoken驗證,若驗證失敗則403錯誤侍候。

在表單中附加csrftoken

後端

 1 from django.shortcuts import render
 2 from django.template.context_processors import csrf
 3 
 4 def ajax_demo(request):
 5      # csrf(request)構造出{‘csrf_token’: token}
 6     return render(request, 'post_demo.html', csrf(request))

前端

 1 $('#send').click(function(){
 2                 
 3     $.ajax({
 4         type: 'POST',
 5         url:'{% url 'ajax:post_data' %}',
 6         data: {
 7                 username: $('#username').val(),
 8                 content: $('#content').val(),
 9                'csrfmiddlewaretoken': '{{ csrf_token }}'  關鍵點
10             },
11         dataType: 'json',
12         success: function(data){
13 
14         },
15         error: function(){
16     
17         }
18     
19     });
20   });
View Code

經過request請求中添加X-CSRFToken請求頭

後端

該方式須要藉助於Cookie傳遞csrftoken, 設置Cookie的方式有兩種。ps:經測試即使什麼都不作,也會設置Cookie,不過官方文檔說,不保證每次都有效

1.表單中添加{%csrf_token%}這個模板標籤

1 <form id="comment_form" action="#"></form>
2 {% csrf_token %}   就是這個
3 <p>姓名: <input type="text" name="useranme" id="username"></p>
4 <p>內容: <textarea name="content" id="content" rows="5" cols="30"></textarea></p>
5 <p><input type="button", id="send" value="提交"></p>

2.ensure_csrf_cookie裝飾器

1 from django.shortcuts import render
2 from django.views.decorators.csrf import ensure_csrf_cookie
3 
4 @ensure_csrf_cookie
5 def ajax_demo(request):
6     return render(request, 'ajax_demo.html')
前端
前端要作的事情,在進行post提交時,獲取Cookie當中的csrftoken並在請求中添加X-CSRFToken請求頭, 該請求頭的數據就是csrftoken。經過$.ajaxSetup方法設置AJAX請求的默認參數選項, 在每次ajax的POST請求時,添加X-CSRFToken請求頭
 1 <script type="text/javascript">
 2     $(function(){
 3 
 4         function getCookie(name) {
 5             var cookieValue = null;
 6             if (document.cookie && document.cookie != '') {
 7                 var cookies = document.cookie.split(';');
 8                 for (var i = 0; i < cookies.length; i++) {
 9                     var cookie = jQuery.trim(cookies[i]);
10                     // Does this cookie string begin with the name we want?
11                     if (cookie.substring(0, name.length + 1) == (name + '=')) {
12                         cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
13                         break;
14                     }
15                 }
16             }
17             return cookieValue;
18         }
19 
20         <!--獲取csrftoken-->
21         var csrftoken = getCookie('csrftoken');
22         console.log(csrftoken);
23 
24         //Ajax call
25         function csrfSafeMethod(method) {
26             // these HTTP methods do not require CSRF protection
27             return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
28         }
29 
30         $.ajaxSetup({
31             crossDomain: false, // obviates need for sameOrigin test
32             //請求前觸發
33             beforeSend: function(xhr, settings) {
34                 if (!csrfSafeMethod(settings.type)) {
35                     xhr.setRequestHeader("X-CSRFToken", csrftoken);
36                 }
37             }
38         });
39 
40         $('#send').click(function(){
41             console.log($("#comment_form").serialize());
42 
43             $.ajax({
44                 type: 'POST',
45                 url:'{% url 'ajax:post_data' %}',
46                 data: {
47                         username: $('#username').val(),
48                         content: $('#content').val(),
49                        //'csrfmiddlewaretoken': '{{ csrf_token }}'
50                     },
51                 dataType: 'json',
52                 success: function(data){
53                          
54                     
55                 },
56                 error: function(){
57 
58                 }
59 
60             });
61         });
62 
63 
64     });
65 </script>

取消csrftoken驗證

經過csrf_exempt, 來取消csrftoken驗證,方式有兩種。
1 .在視圖函數當中添加csrf_exempt裝飾器

1 from django.views.decorators.csrf import csrf_exempt
2 
3 @csrf_exempt
4 def post_data(request):
5     pass

2 .在urlconf當中

1 from django.views.decorators.csrf import csrf_exempt
2 urlpatterns = [
3     url(r'^post/get_data/$', csrf_exempt(post_data), name='post_data'),
4 
5 ]

django csrf注意點:

注意必定注意:ajax POST提交的時候,csrf-token 隨機字符串 直接放在data數據中的方式爲:data:{csrfmiddlewaretoken:"{{ csrf_token }}"}

  如果導入本身寫的JS文件,那上述方法就不能獲取到Django後臺發送的隨機字符串,而是須要利用上面介紹的兩種方式獲取(頁面寫上{% csrf_token %},經過隱藏的input標籤取value值寫在POST提交的data數據中;或是從cookie中獲取,寫在頭文件中。)

使用django框架時:   每次初始化一個項目時都要看看 django.middleware.csrf.CsrfViewMiddleware 這個中間件  每次在模板裏寫 form 時都須要加一個 {% csrf_token %} tag  每次發 ajax POST 請求,都須要加一個 X_CSRFTOKEN 的 header流程:  用戶第一次訪問頁面,確定是get請求,此時服務端就會給客戶端發送一段隨機字符串的數據,當客戶提交數據的時候,常在POST請求中帶回,就會發送隨機字符串給服務端(上一次請求獲取的數據)用於驗證。  服務端給客戶端發送的隨機字符串做爲一種安全機制,客戶端往服務端發送請求時再攜帶回來,用於匹配認證。  能夠從form表單中接收,也能夠在cookies中查看,注意:這兩個的隨機字符串是不一樣的!  若是開啓了csrf認證,後臺沒有拿到對應的字符串的話就會報錯---> 403

相關文章
相關標籤/搜索