新聞中心
本文轉(zhuǎn)載自微信公眾號「HelloGitHub」,作者Teo Selenius。轉(zhuǎn)載本文請聯(lián)系HelloGitHub公眾號。

成都創(chuàng)新互聯(lián)公司長期為上千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為萬柏林企業(yè)提供專業(yè)的成都網(wǎng)站制作、做網(wǎng)站,萬柏林網(wǎng)站改版等技術(shù)服務(wù)。擁有十載豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
對于開發(fā)者而言,網(wǎng)絡(luò)安全的重要性不言而喻。任何一處代碼錯誤、一個依賴項(xiàng)漏洞或是數(shù)據(jù)庫的端口暴露到公網(wǎng),都會有可能直接送你上熱搜。
那么,哪里可以找到詳細(xì)的避雷指引呢?OWASP's top 10 清單太短了,而且它更關(guān)注的是漏洞羅列,而非對預(yù)防。相比之下,ASVS 是個很好的列表,但還是滿足不了實(shí)際需求。
本文這份清單將介紹 72 個實(shí)操要點(diǎn),讓你全方位保護(hù)你的 Web 應(yīng)用程序。各位看官,準(zhǔn)備入坑啦!
一、瀏覽器端的威脅防御
1、用且僅用 HTTPS,防范網(wǎng)絡(luò)攻擊
眾所周知,一個安全的應(yīng)用需要對瀏覽器和 Web 服務(wù)器之間的所有連接進(jìn)行加密。此外,建議禁用一些舊的密碼套件和協(xié)議。使用 HTTPS 時,僅加密網(wǎng)站的“敏感”部分是不夠的。如非這樣,攻擊者可以截獲某個未加密的 HTTP 請求,然后偽造來自服務(wù)器的響應(yīng),返回惡意內(nèi)容。幸運(yùn)的是,HTTPS 目前是很容易做到的。我們可以通過 Let's Encrypt 免費(fèi)獲得證書,加上 CertBot 免費(fèi)續(xù)期。
繼續(xù)我們的清單,下一個是 HSTS 它與 HTTPS 密切相關(guān)。
2、使用 HSTS 和預(yù)加載來保護(hù)用戶免受 SSL 剝離攻擊
服務(wù)器可以用 HSTS 或 Strict Transport Security header 來強(qiáng)制進(jìn)行加密連接。它表示需要一直使用 HTTPS 連接訪問網(wǎng)站。
HSTS 可以防止 SSL 剝離攻擊。所謂的 SSL 剝離攻擊也就是:網(wǎng)絡(luò)上的攻擊者截獲瀏覽器發(fā)出的第一個 HTTP 請求(通常是未加密的),并立即偽造對該請求的回復(fù),假裝是服務(wù)器并將連接降級為明文 HTTP。
值得注意的是,HSTS 僅在用戶至少成功訪問了一次應(yīng)用程序的情況下才能生效。為了克服這個限制,可以把我們的網(wǎng)站提交到 https://hstspreload.org ,這樣,各瀏覽器便可以將我們的域名通過硬編碼寫入到 HSTS 列表中。
如下:
- Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
警告:
在實(shí)施 HSTS 時,將會強(qiáng)制進(jìn)出該網(wǎng)站的所有網(wǎng)絡(luò)請求均被加密,如果網(wǎng)站請求中仍然有純文本,可能無法訪問。所以,先設(shè)置一個小的 max-age 參數(shù)進(jìn)行調(diào)試,如果一切正常工作,再加大這個值。調(diào)試成功后再加上預(yù)加載 (preload) ,把開啟預(yù)加載保留在最后一步,因?yàn)殛P(guān)閉它是件很麻煩和痛苦的事情。
3、設(shè)置安全 Cookie,保護(hù)用戶免受網(wǎng)絡(luò)攻擊
給 Cookie 加上 Secure 屬性。此屬性將防止 Cookie 在(意外或強(qiáng)制的)未加密的連接中泄漏。
Set-Cookie: foo=bar; ...other options... Secure
4、安全生成 HTML 以避免 XSS 漏洞
要避免 XSS(跨站點(diǎn)腳本)漏洞,可以采用下面兩種方法:
- 完全靜態(tài)的網(wǎng)站(例如 JavaScript SPA + 后端API)。避免生成 HTML 問題的最有效方法是根本不生成HTML,如前述方法,當(dāng)然,也可以試試很酷的 NexJS。
- 模板引擎。針對傳統(tǒng)的 Web 應(yīng)用程序,其中的 HTML 大多是在后端服務(wù)器上根據(jù)提供參數(shù)動態(tài)生成的。這種情況下,不要通過字符串連接來創(chuàng)建 HTML 。推薦的做法是使用模板引擎,比如 PHP 語言的 Twig、Java 語言的 Thymeleaf、Python 語言的 Jinja2 等等。
此外,務(wù)必要正確配置模板引擎,從而可以自動對參數(shù)進(jìn)行編碼,并且不要使用任何可以繞過這種編碼的“不安全”函數(shù)。不要把 HTML 放在回調(diào)函數(shù)、屬性(不帶引號)或 href/src 等諸如此類的地方。
5、安全使用 JavaScript 以避免 XSS 漏洞
要避免 JavaScript 端的 XSS(跨站點(diǎn)腳本)漏洞,切忌將不受信任的數(shù)據(jù)傳遞到可執(zhí)行代碼的函數(shù)或?qū)傩灾?。這類常見的函數(shù)或?qū)傩园ǎ?/p>
- eval、setTimeout、setInterval 等。
- innerHTML,React's dangerouslySetInnerHTML 等。
- onClick、onMouseEnter、onError 等。
- href、src 等。
- location, location.href 等。
6、沙箱處理不可信內(nèi)容,避免 XSS 漏洞
最好是能避免不可信的內(nèi)容,但往往又不能完全避免:例如需要從遠(yuǎn)程獲取 HTML 進(jìn)行展示,或者需要允許用戶用所見即所得的編輯器寫文章,等等。
要避免這些場景中的 XSS(跨站點(diǎn)腳本)漏洞,請首先使用 DOMPurify 清理內(nèi)容,然后在沙箱中進(jìn)行內(nèi)容呈現(xiàn)。
即使所見即所得的編輯庫聲稱從 HTML 中移除了惡意內(nèi)容,仍然可以通過重新凈化和沙箱來處理,進(jìn)一步確保安全。
還有一種常見的情況是,我們想在網(wǎng)頁展示廣告等內(nèi)容。這種情況下簡單采用 IFrame 是不夠的,因?yàn)?same-origin 策略會允許跨域的 frame 將父級 frame (也就是我們的網(wǎng)站)的 URL 修改為一個釣魚網(wǎng)站。因此,要記住使用 IFrame 的沙箱屬性來避免此種情況的發(fā)生。
7、采用內(nèi)容安全策略,避免 XSS 漏洞
內(nèi)容安全策略(CSP)可以很好地防御 XSS(跨站點(diǎn)腳本)攻擊、點(diǎn)擊劫持攻擊等。所以,一定要用它!默認(rèn)情況下,CSP 會阻止幾乎所有的危險操作,所以額外的配置越少越好。如下:
- Content-Security-Policy: default-src 'self'; form-action 'self'; object-src 'none'
它允許從 Web 應(yīng)用程序的源代碼加載腳本、樣式、圖像、字體等,但不允許加載其他內(nèi)容。最值得注意的是,它將阻止內(nèi)聯(lián)腳本()的運(yùn)行,從而更好地預(yù)防 XSS 漏洞。
此外,form-action:'self' 指令可防止在網(wǎng)站上創(chuàng)建惡意 HTML 表單(比如“您的會話已過期,請?jiān)诖颂庉斎朊艽a”類似的表單),并將其提交到攻擊者的服務(wù)器。
無論如何,都不要指定 script-src: unsafe inline ,一旦這樣做,CSP 將形同虛設(shè)。
最后,如果你擔(dān)心 CSP 會影響生產(chǎn)環(huán)境,可以先以 Report-Only 模式進(jìn)行部署:
- Content-Security-Policy-Report-Only: default-src 'self'; form-action 'self'
8、設(shè)置 HttpOnly 的 Cookie,保護(hù)用戶免受 XSS 攻擊
為 Cookie 設(shè)置 HttpOnly 屬性,可以防止 Cookie 被 JavaScript 代碼訪問。一旦跨腳本攻擊發(fā)生,該設(shè)置也會讓黑客更難竊取到 Cookie 信息。當(dāng)然,有些需要被 JavaScript 代碼訪問的 Cookie,就不能做這個設(shè)置了。
- Set-Cookie: foo=bar; ...other options... HttpOnly
9、針對下載功能,合理設(shè)置避免 XSS 漏洞
向用戶提供下載功能時,在 header 中設(shè)置 Content-Disposition: attachment,從而避免 XSS 漏洞。該設(shè)置將禁止在用戶瀏覽器直接渲染文件,從而避免 HTML 或 SVG 格式的下載文件可能引發(fā)的漏洞。如下:
- Content-Disposition: attachment; filename="document.pdf"
假如我們想允許特定的文件(如 pdf)能在瀏覽器端打開,并且也確定這樣是安全的,那么,可以針對該類型文件,將 header 省略掉或是將 attachment 換為 inline。
10、針對 API 響應(yīng),合理設(shè)置避免 XSS 漏洞
反射型文件下載(RFD)攻擊往往通過構(gòu)建一個 URL 從 API 下載一個惡意文件來實(shí)現(xiàn)。針對該類漏洞,可采用在 API HTTP 響應(yīng)中返回帶有安全文件名的 Content-Disposition header來防御。
11、利用現(xiàn)有平臺的反跨站請求偽造(CSRF)機(jī)制,避免 CSRF 漏洞
為避免反跨站請求偽造漏洞,務(wù)必確保我們所采用的平臺開啟了反跨站請求偽造功能,并確保該配置發(fā)揮了應(yīng)有的作用。
12、驗(yàn)證 OAuth 身份認(rèn)證的 state 參數(shù),避免 CSRF 漏洞
有一類與 OAuth 身份認(rèn)證相關(guān)的跨站請求偽造漏洞是黑客讓用戶不經(jīng)意間采用其賬戶進(jìn)行登錄。因此,如果有使用 OAuth 身份認(rèn)證,務(wù)必確保對狀態(tài)(state)參數(shù)的驗(yàn)證。
13、正確使用 HTTP 協(xié)議,避免 CSRF 漏洞
除了 POST、PUT、PATCH、DELETE 以外,不要使用其它 HTTP 方法進(jìn)行數(shù)據(jù)更改。GET 請求一般是不包含在反跨站請求偽造機(jī)制中的。
14、為 Cookie 設(shè)置同源屬性,避免 CSRF、XS-leak、XSS 漏洞
為 Cookie 設(shè)置 SameSite 屬性。SameSite 能防止大多數(shù)的跨站點(diǎn)請求偽造攻擊,而且還可以防止許多跨站點(diǎn)泄漏的漏洞。
SameSite 屬性有兩種模式:寬松(lax)和嚴(yán)格(strict)。
寬松模式可以防止大多數(shù)跨站點(diǎn)計(jì)時和跨站點(diǎn)請求偽造攻擊,但對基于 Get 請求的跨站點(diǎn)請求偽造漏洞無效。如下:
- Set-Cookie: foo=bar; ...other options... SameSite=Lax
嚴(yán)格模式則可以防止該類基于 Get 請求的漏洞,以及反射型的跨站點(diǎn)腳本漏洞。然而,嚴(yán)格模式不適合常規(guī)的應(yīng)用程序,因?yàn)樗鼤袛嗌矸蒡?yàn)證鏈接。如果用戶已登錄某個網(wǎng)站,現(xiàn)在要在新的頁面打開指向該應(yīng)用程序的鏈接,則打開的新頁面將不會為該用戶自動登錄。由于嚴(yán)格模式的限制,會話 Cookie 也不會隨請求一起發(fā)送。嚴(yán)格模式設(shè)置如下:
- Set-Cookie: foo=bar; ...other options... SameSite=Strict
15、每次登錄創(chuàng)建一個新的會話 ID,防止會話固定攻擊
會話固定攻擊一般是在以下情形發(fā)生:
- 攻擊者將 Cookie(例如 JSESSIONID=ABC123)注入到用戶的瀏覽器中。
- 用戶使用其憑據(jù)登錄,并在登錄請求中提交攻擊者設(shè)置的 JSESSIONID=ABC123 。
- 應(yīng)用程序?qū)?Cookie 和用戶進(jìn)行身份驗(yàn)證。
- 與此同時,擁有該 Cookie 的攻擊者也就可以通過該用戶的身份進(jìn)行登錄了。
為了防止出現(xiàn)這種情況,程序中需要在身份驗(yàn)證通過后,創(chuàng)建一個新的會話 ID 返回給用戶,而不是驗(yàn)證可能被動了手腳的 Cookie。
16、合理命名 Cookie,防止會話固定攻擊
難道 Cookie 命名也能影響到網(wǎng)絡(luò)應(yīng)用程序的安全性?確實(shí)如此!將 Cookie 采用 __Host-** 的形式來命名,瀏覽器將:
- 不能通過非加密的鏈接訪問該項(xiàng) Cookie, 從而避免會話固定攻擊以及其它涉及到 Cookie 讀取與寫入的攻擊;
- 不允許子域名重寫該項(xiàng) Cookie,從而避免來自子域名網(wǎng)站(抑或是被攻陷,抑或本身就是惡意的)的攻擊。
該項(xiàng)設(shè)置示例如下:
- Set-Cookie: __Host-foo=bar ...other options...
17、設(shè)置 Cache-Control header,防止用戶信息被竊取
緩存是將訪問過的網(wǎng)站、下載過的文件全部存儲在硬盤的某個位置,直到有人手動刪除它們。默認(rèn)情況下,瀏覽器會對頁面的一切內(nèi)容進(jìn)行緩存,從而加快訪問速度、節(jié)約網(wǎng)絡(luò)帶寬。
要在公共網(wǎng)絡(luò)環(huán)境保證信息安全,我們需要將所有 HTTP 響應(yīng)設(shè)置一個合適的 Cache-Control header,特別是針對非公開的和動態(tài)的內(nèi)容。
該項(xiàng)設(shè)置示例如下:
- Cache-Control: no-store, max-age=0
18、設(shè)置 Clear-Site-Data header,防止用戶信息被竊取
另外一個可以有效保證用戶退出后記錄即被清除的 header 是 Clear-Site-Data 。當(dāng)用戶退出登錄時,可以在 HTTP 請求中攜帶該 header。瀏覽器會清除該域名下的緩存、Cookie、存儲以及執(zhí)行上下文。大部分瀏覽器都支持該 header。
該項(xiàng)設(shè)置示例如下:
- Clear-Site-Data: "*"
19、妥當(dāng)?shù)靥幚怼巴顺觥?,防止用戶信息被竊取
用戶退出登錄后,務(wù)必要對訪問令牌和會話識別碼進(jìn)行失效處理。這樣,即使攻擊者從訪問歷史/緩存/內(nèi)存等地方獲取到這些信息,它們也不再有效。
此外,如果有單點(diǎn)登錄,切記要調(diào)用單點(diǎn)登錄的退出端口。否則,因?yàn)閱吸c(diǎn)登錄會話仍處于活躍狀態(tài),此時的退出將會無效,只要用戶再次點(diǎn)擊“登錄”,即可自動登錄。
最后,清理掉你可能用到過的 Cookie、HTML5 存儲等。上面提到的 Clear-Site-Data 還未被某些瀏覽器支持,所以最好還是手工清除一下。
20、針對 JavaScript 密碼采用 SessionStorage,防止用戶信息被后來者竊取
SessionStorage 類似于 LocalStorage,但對每個標(biāo)簽頁都是獨(dú)有的,而且在瀏覽器/標(biāo)簽頁關(guān)閉以后將自動清除。
注意:如果要在系統(tǒng)內(nèi)打開的多個標(biāo)簽頁之間同步用戶的授權(quán)信息,那就需要用事件來同步 sessionStorage 信息。
21、不要通過 URL 傳輸敏感信息
URL 設(shè)計(jì)的初衷就不是為了傳輸敏感信息。它會被顯示在屏幕上,存儲到瀏覽器歷史記錄,也容易隨 referrer header 而泄漏,被記錄在服務(wù)器日志等。所以,切忌在 URL 中傳遞敏感信息。
22、采用 Referrer 策略,防止 URL 地址泄露
默認(rèn)情況下,當(dāng)從系統(tǒng)中鏈接到一個外部網(wǎng)站時,瀏覽器會設(shè)置一個 Referrer 的 header 來告訴該網(wǎng)站此次訪問的來源。這個 header 包含了整個 URL 地址,這可能就涉及到一點(diǎn)隱私。
可以在 HTTP 響應(yīng)中設(shè)置一個 Referrer-Policy 的 header 來禁止該默認(rèn)行為:
- Referrer-Policy: no-referrer
23、為應(yīng)用設(shè)置獨(dú)立域名,防止同源應(yīng)用相互干擾
如果我們這樣設(shè)置應(yīng)用域名:https://www.cdxwcx.com/app1/ 和 https://www.cdxwcx.com/app2/,是非常危險的。因?yàn)闉g覽器會認(rèn)為它們是同源應(yīng)用,也就是同樣的服務(wù)主機(jī)、端口和模式。正因?yàn)槭峭磻?yīng)用,它們將對彼此有完全的訪問權(quán)限。任何影響其中一個的漏洞都會同樣影響到另外一個。
因此,我們需要給每個應(yīng)用一個獨(dú)立的域名。所以,這種情況下應(yīng)該設(shè)置為:https://app1.cdxwcx.com/ 和 https://app2.cdxwcx.com/
注意:位于同一個域名下的子域名是可以為整個域名設(shè)置 Cookie 的。例如 app1.cdxwcx.com 可以為 cdxwcx.com 設(shè)置 Cookie,而這個 Cookie 也將適用于 app2.cdxwcx.com。允許為一個站點(diǎn)設(shè)置 Cookie 有時會給會話固定等類型的漏洞以可乘之機(jī)。公共后綴列表可以用來應(yīng)對該問題。此外,也可以通過將 Cookie 命名為 __Host- 來防止其被子域名所覆蓋。
24、謹(jǐn)慎采用 CORS(跨域資源共享)
瀏覽器的安全模型大部分是依賴于同源策略,它可以防止應(yīng)用的跨域讀取。而 CORS(跨域資源共享)則是一種允許網(wǎng)站進(jìn)行跨域資源訪問的手段。所以,決定使用它之前,最好先搞清楚自己是否真的需要。
25、限制請求來源
如果你在 api.cdxwcx.com 的服務(wù)需要被來自 www.cdxwcx.com 的 GET 請求訪問,那么可以在 api.cdxwcx.com 服務(wù)上指定如下header:
- Access-Control-Allow-Origin: https://www.cdxwcx.com
如果你有個公開的服務(wù)接口(比如說一個提供給互聯(lián)網(wǎng)上 JavaScript 客戶端使用的計(jì)算器服務(wù)),那么你可以指定一個隨機(jī)的來源:
- Access-Control-Allow-Origin: *
如果你只想讓有限的幾個域名訪問它,那么可以在程序中讀取請求的 Origin header,進(jìn)行比對后處理。不過,建議使用現(xiàn)成的庫來操作,不要徒手?jǐn)],很容易出錯。
26、謹(jǐn)慎使用 allow credentials 選項(xiàng)
默認(rèn)情況下,跨域資源共享是不帶用戶憑證的。但如果在 Web 服務(wù)器端指定如下 header,則將允許攜帶:
- Access-Control-Allow-Origin: https://www.cdxwcx.com
- Access-Control-Allow-Credentials: true
這對 header 組合相當(dāng)危險。因?yàn)樗鼤箍缬蛟L問具備已登錄用戶的權(quán)限,并使用該權(quán)限來訪問網(wǎng)站資源。所以,如果你不得不使用它,務(wù)必小心為上。
27、對 HTTP method 進(jìn)行驗(yàn)證
僅允許所需要的 HTTP 方法,從而最小化攻擊面。
- Access-Control-Allow-Methods: GET
28、合理使用 WebSockets, 避免反跨站請求偽造等漏洞
WebSockets 迄今還是比較新的技術(shù),技術(shù)文檔較少使用它難免會有些風(fēng)險。所以,采用時務(wù)必要做到以下幾點(diǎn):
- 對連接進(jìn)行加密
就像我們應(yīng)該用 https:// 而非 http:// 采用 WebSockets 時也要使用 wss:// 而非 ws://
HSTS 也會影響 WebSockets ,它會自動將非加密的 WebSocket 連接升級到 wss://
- 對連接進(jìn)行鑒權(quán)
如果使用的是基于 Cookie 的鑒權(quán)機(jī)制,且 WebSocket 服務(wù)器與應(yīng)用服務(wù)器在同一個域名下,那就可以在 WebSocket 中繼續(xù)使用已有的會話。不過切記要對請求源進(jìn)行驗(yàn)證!
如果不是基于 Cookie ,可以在系統(tǒng)中創(chuàng)建一個單次使用、有時間限制并與用戶 IP 綁定的授權(quán)令牌,用該令牌對 WebSocket 進(jìn)行授權(quán)。
- 對連接源進(jìn)行確認(rèn)
理解 WebSockets 的一個關(guān)鍵點(diǎn)在于要知道同源策略對其是無效的。任何一個能與你的系統(tǒng)建立 WebSocket 連接的網(wǎng)站,在使用 Cookie 鑒權(quán)的時候,都是可以直接獲得用戶信息的。因此,在 WebSocket 握手時,必須要確認(rèn)連接源??梢酝ㄟ^驗(yàn)證請求頭中的 Origin 參數(shù)來確認(rèn)。
如果想要做到雙重保險,可以采用反跨站請求偽造令牌作為 URL 參數(shù)。但針對每個任務(wù)則需要創(chuàng)建一次性的獨(dú)立令牌,而不要直接使用反跨站請求偽造令牌,因?yàn)楹笳咧饕怯脕頌閼?yīng)用的其它部分提供安全保障的。
29、采用 U2F 令牌或客戶端證書,保護(hù)系統(tǒng)關(guān)鍵用戶免受釣魚攻擊
如果系統(tǒng)可能會面臨釣魚攻擊的威脅,說人話也就是,“如果存在這樣的可能性:攻擊者創(chuàng)建一個假的網(wǎng)站,騙取管理員/CEO 或其它用戶的信任,從而盜取其用戶名、密碼和驗(yàn)證碼”,那么就應(yīng)該使用 U2F 令牌或客戶端證書來防止這種攻擊,這樣的話即使攻擊者有了用戶名、密碼和驗(yàn)證碼也無法得逞。
備注:強(qiáng)調(diào)釣魚防護(hù)對于一般用戶而言往往會帶來不必要的麻煩。然而,提供多一種可選項(xiàng)對終端用戶而言也非壞事。此外,向用戶提前告知釣魚攻擊的危險也是非常必要的。
30、針對跨站點(diǎn)泄露進(jìn)行保護(hù)
跨站點(diǎn)泄露是一系列瀏覽器邊信道攻擊。這種攻擊使惡意網(wǎng)站可以從其它 Web 應(yīng)用程序的用戶中推測出信息。
這種攻擊存在已有時日,但是瀏覽器端卻是最近才開始添加針對性的預(yù)防機(jī)制??梢栽?這篇文章 中了解關(guān)于該類攻擊的更多細(xì)節(jié)以及應(yīng)該采取的安全控制措施。
二、服務(wù)器端的威脅防御
其次,是服務(wù)器端的威脅防御,這里從應(yīng)用系統(tǒng)、基礎(chǔ)設(shè)施、應(yīng)用架構(gòu)、應(yīng)用監(jiān)控、事件響應(yīng)等不同側(cè)面,歸納了如下建議:
2.1 應(yīng)用系統(tǒng)
31、對用戶輸入進(jìn)行合法性驗(yàn)證
該類別的措施中最關(guān)鍵的一點(diǎn)就是盡可能嚴(yán)格地對所有用戶輸入進(jìn)行合法性驗(yàn)證。適當(dāng)?shù)尿?yàn)證會使系統(tǒng)漏洞更難被發(fā)現(xiàn)和利用。對不合法的用戶輸入直接拒絕,而不要嘗試去清洗。驗(yàn)證方面包括如下:
- 采用嚴(yán)格的數(shù)據(jù)類型。針對日期采用 DataTime 類型,數(shù)字采用 Integer 類型等等。針對有固定可選項(xiàng)的情況采用枚舉類型。盡量避免采用字符串類型。
- 如果必須采用字符串,至少給一個長度限制。
- 如果必須采用字符串,將可輸入的字符集盡可能地減少。
- 如果要處理 JSON,使用 JSON 模式進(jìn)行驗(yàn)證。
- 如果要處理 XML,使用 XML 模式進(jìn)行驗(yàn)證。
32、異常處理優(yōu)雅化,避免技術(shù)細(xì)節(jié)泄露
對終端用戶不要顯示堆棧記錄或類似的調(diào)試信息。采用全局的異常處理器對異常進(jìn)行處理,展現(xiàn)給瀏覽器端簡單的錯誤信息。這樣會使攻擊者更難發(fā)現(xiàn)和利用系統(tǒng)中的漏洞。
33、不要自己做鑒權(quán)
對用戶進(jìn)行鑒權(quán)時可能會出現(xiàn)各種各樣的問題:要抵御密碼猜想攻擊、用戶枚舉攻擊,要管理密碼重置、存儲用戶憑證,樣樣都不容易。就像密碼處理一樣復(fù)雜,我們普通人還是不要嘗試了。
直接使用 auth0 等類似的工具來進(jìn)行身份驗(yàn)證,采用一些廣泛使用的、安全的軟件模塊來實(shí)現(xiàn)通信協(xié)議(常見的為 OpenID connect)。如果不想用 auth0 這類第三方的身份提供商,也可以自己搭建一個類似 KeyCloak 的服務(wù)來代替。
34、對一切都進(jìn)行鑒權(quán),減少攻擊面
應(yīng)用系統(tǒng)要默認(rèn)對一切都進(jìn)行鑒權(quán),除非是一些靜態(tài)資源、異常頁面或登出頁面。
35、采用多重身份認(rèn)證
萬一有人破解了身份認(rèn)證服務(wù)呢?如果存在這種擔(dān)憂,直接上多重身份認(rèn)證(說人話也就是:除了密碼以外,還需要手機(jī)驗(yàn)證碼)。這樣就算身份認(rèn)證服務(wù)被黑、攻擊者可以冒充到任何人,還是無法知道手機(jī)收到的驗(yàn)證碼。
36、通過嚴(yán)格的權(quán)限控制,避免對數(shù)據(jù)或功能的未授權(quán)訪問
權(quán)限控制雖不是件容易事,但也有妥善處理的方法:只要時刻記住不要在控制器方法中忘了對用戶權(quán)限進(jìn)行驗(yàn)證,從而帶來用戶越權(quán)的漏洞,包括:
- 不要默認(rèn)對所有控制器方法開通訪問權(quán)限。
- 根據(jù)用戶角色劃分每個控制器的訪問權(quán)限。
- 采用方法級別的安全控制,限制對服務(wù)方法的訪問權(quán)限。
- 采用集中化的權(quán)限管理工具,防止對每條記錄的非授權(quán)訪問。
- 采用前端 Web 應(yīng)用和后臺 API 結(jié)合的架構(gòu),對每個 App 和 API 均采取權(quán)限控制,而不僅是對與互聯(lián)網(wǎng)連接的部分進(jìn)行控制。
- 為了進(jìn)一步澄清權(quán)限管理工具,這里總結(jié)了一些要點(diǎn):
- 數(shù)據(jù)記錄要有可以進(jìn)行權(quán)限控制的字段,比如 int ownerId。
- 被授權(quán)的用戶要有一個 ID。
- 要有一個類可用來進(jìn)行權(quán)限評估,在數(shù)據(jù)記錄的 ownerId 與 用戶的 ID 相匹配時,能判斷出用戶具有對應(yīng)的訪問權(quán)限。
- 在以上基礎(chǔ)上,可以將權(quán)限評估類集成到應(yīng)用平臺的權(quán)限控制系統(tǒng)中,比如 Spring Security 產(chǎn)品的 PreAuthorize、PostAuthorize 等等。
- 如果需要更復(fù)雜的權(quán)限控制,也可以搭建一個完善的 ACL 系統(tǒng)。
37、采用合適的工具和技術(shù),避免注入漏洞
注入類的漏洞有很多,而且都很相似,包括 SQL 注入、HTML 注入、XML 注入、XPath 注入、命令注入、SMTP 注入、響應(yīng) header 注入等等。名稱不同但本質(zhì)相同,相應(yīng)地解決方法也類似:
- 問題原因:使用字符串拼接,來構(gòu)建特定協(xié)議下的參數(shù)化消息。
- 解決方案:采用合適的、安全的、現(xiàn)成的工具來實(shí)現(xiàn)這項(xiàng)任務(wù)。
這里不會深入太多細(xì)節(jié),只要記住:不管你是什么協(xié)議,都謹(jǐn)記上面這點(diǎn)。后面會列舉一些常見的注入類漏洞。
38、創(chuàng)建安全的數(shù)據(jù)庫查詢語句,避免 SQL 注入漏洞
如果要避免 SQL 注入漏洞,那就記住絕不要自己用字符串拼接 SQL 查詢語句。采用一個對象關(guān)系映射框架(ORM)來實(shí)現(xiàn),可以讓開發(fā)更高效、應(yīng)用更安全。
如果想要構(gòu)建更細(xì)粒度的查詢,可以使用更底層一點(diǎn)的 ORM。
如果不能使用 ORM,那就嘗試預(yù)處理語句,但也要小心這類語句會比 ORM 更容易出現(xiàn)錯誤。
警告:
ORM 框架也不是萬能的,體現(xiàn)在兩方面:一是,它對原生的 SQL 查詢還是支持的,最好不要使用這類查詢;二是,像其它任何軟件一樣,ORM 框架也會時不時被曝出漏洞。所以,還是遵循我們一而再再而三強(qiáng)調(diào)的策略:對所有輸入進(jìn)行驗(yàn)證,采用網(wǎng)絡(luò)應(yīng)用程序防火墻(WAF),并保持軟件包的更新,這樣基本就可以放心了。
39、謹(jǐn)慎使用操作系統(tǒng)的命令行,防止命令注入的相關(guān)漏洞
如果可以避免,最好不要執(zhí)行操作系統(tǒng)命令。如果不能避免,那最好遵循以下準(zhǔn)則:
- 采用合適的庫/方法來構(gòu)建命令及其參數(shù)。參數(shù)必須是 list 類型。不要用單獨(dú)字符串來創(chuàng)建命令。
- 不用使用 shell 來調(diào)用命令。
- 預(yù)定義好命令參數(shù)。比如 curl,如果允許用戶通過 -o 來指定參數(shù),那么攻擊者就有機(jī)會寫入到本地文件系統(tǒng)。
- 了解程序如何執(zhí)行,并相應(yīng)地對參數(shù)進(jìn)行驗(yàn)證。再比如 curl,你可能只是想讓用戶可以拉取某個網(wǎng)站的內(nèi)容,但如果他拉取了 file:///etc/passwd,那就危險了。
- 想清楚再行動。在上面的例子中,就算驗(yàn)證了訪問地址是以 http:// 或 https:// 開頭,攻擊者也可以發(fā)起以這兩類協(xié)議開頭的攻擊,如:http://192.168.0.1/internal_sensitive_service/admin。
- 再強(qiáng)調(diào)一遍:真得要想清楚了再行動。就算你對 DNS 進(jìn)行驗(yàn)證,確保命令中不含敏感內(nèi)網(wǎng)地址,你有去禁止將特定 DNS 記錄映射到 192.168.0.1 嗎?如果答案是否,那就危險了。
40、合理配置 XML 解析器,避免 XML 漏洞
作為一種標(biāo)記語言,XML 的危險性體現(xiàn)在它可以訪問系統(tǒng)資源。XSLT 的一些實(shí)現(xiàn)甚至支持嵌入代碼。因此,在處理時必須非常謹(jǐn)慎。
- 如果可以,避免接受來自不受信任源的 XML/XSLT。
- 如果要向 XML、XSLT 或 XPath 傳參,記住要使用安全的軟件組件,而不要使用字符串連接/格式化的方式。
- 使用主流、安全的軟件組件來解析 XML/XSLT。不要使用錯誤的庫或代碼來處理 XML。此外,在任何情況下,都不要試圖去徒手?jǐn)]一個解析器(比如 SAML),非常容易出錯。
- 正確配置解析器:禁用 XSLT 文檔、禁用 xinclude、禁用文檔類型定義、禁用外部實(shí)體,啟用 DOS 保護(hù)。具體配置在實(shí)現(xiàn)時會有所不同,但務(wù)必對所選擇的解析器進(jìn)行深入的研究。
41、采用合適的類構(gòu)建URL,避免 URL 注入漏洞
URL 注入經(jīng)常會在以下情況發(fā)生:
- flavour = request.getParam("flavour");
- url = "https:/api.local/pizzas/" + flavour + "/";
- return get(url).json();
如果 flavour 被設(shè)置為:
- ../admin/all-the-sensitive-things/
那么這個 API 請求將會變?yōu)?https://api.local/admin/all-the-sensitive-things/,是不是很兇險?
解決方案依然是采用合適的 URL 構(gòu)建庫來為 URL 傳參,從而能正確地對參數(shù)進(jìn)行編碼。
42、采用合適的類構(gòu)建路徑,避免路徑遍歷漏洞
就像 URL 地址一樣,如果攻擊者設(shè)法在路徑中的某個地方偷偷地插入 ../../../ ,文件路徑可能最終指向意料之外的位置。要避免這種情況,請創(chuàng)建一個類,采用這個類安全地構(gòu)造路徑,并驗(yàn)證最終路徑是否在預(yù)期目錄中。避免在文件路徑中使用不受信任的數(shù)據(jù),或者更好的是,完全避免使用文件系統(tǒng),直接采用云存儲。
43、謹(jǐn)慎采用文件系統(tǒng),接收不受信任的內(nèi)容
如果允許用戶寫入服務(wù)器的文件系統(tǒng),可能會出現(xiàn)各種各樣的問題。改用云存儲,或者在數(shù)據(jù)庫中使用二進(jìn)制 blob。
如果您必須訪問磁盤,則應(yīng)遵循以下指導(dǎo)原則:
- 不要讓不受信任的數(shù)據(jù)影響內(nèi)部文件路徑。
- 將文件保存在遠(yuǎn)離 webroot 的隔離目錄中。
- 在寫入磁盤之前,請驗(yàn)證文件內(nèi)容是否與預(yù)期格式匹配。
- 正確設(shè)置文件系統(tǒng)權(quán)限以防止寫入不需要的位置。
- 不要提取壓縮包(例如 ZIP),因?yàn)樗鼈兛梢园魏挝募ㄖ赶蛳到y(tǒng)任意地方的鏈接和路徑。
44、不要動態(tài)執(zhí)行代碼,避免遠(yuǎn)程代碼執(zhí)行漏洞
不要使用 eval 或等效函數(shù)。找到一種其它的方法來實(shí)現(xiàn)代碼執(zhí)行。否則,不受信任的數(shù)據(jù)將有可能進(jìn)行函數(shù)調(diào)用,從而在有機(jī)會在服務(wù)器上執(zhí)行惡意代碼。
45、合理采用序列化,避免反序列化漏洞
對不受信任的數(shù)據(jù)進(jìn)行反序列化是很危險的,很容易導(dǎo)致遠(yuǎn)程代碼執(zhí)行。
- 如果可以避免,不要使用序列化。
- 如果可以在服務(wù)器端序列化對象,則對其進(jìn)行數(shù)字簽名。當(dāng)需要再次反序列化它們時,請?jiān)诶^續(xù)反序列化之前驗(yàn)證簽名。
- 使用一些主流的軟件組件,并保持更新。許多反序列化庫會一直被發(fā)現(xiàn)漏洞。GSon 是個不錯的選擇。
- 使用簡單的文本格式,如 JSON,而不是二進(jìn)制格式。此外,應(yīng)該避免像XML這樣有問題的格式,因?yàn)檫@樣除了反序列化之外,還需要擔(dān)心 XML 漏洞。
- 在處理序列化對象之前驗(yàn)證它。例如:對于 JSON,在繼續(xù)反序列化之前,根據(jù)嚴(yán)格的 JSON 模式驗(yàn)證 JSON 文檔。
2.2 基礎(chǔ)設(shè)施
46、采用網(wǎng)絡(luò)應(yīng)用程序防火墻(WAF)
安裝防火墻,會減少很多風(fēng)險。ModSecurity 就是一個很好的開源選擇。
47、配置 Web 服務(wù)器,避免 HTTP desync 攻擊
HTTP desync,也稱 HTTP 請求走私攻擊,是指攻擊者劫持隨機(jī)用戶向系統(tǒng)發(fā)出的 HTTP 請求。這類攻擊一般在以下情況下發(fā)生:
- 前端服務(wù)器,比如負(fù)載均衡器或反向代理服務(wù)器,接受攜帶有 Content-length、Transfer-Encoding 等頭部參數(shù)的請求時,將請求未經(jīng)處理隨即傳遞到后臺;
- 后臺接受該請求的服務(wù)器(通常是應(yīng)用服務(wù)器),采用(或被欺騙采用)一個不同于前端服務(wù)器的機(jī)制來確定 HTTP 請求從何處開始、何處結(jié)束,比如前端服務(wù)器使用 Content-Length,而應(yīng)用服務(wù)器采用 Transfer-Encoding;
- 前端服務(wù)器重復(fù)利用與后端服務(wù)器的連接;
- 前端服務(wù)器在與后臺服務(wù)器連接時采用 HTTP/1(而非 HTTP/2)。
那么該如何進(jìn)行防范呢?一般是根據(jù)所采用的產(chǎn)品:
- 咨詢所采用的反向代理產(chǎn)品供應(yīng)商,確保該產(chǎn)品具備主動防范攻擊的能力;
- 配置前端服務(wù)器,在與后臺連接時采用 HTTP/2;
- 配置前端服務(wù)器,防止利用同一個連接發(fā)送多個客戶端的 HTTP 請求;
- 采用網(wǎng)絡(luò)應(yīng)用程序防火墻(WAF),并確保其具備防止請求走私的模塊。
48、采用容器
讓目標(biāo)應(yīng)用隔離其他應(yīng)用來運(yùn)行。這樣,即使發(fā)生了攻擊事件,攻擊者也不會有權(quán)限去訪問未經(jīng)許可的文件、系統(tǒng)或網(wǎng)絡(luò)資源。因此,最好使用 Kubernetes 或一個云端環(huán)境來部署你的應(yīng)用。如果因?yàn)槟撤N原因必須使用一臺服務(wù)器,那么可以手動采用 Docker 來約束應(yīng)用。
49、使用 SELinux/AppArmor
即使通過容器來運(yùn)行應(yīng)用,也還是需要進(jìn)一步采用 SELinux 或 AppArmor 策略來進(jìn)一步地對應(yīng)用做出約束,從而減少容器漏洞引發(fā)的威脅。
50、采用最少權(quán)限的服務(wù)賬戶
這種方法帶來的好處是即使發(fā)生了被攻擊事件,也能減少被攻擊造成的損失。再次重申,列出所有的情形是不可能的,這里僅列舉一些例子幫助大家理解:
- 即使使用了 Docker,甚至是使用了 SELinux/AppArmor,不要用 root 賬戶來運(yùn)行你的應(yīng)用。為你的應(yīng)用單獨(dú)創(chuàng)建一個具備盡可能少的權(quán)限的賬戶,從而降低攻擊者利用容器或內(nèi)核漏洞等進(jìn)行攻擊的可能性;
- 如果有使用數(shù)據(jù)庫,確保應(yīng)用程序中的數(shù)據(jù)庫用戶在訪問數(shù)據(jù)庫時具備盡可能少的權(quán)限;
- 如果應(yīng)用中集成了 API,確保應(yīng)用訪問 API 時具備盡可能少的權(quán)限。
51、限制外部網(wǎng)絡(luò)連接
攻擊者通常需要建立一定的反向通信渠道來建立操控渠道或竊取數(shù)據(jù)。此外,一些漏洞也是需要外部網(wǎng)絡(luò)連接才會被發(fā)現(xiàn)、被利用。
因此,不能讓應(yīng)用隨便訪問外部網(wǎng)絡(luò),包括 DNS。試下在服務(wù)器運(yùn)行命令 nslookup www.cdxwcx.com,如果運(yùn)行成功,則說明你沒有對外部網(wǎng)絡(luò)連接做出適當(dāng)?shù)南拗?。如何處理此類問題,一般則取決于基礎(chǔ)設(shè)施。
針對外部的 TCP/UDP/ICMP 連接,一般可以通過以下方式禁用:
- 網(wǎng)關(guān)防火墻,如果有的話;
- 如果是老式服務(wù)器,可以采用本地的防火墻(例如 iptables 或 Windows 防火墻);
- 如果服務(wù)器端采用 Docker,可以使用 iptables;
- 如果使用了 Kubernetes,可采用網(wǎng)絡(luò)策略定義。
DNS 處理起來稍微麻煩一點(diǎn),我們通常需要允許對一些 hosts 的訪問。
- 如果有本地的 hosts 文件,那就很簡單,可以采取上面的任何一種方式來將 DNS 徹底禁用;
- 如果沒有,那么你需要在你上游的 DNS 中配置一個私有的區(qū)域,在網(wǎng)絡(luò)層限制僅能訪問該指定的 DNS 服務(wù)器。這個私有區(qū)域內(nèi)只允許對一些預(yù)先指定的 hosts 的訪問。
52、跟蹤 DNS 記錄,防止子域名劫持
子域名劫持發(fā)生場景舉例如下:
- 假如我們擁有一個域名 cdxwcx.com;
- 針對一次促銷活動,我們買了另一個域名 www.my-cool-campaign.com ,然后創(chuàng)建了一個別名從 campaign.cdxwcx.com 映射到 www.my-cool-campaign.com;
- 這次促銷活動結(jié)束后,www.my-cool-campaign.com 域名也到期了;
- 但是,從 campaign.cdxwcx.com 到 www.my-cool-campaign.com 的別名映射仍存在;
- 如果有人購買了這個到期的域名,那么 campaign.cdxwcx.com 便可以直接指向該域名;
- 如果攻擊者在 www.my-cool-campaign.com 域名下提供一些惡意內(nèi)容,那么便可以通過 https://campaign.cdxwcx.com 域名直接訪問到。
因此,需要隨時留意你的 DNS 記錄。如果需要處理的類似情況較多,強(qiáng)烈建議你做一個自動監(jiān)控方案。
2.3 架構(gòu)
53、創(chuàng)建內(nèi)部 API 用來訪問數(shù)據(jù)源
對連接互聯(lián)網(wǎng)的網(wǎng)絡(luò)應(yīng)用程序不應(yīng)該太過于信任。例如,不應(yīng)允許它進(jìn)行數(shù)據(jù)庫直連。否則,當(dāng)有人攻破應(yīng)用程序時,整個數(shù)據(jù)庫都將面臨威脅。
相反,我們應(yīng)該搭建多組件組成的架構(gòu),例如:
- 我們域名為 www.cdxwcx.com 的應(yīng)用程序使用 auth0 進(jìn)行鑒權(quán)。
- 該應(yīng)用程序訪問內(nèi)部 API 服務(wù) api.example.local 時,攜帶被授權(quán)用戶的 token,放在請求頭部的 Authorization 中。
- 位于 api.example.local 的 API 服務(wù)根據(jù)用戶的 token 進(jìn)行訪問限制,進(jìn)而根據(jù)被授予的權(quán)限讀寫數(shù)據(jù)庫。
假如現(xiàn)在有黑客想要攻破我們的應(yīng)用程序,即使成功,他也沒有權(quán)限訪問整個數(shù)據(jù)庫,而只是利用某個用戶的 token,進(jìn)而訪問該 token 所允許訪問的那部分?jǐn)?shù)據(jù)。
54、內(nèi)部連接也需加密和驗(yàn)證
不要盲目相信內(nèi)網(wǎng)的安全性,有很多方法可以攻破它。對于系統(tǒng)間的訪問,全部采用 TLS(也就是 HTTPS)進(jìn)行加密,最好在網(wǎng)絡(luò)和系統(tǒng)兩個層次對連接進(jìn)行鑒權(quán)。
55、對敏感信息集中管理
如果沒有采用合適的敏感信息管理方案,就很難保持授權(quán)的短期性化、可審計(jì)性和秘密性。因此,建議采用 HashiCorp Vault 一類的工具來集中管理密碼、加密 key 等類似信息。
2.4 監(jiān)控
56、收集,分析,報(bào)警
集中收集日志到一個獨(dú)立系統(tǒng),比如 SIEM(安全信息和事件監(jiān)控系統(tǒng))。在這個系統(tǒng)中,可以在一些表征脆弱性、攻擊的事件發(fā)生時進(jìn)行報(bào)警。當(dāng)嚴(yán)重威脅發(fā)生時,可以立即通知相關(guān)人員。
57、收集系統(tǒng)安全事件
最重要的日志來源可能就是系統(tǒng)自身了。當(dāng)有可疑行為發(fā)生時,系統(tǒng)應(yīng)能引發(fā)異常,記錄事件,可能的話,甚至可以自動封鎖可能帶來問題的用戶或IP地址。常見可疑行為包括:
- 輸入值的合法性驗(yàn)證錯誤(例如,試圖輸入 UI 中不可能提供的值)
- 訪問控制錯誤 (例如,嘗試訪問一條在 UI 中不可能出現(xiàn)的記錄)
- 數(shù)據(jù)庫語法錯誤表示某個人發(fā)現(xiàn)了一處 SQL 注入的脆弱性,這時候可要動作快點(diǎn)采取行動了
- XML 錯誤表示某個人發(fā)現(xiàn)了一處 XML 注入的脆弱性,或者正嘗試?yán)?XXE(XML 外部實(shí)體)脆弱性進(jìn)行攻擊
- 錯誤請求表示用戶可能發(fā)送了被應(yīng)用拒絕的請求。Spring 框架的 RequstRejectedException 就是一個例子
- 反跨站請求偽造令牌驗(yàn)證錯誤一般表示有人正嘗試尋找系統(tǒng)中存在的脆弱性
58、收集運(yùn)行時安全日志
使用運(yùn)行時安全監(jiān)控工具如 Falco 來對異常系統(tǒng)訪問進(jìn)行檢測。如果采用了 Kubernetes,那么 Falco 就特別有用。遠(yuǎn)程也可以對日志進(jìn)行收集和監(jiān)控。
59、收集 SELinux/AppArmor 日志
假如我們制定了 SELinux 策略防止向外部的連接,但系統(tǒng)忽然向外部某個網(wǎng)站(例如 burpcollaborator.net)發(fā)起 HTTP 請求,那就需要立刻引起關(guān)注。又或者你的系統(tǒng)嘗試訪問 /etc/passwd。這兩種情況都表示有人已經(jīng)發(fā)現(xiàn)了我們系統(tǒng)中的漏洞。
60、收集 Web 服務(wù)器事件
對 Web 服務(wù)器軟件,至少要對訪問日志和錯誤日志進(jìn)行收集,收集后發(fā)送到集中式的日志服務(wù)器。在突發(fā)事件響應(yīng)時,這將輔助我們快速理清時間線。
61、收集網(wǎng)絡(luò)應(yīng)用程序防火墻(WAF)日志
如果你像上文推薦使用了網(wǎng)絡(luò)應(yīng)用程序防火墻(WAF),那么也對這個日志進(jìn)行收集。但不用針對這個日志設(shè)置報(bào)警,因?yàn)樗旧蠒盏絹碜曰ヂ?lián)網(wǎng)各種各樣的問題,而且不部分是你不用擔(dān)心的。
2.5 事件響應(yīng)
62、制定應(yīng)對計(jì)劃
一旦對我們的系統(tǒng)進(jìn)行了監(jiān)控和加固,攻擊者將難以快速定位系統(tǒng)漏洞,即使最終發(fā)現(xiàn),我們也能快速了解情況。
但僅了解情況是不夠的,還需要做出如下準(zhǔn)備:
- 快速分析系統(tǒng)日志,了解當(dāng)前狀況和需采取的對應(yīng)措施
- 在應(yīng)用防火墻等產(chǎn)品中,快速對個別 url 地址和參數(shù)做出限制
- 如有需要,快速關(guān)停系統(tǒng)
2.6 開發(fā)管理
63、威脅模型
系統(tǒng)地考慮一下“可能會出現(xiàn)哪些問題”并據(jù)此做出調(diào)整。設(shè)計(jì)一個新的系統(tǒng)時,越早開始這一步越好。當(dāng)對系統(tǒng)發(fā)生改變時,再重新梳理一遍這個過程。
例如:
小王:如果攻擊者攻破了我們連接了互聯(lián)網(wǎng)的服務(wù)器,怎么辦?
小陳:那可就完蛋了!
小王:好吧!這就說明我們在這里存在著一個信任關(guān)系,我們認(rèn)為連接了互聯(lián)網(wǎng)的服務(wù)器是不會被攻破的。我們可以信任這一點(diǎn)嗎?
小陳:未必吧!有一百種可能導(dǎo)致我們的服務(wù)器被黑掉,例如我們代碼中存在的脆弱性,或者依賴中存在的脆弱性,或者是我們 Web 服務(wù)器所安裝軟件的脆弱性。
小王:好吧!那就讓我們打破這層信任關(guān)系。接下來該做些什么呢?
小陳:我們這樣來分解一下系統(tǒng):創(chuàng)建一些內(nèi)部的接口用來實(shí)際訪問數(shù)據(jù)庫,由此以來,前端的 Web 服務(wù)器就不能直接訪問后臺的所有東西。
小王:這是個好辦法!除此以外,還有其它什么可能出問題呢?
小陳:嗯,如果黑客攻破了我們的內(nèi)網(wǎng)呢?
小王:那所有東西都要丟失了,因?yàn)閮?nèi)網(wǎng)里服務(wù)器之間的連接都是未加密的。
小陳:……
這就是威脅模型,它不需要多么復(fù)雜。使用這種方式,來找出系統(tǒng)中可能存在的威脅。
64、源代碼強(qiáng)制審查
通過技術(shù)控制手段,防止代碼未經(jīng)他人審核便提交入庫。這是構(gòu)建安全開發(fā)環(huán)境的基礎(chǔ),因?yàn)樗梢宰龅剑?/p>
- 如果攻擊者攻陷了一個開發(fā)人員的電腦,或者是開發(fā)人員自身企圖發(fā)起攻擊,將不能直接將惡意代碼遷入代碼庫;
- 如果開發(fā)人員的錯誤導(dǎo)致引入了有漏洞的代碼,很可能在被其他人檢查時及時發(fā)現(xiàn)。
65、自動化持續(xù)集成管道,僅允許簡單訪問
開發(fā)人員應(yīng)該有權(quán)限觸發(fā) Jenkins 構(gòu)建,且 Jenkins 權(quán)限配置也僅該如此,不要再允許其它權(quán)限。單個開發(fā)人員應(yīng)該不能在構(gòu)建階段引入任意代碼。當(dāng)然,如果像上文推薦的強(qiáng)制性地采用了代碼審查,Jenkinsfile 也可以保存在版本管理工具中。
66、對 artifacts 進(jìn)行簽名
如果是構(gòu)建容器鏡像,可以把對鏡像簽名作為構(gòu)建的一步。將簽名密鑰存儲在安全的地方。構(gòu)建階段需要訪問密鑰,但是杜絕將密鑰與 Jenkinsfile 一起存儲在版本管理工具中。更好的方式是將密鑰存儲在 HashiCorp Vault 之類的地方,然后在構(gòu)建時再進(jìn)行拉取。
67、持續(xù)集成管道中加入靜態(tài)應(yīng)用程序掃描器
在持續(xù)集成管道中使用 SpotBugs 和 Find-Sec-Bugs(或者根據(jù)你所采用的技術(shù)棧進(jìn)行選擇)之類的工具。它們可以幫你在部署代碼之前發(fā)現(xiàn)已知的漏洞。
此外,也可以作為 IDE 的插件安裝在開發(fā)人員的電腦上,在代碼遷入之前就運(yùn)行這些工具進(jìn)行檢查。
68、構(gòu)建時對依賴進(jìn)行檢查,保證最小的依賴集
應(yīng)用程序中依賴的每個軟件包都是一個風(fēng)險來源。通過依賴,我們拉取了第三人的代碼并在我們的應(yīng)用服務(wù)器上執(zhí)行,所以,必須要搞清楚我們依賴的這個軟件包是什么,為什么會依賴它?
- 保持最小的依賴集;
- 僅使用我們所信任的依賴。它們必須是廣泛使用和廣為人知的;
- 采用構(gòu)建框架,對依賴進(jìn)行確認(rèn)。
此外,嚴(yán)格控制應(yīng)用服務(wù)器的對外連接,從而避免后門的存在。
69、對依賴進(jìn)行安全掃描
使用 OWASP 依賴檢查工具對依賴中常見的安全問題進(jìn)行掃描。除了在持續(xù)集成管道中,也可以在開發(fā)人員的開發(fā)環(huán)境運(yùn)行這些工具。
70、持續(xù)集成管道對鏡像進(jìn)行安全掃描
如果采用了容器化技術(shù),可以使用 Trivy 等工具對容器鏡像進(jìn)行一些常規(guī)漏洞的掃描。
71、自動化部署和簽名驗(yàn)證
開發(fā)人員可以有權(quán)限到生產(chǎn)環(huán)境中部署,但是權(quán)限范圍應(yīng)該控制在前階段已經(jīng)構(gòu)建和簽名過的特定鏡像,而不是直接訪問生產(chǎn)服務(wù)器。如果是使用 Kubernetes,可以通過 Notary 或開放策略代理來驗(yàn)證待部署鏡像的簽名。
72、設(shè)置一個安全人員
一個人的精力是有限的。我們不能期望每個開發(fā)人員都精通滲透測試或是安全工程師。正如你不能期望所有的安全專家都是優(yōu)秀的開發(fā)人員一樣。因此,可以在團(tuán)隊(duì)中設(shè)置一個專門關(guān)注安全的人員,主要與開發(fā)人員、架構(gòu)師進(jìn)行交流,幫助保護(hù)我們的應(yīng)用程序并在團(tuán)隊(duì)中傳播安全意識。
三、結(jié)論
保證應(yīng)用程序的安全性,光靠避免漏洞時不夠的,必須全面通盤考慮,主動進(jìn)行防御。這里對一些主要方法進(jìn)行了總結(jié):
使用最新版本的的軟件組件來執(zhí)行危險的操作,如身份驗(yàn)證、訪問控制、加密、訪問數(shù)據(jù)庫或解析 XML,并確保正確配置了這些組件,例如 XML 解析時禁用外部實(shí)體。
- 使用平臺提供的安全控制,例如反跨站請求偽造保護(hù)。
- 使用 Web 瀏覽器提供的安全控件,如 HSTS、SameSite Cookie 和內(nèi)容安全策略。
- 對安全控制進(jìn)行集中化處理,特別是身份驗(yàn)證和訪問控制,從而避免一些遺漏,如在某些控制器方法上忘記對安全進(jìn)行控制。
- 使用 Web 應(yīng)用程序防火墻,防止應(yīng)用程序漏洞被發(fā)現(xiàn)和被利用。
- 通過限制對文件、網(wǎng)絡(luò)和系統(tǒng)資源的訪問來對應(yīng)用程序進(jìn)行限制。
- 利用威脅模型發(fā)現(xiàn)架構(gòu)中的威脅,并相應(yīng)進(jìn)行處理。既包括在源代碼層面對每個開發(fā)人員的源代碼進(jìn)行安全控制,也包括在架構(gòu)層面對前端 Web 服務(wù)器的安全控制。
- 對系統(tǒng)進(jìn)行監(jiān)控,制定異常處理預(yù)案。
- 在開發(fā)環(huán)境和持續(xù)集成環(huán)境中使用漏洞掃描程序?qū)Υa、鏡像、依賴進(jìn)行掃描。
- 對開發(fā)人員、架構(gòu)師等開展安全培訓(xùn),并在團(tuán)隊(duì)中配備一名安全人員。
感謝原作者的翻譯授權(quán):
標(biāo)題名稱:72個網(wǎng)絡(luò)應(yīng)用安全實(shí)操要點(diǎn),全方位保護(hù)你的Web應(yīng)用
文章地址:http://www.fisionsoft.com.cn/article/dpsesgj.html


咨詢
建站咨詢
