《NoSQL注入的分析和緩解》要點:
本文介紹了NoSQL注入的分析和緩解,希望對您有用。如果有疑問,可以聯系我們。
本篇文章已經在IEEE Software 雜志上首發.IEEE Software 就今天的戰略性技術問題提供了可靠的、經專家評審過的信息.IT管理者和技術領導應依靠新先進解決方案的IT專業人員,以迎接運行可靠的、靈活的企業這一挑戰.
數據庫安全是信息安全的一個重要內容.訪問企業數據庫授權攻擊者能夠充分控制關鍵性數據.例如,SQL注入攻擊把惡意代碼插入到應用向數據庫層發送的語句中.這使攻擊者幾乎能對數據做任何操作,包括訪問未授權的數據,以及修改、刪除和插入數據.盡管由于框架更安全、人們意識更強,SQL注入這種手段的利用率近幾年來已經穩步下降,但它仍然是個高危的系統漏洞.例如,Web應用每月受到四次或更多次Web攻擊活動,而SQL注入仍然是攻擊零售商最流行的方式1.此外,SQL注入漏洞對32%的Web應用都有影響.
NoSQL(不僅僅是SQL)是數據存儲的一個流行趨勢;它泛指依賴于不同存儲機制的非關系型數據庫,這些存儲機制包括文檔存儲、鍵值對存儲和圖.這些數據庫的廣泛應用是由現代大型應用推動起來的,比如Facebook、Amazon和Twitter,它們需要把數據分布到許多的服務器上.傳統關系型數據庫不滿足這種擴展性需求,它們需要一個單獨的數據庫節點去執行同一事務的所有操作.
于是,發展出一批分布式的、NoSQL鍵值對存儲來滿足這些大型應用的擴展性需求.這些數據存儲包括像MongoDB和Cassandra之類的NoSQL數據庫,也有像Redis和Memcached這樣的內存和緩存存儲.確實,NoSQL的受歡迎程度在過去幾年來一直在穩定上升,其中MongoDB在10個最流行的數據庫中排到了第四位,如圖1所示.
圖1 ?db-engines.com 2015年8月流行度排名中前十個最受歡迎的數據庫.其中NoSQL數據庫有MongoDB、Cassandra和Redis.這三款的受歡迎程度仍在上升.
在本文中,我們將分析NoSQL的威脅和技術,以及它們的緩解機制.
幾乎就像每種新技術一樣,NoSQL數據庫在剛出現時還不夠安全3–5.它們當初缺乏加密、適當的認證、角色管理和細粒度的授權等6.此外,它們還會出現危險的風險暴露和拒絕服務攻擊3.如今,情況已經好轉了,流行的數據庫已經引入了內置的保護機制7.
NoSQL數據庫使用不同的查詢語言,這使傳統的SQL注入技術已經無效了.但這是否意味著NoSQL系統對注入免疫呢?我們的研究表明,盡管這個查詢語言及其驅動的安全性已經大型提升,但仍然存在著注入惡意查詢的手段.已經有人整理出了NoSQL注入技術的列表1,3,4.有些初步應用掃描項目已經涌現出來了(例如nosqlproject.com),而且開放式Web應用程序安全項目(OWASP,Open Web Application Security Project)已經公布了檢查NoSQL注入代碼的建議.然而,這些還僅僅是初步成果,這些問題尚未得到充分的研究,并且未得到應有的關注.
Web應用和服務通常使用NoSQL數據庫去保存客戶數據.圖2展示了一個典型的架構,在此NoSQL用于保存通過Web應用來存取的數據.通過一個驅動程序來進行這個數據庫的訪問,即一個存取協議包裝器,它為多種編程語言編寫的數據庫客戶端提供類庫.盡管該驅動程序自身可能不易受到攻擊,但有時它們提供了不安全的API,當應用開發人員錯誤地使用它們時,就會給該應用引入漏洞了,這些漏洞會被人利用對數據庫進行任意操作.如圖2所示,攻擊者可以偽造一個帶有注入代碼的Web訪問請求,當數據庫客戶端或協議包裝器進行處理時,將會執行預期的非法數據庫操作.
圖2 典型Web應用架構.NoSQL用于保存通過Web應用來存取的數據.通過一個驅動程序來進行這個數據庫的訪問,即一個存取協議包裝器,它為多種編程語言編寫的數據庫客戶端提供類庫.盡管該驅動程序自身可能不易受到攻擊,但有時它們提供了不安全的API,當應用開發人員錯誤地使用它們時,就會給該應用引入漏洞了.
NoSQL相關的SQL攻擊主要機制可以大致分為以下五類:
盡管相對安全,但流行的JSON表述格式仍可受到新類型的注入攻擊.我們將舉例說明MongoDB中的此類攻擊,MongoDB是一個面向文檔的數據庫,已經有多個大型供應商予以采用,其中包括eBay、Foursquare和LinkedIn.
在MongoDB中,查詢和數據以JSON格式描述,這在安全方面要優于SQL,因為它是更充分定義的,容易進行加密和解密,而且在每種編程語言中都有不錯的原生實現.像SQL注入那樣對查詢結構的破壞,在JSON結構的查詢中會更難實現.在MongoDB中常見的插入語句應該是這樣的:
這會插入一個新的文檔到books的集合中,它具有title(標題)和author(作者)字段.常見的查詢條件應該是這樣的:
除限制要查詢的字段之外,查詢中還可以包括正則表達式和條件.
讓我們審視一下圖3中所畫的架構,一個使用PHP實現后端的Web應用,它將用于查詢數據存儲的請求編碼為JSON格式.讓我們使用一個MongoDB示例去演示數組注入漏洞吧,從技術和結果上來看這是一個與SQL注入有些類似的攻擊手段.
圖3 使用MongoDB的PHP應用.一個使用PHP實現后端的Web應用,它把用于查詢數據存儲的請求編碼為JSON格式.
PHP編碼數組為原生JSON.嗯,數組示例如下:
將由PHP編碼為以下JSON格式:
果一個PHP具有登錄機制,由用戶瀏覽器通過HTTP POST(它像HTTP GET一樣容易受到攻擊)發送過來用戶和密碼,常見的POST URL編碼應該是這樣的:
后端PHP代碼針對該用戶對它進行處理并查詢MongoDB,如下所示:
這本身合情合理沒什么問題,直覺上開發人員可能喜歡用以下查詢:
然而,PHP針對關聯數組有個內置的機制,這讓攻擊者有機可乘,可發送以下惡意的數據:
PHP會把該輸入解析為:
它會編碼為如下MongoDB查詢:
因為$ne是MongoDB用來判定條件是否不相等的,所以它會查詢登錄集合中的所有用戶名稱不等于1且密碼也不等于1的記錄.因此,本次查詢將返回登錄集合中的所有用戶.換成SQL的表述法,就等同于以下查詢語句:
在這種情況下,漏洞就為攻擊者提供了一個不必有效憑證即可登錄應用的方式.在其他變體中,該漏洞可能會導致非法數據訪問或由無特權的用戶執行特權操作.為緩解這個問題,我們需要轉換從需求中接收的參數為適當類型,在本例中,可使用字符串,如下所示:
SQL注入漏洞經常是由于未對用戶輸入進行適當編碼而直接拼接查詢造成的.在MongoDB之類的流行數據存儲中,JSON查詢結構使攻擊變得更難了.然而,這并不代表不可能.
讓我們看一個通過HTTP POST發送用戶名和密碼參數到后端的登錄表單,它通過拼接字符串的方式得到查詢語句.例如,開發人員可能會這么做:
具有有效輸入時,得到的查詢語句是應該這樣的:
但具有惡意輸入時,這個查詢語句會被轉換為忽略密碼的,在無需密碼的情況下登錄用戶賬號.惡意輸入示例如下:
該輸入會被構建到該查詢中:
只要用戶名是正確的,這個查詢就可以成功.轉換成SQL的表述,這個查詢類似于以下語句:
密碼成為這個查詢多余的一部分,因為()內的條件總為真,所以不會影響到查詢的最終結果.
這是怎么發生的呢?以下為拼接出的查詢串,用戶輸入為加粗字體,剩余的文本串為無格式字體:
這個攻擊在任何只要用戶名正確的情況下都將成功,一般得到個用戶名并不是什么難事.
NoSQL數據庫中有個共同特性,那就是可以在數據庫引擎中運行JavaScript,從而可以執行復雜的查詢或MapReduce之類的事務.包括MongoDB 和 CouchDB及其后續的 Cloudant 和 BigCouch等流行的數據庫都允許這么做.
如果不干凈的用戶輸入發現這種查詢方式的話,這么執行JavaScript就等于把薄弱面暴露給攻擊者了.
例如,設想一個需要JavaScript代碼的復雜事務,包含有不干凈的用戶輸入作為查詢的參數.讓我們看一下它的存儲模型,它保存了一組條目,每個條目具有價格和數量屬性.為得到這些屬性的總數或平均值,開發人員編寫了一個MapReduce函數,它從用戶那里接收數量或價格作為參數,然后進行處理.在PHP中,看起來是如下代碼($param是用戶輸入):
這段代碼把每個條目按名稱給定的$param合計起來.當時,$param預期是接收數量(amount)或價格(price)的,這段代碼將按預期進行運轉.但是,因為用戶輸入未被轉義,所以惡意輸入(它可能包含任意JavaScript)將被執行.
看一下如下輸入:
a);}},function(kv) { return 1; }, { ? ?out: ‘x’ });db.injection. insert({success:1});return 1;db.stores.mapReduce(function() { { ? ?emit(1,1
第一部分的數據會閉合最初的MapReduce函數,然后攻擊者就可以在數據庫上執行想要的JavaScript了(加粗部分).最終,最后一部分調用一個新的MapReduce以保持被注入代碼的原始語句的平衡.在把會被執行的用戶輸入合并到為字符串后,我們得到以下代碼(注入的用戶輸入加粗顯示):
這個注入看起來與經典的SQL注入非常相似.防御此類攻擊的一種方式是在數據庫配置中禁止執行JavaScript.如果JavaScript是必需的,那么最好的策略是不使用任何用戶輸入.
像Memcached、Redis和Tachyon之類的鍵值對存儲是內存數據存儲,旨在加快應用、云架構和平臺以及大數量框架的執行速度.這些平臺考慮的是反復頻繁訪問的數據的存儲和檢索.它們通常處于數據存儲之前,如圖4所示.緩存架構經常存儲認證令牌及容器訪問控制列表,對于每個后續的用戶請求必須重新使其生效.
圖4 分布式內存數據存儲架構.
被攻擊的Web服務器使用一個鍵值數據存儲進行快速數據檢索.對數據存儲的查詢是在該Web服務器上通過用戶提供的數據構建出來的.如果處理不適當,用戶數據可以導致一個非法查詢注入,它將被該鍵值面目數據存儲處理,導致應用邏輯中的錯誤,以此繞過認證或進行有害的數據檢索.
盡管由于鍵值對查詢很簡單所以通常緩存API也非常簡單,但我們發現一個Memcached(第二受歡迎的鍵值對面目全非)潛在的注入攻擊手段,那就是基于特定PHP版本的Memcached驅動程序中的漏洞.達成以下條件即可進行攻擊:
把一個鍵及相應的值加到使用Memcached的數據庫中的一組操作.當從命令行界面調用時,這組函數使用兩行輸入,第一行是:
然后第二行由要保存的數據構成.
當PHP配置的函數被調用時,它接收的兩個參數看起來是這樣的:
研究人員表示,該驅動程序未能針對帶有回車\r(0x0D)和換行的\n(0x0A)的ASCII碼采取措施,導致攻擊者有機會注入包含有鍵參數的新命令行和其他非計劃內的命令到緩存中8.
看一下如下代碼,其中的$param是用戶輸入并作為鍵來作用:
攻擊者可以提供以下輸入進行注入攻擊:
在本例中,增加到數據庫中的第一個鍵是具有“some value”值的key1.攻擊者可以增加其他的、非計劃內的鍵到數據庫中,即帶有“inject”值的key2.
這種注入也可以發生在get命令上.讓我們看一下Memcached主頁上的示例,它以這三行開頭:
這個示例展示了Memcached的典型用法,在處理輸入之前首先檢查在數據庫中是不是已經存在了.假設用類似代碼檢查從用戶那里接收的認證令牌,驗證他們是不是登錄過了,那么就可以通過傳遞以下作為令牌的字符串來利用它(注入部分已經加粗強調):
當這個字符串作為令牌傳遞時,數據庫將檢查這個“random_token”是否存在,然后將添加一個具有“root”值的“my_crafted_token”.之后,攻擊者就可以發送具有root身份的my_crafted_token令牌了.
可以被這項技術攻擊的其他指令還有:
在此,incr用于增加一個鍵的值,decr用于縮減一個鍵的值,以及delete用于刪除一個鍵.攻擊者也可以用像set和get函數一樣的手段來使用帶來自己鍵參數的這三個函數.
攻擊者可以使用多條目函數進行同樣的注入:deleteMulti、getMulti和setMulti,其中每一個鍵字段都可以被注入.
回車換行注入可以被用于連接多個get請求.在一項我們進行的測試中,包括原始get在內最多可以連接17條.這樣注入返回的結果是第一個鍵及其相應的值.
該驅動程序的漏洞已經在PHP 5.5 中修復,但不幸的是它已存在于之前所有的PHP版本中了.按照W3Techs.com對生產系統的PHP版本的統計來看,超過86%的PHP網站使用了比5.5要老的版本,這意味著如果他們使用了Memcached就很容易受到這種注入攻擊.
NoSQL數據庫的另一個常見特點是,他們能夠常常暴露能夠從客戶端應用進行數據庫查詢的HTTP REST API.暴露REST API 的數據庫包括MongoDB、CouchDB和HBase.暴露REST API 就直接把數據庫暴露給應用了,甚至是僅基于HTML5的應用,因為它不再需要間接的驅動程序了,讓任何編程語言都可以在數據庫上執行HTTP查詢.這么做的優勢非常明顯,但這一特點是否伴隨著安全風險?我們的回答是肯定的:這種REST API給跨站點請求偽造(CSRF)暴露了數據庫,讓攻擊者繞過了防火墻和其他外圍防御.
只要數據庫部署在諸如防火墻之類的安全設施之后的安全網絡中,攻擊者要危害這個數據庫就必須找到能讓他們進入這個安全網絡的漏洞,或者完成能讓他們執行任意查詢的注入.當數據庫在安全網絡內暴露 REST API時,任何能夠訪問該安全網絡的人都可以僅通過HTTP就能在這個數據庫上執行查詢,因此在瀏覽器上就可以發起此類查詢了.如果攻擊者可以在網站上輸入HTML表單,或者欺騙用戶到攻擊者自己的網站上,就能夠通過提交這個表單在數據庫上執行任何post操作了.而post操作包括增加文件.
我們在調查研究審查了Sleepy Mongoose,這是一個針對MongoDB的全功能HTTP接口. Sleepy Mongoose API是以http:// {host name}/{db name}/{collection name}/{action}這樣的URL格式定義的.查找文件的參數可以作為查詢參數包含在內,而新文件也可以作為請求數據予以添加.例如,如果我們想要在safe.internal.db主機上的數據庫中名為hr的管理員集合中增加一個新文件{username:’attacker’} ,就可以發送一個post HTTP請求至http://safe.internal.db/hr/admins/_insert,加上URL編碼過的數據username=attacker.
現在讓我們看看CSRF攻擊是如何使用這個函數增加新文件到管理員集合中的,從而在hr數據庫(它被認為處于安全的內部網絡中)中增加了一個新的管理員用戶,如圖5所示.若想攻擊成功,必須要滿足幾個條件.首先,攻擊者必須能操作一個網站,要么是他們自己的網站,要么是利用不安全的網站.攻擊在該網站放置一個HTML表單以及一段將自動提交該表單的腳本,比如:
圖5 NoSQL HTTP REST API上的跨站請求背負式攻擊示意圖.
藏在防火墻后的內部網絡內的用戶被欺騙訪問一個惡意外部網頁,這將導致在內部網絡的NoSQL數據庫的 REST API 上執行非預期的查詢.
第二,攻擊者必須通過網絡誘騙或感染用戶經常訪問的網站欺騙用戶進入被感染的網站.最后,用戶必須許可訪問Mongoose HTTP接口.
用這種方式,攻擊者不必進入內部網絡即可執行操作,在本例中,是插入新數據到位于內部網絡中的數據庫中.這種攻擊執行很簡單,但要求攻擊者要提前偵察去識別主機、數據庫名稱,等等.
鑒于我們在本文中所提到的這些攻擊手段,NoSQL部署中的安全問題的緩解是非常重要的.但不幸的是,應用層的代碼分析不足以確保所有風險都能得以緩解.三個趨勢使該問題將比之前面臨更多的挑戰.首先,云和大數據系統的形成,它們通常會執行多個復雜應用,這些應用使用異構的開源工具和平臺.而這些應用通常由開源社區開發,大多數情況下,未經受過全面的安全性測試.另一個挑戰是伴隨DevOps方法論而形成的現代代碼開發的速度,因為DevOps追求的是縮短開發和生產之間的時間.最后,大多數應用安全測試工具不能與新編程語言的應用保持同步,例如,大多數安全產品不支持Golang、Scala和 Haskel.
為充分解決由應用層引入的風險,我們需要考慮整個軟件開發生命周期,如圖6所示.
圖6 應用和部署安全的生命周期.為充分解決由應用層引入的風險,我們需要考慮整個軟件開發生命周期.
意識.很明顯,構建阻止注入和其他潛在漏洞的安全軟件是最好、最廉價的解決方案.建議在該軟件生命周期中涉及到的人針對他們的職責接受適應的安全培訓.例如,已經理解漏洞的開發人員就不太可能把它們引入到軟件中.
設計.應用的安全方面必須在開發階段早期予以考慮和定義.定義什么需要在應用內保護,如何確保這個功能已經轉化為開發階段中的任務并得到足夠的重視.
針對代碼的最佳實踐.建議充分利用已經經受過安全驗證處理的共享類庫,從而減少犯安全性錯誤的機會.例如,使用針對認證充分驗證過的類庫,減少開發人員自己實現認證把漏洞引入到算法中的風險.再舉一個使用“消毒后(sanitization)”類庫的例子.所有注入攻擊都是缺乏消毒造成的.使用一個充分測試消毒過的類庫能很大程度上減少以自主研發消毒方法引入漏洞的風險.
特權隔離.在過去,NoSQL不支持適當的認證和角色管理9.現在,在大多數流行的NoSQL數據庫上進行適當的認證管理和基于角色的訪問控制認證已經成為可能.這些機制出于兩個原因非常重要.第一,它們允許實施最少特權的原則,從而避免通過合法用戶的特權升級攻擊.第二,類似于SQL注入攻擊10,當數據存儲暴露在我們本文所說的注入攻擊之下時,適當的特權隔離能將危害最小化.
安全掃描.建議在應用或源碼上運行動態和靜態應用安全測試(分別為DAST和SAST)以發現注入漏洞.問題是目前市場上的許多工具缺乏檢測NoSQL注入的規則.DAST方法被認為比SAST更可靠11.特別是如果用戶使用后端檢查方法提升檢測可靠性的話,這是一種作為交互式應用安全測試提出的方法9,12.它還建議,集成這些掃描工具到持續構建和發布系統中,如此它們就會在每個周期或檢入時執行,缺陷就會及時發現并修復,而不只是在安全測試階段.
由于兩個原因,這可能會減少修復安全性缺陷的工作量.第一個,在開發階段修復缺陷的成本要遠低于生命周期更后的階段,特別是因為安全性測試往往都在功能性測試之后,而且修復安全性缺陷可能會需要重新做功能性測試.第二個,開發人員能在早期了解這些缺陷,在之后的代碼開發中不會犯類似的錯誤.
安全性測試.應該由專業的安全性測試人員測試應用.這些測試應該驗證所有在設計階段定義的安全需求都已經得到滿足,并應該包括應用和主機基礎設施之上(建議盡可能與生產環境類似)的浸透測試.
保持應用一個很重要的部分是確保安全的部署.如果部署不夠安全,所有在應用代碼層的安全性努力可能也就付之東流了.而這一階段有時會被忽視.
網絡隔離.Adobe、RSA Security和Sony等企業遭受了無數的攻擊,在這些攻擊中內網安全的概念已不再成立.內部網絡在某種情況下是滲透的邊界,我們應盡可能讓攻擊者很難從這一點上得到什么.對于某些相對較新缺乏基于角色授權的NoSQL數據庫來講這一點尤其如此.為此,建議嚴格配置網絡,確保數據庫只能由相關主機訪問,比如應用服務器.
API的防護.為緩解REST API暴露和CSRF攻擊的風險,需要對請求加以控制,限制它們的格式.例如,CouchDB已經采用了一些重要的安全措施去緩解因為暴露的REST API導致的風險.這些措施包括只接受JSON內容格式.HTML表單限制為URL編碼的內容格式,所以攻擊者不能使用HTML進行CSRF攻擊.另一項舉措是使用Ajax請求,得益于同源策略從瀏覽器發起的請求會被阻止.要確保在服務器的API中已經取消了JSONP和跨域資源共享,不能從瀏覽器直接發起操作,這一點也很重要.某些數據庫,比如MongoDB,有很多第三方的REST API,其中許多都缺乏我們在此提到的安全措施.
人類容易犯錯,即使遵循所有安全開發最佳實踐,仍有可能在開發完后從軟件中找到漏洞.此外,在開發測試時未知的新的攻擊途徑可能會被發掘出來.因此,建議在運行期進行應用的監控和防御.盡管這些系統可能擅于發現和阻止某些攻擊,但是它們不了解應用邏輯和那些假定運行的應用下的規則,所以它們不能找出所有的漏洞.
Web應用防火墻.Web應用防火墻(WAFs)是檢查HTTP數據流和檢測惡意HTTP事務的安全性工具.它們可以作為電器、網絡嗅探器、代理或網站服務器模塊來實現,具體目標是為Web應用提供一個獨立的安全層,檢測SQL注入之類的攻擊.盡管已知攻擊可以繞過防火墻13,但我們仍然提倡為這些系統增加檢測NoSQL注入的規則.
侵入檢測系統.與可以在網絡層檢測攻擊的防火墻類似,基于主機的侵入檢測系統(HIDSs)監控著應用的執行和服務器上的負載.HIDSs通常了解應用的正常行為,對與預期行為不符的行為給出預警,它們可能是攻擊.此類工具可以檢測在操作系統上傳播的漏洞,但和SQL檢測或CSRF無關.
數據活動監控.數據活動監控工具已成為組織數據防護的常規需求.它們控制數據的訪問,以自定義安全預警監控活動,并創建數據訪問和安全事件審計報告.雖然大多數解決方案定位的都是關系型數據庫,但針對NoSQL數據存儲的監控也已經開始涌現出來了10.我們希望這些將不斷地改進成為NoSQL活動監控的常規實踐.針對我們在本文演示過的注入攻擊,這些工具是非常有用的監控和檢測系統.
安全信息與事件管理(SIEM)系統和威脅警報.安全信息和事件管理系統整理日志并梳理日志的關聯關系去幫助攻擊的檢測.
此外,威脅警報工具可以幫助提供惡意IP地址和域上的數據,以及有危害的其他指標,這能有助于檢測注入.
運行期應用自我保護(RASP).運行期應用自我保護引入了一種新的應用安全方式,在此防御機制是在運行期嵌入到應用中的,使其可以進行自我監控.運行期應用自我保護的優點超過其他安全技術,因為它能夠檢查內部的程序流轉和數據處理.在應用中的關鍵位置設置檢查點能更精確地檢測更多的問題.而不利的一面是,運行期應用自我保護付出了性能的代價,它高度依賴于編程語言,而且可能導致應用在生產環境中中止運行.
NoSQL數據庫遭受像傳統數據庫一相的風險問題.一些低層技術和協議已經變了,但注入風險、不正確的訪問控制管理以及不安全的網絡暴露仍然居高不下.我們建議使用具有內置安全措施的成熟的數據庫.然而,即使使用最安全的數據存儲也無法阻止利用Web應用中的漏洞去訪問數據存儲的注入攻擊.避免這些問題的其中一種方法是通過謹慎的代碼檢查和靜態分析.然而,這些很難實施并且可能有很高的誤報率.盡管動態分析工具已表明對檢測SQL注入攻擊很有作用,但它們需要做出調整去檢測我們在本文中所說的那些特定于NoSQL數據庫的漏洞.此外,與NoSQL風險相關的監控和防御系統也應該利用起來
參考資料
文章來微信公眾號:高效開發運維
轉載請注明本頁網址:
http://www.snjht.com/jiaocheng/4242.html