webapp支持什么数据库_数据库和Webapp安全
webapp支持什么數據庫
威脅模型
這是根據我網站上的快速參考頁松散地討論數據庫和webapp安全的問題。 該頁面變得笨拙,并且使讀者無法輕松地與我或其他人進行交互。
威脅模型
所有安全分析必須從檢查威脅模型開始。 威脅模型要求您回答四個問題:
- 我要保護的是什么?
- 從誰?
- 多長時間?
- 以及(凈)成本是多少?
我要保護什么?
這是顯而易見的起點……您的第一個答案可能是錯誤的! 我的意思是,您可能會回答“數據庫密碼”,但這并不完全正確。 您實際上要保護的是以該用戶身份訪問數據庫–攻擊者可能無需密碼即可進入數據庫,例如SQL注入。
但是,等等,這也不完全正確! 我們真正關心的是阻止攻擊者使用該訪問權造成損害,學習敏感信息等。 在這一點上,我們應該列舉出我們的實際關注點,例如,我們的數據庫可能包含
- 用戶內容
- 財務信息
- 用戶認證和授權
- 日志
- 靜態內容
我們訪問和使用此信息的方式各不相同
- 用戶內容– 需要持續的讀/寫訪問權限
- 財務信息– 需要預言(用于批準),并且可以將詳細信息留給履行流程
- 用戶身份驗證和授權– 用戶登錄時需要一個oracle(用于批準和授權),但以后再不需要(oracle)
- 日志– 需要正在進行的僅追加訪問(oracle)
- 靜態內容– 啟動時需要只讀訪問權限(oracle)
(所有訪問權限都以維護需求為模。)
oracle是一個獨立方法,它采用(可選)值并返回true或false 。 一般而言,它可以返回任何獨立的,不變的對象。 oracle的一個好的實現選擇是數據庫中的存儲過程,一個更好的選擇是使用獨立數據庫對另一個webapp進行REST調用。
Oracle的兩個例子:
用戶身份驗證:使用帶有用戶名和密碼并返回一個布爾值的oracle值,該值指示其是否有效。 (或者:成功后返回完整的authn / authz結構。)非oracle方法是讓應用程序對用戶和密碼表進行查詢并比較密碼本身。
信用卡身份驗證:使用一個預告片,該預告片將獲取信用卡信息和購買金額,并返回確認號或錯誤指示。 該應用程序可以依靠oracle保留以前提供的值的副本(而不是CVV!),因此用戶不必每次都填寫相同的信息。 。 非Oracle方法是應用程序將信息本身捆綁在一起。
我在這里要指出的是,確定需要保護的內容是一個體系結構問題,而一些遠見卓識會對威脅模型產生巨大影響。 您希望盡可能少地接觸不受信任的用戶(例如,Web應用程序),而小的更改可能會帶來很大的不同。
最后但并非最不重要的一點是,還應保護另一件事:您的聲譽。 不是公司的-開發人員的。 當您接到公司總裁打來的電話,要求知道為什么公司將成為夜間新聞的主角時,您怎么說? 您無法防御所有攻擊,但是當有人要求知道為什么您沒有采取基本步驟來保護系統時,您就不會無言以對。
從誰?
大家。
好吧,我開玩笑。 但是還有比您最初想的要廣泛得多的列表。
- 員工無所適從。 我們都做到了。 他們已經具有合法訪問權限。
- 心懷不滿的員工,尤其是即將離職的員工。 他們已經擁有合法的使用權和動力。
- 腳本小子。 我們傾向于認為它們并不復雜,但是它們可能正在運行由專家編寫的破解工具。 如果您的網站相當安全,他們可能會轉向更簡單的目標。
- 高級持續性威脅(ATP)。 這些人有很強的動力和強大的技術技能。 假設他們會進來。
該列表并非詳盡無遺,列出其他“潛在攻擊者”作為練習是留給讀者的。
多長時間?
冒著被暴露的風險,存在三大類
- 必須保護到相對不久的特定日期的信息或訪問,然后才是公開知識,例如公司財務報告。
- 隨時間推移價值不斷下降的信息或訪問。
- 必須永遠受到保護的信息或訪問,例如機密的法律和醫療文件。
第一類很簡單,因為已知最知名的算法和攻擊,并且攻擊者的工作時間有限。
最后一類很困難,因為我們知道無法預測未來的攻擊。 10年前不可能實現的某些事情現在已經行之有效。 一個很好的建議:我們不保留的東西就是我們不需要保護的東西。 保持盡可能少但不要少。
對該博客條目的范圍進行全面分析,但這是一個不容忽視的重要問題。
以什么(凈)成本?
“費用”是一個靈活的概念,因為間接費用和推斷費用都很多。 例如,使人們更難以完成工作會付出什么代價……或者由于系統在漏洞發生后的幾天內不會宕機,它會更便宜嗎? 人們沮喪地離開網站的成本是多少,而在您的網站發生違規行為之后,人們沒有集體離開網站的收益是什么呢?
最重要的是,這最終是一個非技術性的問題。 您所能做的就是確定直接和間接的問題,并讓將要做出的決定權得到最終確定。
把它放在一起
最重要的是,威脅模型最終是業務決策。 我們可以提供分析和建議,但最終決定必須來自于上級。
也就是說,我們可以主動采取許多行動。 討論將解決其中一些問題。
SQL注入
什么是SQL注入?
SQL注入是攻擊者將任意SQL命令插入系統的能力。
樣本攻擊
看下面的代碼:
ResultSet rs = stmt.execute('select * from users where username='' + username +'' and password='' + password + ''');可能出什么問題了? 假設我們使用以下值:
String username = 'bob' or 1=1; --'; String password = 'dont care';當我們調用較早的代碼時,生成的代碼是
select * from users where username='bob' or 1=1; --'and password='dont care'這將列出所有用戶。 一些Web框架將列出系統中的所有用戶。 如果返回了多個記錄,則編寫更仔細的應用程序將發出警報。 這很容易修復
String username = 'bob' or 1=1 order by userid limit 1; --'; String password = 'dont care';生產
select * from users where username='bob' or 1=1order by userid limit 1; --' and password='dont care'“ order by”節確保我們看到系統中的第一個用戶。 通常是管理員–攻擊者不會忘記的事情。
錯誤的方法
許多沒有經驗的程序員試圖通過顯式清理用戶提供的輸入來解決此問題。
ResultSet rs = stmt.execute('select * from users where username='' +username.replaceAll(''', ? '''') +'' and password='' + password.replaceAll(''', '''') + ''');這可能在1980年代有效,但當今世界使用的字符數超過了ASCII。 正確地識別引號字符是一個不小的問題,應該留給其他人解決。 JDBC編寫器通常為此使用特定于數據庫的方法,但是它們可能與數據庫不同步,并且當然是特定于數據庫的。
準備好的聲明和占位符
解決此問題的標準方法是使用準備好的語句和占位符。 這代替了代碼
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()
局限性
有時候,準備好的語句是不合適的。 一個常見的示例是多插入語句。 這些可以比多個準備好的語句調用快得多。
多插入語句的一個示例是
insert into squares(x, y)values (1, 1),(2, 4),(3, 9),(4, 16),(5, 25);通常,不應將其與用戶提供的數據一起使用。 如果絕對需要,請使用JDBC提供程序提供的特定于數據庫的方法,而不是滾動自己的解決方案。
成本效益分析
使用準備好的語句占位符的成本/收益分析是無關緊要的,這只是您要做的事情之一。
存儲過程中SQL注入
什么是存儲過程和CallableStatements?
存儲過程是數據庫中保留的部分代碼。 最常見的形式是類似SQL的腳本語言,但支持其他語言-PERL,tcl,ruby,java等。
重要的是要記住,存儲過程是在數據庫觸發器中使用的-即使您使用hibernate進行所有工作,也應注意它們。
錯誤的方法
錯誤的方法是創建動態SQL查詢而不進行清理。
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 ;(注意:此代碼片段是一個示例,來自下面的參考。)
除了非常適度的封裝外,此存儲過程與我們之前看到的“錯誤答案”沒有任何關系。
旁注:這是一個oracle的示例。 它返回有關用戶身份驗證的最少信息–“豎起大拇指”或“豎起大拇指”。 由于調用者已經知道用戶名和密碼,所以此實現中沒有信息泄漏,但是更可靠的實現也可以驗證用戶帳戶是否已禁用等。
存儲過程和參數化
第一種安全的方法是直接執行SQL,而不是創建動態SQL。
第二種安全方法是在存儲過程中進行參數化。 這直接等效于Java準備好的語句和占位符。
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消毒
如果您愿意與特定的數據庫供應商聯系,則還有另一種選擇。 實際上,這通常不是問題-Hibernate為您提供了一些數據庫透明性,但是存儲過程將始終與數據庫緊密聯系。
在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
最終的安全方法是使用具有最小參數大小的直接SQL調用。 CERT網站上提到了這一點,但我會猶豫使用它,因為很容易偶然引入不安全的代碼。
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查詢更難利用,但這常常給人一種錯誤的安全感。 對于敏感信息(用戶身份驗證,審核日志記錄),應將其視為強制性的;在所有其他情況下,強烈建議使用此方法。
架構所有權
什么是DDL,DML,DCL和TCL?
SQL包含四種不同類型的語句。
數據定義語言
數據定義語言(DDL)語句定義數據庫結構。 可以將其視為建造倉庫但將鑰匙交給承租人的房東。
聲明:
- 創建– 創建表,視圖,索引等。
- alter – 更改表,視圖,索引,列等。
- drop – 刪除表,視圖,索引等
- 截斷– 從表中刪除所有記錄
- 注釋– 向表,列,視圖等添加注釋。
- 重命名– 重命名表,視圖等。
數據處理語言
數據操作語言(DML)語句在DDL創建的結構內管理數據。 可以將其視為倉庫的租戶-它可以使用倉庫,但不能撞墻。
聲明:
- 選擇– 檢索數據
- insert – 將新數據插入表中
- 更新– 更新表中的現有數據
- 刪除– 從表中刪除數據
- 調用– 調用PL / SQL或其他存儲過程
- 解釋計劃– 解釋如何執行查詢
- 鎖定表– 鎖定表以限制并發
數據控制語言
數據控制語言(CDL)語句控制對數據和架構的訪問權限。 可以將其視為門上的鎖,允許在倉庫內移動墻壁等。
聲明:
- 授予– 向用戶授予其他特權
- 撤消– 刪除用戶權限
交易控制語言
事務控制語言(TCL)語句用于控制事務。
聲明:
- 提交– 保存已完成的工作
- 回滾– 撤消已完成的工作
- savepoint – 標記一個可以在以后回滾而不必回滾整個交易的點
- 設置交易– 設置交易選項
使用不同的數據庫用戶進行模式和數據所有權
該模式應由一個數據庫用戶(例如app_owner)擁有,而數據應由另一個數據庫用戶(例如app_user)擁有 。
所有者應:
- 能夠運行DDL和DCL語句
- 可以說沒有能力運行DML語句
- 永遠不會通過webapp訪問
用戶應
- 能夠運行DML和TCL語句
- 沒有能力運行DDL或DCL語句
- 可通過webapp訪問
成本效益分析
分離架構和數據庫的所有權有一個非常有利的成本/收益比。 創建和維護數據庫時,成本會稍高一些,但實際上,它消除了Web入侵者破壞數據庫架構本身的能力。 另一方面,數據仍然可以被刪除。
用戶認證和授權信息
用戶身份驗證( authn )是我們如何知道用戶就是他聲稱的身份的人。 至少是用戶名和密碼,但是如果使用兩因素身份驗證,則可以包括更多用戶名和密碼。
用戶授權( authz )是我們允許用戶執行的操作。
這些是非常不同的問題,應這樣對待。 某些體系結構,例如,如果站點使用siteminder或類似工具,則它根本無法訪問身份驗證信息-它只能添加身份驗證。
什么是用戶身份驗證/身份驗證信息? 它是
- 用戶名和/或電子郵件
- 密碼
- 單點登錄(SSO)標識
- 安全令牌(用于雙重身份驗證)
- 安全圖片/短語(用于證明您的網站對用戶合法)
- 團體和角色
什么是用戶身份驗證/身份驗證信息?
- 聯系信息
- 內容訂閱
- 或驗證或授權用戶不需要的其他任何內容。
錯誤的方法
將所有內容(用戶身份驗證/身份驗證,靜態內容和動態內容)放入單個數據庫架構中。
很快
這很容易。
這是自動生成工具的默認行為。
這是非常非常錯誤的,因為任何破解您的Web應用程序的人都還破解了您的用戶authn / authz數據。 充其量您將獲得拒絕服務。 在最壞的情況下,他們可以偽裝成其他用戶,可以添加自己的高度特權帳戶等。
單獨的架構和連接池
最快的解決方案是為用戶authn / authz數據創建一個單獨的架構,并在訪問該數據時使用專用的數據源(或Hibernate會話)。 該模式不能從標準數據源(或Hibernate會話)中讀取。 這為您提供了一個很好的防火墻,但它并不完美。
一個看似更健壯的解決方案是為用戶authn / auhtz數據使用單獨的數據庫,而不僅僅是單獨的模式。 這似乎可以保護您免受權限配置錯誤的影響,該權限配置允許動態內容數據源訪問用戶數據源。
可悲的是,在某些RDMBS中,模式和數據庫之間沒有明顯的區別,如果授予必要的權限,則與一個“數據庫”的連接仍可以訪問另一個“數據庫”。 您無法確定,除非您具有用于用戶authn / authz和動態內容的單獨的數據庫實例。 如果您的體系結構具有專用于用戶authn / authz的服務器,那么這可能不是一個不適當的負擔。 對于虛擬服務器或云設計而言,這并非不合理。
基于容器的身份驗證
更好的解決方案是基于容器的身份驗證。 將用戶authn / authz完全從Web應用程序中拉出-到Web應用程序獲取請求時,HttpServletRequest已經填充了所有必要的信息。 您的Web應用無法訪問容器的身份驗證信息。 (對上述注釋取模-如果容器與動態內容位于相同的架構中,則不會有任何收獲。)
這種方法的一種變體是放在Web應用程序前面的身份驗證過濾器,例如,來自Spring Security的那些過濾器。 這是一種不同的機制,但具有相同的目的,即在用戶數據和動態內容之間保持非常清晰的區分。
小故障–添加和更新用戶
這里有一個小故障-如果您的Web應用程序無法訪問用戶authn / authz表,如何添加或更新用戶信息?
第一種方法是創建一個單獨的webapp來處理此問題。 您的主Web應用程序可以根據需要透明地重定向到第二個Web應用程序。 好處是您可以擁有一致的外觀和感覺,缺點是您將用戶的authn / authz信息再次暴露給了weeb。
第二種方法是創建一個單獨的REST服務來處理此問題。 您的Web應用程序可以提供用戶界面,但可以調用REST服務而不是標準業務層。 REST服務可以在您的防火墻內。
第三種方法是將其完全推遲到容器中。 這樣可以確保最大程度的分離,但是很難保持一致的外觀。
相關鏈接
https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=70288108
參考: 數據庫和Webapp安全,第1部分:威脅模型 , 數據庫和Webapp安全,第2部分:SQL注入 , 數據庫和Webapp安全,第3部分:存儲過程中SQL注入 , 數據庫和Webapp安全,第4部分:模式所有權 , 數據庫Webapp安全性,第5部分: JCG合作伙伴 Bear Giles在Invariant Properties博客上的用戶身份驗證 。
翻譯自: https://www.javacodegeeks.com/2012/11/database-and-webapp-security.html
webapp支持什么數據庫
總結
以上是生活随笔為你收集整理的webapp支持什么数据库_数据库和Webapp安全的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 路由器在手机上怎么设置用手机如何设置家里
- 下一篇: 怎样辨别电脑装的是不是固态硬盘如何看电脑