数据库和Webapp安全
威脅模型
這是根據(jù)我網(wǎng)站上的快速參考頁松散地討論數(shù)據(jù)庫和Webapp安全的問題。 該頁面變得笨拙,并且使讀者無法輕松地與我或其他人進(jìn)行交互。
威脅模型
所有安全分析都必須從檢查威脅模型開始。 威脅模型要求您回答四個問題:
- 我要保護(hù)的是什么?
- 從誰?
- 多長時間?
- 以及(凈)成本是多少?
我要保護(hù)什么?
這是顯而易見的起點(diǎn)……您的第一個答案可能是錯誤的! 我的意思是,您可能會回答“數(shù)據(jù)庫密碼”,但這并不完全正確。 您實(shí)際上要保護(hù)的是以該用戶身份訪問數(shù)據(jù)庫–攻擊者可能無需密碼即可進(jìn)入數(shù)據(jù)庫,例如SQL注入。
但是,等等,那也不完全正確! 我們真正關(guān)心的是阻止攻擊者使用該訪問權(quán)造成損害,學(xué)習(xí)敏感信息等。 在這一點(diǎn)上,我們應(yīng)該列舉我們的實(shí)際關(guān)注點(diǎn),例如,我們的數(shù)據(jù)庫可能包含
- 用戶內(nèi)容
- 財(cái)務(wù)信息
- 用戶認(rèn)證和授權(quán)
- 日志
- 靜態(tài)內(nèi)容
我們訪問和使用此信息的方式各不相同
- 用戶內(nèi)容– 需要持續(xù)的讀/寫訪問權(quán)限
- 財(cái)務(wù)信息– 需要預(yù)言(用于批準(zhǔn)),并且可以將詳細(xì)信息留給履行流程
- 用戶身份驗(yàn)證和授權(quán)– 用戶登錄時需要一個oracle(用于批準(zhǔn)和授權(quán)),但以后再不需要(oracle)
- 日志– 需要正在進(jìn)行的僅追加訪問(oracle)
- 靜態(tài)內(nèi)容– 啟動時需要只讀訪問權(quán)限(oracle)
(所有訪問權(quán)限都以維護(hù)需求為模。)
oracle是一個獨(dú)立方法,它采用(可選)值并返回true或false 。 一般而言,它可以返回任何獨(dú)立的,不變的對象。 oracle的一個好的實(shí)現(xiàn)選擇是數(shù)據(jù)庫中的存儲過程,一個更好的選擇是使用獨(dú)立數(shù)據(jù)庫對另一個webapp進(jìn)行REST調(diào)用。
甲骨文的兩個例子:
用戶身份驗(yàn)證:使用一個使用用戶名和密碼并返回一個布爾值的oracle值,該值指示其是否有效。 (或者:成功后返回完整的authn / authz結(jié)構(gòu)。)非oracle方法是使應(yīng)用程序?qū)τ脩艉兔艽a表進(jìn)行查詢,并比較密碼本身。
信用卡身份驗(yàn)證:使用一個預(yù)告片,該預(yù)告片將獲取信用卡信息和購買金額并返回確認(rèn)號或錯誤指示。 該應(yīng)用程序可以依靠oracle保留以前提供的值的副本(而不是CVV!),因此用戶不必每次都填寫相同的信息。 。 非Oracle方法是應(yīng)用程序?qū)⑿畔⒈旧砝壴谝黄稹?
我在這里提出的觀點(diǎn)是,確定需要保護(hù)的內(nèi)容是一個體系結(jié)構(gòu)問題,而一些遠(yuǎn)見卓識會對威脅模型產(chǎn)生巨大影響。 您希望盡可能少地接觸不受信任的用戶(例如,Web應(yīng)用程序),而小的更改可能會帶來很大的不同。
最后但并非最不重要的一點(diǎn)是,應(yīng)該保護(hù)另一件事:您的聲譽(yù)。 不是公司的-開發(fā)人員的。 當(dāng)您接到公司總裁打來的電話,要求知道為什么公司將成為夜間新聞的主角時,您怎么說? 您無法防御所有攻擊,但是當(dāng)有人要求知道為什么您沒有采取基本步驟來保護(hù)系統(tǒng)時,您就不會無言以對。
從誰?
大家。
好吧,我開玩笑。 但是還有比您最初想的要廣泛得多的列表。
- 員工流于糊涂。 我們都做到了。 他們已經(jīng)具有合法訪問權(quán)限。
- 心懷不滿的員工,尤其是即將離職的員工。 他們已經(jīng)擁有合法的使用權(quán)和動力。
- 腳本小子。 我們傾向于認(rèn)為它們并不復(fù)雜,但是它們可能正在運(yùn)行由專家編寫的破解工具。 如果您的網(wǎng)站相當(dāng)安全,他們可能會轉(zhuǎn)向更輕松的目標(biāo)。
- 高級持續(xù)威脅(ATP)。 這些人有很強(qiáng)的動力和強(qiáng)大的技術(shù)技能。 假設(shè)他們會進(jìn)來。
該列表并非詳盡無遺,列出其他“潛在攻擊者”作為練習(xí)是留給讀者的。
多長時間?
冒著被暴露的風(fēng)險(xiǎn),存在三大類
- 必須保護(hù)直到相對不久的特定日期的信息或訪問權(quán),然后才是公開知識,例如公司財(cái)務(wù)報(bào)告。
- 隨時間推移價(jià)值下降的信息或訪問。
- 必須永遠(yuǎn)受到保護(hù)的信息或訪問,例如機(jī)密的法律和醫(yī)療文件。
第一類很簡單,因?yàn)橐阎钪乃惴ê凸?#xff0c;并且攻擊者的工作時間有限。
最后一類很困難,因?yàn)槲覀冎罒o法預(yù)測未來的攻擊。 10年前不可能實(shí)現(xiàn)的某些事情現(xiàn)在已經(jīng)行之有效。 一個很好的建議:我們不保留的東西就是我們不需要保護(hù)的東西。 保持盡可能少但不要少。
對該博客條目的范圍進(jìn)行全面分析,但這是一個不容忽視的重要問題。
凈價(jià)是多少?
“成本”是一個靈活的概念,因?yàn)榇嬖谠S多間接成本和推斷成本。 例如,使人們更難以完成工作需要付出什么代價(jià)……或者由于系統(tǒng)在漏洞發(fā)生后的幾天內(nèi)不會宕機(jī),它會更便宜嗎? 人們沮喪地離開站點(diǎn)的成本是多少,而當(dāng)您的站點(diǎn)遭到破壞成為全國新聞之后人們沒有集體離開站點(diǎn)的收益又是什么呢?
最重要的是,這最終是一個非技術(shù)性的問題。 您所能做的就是確定直接和間接的問題,并讓將要做出的決定權(quán)得到最終確定。
把它放在一起
最重要的是,威脅模型最終是業(yè)務(wù)決策。 我們可以提供分析和建議,但最終決定必須來自于上級。
也就是說,我們可以主動采取許多行動。 討論將解決其中一些問題。
SQL注入
什么是SQL注入?
SQL注入是攻擊者將任意SQL命令插入系統(tǒng)的能力。
樣本攻擊
看下面的代碼:
ResultSet rs = stmt.execute('select * from users where username='' + username +'' and password='' + password + ''');可能出什么問題了? 假設(shè)我們使用以下值:
String username = 'bob' or 1=1; --'; String password = 'dont care';當(dāng)我們調(diào)用較早的代碼時,生成的代碼是
select * from users where username='bob' or 1=1; --'and password='dont care'這將列出所有用戶。 一些Web框架將列出系統(tǒng)中的所有用戶。 如果返回了多個記錄,則編寫更仔細(xì)的應(yīng)用程序?qū)l(fā)出警報(bào)。 這很容易修復(fù)
String username = 'bob' or 1=1 order by userid limit 1; --'; String password = 'dont care';生產(chǎn)
select * from users where username='bob' or 1=1order by userid limit 1; --' and password='dont care'“ order by”節(jié)確保我們看到系統(tǒng)中的第一個用戶。 通常是管理員–攻擊者不會忘記的事情。
錯誤的方法
許多沒有經(jīng)驗(yàn)的程序員試圖通過顯式清理用戶提供的輸入來解決此問題。
ResultSet rs = stmt.execute('select * from users where username='' +username.replaceAll(''', ? '''') +'' and password='' + password.replaceAll(''', '''') + ''');這可能在1980年代奏效,但當(dāng)今世界使用的字符數(shù)超過了ASCII。 正確地識別引號字符是不平凡的問題,應(yīng)留給其他人解決。 JDBC編寫器通常為此使用特定于數(shù)據(jù)庫的方法,但是它們可能與數(shù)據(jù)庫不同步,并且當(dāng)然是特定于數(shù)據(jù)庫的。
準(zhǔn)備好的聲明和占位符
解決此問題的標(biāo)準(zhǔn)方法是使用準(zhǔn)備好的語句和占位符。 這代替了代碼
ResultSet rs = stmt.execute('select * from users where username='' +username + '' and password='' + password + ''');與
PreparedStatment stmt = conn.prepareStatement('select * from users where username=? and password=? limit 1'); stmt.setString(1, username); stmt.setString(2, password); ResultSet rs = stmt.execute()
局限性
有時候,準(zhǔn)備好的語句是不合適的。 一個常見的示例是多插入語句。 這些可以比多個準(zhǔn)備好的語句調(diào)用快得多。
多插入語句的一個示例是
insert into squares(x, y)values (1, 1),(2, 4),(3, 9),(4, 16),(5, 25);通常,不應(yīng)將其與用戶提供的數(shù)據(jù)一起使用。 如果絕對需要,請使用JDBC提供程序提供的特定于數(shù)據(jù)庫的方法,而不是滾動自己的解決方案。
成本效益分析
使用準(zhǔn)備好的語句占位符的成本/收益分析是無關(guān)緊要的,這只是您要做的事情之一。
存儲過程中的SQL注入
什么是存儲過程和CallableStatements?
存儲過程是數(shù)據(jù)庫中保留的部分代碼。 最常見的形式是類似SQL的腳本語言,但支持其他語言-PERL,tcl,ruby,java等。
重要的是要記住,數(shù)據(jù)庫觸發(fā)器中使用了存儲過程–即使您使用休眠狀態(tài)進(jìn)行所有工作,也應(yīng)注意它們。
錯誤的方法
錯誤的方法是創(chuàng)建動態(tài)SQL查詢而不進(jìn)行清理。
DELIMITER $$ DROP PROCEDURE IF EXISTS SP_AUTHENTICATE$$ CREATE PROCEDURE SP_AUTHENTICATE(IN username VARCHAR(20),IN password VARCHAR(20),OUT success INT) BEGINSET @query = CONCAT('SELECT COUNT(credentials.username) INTO @succFROM credentialsWHERE credentials.username = \'', username,'\' AND credentials.password = \'', password, '\'');PREPARE stmt FROM @query;EXECUTE stmt;SELECT @succ;SET success = @succ; END; $$ DELIMITER ;(注意:此代碼片段是一個示例,來自下面的參考。)
除了非常適度的封裝外,此存儲過程與我們之前看到的“錯誤答案”沒有任何關(guān)系。
旁注:這是一個oracle的示例。 它返回有關(guān)用戶身份驗(yàn)證的最少信息–“豎起大拇指”或“豎起大拇指”。 由于調(diào)用者已經(jīng)知道用戶名和密碼,所以此實(shí)現(xiàn)中沒有信息泄漏,但是更可靠的實(shí)現(xiàn)也可以驗(yàn)證用戶帳戶是否已禁用等。
存儲過程和參數(shù)化
第一種安全的方法是直接執(zhí)行SQL,而不是創(chuàng)建動態(tài)SQL。
第二種安全方法是在存儲過程中進(jìn)行參數(shù)化。 這直接等效于Java準(zhǔn)備好的語句和占位符。
DELIMITER $$ DROP PROCEDURE IF EXISTS SP_AUTHENTICATE$$ CREATE PROCEDURE SP_AUTHENTICATE(IN username VARCHAR(20),IN password VARCHAR(20),OUT success INT) BEGINSET @query = 'SELECT COUNT(credentials.username) INTO @succFROM credentialsWHERE credentials.username = ? AND credentials.password = ?';PREPARE stmt FROM @query;SET @usernm = username;SET @pass = password;EXECUTE stmt USING @usernm, @pass;SELECT @succ;SET success = @succ; END; $$ DELIMITER ;
PLPSQL消毒
如果您愿意與特定的數(shù)據(jù)庫供應(yīng)商聯(lián)系,則還有另一種選擇。 實(shí)際上,這通常不是問題-休眠為您提供了一些數(shù)據(jù)庫透明性,但是存儲過程將始終與數(shù)據(jù)庫緊密聯(lián)系。
在plpsql (PostgreSQL)中,有兩個命令可用于清理輸入: quote_ident和quote_literal 。 毫無疑問,其他存儲過程語言中也有類似的命令。
更新上面的錯誤答案,我們有:
DELIMITER $$ DROP PROCEDURE IF EXISTS SP_AUTHENTICATE$$ CREATE PROCEDURE SP_AUTHENTICATE(IN username VARCHAR(20),IN password VARCHAR(20),OUT success INT) BEGINSET @query = CONCAT('SELECT COUNT(credentials.username) INTO @succFROM credentialsWHERE credentials.username = ', quote_literal(username),'AND credentials.password = ', quote_literal(password));PREPARE stmt FROM @query;EXECUTE stmt;SELECT @succ;SET success = @succ; END; $$ DELIMITER ;
直接SQL
最終的安全方法是使用具有最小參數(shù)大小的直接SQL調(diào)用。 CERT網(wǎng)站上提到了這一點(diǎn),但是我會猶豫使用它,因?yàn)楹苋菀着既灰氩话踩拇a。
DELIMITER $$ DROP PROCEDURE IF EXISTS SP_AUTHENTICATE$$ CREATE PROCEDURE SP_AUTHENTICATE(IN username VARCHAR(8),IN password VARCHAR(20),OUT success INT) BEGINSELECT COUNT(credentials.username) INTO successFROM credentialsWHERE credentials.username = username AND credentials.password = password; END; $$ DELIMITER ;
成本效益分析
存儲過程比裸SQL查詢更難利用,但這常常給人一種錯誤的安全感。 對于敏感信息(用戶身份驗(yàn)證,審核日志記錄),應(yīng)將其視為強(qiáng)制性的;在所有其他情況下,強(qiáng)烈建議使用此方法。
架構(gòu)所有權(quán)
什么是DDL,DML,DCL和TCL?
SQL包含四種不同類型的語句。
數(shù)據(jù)定義語言
數(shù)據(jù)定義語言(DDL)語句定義數(shù)據(jù)庫結(jié)構(gòu)。 可以將其視為建造倉庫但將鑰匙交給承租人的房東。
聲明:
- 創(chuàng)建– 創(chuàng)建表,視圖,索引等。
- alter – 更改表,視圖,索引,列等。
- drop – 刪除表,視圖,索引等
- 截?cái)啜C 從表中刪除所有記錄
- comment – 向表,列,視圖等添加注釋。
- 重命名– 重命名表,視圖等。
數(shù)據(jù)處理語言
數(shù)據(jù)操作語言(DML)語句在DDL創(chuàng)建的結(jié)構(gòu)內(nèi)管理數(shù)據(jù)。 可以將其視為倉庫的租戶-它可以使用倉庫,但不能拆除墻壁。
聲明:
- 選擇– 檢索數(shù)據(jù)
- insert – 將新數(shù)據(jù)插入表中
- 更新– 更新表中的現(xiàn)有數(shù)據(jù)
- 刪除– 從表中刪除數(shù)據(jù)
- 調(diào)用– 調(diào)用PL / SQL或其他存儲過程
- 解釋計(jì)劃– 解釋如何執(zhí)行查詢
- 鎖定表– 鎖定表以限制并發(fā)
數(shù)據(jù)控制語言
數(shù)據(jù)控制語言(CDL)語句控制對數(shù)據(jù)和架構(gòu)的訪問權(quán)限。 可以將其視為門上的鎖,允許在倉庫內(nèi)移動墻壁等。
聲明:
- 授予– 向用戶授予其他特權(quán)
- 撤消– 刪除用戶權(quán)限
交易控制語言
事務(wù)控制語言(TCL)語句用于控制事務(wù)。
聲明:
- 提交– 保存已完成的工作
- 回滾– 撤消已完成的工作
- savepoint – 標(biāo)記一個可以在以后回滾而不必回滾整個事務(wù)的點(diǎn)
- 設(shè)置交易– 設(shè)置交易選項(xiàng)
使用不同的數(shù)據(jù)庫用戶進(jìn)行模式和數(shù)據(jù)所有權(quán)
該模式應(yīng)由一個數(shù)據(jù)庫用戶(例如app_owner)擁有,而數(shù)據(jù)應(yīng)由另一個數(shù)據(jù)庫用戶(例如app_user)擁有 。
所有者應(yīng):
- 能夠運(yùn)行DDL和DCL語句
- 可以說沒有能力運(yùn)行DML語句
- 永遠(yuǎn)不會通過webapp訪問
用戶應(yīng)
- 能夠運(yùn)行DML和TCL語句
- 沒有能力運(yùn)行DDL或DCL語句
- 可通過webapp訪問
成本效益分析
分離模式和數(shù)據(jù)庫的所有權(quán)有一個非常有利的成本/收益比。 創(chuàng)建和維護(hù)數(shù)據(jù)庫時,成本會稍高一些,但實(shí)際上,它消除了Web入侵者破壞數(shù)據(jù)庫架構(gòu)本身的能力。 另一方面,數(shù)據(jù)仍然可以被刪除。
用戶認(rèn)證和授權(quán)信息
用戶身份驗(yàn)證( authn )是我們?nèi)绾沃烙脩艟褪撬暦Q的身份的人。 至少是用戶名和密碼,但是如果使用兩因素身份驗(yàn)證,則可以包括更多用戶名和密碼。
用戶授權(quán)( authz )是我們允許用戶執(zhí)行的操作。
這些是非常不同的問題,應(yīng)這樣對待。 某些架構(gòu),例如,如果站點(diǎn)使用siteminder或類似工具,則它根本無法訪問身份驗(yàn)證信息-它只能添加身份驗(yàn)證。
什么是用戶身份驗(yàn)證/身份驗(yàn)證信息? 它是
- 用戶名和/或電子郵件
- 密碼
- 單點(diǎn)登錄(SSO)標(biāo)識
- 安全令牌(用于雙重身份驗(yàn)證)
- 安全圖片/短語(用于證明您的網(wǎng)站對用戶合法)
- 團(tuán)體和角色
什么是用戶身份驗(yàn)證/身份驗(yàn)證信息?
- 聯(lián)系信息
- 內(nèi)容訂閱
- 或驗(yàn)證或授權(quán)用戶不需要的其他任何內(nèi)容。
錯誤的方法
將所有內(nèi)容(用戶身份驗(yàn)證/身份驗(yàn)證,靜態(tài)內(nèi)容和動態(tài)內(nèi)容)放入單個數(shù)據(jù)庫架構(gòu)中。
很快
這簡單。
這是自動生成工具的默認(rèn)行為。
這是非常非常錯誤的,因?yàn)槿魏纹平饽腤eb應(yīng)用程序的人都還破解了您的用戶authn / authz數(shù)據(jù)。 充其量您將獲得拒絕服務(wù)。 在最壞的情況下,他們可以偽裝成其他用戶,可以添加自己的高度特權(quán)帳戶等。
單獨(dú)的架構(gòu)和連接池
最快的解決方案是為用戶authn / authz數(shù)據(jù)創(chuàng)建一個單獨(dú)的架構(gòu),并在訪問該數(shù)據(jù)時使用專用的數(shù)據(jù)源(或Hibernate會話)。 從標(biāo)準(zhǔn)數(shù)據(jù)源(或Hibernate會話)應(yīng)該無法讀取該模式。 這為您提供了一個不錯的防火墻,但它并不完美。
一個看似更健壯的解決方案是對用戶authn / auhtz數(shù)據(jù)使用單獨(dú)的數(shù)據(jù)庫,而不僅僅是單獨(dú)的模式。 這似乎可以保護(hù)您免受權(quán)限配置錯誤的影響,該權(quán)限配置允許動態(tài)內(nèi)容數(shù)據(jù)源訪問用戶數(shù)據(jù)源。
可悲的是,在某些RDMBS中,模式和數(shù)據(jù)庫之間沒有明確的區(qū)別,并且如果授予必要的權(quán)限,則與一個“數(shù)據(jù)庫”的連接仍可以訪問另一個“數(shù)據(jù)庫”。 您無法確定,除非您具有用于用戶authn / authz和動態(tài)內(nèi)容的單獨(dú)的數(shù)據(jù)庫實(shí)例。 如果您的體系結(jié)構(gòu)具有專用于用戶authn / authz的服務(wù)器,那么這可能不是一個不適當(dāng)?shù)呢?fù)擔(dān)。 對于虛擬服務(wù)器或云設(shè)計(jì)而言,這并非不合理。
基于容器的身份驗(yàn)證
更好的解決方案是基于容器的身份驗(yàn)證。 將用戶authn / authz完全從Web應(yīng)用程序中拉出-到Web應(yīng)用程序獲取請求時,HttpServletRequest已經(jīng)填充了所有必要的信息。 您的Web應(yīng)用無法訪問容器的身份驗(yàn)證信息。 (對上述注釋進(jìn)行模數(shù)化-如果容器與動態(tài)內(nèi)容位于相同的架構(gòu)中,您將不會有任何收獲。)
這種方法的一種變體是放在Web應(yīng)用程序前面的身份驗(yàn)證過濾器,例如,來自Spring Security的那些過濾器。 這是一種不同的機(jī)制,但具有相同的目的,即在用戶數(shù)據(jù)和動態(tài)內(nèi)容之間保持非常清晰的區(qū)分。
小故障–添加和更新用戶
這里有一個小故障-如果您的Web應(yīng)用程序無法訪問用戶的authn / authz表,如何添加或更新用戶信息?
第一種方法是創(chuàng)建一個單獨(dú)的處理該問題的Web應(yīng)用程序。 您的主Web應(yīng)用程序可以根據(jù)需要透明地重定向到第二個Web應(yīng)用程序。 好處是您可以擁有一致的外觀和感覺,缺點(diǎn)是您將用戶的authn / authz信息再次暴露給了weeb。
第二種方法是創(chuàng)建一個單獨(dú)的REST服務(wù)來處理此問題。 您的Web應(yīng)用程序可以提供用戶界面,但可以調(diào)用REST服務(wù)而不是標(biāo)準(zhǔn)業(yè)務(wù)層。 REST服務(wù)可以在您的防火墻內(nèi)。
第三種方法是將其完全推遲到容器中。 這樣可以確保最大程度的分離,但是很難保持一致的外觀。
相關(guān)鏈接
https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=70288108
參考: 數(shù)據(jù)庫和Webapp安全性,第1部分:威脅模型 , 數(shù)據(jù)庫和Webapp安全性,第2部分:SQL注入 , 數(shù)據(jù)庫和Webapp安全性,第3部分:存儲過程中的SQL注入 , 數(shù)據(jù)庫和Webapp安全性,第4部分:模式所有權(quán) , 數(shù)據(jù)庫Webapp安全性,第5部分: JCG合作伙伴 Bear Giles在Invariant Properties博客上的用戶身份驗(yàn)證 。
翻譯自: https://www.javacodegeeks.com/2012/11/database-and-webapp-security.html
總結(jié)
以上是生活随笔為你收集整理的数据库和Webapp安全的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaOne 2012:在JVM上诊断
- 下一篇: 在MySQL数据库上使用Quartz S