CSRF、XSS、clickjacking、SQL 的攻擊與防護

CSRF攻擊css

 

原理html

  跨站請求僞造。是一種挾制用戶在當前已登陸的Web應用程序上執行非本意的操做的攻擊方法。jquery

  網站經過cookie來實現登陸功能。而cookie只要存在瀏覽器中,那麼瀏覽器在訪問含有這個cookie的服務器的時候,會自動的攜帶cookie信息到服務器上去。就會存在一個漏洞:當你訪問了一個病毒網站時,該網站能夠在網頁源代碼中插入js代碼,使用js代碼給其餘服務器發送請求(如ICBC的轉帳請求)。由於在發送請求的時候,瀏覽器會自動的把cookie發送給對應的服務器,這時候相應的服務器(如ICBC網站)不知道這個請求是僞造的,就被欺騙過去了。從而達到在用戶不知情的狀況下,給某個服務器發送了一個請求(好比轉帳)。ajax

 

iframe:正則表達式

  1. 能夠加載嵌入別的域名下的網頁。便可以發送跨域請求。
  2. 由於iframe加載的是別的域名下的網頁。根據同源策略,js只能操做屬於本域名下的代碼,所以js不能操做經過iframe加載來的DOM元素。
  3. 若是ifrmae的src屬性爲空,那麼就沒有同源策略的限制,這時候能夠操做iframe下面的代碼了。而且,若是src爲空,那麼能夠在iframe中,給任何域名均可以發送請求。
  4. 直接在iframe中寫html代碼,瀏覽器是不會加載的。

 

可利用iframe的功能對網站進行攻擊sql

例:銀行網站的轉帳相關簡易代碼數據庫

 1 # 轉帳
 2 # 登陸後,進行轉帳時確認轉帳用戶的郵箱及轉帳金額;
 3 @method_decorator(login_required,name='dispatch')
 4 class TransferView(View):
 5     def get(self,request):
 6         return render(request,'transfer.html')
 7 
 8     def post(self,request):
 9         form = TransferForm(request.POST)
10         if form.is_valid():
11             email = form.cleaned_data.get('email')
12             money = form.cleaned_data.get('money')
13             # 驗證是否有session信息
14             user = request.front_user
15             if user.balance >= money:
16                 User.objects.filter(email=email).update(balance=F('balance')+money)
17                 # 當前用戶;
18                 user.balance -= money
19                 user.save()
20                 return HttpResponse('轉帳成功!')
21             else:
22                 return HttpResponse('餘額不足!')
23         else:
24             print(form.errors)
25             return redirect(reverse('transfer'))

 

攻擊方的代碼:django

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>首頁</title>
 6     <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
 7 </head>
 8 <body>
 9 <!--用戶看到的界面圖片-->
10 <img src="http://cms-bucket.nosdn.127.net/312e057a25f148519dc02b40812c78fe20170510155251.gif" alt="" width="100%" height="100%">
11 
12 <!--使用iframe,src不加載網頁,爲空可給任何域名發送請求,添加id的值獲取HTML代碼-->
13 <iframe id="stealframe" src="" frameborder="0" style="width:0;height:0;">
14 </iframe>
15 <div id="box" style="width: 0;height: 0;">
16         <form action="http://127.0.0.1:8000/transfer/" method="post" id="myform">
17             <input type="text" name="email" value="attacker123@qq.com">
18             <input type="text" name="money" value="100">
19         </form>
20 </div>
21     <script>
22         //獲取html=myform的代碼
23         window.onload = function () {
24             $('#stealframe').contents().find('html').html($('#myform'));
25             //自動提交代碼
26             $('#stealframe').contents().find('html').children('#myform').submit();
27         }
28     </script>
29 </body>
30 </html>

每運行一次攻擊者網站,內部將提交一遍 id=form 的html代碼, iframe 設置其爲不加載該HTML網頁但進行網頁內部的請求操做。跨域

 

防護CSRF攻擊
瀏覽器

 

  CSRF攻擊的要點就是在向服務器發送請求的時候,相應的cookie會自動的發送給對應的服務器。形成服務器不知道這個請求是用戶發起的仍是僞造的。這時候,能夠在用戶每次訪問有表單的頁面的時候,在網頁源代碼中加一個隨機的字符串叫作 csrf_token ,在cookie中也加入一個相同值的 csrf_token 字符串。之後給服務器發送請求的時候,服務器只有檢測到cookie中和網頁body中的 csrf_token 都相同,才認爲這個請求是正常的,不然就是僞造的。

 

在Django中防護CSRF攻擊

  1. settings.MIDDLEWARE中添加 CsrfMiddleware 中間件。
  2. 在模版代碼中添加一個input標籤,加載 csrf_token 。
    • 模版中添加代碼: <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"/> 
    • 或直接使用‘csrf_token標籤’,來自動生成一個帶有 csrf token 的‘input標籤’: {% csrf_token %} 

 


使用ajax處理csrf防護

  用ajax來處理csrf防護,須要手動的在form中添加csrfmiddlewaretoken,或者是在請求頭中添加 X-CSRFToken 。咱們能夠從返回的cookie中提取csrf token,再設置進去。

 1 //static:myajax.js
 2 function getCookie(name) {
 3     var cookieValue = null;
 4     if (document.cookie && document.cookie !== '') {
 5         var cookies = document.cookie.split(';');
 6         for (var i = 0; i < cookies.length; i++) {
 7             var cookie = jQuery.trim(cookies[i]);
 8             // Does this cookie string begin with the name we want?
 9             if (cookie.substring(0, name.length + 1) === (name + '=')) {
10                 cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
11                 break;
12             }
13         }
14     }
15     return cookieValue;
16 }
17 
18 var myajax = {
19     'get': function (args) {
20         args['method'] = 'get';
21         this.ajax(args);
22     },
23     'post': function (args) {
24         args['method'] = 'post';
25         this._ajaxSetup();
26         this.ajax(args);
27     },
28     'ajax': function (args) {
29         $.ajax(args);
30     },
31     '_ajaxSetup': function () {
32         $.ajaxSetup({
33             beforeSend: function(xhr, settings) {
34                 if (!/^(GET|HEAD|OPTIONS|TRACE)$/.test(settings.type) && !this.crossDomain) {
35                     xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
36                 }
37             }
38         });
39     }
40 };

在模板中導入:

 1 {% load static %}
 2 <!DOCTYPE html>
 3 <html lang="en">
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>中國工商銀行-轉帳</title>
 7     <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
 8     <script src="{% static 'myajax.js' %}"></script>
 9     <script>
10         $(function () {
11             $("#submit").click(function (event) {
12                 event.preventDefault();
13                 var email = $("input[name='email']").val();
14                 var money = $("input[name='money']").val();
15 
16                 myajax.post({
17                     'url': '/transfer/',
18                     'data': {
19                         'email': email,
20                         'money': money
21                     },
22                     'success': function (data) {
23                         // 若是狀態碼是等於200纔會走到success的回調中
24                         console.log(data);
25                     },
26                     'fail': function (error) {
27                         console.log(error);
28                     }
29                 });
30             });
31         });
32     </script>
33 </head>
34 --snip--

 

 

XSS攻擊:

  跨站腳本攻擊。是一種網站應用程序的安全漏洞攻擊,是代碼注入的一種,利用網頁開發時留下的漏洞,注入惡意指令代碼到網頁,使用戶加載並執行攻擊者惡意製造的網頁程序。

  好比A網站有一個發佈帖子的入口,若是用戶在提交數據的時候,提交了一段js代碼 <script>alert("hello world");</script> ,而後A網站在渲染這個帖子的時候,直接把這個代碼渲染了,那麼這個代碼就會執行,會在瀏覽器的窗口中彈出一個模態對話框來顯示 hello world! ,攻擊者可利用該漏洞進行攻擊。

<li>&lt;script&gt;alert(&quot;Hello world&quot;)&lt;/script&gt;</li>

 

防護:

  1. 若是不須要顯示一些富文本,那麼在渲染用戶提交的數據的時候,直接進行轉義。在Django的模板中默認就是轉義的。也能夠把數據在存儲到數據庫以前,先轉義再存儲進去,這樣之後在渲染的時候,即便不轉義也不會有安全問題。
    1 # 使用escape在存儲前先進行轉義
    2 @require_http_methods(['POST'])
    3 def add_comment(request):
    4     content = request.POST.get('content')
    5     content = escape(content)
    6     Comment.objects.create(content=content)
    7     return redirect(reverse('index'))

     

  2. 若是對於用戶提交上來的數據包含了一些富文本(好比:給字體換色,字體加粗等),在渲染的時候也要以富文本的形式進行渲染,也即須要使用 safe過濾器 將其標記爲安全的,這樣才能顯示出富文本樣式,但標籤全經過會有安全隱患。因此可使用 bleach庫 的 sanitizer ,在服務器處理數據的時候,將須要的標籤保留下來,把那些不須要的標籤進行轉義或者移除掉。
    1 <!--html模板代碼-->
    2 <!--safe會經過全部的標籤-->
    3     {% for comment in comments %}
    4         <li>{{ comment.content | safe}}</li>
    5     {% endfor %}
     1 # 使用bleach庫
     2 
     3 from django.shortcuts import render,redirect,reverse
     4 from .models import Comment
     5 from django.views.decorators.http import require_http_methods
     6 from django.template.defaultfilters import escape
     7 import bleach
     8 from bleach.sanitizer import ALLOWED_TAGS,ALLOWED_ATTRIBUTES
     9 
    10 # 首頁,顯示出數據庫中comments全部的值,
    11 def index(request):
    12     context = {
    13         'comments':Comment.objects.all()
    14     }
    15     return render(request,'index.html',context=context)
    16 
    17 # 將提交的數據保存並返回首頁
    18 @require_http_methods(['POST'])
    19 def add_comment(request):
    20     content = request.POST.get('content')
    21     # 在bleach庫已默認容許經過的標籤、屬性上再添加須要的新標籤及屬性
    22     tags = ALLOWED_TAGS + ['img']
    23     attributes = {**ALLOWED_ATTRIBUTES,'img':['src']}
    24     # 對提交的數據進行過濾
    25     cleaned_data = bleach.clean(content,tags=tags,attributes=attributes)
    26     Comment.objects.create(content=cleaned_data)
    27     return redirect(reverse('index'))

     

bleach庫:

  • tags:表示容許哪些標籤。
  • attributes:表示標籤中容許哪些屬性。
  • ALLOWED_TAGS:默認定義的一些標籤。若是不符合要求,能夠對其進行增長或者刪除。
  • ALLOWED_ATTRIBUTES:默認定義的一些屬性。若是不符合要求,能夠對其進行增長或者刪除。

 

clickjacking攻擊:

  又稱做點擊劫持攻擊。是一種在網頁中將惡意代碼等隱藏在看似無害的內容(如按鈕)之下,並誘使用戶點擊的手段。

兩種攻擊方式:

  1. 攻擊者使用一個透明的iframe,覆蓋在一個網頁上,而後使用戶在該頁面上進行操做,如網頁包含了一個按鈕A,按鈕上面浮了一個透明的iframe標籤,用戶將在不知情的狀況下點擊透明的iframe頁面進行加載。
  2. 攻擊者使用一張圖片覆蓋在網頁,遮擋網頁原有位置的含義;如用戶收到一封包含一段視頻的電子郵件,但其中的「播放」按鈕並不會真正播放視頻,而是鏈入一購物網站。這樣當用戶試圖「播放視頻」時,實際是被誘騙而進入了一個購物網站。
1 # clickjacking攻擊
2 def index(request):
3     return render(request,'clickjacking.html')
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>點擊劫持</title>
 6     <style>
 7         iframe{
 8             width:100%;
 9             height:100%;
10             display:block;
11             position: absolute;
12             z-index: 2;
13             opacity: 0.01;
14         }
15         button{
16             position: absolute;
17             top: 45px;
18             left: 180px;
19             z-index: 1;
20         }
21     </style>
22 </head>
23 <body>
24 點擊下方的按鈕將會進行跳轉:
25 <button>跳轉按鈕</button>
26 <iframe src="https://www.bilibili.com/video/av21663728/?p=33" frameborder="0"></iframe>
27 </body>
28 </html>

z-index :設置元素的堆疊順序。擁有更高堆疊順序的元素老是會處於堆疊順序較低的元素的前面。

position: 規定元素的定位類型。

opacity :設置元素的不透明級別。

 

clickjacking防護

  設置網站不容許使用iframe被加載到其餘網頁中,就能夠避免這種攻擊。能夠經過在響應頭中設置 X-Frame-Options 來設置這種操做。

X-Frame-Options 可設置的值:

  • DENY:不讓任何網頁使用iframe加載該頁面。
  • SAMEORIGIN:只容許在相同域名(即本人的網站)下使用iframe加載該頁面。
  • ALLOW-FROM origin:容許任何網頁經過iframe加載該網頁。

  在Django中可以使用中間件 django.middleware.clickjacking.XFrameOptionsMiddleware ,這個中間件設置了「X-Frame-Option」爲 SAMEORIGIN ,即在同域名的網站下才可使用iframe加載這個網頁,可避免被攻擊者經過iframe去加載了。

 

SQL注入

 

  經過把SQL命令插入到表單中或頁面請求的查詢字符串中,程序忽略了字符檢查,最終達到欺騙服務器執行惡意的SQL命令。利用現有應用程序,將(惡意的)SQL命令注入到後臺數據庫引擎執行的能力,經過在Web表單中輸入(惡意)SQL語句獲得一個存在安全漏洞的網站上的數據庫,而不是按照設計者意圖去執行SQL語句。 

 

下方代碼在網頁輸入 ?username=*** 時,可在後面再添加內容進行注入攻擊:

 1 # SQL注入攻擊
 2 def index(request):
 3     username = request.GET.get('username')
 4     context = {}
 5     if username:
 6         cursor = connection.cursor()
 7         cursor.execute("select id,username from front_user where username='%s'" % username)
 8         rows = cursor.fetcall()
 9         context['rows'] = rows
10     return render(request,'sql.html',context=context)

當輸入 ?usename=***'or'1=1 時:

1 # 若是輸入:http://127.0.0.1:8000/?username=jack'or'1+1 而不是隻輸入:http://127.0.0.1/?username=jack
2 sql = "select id,username from front_user where username='%s'" % "jack ' & '1=1"
3 # 代碼內容將會被改變
4 sql = "select id,username from front_user where username='jack' or '1=1'"

這將會顯示出全部的內容而不僅僅一個;

 

sql注入防護:

  • 不要信任用戶的輸入。對用戶的輸入進行校驗,能夠經過正則表達式,或限制長度;對單引號和 雙"-"進行轉換等。
  • 不要使用動態拼裝sql,可使用參數化的sql或者直接使用存儲過程進行數據查詢存取。
  • 不要使用管理員權限的數據庫鏈接,爲每一個應用使用單獨的權限有限的數據庫鏈接。
  • 不要把機密信息直接存放,加密或者hash掉密碼和敏感的信息。
  • 應用的異常信息應該給出儘量少的提示,最好使用自定義的錯誤信息對原始錯誤信息進行包裝。
     1 # 使用參數化
     2 def index(request):
     3     username = request.GET.get('username')
     4     context = {}
     5     if username:
     6         cursor = connection.cursor()
     7         sql = 'select id,username from front_user where username=%s'
     8         cursor.execute(sql,(username,))
     9         rows = cursor.fetchall()
    10         context['rows'] = rows
    11     return render(request,'sql.html',context=context)

     

Django防護sql注入:

  • 使用ORM來作數據的增刪改查。由於ORM使用的是參數化的形式執行sql語句的。
  • 若是萬一要執行原生sql語句,那麼建議不要拼接sql,而是使用參數化的形式。
相關文章
相關標籤/搜索