隨著安全得到越來越多的關注,一些跟安全相關的理論(比如<u>BSI</u>)脫穎而出,盡管這些理論提出來已經有一段時間,卻很少看到其在開發團隊被成功地應用。我們知道微軟曾在十多年前就提出了<u>SDL</u>,卻沒能在業界推廣開來,并不是人們不認可微軟這種“從軟件生命周期保障安全”的理念,而是考慮到其落地實施的難度,很多企業知難而退,那么這些安全理論對我們的軟件安全真的有幫助嗎?安全實踐能落地嗎?
很幸運地,我有機會在一個成熟的敏捷開發交付小組中經歷了“從完全沒有安全實踐到BSI”的過程,我們也曾遇到過很多困難,但最終得到了客戶的認可,并成功把安全實踐推廣到了整個團隊,所以想跟大家分享一下我們是如何將安全在敏捷團隊落地的,希望能給大家一些幫助。文中會拿Web系統舉例,但一些落地的實踐同樣適用于非Web系統。
為什么安全理論很難落地?
結合對一些團隊的了解,原因大多來自以下三個方面:
認為安全不重要
認為安全太難,需要很廣很深的領域知識,只有專業人員才能做到
不知道應該用什么樣的流程來做安全
那么針對第一點,因為我本身也是交付團隊的一員,我觀察到的大多數軟件開發團隊,不管是業務分析師、開發人員、測試人員、體驗設計師還是項目經理,都很少有人真正把“安全”作為非常重要的一件事情,尤其是在交付壓力比較大的情況下,我們都會舍棄對于安全的投入,而花時間在更容易可視化出來的用戶功能上。安全,很多時候就像滅火器,如果不發生火災,我們甚至都感覺不到它的存在。那么,安全,真的重要嗎?
換位思考一下,如果我們是用戶,面對以下兩種選擇,我們會選擇哪一種?
- 系統A:設計非常完美,功能缺陷幾乎沒有,性能也很棒,但是沒有做任何跟安全相關的防護,用戶的敏感信息很容易泄露;
- 系統B:設計比較差,有一些功能缺陷,性能也差一點點,但是采取了特別多的安全措施,能夠保障用戶的數據安全性;
相信幾乎所有人都會毫不猶豫選擇B系統,除非這是一個完全沒有用戶敏感數據、完全不需要安全保障的系統(那這樣的系統又有什么用?),所以只要我們把自己放在產品使用者的角度,而不是產品制造者的角度,就能很容易地理解和認可安全對于軟件系統來說是比功能更重要的一個因素,安全是軟件的靈魂。
那么對于很多已經深刻認識到安全重要性的團隊,為什么依然很難將安全理論落地呢?原因大多來自前面提到的第二點和第三點,一是從技術上認為安全是一個很難的領域,需要專業的安全人士;二是從流程上不知道該如何開展;從這兩個角度出發,“安全”需要巨大的投入,所以很多團隊望而卻步。那么安全真的這么難落地嗎? 接下來我會簡單介紹一些Web安全知識,然后通過我所在團隊的落地過程給大家一個答案。
如何讓安全在敏捷團隊落地
什么是Web安全?
所謂Web安全問題,就是攻擊者可以通過非正常的手段,獲得Web系統訪問權限,從而破壞網站行為,盜取甚至修改用戶數據的一系列問題。
那么為什么攻擊者可以獲得Web系統權限呢?這種幾率到底有多大呢?如果可能性非常小,我們是不是不必花費太多精力在安全上面呢?
我們來看一下Web系統的組成,一個最簡單的系統都至少有這么幾個部分:
如上圖,瀏覽器發送請求到服務器,服務器給瀏覽器響應,服務器會查詢數據庫,數據庫返回結果。在這個過程中,我們開發的Web程序不可避免的存在安全漏洞,甚至我們開發系統所使用的編程語言也會有安全問題。在開發時,我們常常會引用一些第三方的工具、組件,而第三方的安全性也沒有辦法保障,甚至數據傳輸過程中使用的協議、操作系統本身也會有安全問題。所以可以想象一下,如果我們不做任何的安全防范,那么每一個軟件都是一個非常脆弱的系統,很容易出現安全問題。
常見的Web安全問題
既然這么多環節都有潛在的安全風險,那么該如何著手呢?可以參考<u>OWASP TOP 10</u>,以便對最嚴重的Web應用程序安全問題有個大致的了解。
敏捷開發模式現狀
我們是一個已經實施敏捷開發七年的團隊,一共有五十多人,劃分成不同的Feature小組進行日常的工作,其敏捷開發模式已經非常成熟,我所在的Feature小組有6個開發人員,1個業務分析師,1個QA,我們每個小組的交付模式都是這樣的:
如上圖,以<u>用戶故事</u>為單元,所有的用戶故事都會經歷一個從分析到最后給客戶演示的生命周期,多個用戶故事組成一個Feature,然后我們會進行Feature的功能測試,給客戶展示整個功能,最后在發布之前,客戶會邀請第三方的專業安全公司做滲透測試,然后找我們的開發團隊修復安全缺陷。
那么這種方式有什么問題呢?
守門員模式,安全測試非常滯后
安全問題的修復時間非常有限
只有少數人關注和了解安全
依賴獨立的滲透測試
所謂守門員模式,指的就是把所有的問題和風險都留在最后,靠少數人來保障,在當時的開發模式下,第三方的安全公司就是我們系統的安全守門員,可想而知,如果我們的團隊對安全沒有任何了解,在用戶故事的開發階段引入的安全問題要等到發布之前才能夠被發現,安全測試是非常滯后的,反饋周期特別長。
另外當第三方的安全公司發現問題,留給我們團隊修復問題的時間特別有限,因為滲透測試是發布前的最后一個階段,長時間的修復又會導致發布延期,所以經常會導致安全修復以補丁的方式發布。
而且除了少數修復過安全缺陷的開發人員對安全有一點點了解之外,團隊內是沒有人關心安全的。
最大的問題是,所有的安全防范都依賴于最后的獨立滲透測試。雖然因為執行滲透測試的是專業的第三方安全公司,他們有專業的安全知識,可以發現很多公共的安全問題,也可以提供專業的極具權威性的安全報告,但這種方式的滲透測試有個致命的弱點,他們對業務知識了解不夠,很難發現跟業務相關的安全問題,而這一類的安全問題又占了相當大的比重。
可以看到,這種敏捷開發模式的現狀就是:試圖將安全注入一個已經成型的系統中。
安全落地嘗試
那么了解了之前開發模式存在的問題,安全又這么重要,客戶和團隊都希望可以改變這種現狀,提高安全質量,減少補丁,讓每一個人都關心安全,但是我們都擔心安全需要巨大的投入,會影響功能的發布,所以我們決定選擇一個Feature小組做為安全試點,目標周期為一個月(我們的發布周期),觀察投入產出比,然后決定是否要在整個團隊實行。
首先我們小組開始學習BSI,我們認為它所傳遞的是這樣一些理念:
將安全融入整個軟件開發過程中
所有團隊成員一起為安全負責
安全的設計和實施一個持續進行的過程
那么在一個幾乎沒有安全知識儲備的團隊中,如何將以上理念在團隊應用呢?我們遇到了很多的困難,比如:
不知道怎么把安全和日常開發結合起來
不知道如何編寫安全需求,怎么做安全測試
接受了很多安全培訓,不知道如何下手
對安全缺乏專業的認知,對安全開發和測試沒有信心
不知道如何滿足客戶期望
分析這些困難,我們開始邁出了艱難的第一步。
首先,召集團隊的核心成員(包括了業務分析師,開發人員,測試人員,技術主管),同時我們邀請了公司的一位安全專家幫我們解答難題,大家<u>頭腦風暴</u>,參考OWASP TOP 10, 結合曾經項目上出現過的安全問題以及對于業務領域的深入了解,嘗試總結屬于我們自己的安全問題項目并且和OWASP TOP 10進行關聯,比如我們討論后的成果是這樣的:
可以看到,我們總結出來的這十項并不是將OWASP TOP 10調換順序這么簡單,我們是針對業務需求,有針對性地進行了重新整理和組織,比如其中的<u>Sensitive Data Exposure</u>,我們就結合項目將它劃分成了四類(1.Authentication,2.Error Handling,3.Code Leak,4.Cookie Management),之所以會劃分的這么具體,是因為我們自己的TOP10更貼近實現。另外我們還針對每一項添加了項目上的例子作為參考,讓團隊每一個人都清楚地知道我們自己的TOP 10都是什么樣的以及業務場景下可能出現的安全問題。
然后我們將項目專屬TOP 10作為模板加入到了每個用戶故事中,這么做有兩個好處:
- 第一,業務分析師在寫用戶故事的時候,可以將其作為參考來編寫安全驗收標準;
- 第二,如果業務分析師在缺乏安全知識的情況下很難編寫安全需求,我們可以將其直接作為安全需求以防遺漏。
當然這還遠遠不夠,更理想的情況是在需求分析階段、業務分析師和客戶在討論需求的過程中盡量參考一些基本的原則,比如最小權限原則,來確定和編寫更加準確的安全驗收標準。如下圖。還可以讓更多的人參與到需求分析階段,通過<u>威脅建模</u>等手段分析出更全面的安全需求。當然這就需要我們的業務分析師增加安全相關的知識儲備,我們也在向這個方向努力。
然后在用戶故事的啟動階段,業務分析師、QA和開發人員會一起針對用戶故事模板中我們自己的TOP 10進行篩選,將和用戶故事相關的內容標識出來作為安全驗收標準。如果在故事分析階段,業務分析師已經遵循一些原則細化了安全驗收標準,在這個階段,也可以多個角色針對這些安全驗收標準進行探討,確保大家理解一致。
到了用戶故事的開發階段,通常開發人員都會按照驗收標準來編寫代碼和測試,基于我們已經有了足夠的安全驗收標準,相應地,開發人員也會編碼來實現這些安全條件并且添加相應的自動化測試保障,當然,除了滿足安全驗收標準之外,我們也會做一些靜態代碼的掃描和第三方依賴的掃描,雙重保障。
用戶故事的驗收階段非常重要,因為如果在這個階段發現缺陷可以快速修復,我們一般是QA、開發人員和業務分析師一起,逐個驗收我們之前制定的安全驗收標準。當然,除了簡單地從前端進行驗證,針對安全驗收我們需要借助一些工具(如<u>Burp Suite</u>),繞過前端修改請求,檢查是否后端接口也作了相應的防范,如果發現安全問題,會在這個階段及時修復并且增加相關的測試保障。
到了用戶故事的測試階段,QA會做跟安全相關的探索性測試,在這個階段,需要QA從一個全新的視角來做測試,之前我們的模式是從正常用戶的角度來測試功能,而針對安全的探索性測試則截然不同,我們要用攻擊者的角度來思考問題,嘗試各種看似不可能的手段,尋找安全漏洞。另外,在這個階段,我們也會借助一些自動掃描工具(比如<u>ZAP</u>),來檢測是否有一些通用的安全問題。
安全的演示階段比較有挑戰性,前面提到過,它不像功能需求那么可見,所以我們采用了一種全新的方式去展示,通常功能演示我們是給客戶展示用戶界面,如何使用系統等,而對于安全,我們嘗試了展示安全缺陷以及我們的缺陷分布分析。比如在這一個月里,我們發現了六個安全問題,其中兩個是通過ZAP掃描出來的共通的安全問題,另外四個是和業務強相關的安全問題(比如賬戶A可以通過特殊手段修改其本來沒有權限的數據,屬于我們自己的TOP 10的Authentication那一類)。
回顧整個過程,其實我們在用戶故事的每個階段都增加了和安全相關的實踐,并且讓團隊所有人員都參與了進去,將安全融入到日常的工作中,不斷改進,持續關注,而這些正是BSI所傳達的理念。
客戶看到我們的安全成果展示后非常滿意,進而在我們整個團隊開展了這樣的安全實踐。
在維持這樣的安全模式幾個發布周期之后,我驚喜地發現我們的開發人員開始有了安全的意識,比如前不久我們有一個用戶故事需要實現一個郵件模板,系統要求能夠接受用戶定制化的html,功能實現非常簡單,可是開發人員一籌莫展,接到用戶故事后馬上找到我,探討如何讓我們的系統允許接受html后還可以避免script攻擊,這讓我深刻感受到,BSI(Build Security in our DNA)這個理念的精確含義,我們不是為了讓大家遵循實踐而去實踐,而是讓每個人都有安全的意識,每當我們接觸到一個新的功能,馬上會想到可能有哪些安全問題,而不是急于實現功能,長此以往,安全就真的進入了團隊的DNA。
總結
回想之前我們想要開始在團隊實施安全時的恐懼以及止步不前,到最后我們成功將安全實踐落地并且推廣,這個過程讓我體會到,從一個小組開始嘗試,觀察投入產出比,再推廣到整個大的團隊是個很好的實踐。
另外,不要期望一步到位、迅速成為安全專家,安全的設計和實施是一個持續進行的過程,可以從日常工作中的點滴做起,從保障每一個安全需求做起,想象一下,如果我們每一個用戶故事都注入了和安全相關的實踐,那么feature就會是這些安全的用戶故事的結合,系統就會變成一個充滿安全投入的整體。
和之前“靠最后的滲透測試來補救安全問題”的方式相比,這種從源頭就將安全滲透進軟件系統的方式更能保障我們軟件的安全。
更多精彩洞見,請關注微信公眾號:ThoughtWorks