果你運行交互式網站或應用程序,JavaScript 安全性是重中之重。 從程序錯誤和不安全的用戶輸入到惡意攻擊,有很多事情可能會出錯。
為了幫助你保護自己和你的用戶,這里給大家介紹幾個基本的易于實現的JavaScript安全最佳實踐,并推薦了一些工具,可以幫助你消除常見漏洞并防止對你的網站或應用程序的惡意攻擊。
1. 使用 JavaScript linter
避免 JavaScript 安全問題的最簡單和最簡單的方法是檢查代碼。Linter 是靜態代碼分析工具,可檢查你的代碼是否存在編程和風格錯誤、代碼異味和已知的安全漏洞。
三種最著名的 JavaScript linter 是 JSHint、JSLint 和 ESLint。 現代源代碼編輯器,例如 Visual Studio Code 和 Atom,也帶有可插入的 JavaScript linting 功能。
2. 避免使用內聯 JavaScript 并建立內容安全策略
使用內聯腳本標簽會使你的網站或應用程序更容易受到跨站點腳本 (XSS) 攻擊。 你可以通過將所有腳本(包括內聯事件處理程序(例如 onclick))添加為外部 .js 文件來避免這種 JavaScript 安全風險。
為了提高安全性,我們還建議你建立內容安全策略 (CSP)。 這是客戶端和服務器之間通信中的一個安全層,允許你向 HTTP 響應標頭添加內容安全規則。
如果你的頁面上沒有任何內聯腳本,則設置更有效的 CSP 會更容易。 你可以使用 script-src 和 default-src 指令來阻止所有內聯腳本,因此如果任何惡意內聯腳本試圖在你的站點上執行,它將自動失敗。
3. 驗證用戶輸入
在客戶端和服務器端驗證用戶輸入對于避免惡意代碼注入至關重要。
HTML5 表單帶有內置的表單驗證屬性,例如 required、min、max、type 等,讓你無需在客戶端使用任何 JavaScript,即可檢查用戶數據并返回錯誤消息。 你還可以使用模式 HTML 屬性通過正則表達式驗證輸入的值。
除了這些 HTML5 屬性之外,現代瀏覽器還支持 Constraint Validation API,允許你使用 JavaScript 執行自定義輸入驗證。
這是一個 Web API,它擴展了屬于表單中使用的不同 HTML 元素(例如 HTMLInputElement、HTMLSelectElement 和 HTMLButtonElement)的 JavaScript 接口,并提供了有用的屬性和方法,用于根據不同的約束檢查輸入有效性、報告有效性狀態以及執行其他操作。
4. 轉義或編碼用戶輸入
為了避免 XSS 攻擊,對傳入或不安全的數據進行轉義或編碼也很重要。轉義和編碼是將可能構成安全風險的特殊字符轉換為安全形式的兩種技術。
雖然編碼會在潛在危險字符之前添加一個額外字符,例如 JavaScript 中引號前的 \ 字符,但轉義會將字符轉換為等效但安全的格式,例如將 > 字符轉換為 > HTML 中的字符串。
根據經驗,當 HTML 實體(例如 < 和 > 字符)來自不受信任的來源時,你應該始終對其進行編碼。要轉義 URI 和 JavaScript 代碼,你可以使用免費的轉義/編碼工具,例如 FreeFormatter 的 JavaScript String Escaper 和 URL Encoder/Decoder。
最好避免使用返回未轉義字符串的 JavaScript 屬性和方法。例如,你可以使用安全 textContent 屬性而不是解析為 HTML 的 innerHTML(因此字符不會被轉義)。
5. 壓縮、捆綁和混淆你的JavaScript代碼
最后,你可以使用 Webpack 等具有更多安全功能的工具來縮小和捆綁你的代碼,從而使黑客更難理解你的腳本的結構和邏輯。例如,你可以向它加載的每個腳本添加一個隨機數。
雖然縮小和捆綁腳本通常被視為 JavaScript 最佳實踐,但混淆是一個有爭議的話題。 這是因為瀏覽器加載混淆腳本需要更長的時間,這會降低性能和用戶體驗,尤其是在更高的混淆級別。 但是,如果你仍然決定對部分或全部腳本進行混淆,則可以使用免費工具(例如 Obfuscator.io),該工具還具有適用于 Webpack、Grunt、Rollup、Netlify 等流行工具的插件。
遵循這些 JavaScript 安全最佳實踐可以幫助你使腳本更安全并防止常見攻擊,例如跨站點腳本、跨站點請求偽造、第三方安全漏洞等。
了解更多
繼上一篇: 我用一個小小的開放設計題,干掉了40%的面試候選人 聊到了Web安全之后,好多朋友也在關注這個話題,今天特意再寫一篇。
安全世界觀一詞是《白帽子講Web安全》一書的開篇章節,多年后再讀經典,仍然受益匪淺!
正如開篇所說的:“互聯網本來是安全的,自從有了研究安全的人,互聯網就不安全了。” 世上沒有攻不破的系統,只有還沒攻破的系統,有多少條路可以通羅馬,大概就有多少種攻克之道。
“破壞往往比建設容易”,但凡事都不是絕對的。
跟機場安全檢查進行類比。通過一個安全檢查(過濾,凈化)的過程,可以梳理未知的人或物,使其變得可信任。被劃分出來的具有不同信任級別的區域,我們稱為信任域,劃分兩個不同信任域之間的邊界,我們稱之為信任邊界。
數據從高等級的信任域流向低等級的信任域,是不需要經過安全檢查的;數據從低等級的信任域流向高等級的信任域,是需要經過信任邊界的安全檢查。
安全問題的本質是信任的問題。
一切的安全方案設計的基礎,都是建立在信任關系上的。我們必須相信一些東西,必須要有一些最基本的假設,安全方案才能得以建立。
安全的三要素是安全的基本組成元素,分別為:
機密性要求數據內容不能泄露,加密是實現機密性要求的常見手段。如果不將文件存在抽屜里,而是放在透明的盒子里,那么雖然無法得到這個文件,但是文件的內容將會被泄露。
完整性則要求保護數據內容是完整,沒有被篡改的。常見的保證一致性的技術手段是數字簽名。
可用性要求保護資源是“隨需而得”。
舉例來說,假如有100個車位,有一天一個壞人搬了100塊大石頭將車位全占了,那么停車場無法再提供正常服務。在安全領域中叫做拒絕服務攻擊,簡稱DoS(Denial of Service)。拒絕服務攻擊破壞的是安全的可用性。
1)黑名單、白名單
實際上,Secure By Default原則,也可以歸納為白名單,黑名單的思想。如果更多地使用白名單,那么系統就會變得更安全。
2)最小權限原則
最小原則要求系統只授予主體必要的權限,而不要過度授權,這樣能有效地減少系統,網絡,應用,數據庫出錯的機會。
如果網站只提供Web服務,只允許開啟80,443端口,屏蔽其它端口。
縱深防御原則包含兩層含義:
1)要在各個不同層面,不同方面實施安全方案,避免出現疏漏,不同安全方案之間需要相互配合,構成一個整體;
2)要在正確的地方做正確的事情,即:在解決根本問題的地方實施針對性的安全方案。
這一原則適用于各種由于“注入”而引發安全問題的場景。
實際上,緩沖區溢出,也可以認為是程序違背了這一原則的后果——程序在棧或者堆中,將用戶數據當做代碼執行,混淆了代碼與數據的邊界,從而導致安全問題的發生。
微軟使用的ASLR技術,在較新版本的Linux內核中也支持。在ASLR的控制下,一個程序每次啟動時,其進程的棧基址都不相同,具有一定的隨機性,對于攻擊者來說,這就是“不可預測性”。
不可預測性,能有效地對抗基于篡改,偽造的攻擊。
不可預測性的實現往往需要用到加密算法,隨機數算法,哈希算法,好好利用這條規則,在設計安全方案時往往會事半功倍。
XSS (Cross Site Script),跨站腳本攻擊,因為縮寫和 CSS (Cascading Style Sheets) 重疊,所以只能叫 XSS。
XSS 的原理是惡意攻擊者往 Web 頁面里插入惡意可執行網頁腳本代碼,當用戶瀏覽該頁之時,嵌入其中 Web 里面的腳本代碼會被執行,從而可以達到攻擊者盜取用戶信息或其他侵犯用戶安全隱私的目的。XSS 的攻擊方式千變萬化,但還是可以大致細分為幾種類型:
CSRF(Cross-Site Request Forgery),名為:跨站請求偽造攻擊。
那么 CSRF 到底能夠干嘛呢?
你可以這樣簡單地理解:攻擊者可以盜用你的登陸信息,以你的身份模擬發送各種請求。攻擊者只要借助少許的社會工程學得詭計。
例如通過 QQ 等聊天軟件發送的鏈接(有些還偽裝成短域名,用戶無法分辨),攻擊者就能迫使 Web 應用的用戶去執行攻擊者預設的操作。例如,當用戶登錄網絡銀行去查看其存款余額,在他沒有退出時,就點擊了一個 QQ 好友發來的鏈接,那么該用戶銀行帳戶中的資金就有可能被轉移到攻擊者指定的帳戶中。
所以遇到 CSRF 攻擊時,將對終端用戶的數據和操作指令構成嚴重的威脅。當受攻擊的終端用戶具有管理員帳戶的時候,CSRF 攻擊將危及整個 Web 應用程序。
CSRF 原理
下圖大概描述了 CSRF 攻擊的原理:
CSRF 攻擊必須要有三個條件 :
1. 用戶已經登錄了站點 A,并在本地記錄了 cookie
2 . 在用戶沒有登出站點 A 的情況下(也就是 cookie 生效的情況下),訪問了惡意攻擊者提供的引誘危險站點 B (B 站點要求訪問站點A)。
3 . 站點 A 沒有做任何 CSRF 防御
預防 CSRF
CSRF 的防御可以從服務端和客戶端兩方面著手,防御效果是從服務端著手效果比較好,現在一般的 CSRF 防御也都在服務端進行。服務端的預防 CSRF 攻擊的方式方法有多種,但思路上都是差不多的,主要從以下兩個方面入手 :
1 . 正確使用 GET,POST 請求和 cookie
2 . 在非 GET 請求中增加 token
CSRF 的防御可以根據應用場景的不同自行選擇。CSRF 的防御工作確實會在正常業務邏輯的基礎上帶來很多額外的開發量,但是這種工作量是值得的,畢竟用戶隱私以及財產安全是產品最基礎的根本。
SQL 注入漏洞(SQL Injection)是 Web 開發中最常見的一種安全漏洞。攻擊者利用這個漏洞,可以訪問或修改數據,或者利用潛在的數據庫漏洞進行攻擊。
而造成 SQL 注入的原因是因為程序沒有有效的轉義過濾用戶的輸入,使攻擊者成功地向服務器提交惡意的 SQL 查詢代碼,程序在接收后錯誤地將攻擊者的輸入作為查詢語句的一部分執行,導致原始的查詢邏輯被改變,額外的執行了攻擊者精心構造的惡意代碼。
如何預防
防止 SQL 注入主要是不能允許用戶輸入的內容影響正常的 SQL 語句的邏輯,當用戶的輸入信息將要用來拼接 SQL 語句的話,我們應該永遠選擇不相信,任何內容都必須進行轉義過濾,當然做到這個還是不夠的,下面列出防御 SQL 注入的幾點注意事項:
DDoS 又叫分布式拒絕服務,全稱 Distributed Denial of Service。
其原理就是利用大量的請求造成資源過載,導致服務不可用,這個攻擊應該不能算是安全問題,這應該算是一個另類的存在,因為這種攻擊根本就是耍流氓的存在,「傷敵一千,自損八百」的行為。
DDoS 攻擊可以理解為:「你開了一家店,隔壁家店看不慣,就雇了一大堆黑社會人員進你店里干坐著,也不消費,其他客人也進不來,導致你營業慘淡」。
也許你的站點遭受過 DDoS 攻擊,具體什么原因怎么解讀見仁見智。DDos 攻擊從層次上可分為網絡層攻擊與應用層攻擊,從攻擊手法上可分為快型流量攻擊與慢型流量攻擊,但其原理都是造成資源過載,導致服務不可用。
主要分類
應用層的防御有時比網絡層的更難,因為導致應用層被 DDoS 攻擊的因素非常多,有時往往是因為程序員的失誤,導致某個頁面加載需要消耗大量資源,有時是因為中間件配置不當等等。
而應用層 DDoS 防御的核心就是區分人與機器(爬蟲),因為大量的請求不可能是人為的,肯定是機器構造的。因此如果能有效的區分人與爬蟲行為,則可以很好地防御此攻擊。
Web 安全的對于 Web 從業人員來說是一個非常重要的課題。本文介紹了安全世界觀,以及常見Web 相關的三種安全防御知識,希望大家以后的工作中不要誤入踩雷,希望對大家有所幫助!
安全是一門樸素的學問,也是一種平衡的藝術,無論是傳統安全,還是互聯網安全,其內在原理都是一樣的。我們只需抓住安全問題的本質,之后無論遇到任何安全問題,都會無往而不利!
- END -
作者:架構精進之路,專注軟件架構研究,技術學習與個人成長,關注并私信我回復“01”,送你一份程序員成長進階大禮包,歡迎勾搭。
Thanks for reading!
eb 安全地對于 Web 從業人員來說是一個非常重要的課題,所以在這里總結一下 Web 相關的安全攻防知識,希望以后不要再踩雷,也希望對看到這篇文章的同學有所幫助。今天這邊文章主要的內容就是分析幾種常見的攻擊的類型以及防御的方法。
也許你對所有的安全問題都有一定的認識,但最主要的還是在編碼設計的過程中時刻繃緊安全那根弦,需要反復推敲每個實現細節,安全無小事。
本文代碼 Demo 都是基于 Node.js 講解,其他服務端語言同樣可以參考。
首先說下最常見的 XSS 漏洞,XSS (Cross Site Script),跨站腳本攻擊,因為縮寫和 CSS (Cascading Style Sheets) 重疊,所以只能叫 XSS。
XSS 的原理是惡意攻擊者往 Web 頁面里插入惡意可執行網頁腳本代碼,當用戶瀏覽該頁之時,嵌入其中 Web 里面的腳本代碼會被執行,從而可以達到攻擊者盜取用戶信息或其他侵犯用戶安全隱私的目的。XSS 的攻擊方式千變萬化,但還是可以大致細分為幾種類型。
非持久型 XSS 漏洞,也叫反射型 XSS 漏洞,一般是通過給別人發送帶有惡意腳本代碼參數的 URL,當 URL 地址被打開時,特有的惡意代碼參數被 HTML 解析、執行。
舉一個例子,比如你的 Web 頁面中包含有以下代碼:
|
|
攻擊者可以直接通過 URL 注入可執行的腳本代碼。
非持久型 XSS 漏洞攻擊有以下幾點特征:
為了防止出現非持久型 XSS 漏洞,需要確保這么幾件事情:
escape 轉義的目的是將一些構成 HTML 標簽的元素轉義,比如 <,>,空格 等,轉義成 <,>, 等顯示轉義字符。有很多開源的工具可以協助我們做 escape 轉義。
持久型 XSS 漏洞,也被稱為存儲型 XSS 漏洞,一般存在于 Form 表單提交等交互功能,如發帖留言,提交文本信息等,黑客利用的 XSS 漏洞,將內容經正常功能提交進入數據庫持久保存,當前端頁面獲得后端從數據庫中讀出的注入代碼時,恰好將其渲染執行。
主要注入頁面方式和非持久型 XSS 漏洞類似,只不過持久型的不是來源于 URL,refferer,forms 等,而是來源于后端從數據庫中讀出來的數據。持久型 XSS 攻擊不需要誘騙點擊,黑客只需要在提交表單的地方完成注入即可,但是這種 XSS 攻擊的成本相對還是很高。攻擊成功需要同時滿足以下幾個條件:
持久型 XSS 有以下幾個特點:
為了防止持久型 XSS 漏洞,需要前后端共同努力:
其實現在很多的瀏覽器以及各種開源的庫都專門針對了 XSS 進行轉義處理,盡量默認抵御絕大多數 XSS 攻擊,但是還是有很多方式可以繞過轉義規則,讓人防不勝防。比如「基于字符集的 XSS 攻擊」就是繞過這些轉義處理的一種攻擊方式,比如有些 Web 頁面字符集不固定,用戶輸入非期望字符集的字符,有時會繞過轉義過濾規則。
以基于 utf-7 的 XSS 為例
utf-7 是可以將所有的 unicode 通過 7bit 來表示的一種字符集 (但現在已經從 Unicode 規格中移除)。
這個字符集為了通過 7bit 來表示所有的文字, 除去數字和一部分的符號,其它的部分將都以 base64 編碼為基礎的方式呈現。
|
|
可以形成「基于字符集的 XSS 攻擊」的原因是由于瀏覽器在 meta 沒有指定 charset 的時候有自動識別編碼的機制,所以這類攻擊通常就是發生在沒有指定或者沒來得及指定 meta 標簽的 charset 的情況下。
所以我們有什么辦法避免這種 XSS 呢?
基于 Flash 的跨站 XSS 也是屬于反射型 XSS 的一種,雖然現在開發 ActionScript 的產品線幾乎沒有了,但還是提一句吧,AS 腳本可以接受用戶輸入并操作 cookie,攻擊者可以配合其他 XSS(持久型或者非持久型)方法將惡意 swf 文件嵌入頁面中。主要是因為 AS 有時候需要和 JS 傳參交互,攻擊者會通過惡意的 XSS 注入篡改參數,竊取并操作cookie。
避免方法:
有一些場景是后端需要對一個傳進來的待跳轉的 URL 參數進行一個 302 跳轉,可能其中會帶有一些用戶的敏感(cookie)信息。如果服務器端做302 跳轉,跳轉的地址來自用戶的輸入,攻擊者可以輸入一個惡意的跳轉地址來執行腳本。
這時候需要通過以下方式來防止這類漏洞:
CSRF(Cross-Site Request Forgery),中文名稱:跨站請求偽造攻擊
那么 CSRF 到底能夠干嘛呢?你可以這樣簡單的理解:攻擊者可以盜用你的登陸信息,以你的身份模擬發送各種請求。攻擊者只要借助少許的社會工程學得詭計,例如通過 QQ 等聊天軟件發送的鏈接(有些還偽裝成短域名,用戶無法分辨),攻擊者就能迫使 Web 應用的用戶去執行攻擊者預設的操作。例如,當用戶登錄網絡銀行去查看其存款余額,在他沒有退出時,就點擊了一個 QQ 好友發來的鏈接,那么該用戶銀行帳戶中的資金就有可能被轉移到攻擊者指定的帳戶中。
所以遇到 CSRF 攻擊時,將對終端用戶的數據和操作指令構成嚴重的威脅。當受攻擊的終端用戶具有管理員帳戶的時候,CSRF 攻擊將危及整個 Web 應用程序。
下圖大概描述了 CSRF 攻擊的原理,可以理解為有一個小偷在你配鑰匙的地方得到了你家的鑰匙,然后拿著要是去你家想偷什么偷什么。
完成 CSRF 攻擊必須要有三個條件:
你也許會問:「如果我不滿足以上三個條件中的任意一個,就不會受到 CSRF 的攻擊」。其實可以這么說的,但你不能保證以下情況不會發生:
CSRF 的防御可以從服務端和客戶端兩方面著手,防御效果是從服務端著手效果比較好,現在一般的 CSRF 防御也都在服務端進行。服務端的預防 CSRF 攻擊的方式方法有多種,但思路上都是差不多的,主要從以下兩個方面入手:
一般而言,普通的 Web 應用都是以 GET、POST 請求為主,還有一種請求是 cookie 方式。我們一般都是按照如下規則設計應用的請求:
當正確的使用了 GET 和 POST 請求之后,剩下的就是在非 GET 方式的請求中增加隨機數,這個大概有三種方式來進行:
CSRF 的防御可以根據應用場景的不同自行選擇。CSRF 的防御工作確實會在正常業務邏輯的基礎上帶來很多額外的開發量,但是這種工作量是值得的,畢竟用戶隱私以及財產安全是產品最基礎的根本。
SQL 注入漏洞(SQL Injection)是 Web 開發中最常見的一種安全漏洞。可以用它來從數據庫獲取敏感信息,或者利用數據庫的特性執行添加用戶,導出文件等一系列惡意操作,甚至有可能獲取數據庫乃至系統用戶最高權限。
而造成 SQL 注入的原因是因為程序沒有有效的轉義過濾用戶的輸入,使攻擊者成功的向服務器提交惡意的 SQL 查詢代碼,程序在接收后錯誤的將攻擊者的輸入作為查詢語句的一部分執行,導致原始的查詢邏輯被改變,額外的執行了攻擊者精心構造的惡意代碼。
很多 Web 開發者沒有意識到 SQL 查詢是可以被篡改的,從而把 SQL 查詢當作可信任的命令。殊不知,SQL 查詢是可以繞開訪問控制,從而繞過身份驗證和權限檢查的。更有甚者,有可能通過 SQL 查詢去運行主機系統級的命令。
下面將通過一些真實的例子來詳細講解 SQL 注入的方式的原理。
考慮以下簡單的管理員登錄表單:
|
|
后端的 SQL 語句可能是如下這樣的:
|
|
目的就是來驗證用戶名和密碼是不是正確,按理說乍一看上面的 SQL 語句也沒什么毛病,確實是能夠達到我們的目的,可是你只是站在用戶會老老實實按照你的設計來輸入的角度來看問題,如果有一個惡意攻擊者輸入的用戶名是 zoumiaojiang' OR 1 = 1 --,密碼隨意輸入,就可以直接登入系統了。WFT!
冷靜下來思考一下,我們之前預想的真實 SQL 語句是:
|
|
可以惡意攻擊者的奇怪用戶名將你的 SQL 語句變成了如下形式:
|
|
在 SQL 中,-- 是注釋后面的內容的意思,所以查詢語句就變成了:
|
|
這條 SQL 語句的查詢條件永遠為真,所以意思就是惡意攻擊者不用我的密碼,就可以登錄進我的賬號,然后可以在里面為所欲為,然而這還只是最簡單的注入,牛逼的 SQL 注入高手甚至可以通過 SQL 查詢去運行主機系統級的命令,將你主機里的內容一覽無余,這里我也沒有這個能力講解的太深入,畢竟不是專業研究這類攻擊的,但是通過以上的例子,已經了解了 SQL 注入的原理,我們基本已經能找到防御 SQL 注入的方案了。
防止 SQL 注入主要是不能允許用戶輸入的內容影響正常的 SQL 語句的邏輯,當用戶的輸入的信息將要用來拼接 SQL 語句的話,我們應該永遠選擇不相信,任何內容都必須進行轉義過濾,當然做到這個還是不夠的,下面列出防御 SQL 注入的幾點注意事項:
|
|
碰到要操作的數據庫的代碼,一定要慎重,小心使得萬年船,多找幾個人多來幾次 code review,將問題都暴露出來,而且要善于利用工具,操作數據庫相關的代碼屬于機密,沒事不要去各種論壇曬自家站點的 SQL 語句,萬一被人盯上了呢?
命令行注入漏洞,指的是攻擊者能夠通過 HTTP 請求直接侵入主機,執行攻擊者預設的 shell 命令,聽起來好像匪夷所思,這往往是 Web 開發者最容易忽視但是卻是最危險的一個漏洞之一,看一個實例:
假如現在需要實現一個需求:用戶提交一些內容到服務器,然后在服務器執行一些系統命令去產出一個結果返回給用戶,接口的部分實現如下:
|
|
這段代碼確實能夠滿足業務需求,正常的用戶也確實能從指定的 git repo 上下載到想要的代碼,可是和 SQL 注入一樣,這段代碼在惡意攻擊者眼中,簡直就是香餑餑。
如果 params.repo 傳入的是 https://github.com/zoumiaojiang/zoumiaojiang.github.io.git 當然沒問題了。
可是如果 params.repo 傳入的是 https://github.com/xx/xx.git && rm -rf /* && 恰好你的服務是用 root 權限起的就慘了。
具體惡意攻擊者能用命令行注入干什么也像 SQL 注入一樣,手法是千變萬化的,比如「反彈 shell 注入」等,但原理都是一樣的,我們絕對有能力防止命令行注入發生。防止命令行注入需要做到以下幾件事情:
還是前面的例子,我們可以做到如下:
|
|
無論是在何種后端語言環境中,凡是涉及到代碼調用系統 shell 命令的時候都一定要謹慎。
DDoS 又叫分布式拒絕服務,全稱 Distributed Denial of Service,其原理就是利用大量的請求造成資源過載,導致服務不可用,這個攻擊應該不能算是安全問題,這應該算是一個另類的存在,因為這種攻擊根本就是耍流氓的存在,「傷敵一千,自損八百」的行為。出于保護 Web App 不受攻擊的攻防角度,還是介紹一下 DDoS 攻擊吧,畢竟也是挺常見的。
DDoS 攻擊可以理解為:「你開了一家店,隔壁家點看不慣,就雇了一大堆黑社會人員進你店里干坐著,也不消費,其他客人也進不來,導致你營業慘淡」。為啥說 DDoS 是個「傷敵一千,自損八百」的行為呢?畢竟隔壁店還是花了不少錢雇黑社會但是啥也沒得到不是?DDoS 攻擊的目的基本上就以下幾個:
也許你的站點遭受過 DDoS 攻擊,具體什么原因怎么解讀見仁見智。DDos 攻擊從層次上可分為網絡層攻擊與應用層攻擊,從攻擊手法上可分為快型流量攻擊與慢型流量攻擊,但其原理都是造成資源過載,導致服務不可用。
網絡層 DDos 攻擊包括 SYN Flood、ACK Flood、UDP Flood、ICMP Flood 等。
SYN Flood 攻擊
SYN flood 攻擊主要利用了 TCP 三次握手過程中的 Bug,我們都知道 TCP 三次握手過程是要建立連接的雙方發送 SYN,SYN + ACK,ACK 數據包,而當攻擊方隨意構造源 IP 去發送 SYN 包時,服務器返回的 SYN + ACK 就不能得到應答(因為 IP 是隨意構造的),此時服務器就會嘗試重新發送,并且會有至少 30s 的等待時間,導致資源飽和服務不可用,此攻擊屬于慢性 DDoS 攻擊。
ACK Flood 攻擊
ACK Flood 攻擊是在 TCP 連接建立之后,所有的數據傳輸 TCP 報文都是帶有 ACK 標志位的,主機在接收到一個帶有 ACK 標志位的數據包的時候,需要檢查該數據包所表示的連接四元組是否存在,如果存在則檢查該數據包所表示的狀態是否合法,然后再向應用層傳遞該數據包。如果在檢查中發現該數據包不合法,例如該數據包所指向的目的端口在本機并未開放,則主機操作系統協議棧會回應 RST 包告訴對方此端口不存在。
UDP Flood 攻擊
UDP flood 攻擊是由于 UDP 是一種無連接的協議,因此攻擊者可以偽造大量的源 IP 地址去發送 UDP 包,此種攻擊屬于大流量攻擊。正常應用情況下,UDP 包雙向流量會基本相等,因此發起這種攻擊的攻擊者在消耗對方資源的時候也在消耗自己的資源。
ICMP Flood 攻擊
ICMP Flood 攻擊屬于大流量攻擊,其原理就是不斷發送不正常的 ICMP 包(所謂不正常就是 ICMP 包內容很大),導致目標帶寬被占用,但其本身資源也會被消耗。目前很多服務器都是禁 ping 的(在防火墻外可以屏蔽 ICMP 包),因此這種攻擊方式已經落伍。
網絡層的 DDoS 攻擊究其本質其實是無法防御的,我們能做得就是不斷優化服務本身部署的網絡架構,以及提升網絡帶寬。當然,還是做好以下幾件事也是有助于緩解網絡層 DDoS 攻擊的沖擊:
應用層 DDoS 攻擊不是發生在網絡層,是發生在 TCP 建立握手成功之后,應用程序處理請求的時候,現在很多常見的 DDoS 攻擊都是應用層攻擊。應用層攻擊千變萬化,目的就是在網絡應用層耗盡你的帶寬,下面列出集中典型的攻擊類型。
CC 攻擊
當時綠盟為了防御 DDoS 攻擊研發了一款叫做 Collapasar 的產品,能夠有效的防御 SYN Flood 攻擊。黑客為了挑釁,研發了一款 Challenge Collapasar 攻擊工具(簡稱 CC)。
CC 攻擊的原理,就是針對消耗資源比較大的頁面不斷發起不正常的請求,導致資源耗盡。因此在發送 CC 攻擊前,我們需要尋找加載比較慢,消耗資源比較多的網頁,比如需要查詢數據庫的頁面、讀寫硬盤文件的等。通過 CC 攻擊,使用爬蟲對某些加載需要消耗大量資源的頁面發起 HTTP 請求。
DNS Flood
DNS Flood 攻擊采用的方法是向被攻擊的服務器發送大量的域名解析請求,通常請求解析的域名是隨機生成或者是網絡世界上根本不存在的域名,被攻擊的DNS 服務器在接收到域名解析請求的時候首先會在服務器上查找是否有對應的緩存,如果查找不到并且該域名無法直接由服務器解析的時候,DNS 服務器會向其上層 DNS 服務器遞歸查詢域名信息。域名解析的過程給服務器帶來了很大的負載,每秒鐘域名解析請求超過一定的數量就會造成 DNS 服務器解析域名超時。
根據微軟的統計數據,一臺 DNS 服務器所能承受的動態域名查詢的上限是每秒鐘 9000 個請求。而我們知道,在一臺 P3 的 PC 機上可以輕易地構造出每秒鐘幾萬個域名解析請求,足以使一臺硬件配置極高的 DNS 服務器癱瘓,由此可見 DNS 服務器的脆弱性。
HTTP 慢速連接攻擊
針對 HTTP 協議,先建立起 HTTP 連接,設置一個較大的 Conetnt-Length,每次只發送很少的字節,讓服務器一直以為 HTTP 頭部沒有傳輸完成,這樣連接一多就很快會出現連接耗盡。
應用層的防御有時比網絡層的更難,因為導致應用層被 DDoS 攻擊的因素非常多,有時往往是因為程序員的失誤,導致某個頁面加載需要消耗大量資源,有時是因為中間件配置不當等等。而應用層 DDoS 防御的核心就是區分人與機器(爬蟲),因為大量的請求不可能是人為的,肯定是機器構造的。因此如果能有效的區分人與爬蟲行為,則可以很好地防御此攻擊。
發起 DDoS 也是需要大量的帶寬資源的,但是互聯網就像森林,林子大了什么鳥都有,DDoS 攻擊者也能找到其他的方式發起廉價并且極具殺傷力的 DDoS 攻擊。
利用 XSS
舉個例子,如果 12306 頁面有一個 XSS 持久型漏洞被惡意攻擊者發現,只需在春節搶票期間在這個漏洞中執行腳本使得往某一個小站點隨便發點什么請求,然后隨著用戶訪問的增多,感染用戶增多,被攻擊的站點自然就會迅速癱瘓了。這種 DDoS 簡直就是無本萬利,不用驚訝,現在大站有 XSS 漏洞的不要太多。
來自 P2P 網絡攻擊
大家都知道,互聯網上的 P2P 用戶和流量都是一個極為龐大的數字。如果他們都去一個指定的地方下載數據,成千上萬的真實 IP 地址連接過來,沒有哪個設備能夠支撐住。那 BT 下載來說,偽造一些熱門視頻的種子,發布到搜索引擎,就足以騙到許多用戶和流量了,但是這只是基礎攻擊。
高級的 P2P 攻擊,是直接欺騙資源管理服務器。如迅雷客戶端會把自己發現的資源上傳到資源管理服務器,然后推送給其它需要下載相同資源的用戶,這樣,一個鏈接就發布出去。通過協議逆向,攻擊者偽造出大批量的熱門資源信息通過資源管理中心分發出去,瞬間就可以傳遍整個 P2P 網絡。更為恐怖的是,這種攻擊是無法停止的,即使是攻擊者自身也無法停止,攻擊一直持續到 P2P 官方發現問題更新服務器且下載用戶重啟下載軟件為止。
最后總結下,DDoS 不可能防得住,就好比你的店只能容納 50 人,黑社會有 100 人,你就換一家大店,能容納 500 人,然后黑社會又找來了 1000 人,這種堆人頭的做法就是 DDoS 本質上的攻防之道,「道高一尺,魔高一丈,魔高一尺,道高一丈」,講真,必要的時候就答應勒索你的人的條件吧,實在不行就報警吧。
流量劫持應該算是黑產行業的一大經濟支柱了吧?簡直是讓人惡心到吐,不吐槽了,還是繼續談干貨吧,流量劫持基本分兩種:DNS 劫持 和 HTTP 劫持,目的都是一樣的,就是當用戶訪問網站的時候,給你展示的并不是或者不完全是 網站 提供的 “內容”。
DNS 劫持,也叫做域名劫持,可以這么理解,「你打了一輛車想去商場吃飯,結果你打的車是小作坊派來的,直接給你拉到小作坊去了」,DNS 的作用是把網絡地址域名對應到真實的計算機能夠識別的 IP 地址,以便計算機能夠進一步通信,傳遞網址和內容等。如果當用戶通過某一個域名訪問一個站點的時候,被篡改的 DNS 服務器返回的是一個惡意的釣魚站點的 IP,用戶就被劫持到了惡意釣魚站點,然后繼而會被釣魚輸入各種賬號密碼信息,泄漏隱私。
這類劫持,要不就是網絡運營商搞的鬼,一般小的網絡運營商與黑產勾結會劫持 DNS,要不就是電腦中毒,被惡意篡改了路由器的 DNS 配置,基本上做為開發者或站長卻是很難察覺的,除非有用戶反饋,現在升級版的 DNS 劫持還可以對特定用戶、特定區域等使用了用戶畫像進行篩選用戶劫持的辦法,另外這類廣告顯示更加隨機更小,一般站長除非用戶投訴否則很難覺察到,就算覺察到了取證舉報更難。無論如何,如果接到有 DNS 劫持的反饋,一定要做好以下幾件事:
HTTP 劫持您可以這么理解,「你打了一輛車想去商場吃飯,結果司機跟你一路給你遞小作坊的廣告」,HTTP 劫持主要是當用戶訪問某個站點的時候會經過運營商網絡,而不法運營商和黑產勾結能夠截獲 HTTP 請求返回內容,并且能夠篡改內容,然后再返回給用戶,從而實現劫持頁面,輕則插入小廣告,重則直接篡改成釣魚網站頁面騙用戶隱私。能夠實施流量劫持的根本原因,是 HTTP 協議沒有辦法對通信對方的身份進行校驗以及對數據完整性進行校驗。如果能解決這個問題,則流量劫持將無法輕易發生。所以防止 HTTP 劫持的方法只有將內容加密,讓劫持者無法破解篡改,這樣就可以防止 HTTP 劫持了。
HTTPS 協議就是一種基于 SSL 協議的安全加密網絡應用層協議,可以很好的防止 HTTP 劫持。這里有篇 文章 講的不錯。HTTPS 在這就不深講了,后面有機會我會單獨好好講講 HTTPS。如果不想站點被 HTTP 劫持,趕緊將你的站點全站改造成 HTTPS 吧。
服務器除了以上提到的那些大名鼎鼎的漏洞和臭名昭著的攻擊以外,其實還有很多其他的漏洞,往往也很容易被忽視,在這個小節也稍微介紹幾種。
如果你的系統是有登錄控制的,那就要格外小心了,因為很有可能你的系統越權操作漏洞,越權操作漏洞可以簡單的總結為 「A 用戶能看到或者操作 B 用戶的隱私內容」,如果你的系統中還有權限控制就更加需要小心了。所以每一個請求都需要做 userid 的判斷
以下是一段有漏洞的后端示意代碼:
|
|
以上代碼是任何人都可以查詢到任何用戶的消息,只要有 msg_id 就可以,這就是比較典型的越權漏洞,需要如下這么改進一下:
|
|
嗯,大概就是這個意思,如果有更嚴格的權限控制,那在每個請求中凡是涉及到數據庫的操作都需要先進行嚴格的驗證,并且在設計數據庫表的時候需要考慮進 userId 的賬號關聯以及權限關聯。
目錄遍歷漏洞指通過在 URL 或參數中構造 ../,./ 和類似的跨父目錄字符串的 ASCII 編碼、unicode 編碼等,完成目錄跳轉,讀取操作系統各個目錄下的敏感文件,也可以稱作「任意文件讀取漏洞」。
目錄遍歷漏洞原理:程序沒有充分過濾用戶輸入的 ../ 之類的目錄跳轉符,導致用戶可以通過提交目錄跳轉來遍歷服務器上的任意文件。使用多個.. 符號,不斷向上跳轉,最終停留在根 /,通過絕對路徑去讀取任意文件。
目錄遍歷漏洞幾個示例和測試,一般構造 URL 然后使用瀏覽器直接訪問,或者使用 Web 漏洞掃描工具檢測,當然也可以自寫程序測試。
|
|
防御 方法就是需要對 URL 或者參數進行 ../,./ 等字符的轉義過濾。
物理路徑泄露屬于低風險等級缺陷,它的危害一般被描述為「攻擊者可以利用此漏洞得到信息,來對系統進一步地攻擊」,通常都是系統報錯 500 的錯誤信息直接返回到頁面可見導致的漏洞。得到物理路徑有些時候它能給攻擊者帶來一些有用的信息,比如說:可以大致了解系統的文件目錄結構;可以看出系統所使用的第三方軟件;也說不定會得到一個合法的用戶名(因為很多人把自己的用戶名作為網站的目錄名)。
防止這種泄漏的方法就是做好后端程序的出錯處理,定制特殊的 500 報錯頁面。
和物理路徑泄露類似,就是攻擊者可以通過請求直接獲取到你站點的后端源代碼,然后就可以對系統進一步研究攻擊。那么導致源代碼暴露的原因是什么呢?基本上就是發生在服務器配置上了,服務器可以設置哪些路徑的文件才可以被直接訪問的,這里給一個 koa 服務器的例子,正常的 koa 服務器可以通過 koa-static 中間件去指定靜態資源的目錄,好讓靜態資源可以通過路徑的路由訪問。比如你的系統源代碼目錄是這樣的:
|
|
你想要將 static 的文件夾配成靜態資源目錄,你應該會在 server.js 做如下配置:
|
|
但是如果配錯了靜態資源的目錄,可能就出大事了,比如:
|
|
這樣所有的源代碼都可以通過路由訪問到了,所有的服務器都提供了靜態資源機制,所以在通過服務器配置靜態資源目錄和路徑的時候,一定要注意檢驗,不然很可能產生漏洞。
最后,希望 Web 開發者們能夠管理好自己的代碼隱私,注意代碼安全問題,比如不要將產品的含有敏感信息的代碼放到第三方外部站點或者暴露給外部用戶,尤其是前端代碼,私鑰類似的保密性的東西不要直接輸出在代碼里或者頁面中。也許還有很多值得注意的點,但是歸根結底還是繃住安全那根弦,對待每一行代碼都要多多推敲。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。