1. 程式人生 > >每一個工程師都要學的安全測試,老闆再也不用擔心伺服器被黑

每一個工程師都要學的安全測試,老闆再也不用擔心伺服器被黑

本文由雲+社群發表

本篇包含了XSS漏洞攻擊及防禦詳細介紹,包括漏洞基礎、XSS基礎、編碼基礎、XSS Payload、XSS攻擊防禦。


第一部分:漏洞攻防基礎知識

XSS屬於漏洞攻防,我們要研究它就要了解這個領域的一些行話,這樣才好溝通交流。同時我建立了一個簡易的攻擊模型用於XSS漏洞學習。

1. 漏洞術語

瞭解一些簡單術語就好。

VUL

Vulnerability漏洞,指能對系統造成損壞或能借之攻擊系統的Bug。

POC

Proof of Concept,漏洞證明;可以是可以證明漏洞存在的文字描述和截圖,但更多的一般是證明漏洞存在的程式碼;一般不會破壞存在漏洞的系統。

EXP

exploit,漏洞利用;利用漏洞攻擊系統的程式碼。

Payload

(有效攻擊負載)是包含在你用於一次漏洞利用(exploit)中的攻擊程式碼。

PWN

是一個黑客語法的俚語詞 ,是指攻破裝置或者系統。

0DAY漏洞和0DAY攻擊

零日漏洞或零時差漏洞(Zero-dayexploit)通常是指還沒有補丁的安全漏洞。

零日攻擊或零時差攻擊(Zero-dayattack)則是指利用這種漏洞進行的攻擊。

零日漏洞不但是黑客的最愛,掌握多少零日漏洞也成為評價黑客技術水平的一個重要引數。

CVE漏洞編號

Common Vulnerabilities and Exposures,公共漏洞和暴露,為廣泛認同的資訊保安漏洞或者已經暴露出來的弱點給出一個公共的名稱。

可以在https://cve.mitre.org/網站根據漏洞的CVE編號搜尋該漏洞的介紹。也可以在中文社群http://www.scap.org.cn/上搜索關於漏洞的介紹

2. 漏洞攻擊模型

img1.png

上圖為一個簡單的攻擊模型。攻擊就是將Payload通過注入點注入到執行點執行的過程。過程順暢就表明這個漏洞被利用了。

第二部分:XSS基礎知識

基礎知識看完,現在我們可以開始接觸瞭解XSS基礎了。XSS基礎不好就不用研究了,大家沒用共同語言。

1. 什麼是XSS?

XSS全稱Cross-site scripting,跨站指令碼攻擊。攻擊者通過網站注入點注入惡意客戶端可執行解析的Payload,當被攻擊者訪問網站時Payload通過客戶端執行點執行來達到某些目的,比如獲取使用者許可權、惡意傳播、釣魚等行為。

2. XSS的分類

不瞭解分類其實很難學好XSS,大家對XSS分類有很多誤解,而且很多文章上都解釋錯的,這裡我給出一個相對好的XSS分類。

2.1 按照Payload來源劃分

儲存型XSS

Payload永久存在伺服器上,所以也叫永久型XSS,當瀏覽器請求資料時,包含Payload的資料從伺服器上傳回並執行。

過程如圖:

img2.png

儲存型XSS例子:

發表帖子內容包含Payload->存入資料庫->被攻擊者訪問包含該帖子的頁面Payload被執行

反射型XSS

又稱非持久型XSS,第一種情況:Payload來源在客戶端然後在客戶端直接執行。第二種情況:客戶端傳給服務端的臨時資料,直接回顯到客戶端執行。

過程如圖:

img3.png

反射型XSS例子 :

  1. 傳播一個連結,這個連結引數中包含Payload->被攻擊者訪問這個連結Payload在客戶端被執行。
  2. 在客戶端搜尋框輸入包含payload的內容->服務端回顯一個頁面提示搜尋內容未找到,payload就被執行了。

2.2 按照Payload的位置劃分

DOM-based XSS

由客戶端JavaScript程式碼操作DOM或者BOM造成Payload執行的漏洞。由於主要是操作DOM造成的Payload執行,所以叫做DOM-based XSS,操作BOM同樣也可以造成Payload執行,所以這個名詞有些不準確,其實叫JavaScript-based XSS更好。

DOM-based的Payload不在html程式碼中所以給自動化漏洞檢測帶來了困難。

過程如圖:

img4.png

反射型DOM-based XSS的例子:

在客戶端搜尋框輸入包含payload的內容->服務端回顯一個頁面提示搜尋內容未找到,payload就被執行了。

儲存型DOM-based XSS的例子:

從服務端介面中獲取包含Payload的內容->JavaScript通過操作DOM、BOM造成Payload執行

HTML-based XSS

Payload包含在服務端返回的HTML中,在瀏覽器解析HTML的時候執行。這樣的漏洞易於做自動化漏洞檢測,因為Payload就在HTML裡面。當然HTML-based XSS也有反射型和儲存型的。

過程如圖:

img5.png

反射型HTML-based XSS的例子:

在客戶端搜尋框輸入包含payload的內容->服務端回顯一個頁面提示搜尋內容未找到,payload包含在HTML被執行。

儲存型HTML-based XSS的例子:

發表帖子內容包含Payload->存入資料庫->被攻擊者訪問包含該帖子的頁面Payload在HTML頁面中被執行

3. XSS的攻擊目的及危害

很多寫出不安全程式碼的人都是對漏洞的危害沒有清晰的認識,下圖是2017 OWASP 網路威脅Top10:

img6_頭圖 自擷取.jpg

可以看到XSS在網路威脅中的地位舉足輕重。

3.1 目的

  1. cookie劫持
  2. 篡改網頁,進行釣魚或者惡意傳播
  3. 網站重定向
  4. 獲取使用者資訊

3.2 危害

  1. 傳播類危害
  2. 系統安全威脅

第三部分:XSS攻擊的Payload

這部分我們分析下攻擊模型中的Payload,瞭解Payload必須瞭解編碼,學習好JS也必須要了解好編碼。要想真正做好網路安全編碼是最基本的。

1. 編碼基礎

編碼部分是最重要的雖然枯燥但必須要會。後面很多變形的Payload都建立在你的編碼基礎。這裡通16進位制編碼工具讓你徹底學會編碼。

1.1 編碼工具

16進位制檢視器:方便檢視檔案16進位制編碼

MAC:HEx Friend

windows: HxD

編輯器Sublime:可以通過Sublime將檔案儲存不同編碼型別

img7.jpg

1.2 ASCII

定義:美國資訊交換標準程式碼,是基於拉丁字母的一套計算機編碼系統,主要用於顯示現代英語和其他西歐語言。

編碼方式:屬於單子節編碼。ASCII碼一共規定了128個字元的編碼,只佔用了一個位元組的後面7位,最前面的1位統一規定為0。0~31及127(共33個)是控制字元或通訊專用字元。32~126(共95個)是字元(32是空格。

1.3 ISO-8859-1(Latin1)

定義:Latin1是ISO-8859-1的別名,ISO-8859-1收錄的字元除ASCII收錄的字元外,還包括西歐語言、希臘語、泰語、阿拉伯語、希伯來語對應的文字元號。歐元符號出現的比較晚,沒有被收錄在ISO-8859-1當中。

編碼方式:ISO-8859-1編碼是單位元組編碼,向下相容ASCII,其編碼範圍是0x00-0xFF,0x00-0x7F之間完全和ASCII一致,0x80-0x9F之間是控制字元,0xA0-0xFF之間是文字元號。

注意:ISO-8859-1編碼表示的字元範圍很窄,無法表示中文字元。但是,由於是單位元組編碼,和計算機最基礎的表示單位一致,所以很多時候,仍舊使用ISO-8859-1編碼來表示。比如,雖然”中文”兩個字不存在iso8859-1編碼,以gb2312編碼為例,應該是”d6d0 cec4”兩個字元,使用iso8859-1編碼的時候則將它拆開為4個位元組來表示:”d6 d0 ce c4”(事實上,在進行儲存的時候,也是以位元組為單位處理的)。所以mysql中latin1可以表示任何編碼的字元。

Latin1與ASCII編碼的關係:完全相容ASCII。

1.4 Unicode編碼(UCS-2)

Code Point: 碼點,簡單理解就是字元的數字表示。一個字符集一般可以用一張或多張由多個行和多個列所構成的二維表來表示。二維表中行與列交叉的點稱之為碼點,每個碼點分配一個唯一的編號,稱之為碼點值或碼點編號。

BOM(Byte Order Mark):位元組序,出現在檔案頭部,表示位元組的順序,第一個位元組在前,就是”大端方式”(Big-Endian),第二個位元組在前就是”小端方式”(Little-Endian)。

在Unicode字符集中有一個叫做”ZERO WIDTH NO-BREAK SPACE“的字元,它的碼點是FEFF。而FFFE在Unicode中是不存在的字元,所以不應該出現在實際傳輸中。在傳輸位元組流前,我們可以傳字元”ZERO WIDTH NO-BREAK SPACE“表示大小端,因此字元”ZERO WIDTH NO-BREAK SPACE“又被稱作BOM。

BOM還可以用來表示文字編碼方式,Windows就是使用BOM來標記文字檔案的編碼方式的。Mac上檔案有沒有BOM都可以。

例如:\u00FF :00是第一個位元組,FF是第二個位元組。和碼點表示方式一樣屬於大端方式。

Unicode編碼字符集:旨在收集全球所有的字元,為每個字元分配唯一的字元編號即程式碼點(Code Point),用 U+緊跟著十六進位制數表示。所有字元按照使用上的頻繁度劃分為 17 個平面(編號為 0-16),即基本的多語言平面和增補平面。基本的多語言平面又稱平面 0,收集了使用最廣泛的字元,程式碼點從 U+0000 到 U+FFFF,每個平面有 216=65536 個碼點;

Unicode編碼:Unicode 字符集中的字元可以有多種不同的編碼方式,如 UTF-8、UTF-16、UTF-32、壓縮轉換等。我們通常所說的Unicode編碼是UCS-2 將字元編號(同 Unicode 中的碼點)直接對映為字元編碼,亦即字元編號就是字元編碼,中間沒有經過特別的編碼演算法轉換。是定長雙位元組編碼:因為我們UCS-2只包括本的多語言平面(U+0000 到 U+FFFF)。

UCS-2的BOM:大端模式:FEFF。小端模式:FFFE。

檔案儲存成UTF-16 BE with BOM相當於UCS-2的大端模式,可以看到16進位制開頭為FEFF

Latin1與Unicode編碼的關係:Latin1對應於Unicode的前256個碼位。

img8.png

1.5 UTF-16

定義及編碼:UTF-16是Unicode的其中一個使用方式,在Unicode基本多文種平面定義的字元(無論是拉丁字母、漢字或其他文字或符號),一律使用2位元組儲存。而在輔助平面定義的字元,會以代理對(surrogate pair)的形式,以兩個2位元組的值來儲存。是雙位元組編碼。

UTF-16與UCS-2的關係:UTF-16可看成是UCS-2的父集。在沒有輔助平面字元(surrogate code points)前,UTF-16與UCS-2所指的是同一的意思。但當引入輔助平面字元後,就稱為UTF-16了。現在若有軟體聲稱自己支援UCS-2編碼,那其實是暗指它不能支援在UTF-16中超過2bytes的字集。對於小於0x10000的UCS碼,UTF-16編碼就等於UCS碼。

UTF-16的BOM:大端模式:FEFF。小端模式:FFFE。

1.6 UTF-8

定義及編碼:UTF-8就是在網際網路上使用最廣的一種Unicode的實現方式,這是為傳輸而設計的編碼,並使編碼無國界,這樣就可以顯示全世界上所有文化的字元了。UTF-8最大的一個特點,就是它是一種變長的編碼方式。它可以使用1~4個位元組表示一個符號,根據不同的符號而變化位元組長度,當字元在ASCII碼的範圍時,就用一個位元組表示,保留了ASCII字元一個位元組的編碼作為它的一部分,注意的是unicode一箇中文字元佔2個位元組,而UTF-8一箇中文字元佔3個位元組)。從unicode到utf-8並不是直接的對應,而是要過一些演算法和規則來轉換。

Unicode符號範圍 UTF-8編碼方式(十六進位制)
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

UTF8的BOM:EFBBBF。UTF-8不存在字元序列的問題,但是可以用用BOM表示這個檔案是一個UTF-8檔案。

檔案儲存成UTF-8 BE with BOM,可以看到16進位制開頭為EFBBBF

img9.png

1.7 GBK/GB2312

定義及編碼:GB2312是最早一版的漢字編碼只包含6763漢字,GB2312只支援簡體字而且不全,顯然不夠用。GBK編碼,是對GB2312編碼的擴充套件,完全相容GB2312標準,支援簡體字繁體字,包含全部中文字元。GBK編碼採用單雙位元組編碼方案,單位元組和Latin1一致,雙位元組是漢字部分,其編碼範圍:8140-FEFE,剔除xx7F碼位,共23940個碼位。

GBK與Latin1的關係:GBK單位元組編碼區和Latin1編碼一致。

GBK與Unicode的關係:GBK與Unicode字符集編碼不同但是相容的。如"漢"的Unicode值與GBK雖然是不一樣的,假設Unicode為a040,GBK為b030,但是可以對應轉化的。漢字的Unicode區:4E00-u9FA5。

GBK與UTF-8:GBK漢字採用雙位元組編碼比在UTF-8中的三位元組要小。但是UTF-8更通用。GBK與UTF-8轉化:GBK—> Unicode —> UTF8

2. 前端中的編碼

有了編碼基礎就可以來認識一下前端中的編碼,這樣你才能真正認識Payload。我這裡的應該是總結最全的。

2.1 Base64

Base64可以用來將binary的位元組序列資料編碼成ASCII字元序列構成的文字。使用時,在傳輸編碼方式中指定Base64。使用的字元包括大小寫拉丁字母各26個、數字10個、加號+和斜槓/,共64個字元及等號=用來作為字尾用途。所以總共65個字元。

將3位元組的資料,先後放入一個24位的緩衝區中,先來的位元組佔高位。資料不足3位元組的話,於緩衝器中剩下的位元用0補足。每次取出6bit對原有資料用Base64字元作為編碼後的輸出。編碼若原資料長度不是3的倍數時且剩下1個輸入資料,則在編碼結果後加2個=;若剩下2個輸入資料,則在編碼結果後加1個=。可以看出Base64編碼資料大約是原來資料的3/4。

標準的Base64並不適合直接放在URL裡傳輸,因為URL編碼器會把標準Base64中的/和+字元變為形如%XX的形式,而這些%號在存入資料庫時還需要再進行轉換,因為ANSI SQL中已將%號用作萬用字元。為解決此問題,可採用一種用於URL的改進Base64編碼,它不在末尾填充=號,並將標準Base64中的+和/分別改成了-和_,這樣就免去了在URL編解碼和資料庫儲存時所要做的轉換,避免了編碼資訊長度在此過程中的增加,並統一了資料庫、表單等處物件識別符號的格式。

window.btoa/window.atob base64編碼(binary to ascii)和解碼僅支援Latin1字符集。

2.2 JS轉義字元

js字元字串中包含一些反斜槓開頭的特殊轉義字元,用來表示非列印符、其他用途的字元還可以轉義表示unicode、Latin1字元。

轉義字元 含義
單引號
雙引號
& 和號
\ 反斜槓
\n 換行符
\r 回車符
\t 製表符
\b 退格符
\f 換頁符
\n … \nnn 由一位到三位八進位制數(1到377)指定的Latin-1字元
\xnn 以16進位制nn(n:0~F)表示一個Latin1字元。\x41表示字元A
\unnnn 以16進位制nnnn(n:0~F)表示一個Unicode字元。只限於碼點在\u0000~\uFFFF範圍內
\u{n} … \u{nnnnnn} Unicode碼點值表示一個Unicode字元

特別注意:

  1. 換行符\n在innerHTML使用只會展示一個空格並不會換行。
  2. 通過\n、\u和\x可以代表任意unicode字元和Latin1字元。通過這個可以對js加密保證js安全和進行隱蔽攻擊。

例子:

function toUnicode(theString) {  //字串轉換為unicode編碼字串,切記這個字串是複製用的,不是讓你拿來直接執行的。
 var unicodeString = '';
 for (var i = 0; i < theString.length; i++) {
  var theUnicode = theString.charCodeAt(i).toString(16).toUpperCase();
  while (theUnicode.length < 4) {
    theUnicode = '0' + theUnicode;
  }
  theUnicode = '\\u' + theUnicode;
  unicodeString += theUnicode;
 }
 return unicodeString;
}
var xssStr = "alert('xss')";
var xssStrUnicode = toUnicode(xssStr);
//輸出:"\u0061\u006C\u0065\u0072\u0074\u0028\u0027\u0078\u0073\u0073\u0027\u002"
eval("\u0061\u006C\u0065\u0072\u0074\u0028\u0027\u0078\u0073\u0073\u0027\u002"); //彈出xss彈窗

2.3 URL編碼

RFC 1738做出規定”只有字母和數字0-9a-zA-Z、一些特殊符號”$-_.+!*’(),”不包括雙引號、以及某些保留字,才可以不經過編碼直接用於URL”。所以當連結中包含中文或者其他不符合規定的字元的時候都需要經過編碼的。然而由於瀏覽器廠商眾多,對url進行編碼的形式多種多樣,如果不對編碼進行統一處理,會對程式碼開發造成很大的影響,出現亂碼現象。

URL編碼規則:需要編碼的字元轉換為UTF-8編碼,然後在每個位元組前面加上%。

例如:

'牛'-->UTF-8編碼E7899B-->URL編碼是%E7%89%9B

JS為我們提供了3個對字串進行URL編碼的方法:escape ,encodeURI,encodeURIComponent

escape:由於eccape已經被建議放棄所以大家就不要用了

encodeURI:encodeURI不編碼的82個字元:!#$&’()*+,/:;[email protected]_~0-9a-zA-Z,從中可以看不會對url中的保留字元進行編碼,所以適合url整體編碼

encodeURIComponent:這個對於我們來說是最有用的一個編碼函式,encodeURIComponent不編碼的字元有71個:!, ‘,(,),*,-,.,_,~,0-9,a-z,A-Z。

可以看出對url中的保留字進行的編碼,所以當傳遞的引數中

包含這些url中的保留字(@,&,=),就可以通過這個方法編碼後傳輸

這三個方法對應的解碼方法: unescape、decodeURI、decodeURIComponent

2.4 HTML字元實體

HTML中的預留字元必須被替換為字元實體。這樣才能當成字元展示,否則會當成HTML解析。

字元實體編碼規則:轉義字元 = &#+ascii碼; = &實體名稱;

XSS字串需要防禦字元的實體轉換表:

img10.png

轉化方法:

function encodeHTML (a) {
 return String(a)
   .replace(/&/g, "&")
   .replace(/</g, "<")
   .replace(/>/g, ">")
   .replace(/"/g, """)
   .replace(/'/g, "'");
};

2.5 頁面編碼

頁面編碼設定:

指令碼編碼設定:

注意:要想JS即可在UTF-8中正常使用又可以在GBK中正常使用,可以對JS中所有包含中文的字串做字元轉義。

例子:

alert("網路錯誤");     //彈出網路錯誤
alert("\u7f51\u7edc\u9519\u8bef"); //彈出網路錯誤

3. Payload的分類

現在可以認識Payload的了,我不得不說這裡對Payload的分類可以很好的讓你認識Payload。也幫助你更好的對應到執行點。

3.1 原子Payload

最低層級的Payload。

javascript程式碼片段

可在eval、setTimeout、setInterval中直接執行,也可通過HTML等構成高階Payload

javascript:javascript偽協議

結構:javascript:+js程式碼。可以在a標籤的href屬性被點選和window.location.href賦值的時候執行。

DATA URI協議

DATA URI結構:data:, 。DATA URI資料在包含在iframe的src屬性和object data屬性中將會變成可執行的Payload.

字串轉義變種javascript程式碼片段

unicode或者Latin-1表示字串。

eval("\u0061\u006C\u0065\u0072\u0074\u0028\u0027\u0078\u0073\u0073\u0027\u002"); //可執行的JS

3.2 純HTMLPayload

這種Payload特點不具有可執行的JS,但是存在傳播風險,可以把別的站點注入到被攻擊網站。

包含連結跳轉的HTML片段

主要是傳播危害

<a href="http://ha.ck">哈哈,我來釣魚了</a>

3.3 包含原子Payload的HTML片段Payload

script標籤片段

script標籤片段這種Payload可以引入外部JS或者可直接執行的script。這種Payload一般不能通過直接複製給innerHTML執行,不過在IE上可以。不過通過document.write是可以執行。

例子:

// Payload原始值:data:text/html,<script>alert('xss');</script>
var inputStr ="<script>alert('xss');<\/script>";
document.write(inputStr);

包含事件處理的HTML片段

例如:包含img的onerror, svg的onload,input的onfocus等的HTML片段,都可以變成可執行的Payload。

var inputStr ="<img src=x onerror=alert('xss');>";
 var inputStr ="<svg/onload=alert('xss')>";
 var inputStr ="<input autofocus onfocus=alert('xss')>";
 xssDom.innerHTML = inputStr;

包含可執行JS屬性的HTML片段

  1. javascript偽協議
xssLink.setAttribute("href","javascript:alert('xss')")//點選可觸發
var inputStr = "javascript:alert('xss')";
window.location.href = inputStr;
  1. DATA URI

例子:

// Payload原始值:data:text/html,<script>alert('xss');</script>
//var inputStr = '<iframe src="data:text/html,<script>alert("xss");</script>"></iframe>';
// var inputStr = '<object data="data:text/html;base64,ZGF0YTp0ZXh0L2h0bWwsPHNjcmlwdD5hbGVydCgneHNzJyk7PC9zY3JpcHQ+"></object>';
xssDom.innerHTML = inputStr; //彈出alert("xss")

這裡只是介紹了主要的Payload,還有很多不常見的Payload。

第四部分:XSS攻擊模型分析

這部分我們根據漏洞攻擊模型分析一下XSS的執行點和注入點。分析這兩點其實就是找漏洞的過程。

1. XSS漏洞執行點

  1. 頁面直出Dom
  2. 客戶端跳轉連結: location.href / location.replace() / location.assign()
  3. 取值寫入頁面:innerHTML、document.write及各種變種。這裡主要會寫入攜帶可執行Payload的HTML片段。
  4. 指令碼動態執行:eval、setTimeout()、setInterval()
  5. 不安全屬性設定:setAttribute。不安全屬性前面見過:a標籤的href、iframe的src、object的data
  6. HTML5 postMessage來自不安全域名的資料。
  7. 有缺陷的第三方庫。

2. XSS漏洞注入點

看看我們可以在哪些位置注入我們的Payload

  1. 服務端返回資料
  2. 使用者輸入的資料
  3. 連結引數:window.location物件三個屬性href、search、search
  4. 客戶端儲存:cookie、localStorage、sessionStorage
  5. 跨域呼叫:postMessage資料、Referer、window.name

上面內容基本包含了所有的執行點和注入點。對大家進行XSS漏洞攻防很有幫助。

第五部分 XSS攻擊防禦策略

1. 騰訊內部公共安全防禦及應急響應

  1. 接入公共的DOM XSS防禦JS
  2. 內部漏洞掃描系統掃描
  3. 騰訊安全應急響應中心:安全工作者可以通過這個平臺提交騰訊相關的漏洞,並根據漏洞評級獲得獎勵。
  4. 重大故障應急響應制度。

2. 安全編碼

2.1 執行點防禦方法

執行點 防禦
頁面直出Dom 服務端XSS過濾
客戶端跳轉連結 域名白名單(例如:只允許qq.com域)、連結地址XSS過濾
取值寫入頁面 客戶端XSS過濾
指令碼動態執行 確保執行Js字串來源可信

|

| 不安全屬性設定 | 內容XSS過濾,包含連結同客戶端跳轉連結 |

|HTML5 postMessage|origin限制來源|

| 有缺陷的第三方庫 | 不使用

2.2 其他安全防禦手段

  1. 對於Cookie使用httpOnly
  2. 在HTTP Header中使用Content Security Policy

3. 程式碼審查

總結XSS檢查表做程式碼自測和檢視

4. 自動化檢測XSS漏洞的工具

手工檢測XSS漏洞是一件比較費時間的事情,我們能不能寫一套自動檢測XSS自動檢測工具。竟然我知道了注入點、執行點、Payload自動化過程是完全有可能的。

XSS自動化檢測的難點就在於DOM型XSS的檢測。因為前端JS複雜性較高,包括靜態程式碼分析、動態執行分析都不容易等。

第六部分 總結

上面內容文字比較多,看完還是很累的,總結起來就一句話:安全大於一切,不要心存僥倖,希望以上內容對您有幫助,不過以上內容僅代表個人理解,如有不對歡迎指正討論。

此文已由作者授權騰訊雲+社群釋出