Web Service讓組織能夠跨越異質平台與使用者互連,提供後者取得所需的資訊。更進一步來看,Web Service是一個非常複雜的組合,包含服務導向架構(service oriented architecture)、語意網路(semantic web)、XML(可延伸標記語言,extensible markup language)、自我描述軟體(self-describing software),以及SOAP(簡單物件存取協定,simple object access protocol)。
採用Web Service,意味著需要將相關技術與各種應用技巧組合成一個無縫的架構。為了解決這項難題,微軟建立了.NET,並將之整合到自己的作業系統,與重要的伺服器應用程式裡面,藉以提供整個產品系列的無縫整合。
任何時候,當你聽聞有新的開發平台可以提供動態下載與遠端執行程式的能力,你的安全雷達都應該立刻迅速地啟動。Web Service不僅開創了動態互連與交易的世界,同時也開啟了企業攻擊的大門,因為程式碼與底層認證機制可能存在漏洞風險。
儘管安全性似乎仍舊處在鼓吹人們,遵守健全防駭的程式撰寫原則與習慣的階段,然而多虧.NET提供了若干內建機制,可以避免一些常見易犯的程式設計錯誤發生。現在就讓我們來試試看其中幾個重要的功能吧。
分層防禦
談到應用程式的安全性,有幾點非常重要的,那必須確保每位使用者要求的存取都是徹底經過驗證的,並且只給予他們必要的權限,以及記錄其行為。
多數應用程式的作法,是在使用者一開始利用帳號與密碼進行認證時,即實施控管。當使用者要更進一步存取需要經過授權的公司資源時,通常不會被要求重新認證,所以一旦有人攔截了這次的工作階段(session),那麼攻擊者便可能擁有不受限制的存取權限,進而有機會重創整個企業。
除此之外,甚至就連合法的使用者,也傾向於希望能夠擁有大於本身實際所需的檔案存取權限。
.NET解決這項問題的作法,是讓程式設計人員能夠在每一個操作層級(舉凡網頁伺服器、程式設計語言、作業系統,以及資料庫)裡面,建構安全管理。
一般而言,使用者會先與IIS網頁伺服器互動,以便進行基本的認證與取得有限的存取權限。.NET能夠讓企業在各個階層裡面建構安全防護,作法是在使用者開始需要存取額外資源時先去下載行動程式(mobile code),再以此程式來執行商務應用,並存取位於公司後端平台的資料。
讓我們在.NET環境裡面跑一遍上述的流程看看吧。首先使用者經由網頁伺服器連接到一個系統,此時的使用者身分驗證,可以透過憑證或者基本的密碼來進行;然後他們根據自己的子網路被授與權限,並且獲得對於這個網頁應用程式的存取能力。這個網頁應用程式可以要求使用Passport帳號,也可以利用URL驗證來賦予使用者某種.NET角色(role)。在應用程式進行完這項檢查之後,伺服器自然也就完成認證了。最後,當使用者試著要存取資料的時候,Windows認證便會啟動,並且根據內建於SQL Server的物件角色定義,來授與受到約束的資料存取權限。
接下來,就讓我們來看看.NET的角色是如何實現滴水不漏的安全性,以及如何讓管理變得更容易吧。
身分驗證
一般而言,開發平台所提供的存取控制設計,可以是嚴格且強韌的,也可以是非常彈性但不夠安全。而.NET的存取控制架構則是同時為使用者與應用程式提供了彈性,亦即只給予所需的必要權限。.NET採取的是下列這兩種基本作法。
以角色為基礎的存取控制(role-based access control)解決了存在於高度安全、但是嚴格的強制存取控制(MAC, mandatory access control)架構,與富有彈性、但是不夠牢靠的隨意存取控制(DAC ,discretionary access control)平台兩者之間的差距問題。
MAC通常是早期大型主機與一些高度機密的政府系統所採行的方法。MAC具有高度的安全性,因為作業系統會控制主體(subject)與受體物件(object)之間的所有存取動作;每位使用者都會被賦予一個許可證級別(例如「機密」),而每個物件或檔案也都會被賦予一個分類級別(例如「最高機密」)。這種作法提供了很好的控制,但是實作與維護同樣需要「很大」的心力。基於這個理由,現在MAC已經很少見了。
大部分的現代作業系統都是採用DAC,由管理者決定哪些物件應該具有何種存取權限,並根據此原則來進行分配。DAC具有很大的彈性,可以控制誰擁有存取什麼物件的權限,然而這可能也是安全方面的夢魘。雖然組織應該要有一條原則,規定在賦予某人存取權限之前,需要經過合乎程序的授權作業,然而我們無法確知組織是否真的做到,或者是否完全做到。此外,因為存取權限已經給了使用者,所以管理者必須確定在他們轉換或者結束作業的時候,能夠撤銷相關的權限,並且重新賦予其他符合現況的對等權限。
NET克服這項問題的作法是,允許開發人員在應用程式裡面指派一些內建的角色,藉以確保能夠提供徹底而全面的控制(請見圖1)。因為安全性從一開始就必須被建構到整個設計裡面,所以這樣的作法使得安全防護能夠成為架構的一部分,並且融入程式碼裡面。另一方面,管理者必須負責決定誰應該取得什麼角色,但是卻不能夠變更已經建立好的整體安全規範。
以辨識為基礎的存取控制(evidence-based access control)建構了一個額外的安全層,將存取權限依附至程式本身,藉以限制程式的執行。在Web環境中,小型的行動程式必須具備足夠的彈性,以便與其他程式進行互動,而且是安全的互動。有一種危險情況是,來自網際網路未受信任的程式,可能會存取系統上的其他應用程式,導致危害到整個系統,或者被取走機密資料。
如果採用.NET的話,程式會跟使用者一樣被分派安全限制,藉以告訴程式可以在什麼時候、什麼地方執行。當一段行動程式被下載之後,需要具備於系統上執行的適當權限。.NET的控制會去檢查程式由安全原則所定義的辨識項,比方說數位簽章(digital signature)便能夠對程式進行驗證,並且定義程式應該在哪些限制之下運作。
安全變簡單了
至目前為止,「安全」依舊不是那些必須確保應用程式功能可以正確運作,以及必須讓應用程式按照預定時程推出的開發人員,會去關心的重要議題。
其結果就是存在可能遭受利用的弱點,常見的是不恰當的錯誤檢查機制(有時甚至根本沒有進行錯誤檢查)。舉例而言,攻擊者可能會故意製造緩衝區溢位,假設開發人員配置了記憶體數量為“x”的空間,但是卻沒有針對數量是否超過範圍進行檢查的話,一旦攻擊者輸入的資料為“x-plus”的時候,將會覆寫返回指標的位址,導致執行到攻擊者自己所寫的惡意程式(malicious code)。另一種情況則是,假設攻擊者可以輸入超過帳戶號碼所要求,比方說8個位數時,那麼他可能只要在後面附加一個分號,然後寫入額外的敘述句,便能夠執行SQL隱碼攻擊。
雖然你可以撰寫大量的錯誤檢查程式碼,來阻止這些情況發生,不過程式也可能會變得非常複雜、運算耗時,而且容易發生失誤。
有了.NET,要將錯誤檢查整合到程式裡面變得更容易了,幾乎不必付出任何額外的程式設計努力,只需要在記憶體檢查的部分設定參數即可(請見圖2)。此外,就算沒有設定參數,.NET也會在編譯期間向程式設計人員提出警告。
現在,讓我們來考慮另一個關於.NET如何幫助開發人員,簡化其撰寫防駭程式工作的例子。因為HTTP是沒有狀態的(stateless),所以電子商務應用程式需要由開發人員去加入工作階段的ID並且負責維護,以便追蹤程式的狀態。對於開發人員而言,這意味著額外的工作負荷,而對於導入的錯誤來說,則意味著一條可能導致產生潛在漏洞威脅的途徑。
透過.NET,因為相關功能已經寫好放在.NET Framework裡面了,所以可以在Web Service架構需要強化安全的任何地方利用這些功能。在網頁層級,藉由將“trace=true”這個屬性新增到程式當中,.NET將會自動記錄接下來的要求細節、追蹤資訊、控制樹狀圖、工作階段狀態、Cookie集合、標頭集合,以及伺服器變數。
事在人為
當然,.NET安全性功能還有許多豐富的內容。其他強大的內建功能主要是加解密的實作,包括針對靜態儲存的與動態傳輸中的資料。.NET提供了PKI(公開金鑰基礎建設,public key infrastructure)與RSACryptoServiceProvider(讓你無須掛心PKI,也能夠產生與管理金鑰)加解密程式庫。畢竟,你不會想為網際網路上的每位使用者都實作PKI。儘管金鑰管理仍舊是個棘手的問題,不過.NET Framework提供了簡單的方法,可以讓你在程式裡面控制與管理金鑰。
儘管如此,雖然.NET頻道的開發人員致力於撰寫防駭程式,並且在網頁上展示.NET Framework強大而深入的安全功能,不過公司的方針與實踐(而非功能強健的工具)才是促使Web應用程式足以防駭的安全關鍵。如果你在開發工作的流程當中,做出了嚴格的安全及測試指示,那麼.NET將會提供非常大的幫助,以成功作為你努力的回報。
Eric Cole, CISSP, GIAC,是Sytex Group的首席科學家,也是Hackers Beware以及Network Security Bible作家。