<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何有效預(yù)防脫庫

          共 7812字,需瀏覽 16分鐘

           ·

          2021-10-09 19:04

          本篇不從DBA、網(wǎng)絡(luò)架構(gòu)層面來講述數(shù)據(jù)安全,這部分有很專業(yè)的架構(gòu)和云上產(chǎn)品來解決,本篇重點(diǎn)從開發(fā)人員角度講述如何避免數(shù)據(jù)安全的漏洞。

          相信大部分人都看到過這樣的新聞,某某論壇泄漏了用戶密碼,某某物流公司泄漏了用戶的手機(jī)號等等,我一直堅(jiān)信大部分?jǐn)?shù)據(jù)泄漏都是內(nèi)部管理出現(xiàn)了問題,大部分都是內(nèi)部團(tuán)隊(duì)有意或無意泄漏了數(shù)據(jù),如果要從外界通過漏洞攻克不是沒有可能但是成本是巨大的,所以人為的泄漏往往是需要更加關(guān)注的問題,那作為軟件生產(chǎn)的主力軍(程序員)如何來避免挖坑?那我們接下來就主要講講從開發(fā)角度如何避免數(shù)據(jù)泄漏的可能性。

          從網(wǎng)上找了一些?數(shù)據(jù)安全治理?的相關(guān)資料,有興趣可以參考一下。

          我們從程序員角度來講講如何有效的預(yù)防數(shù)據(jù)安全問題。

          數(shù)據(jù)的訪問控制

          我們先來看看哪些是經(jīng)常訪問數(shù)據(jù)庫的用戶?

          1. 軟件程序(應(yīng)用程序、數(shù)據(jù)庫中間件)

          2. 人員:運(yùn)維、開發(fā)、測試、產(chǎn)品、等

          那接下來我們就來看看從這幾點(diǎn)如何來控制數(shù)據(jù)庫的訪問。

          軟件程序?qū)用?/strong>

          這里說的軟件程序包含:應(yīng)用程序、數(shù)據(jù)庫中間件等,作為數(shù)據(jù)庫的第一用戶我們?nèi)绾斡行У囊?guī)避數(shù)據(jù)安全的問題呢?

          我們先來說說現(xiàn)在的軟件開發(fā)用到的一些框架,無論是java、go、python或其他,已經(jīng)有很豐富的ormdatasource框架或工具,我下面羅列一些java中常用jdbc連接池和orm框架以及數(shù)據(jù)庫中間件

          名稱說明是否有加解密策略
          druid阿里巴巴開源的數(shù)據(jù)庫連接池
          dbcpApache的開源數(shù)據(jù)庫連接池
          c3p0一個(gè)開源的JDBC連接池
          atomikos一款分布式事務(wù)框架
          mybatis一款開源orm框架
          hibernate一款開源orm框架
          mycat開源分布式數(shù)據(jù)庫中間件
          shardingsphereApache的開源分布式數(shù)據(jù)庫中間件
          cobar阿里巴巴開源分片數(shù)據(jù)庫和表的代理

          我相信很多程序的數(shù)據(jù)庫連接與密碼都是通過配置文件來保存的,假如應(yīng)用服務(wù)器被黑客利用軟件漏洞拿下,我相信通過部署的軟件可以翻出數(shù)據(jù)庫連接的配置,那么針對這一點(diǎn)我們?nèi)绾斡行У谋苊饽兀?/span>

          數(shù)據(jù)庫連接密碼加密

          一般我們?yōu)榱俗鰯?shù)據(jù)庫高可用都會給數(shù)據(jù)庫集群中間做一層代理,通過域名的方式來暴漏連接,這樣做的好處就是數(shù)據(jù)庫failover的時(shí)候應(yīng)用程序可以不需要重啟,只用重新創(chuàng)建連接即可。因此這層代理可以有效的防止數(shù)據(jù)庫真實(shí)部署的機(jī)器被暴漏出去,起到了一定的安全作用。

          雖然連接層面有一層代理來杜絕真實(shí)服務(wù)器被暴漏,但是我們在通過jdbc連接的時(shí)候往往是有密碼訪問的,我相信很多數(shù)據(jù)庫的密碼是明文的存儲在配置文件中,雖然現(xiàn)在都用配置中心(configcenter)來統(tǒng)一管理應(yīng)用的配置,如果使用明文來保存密碼始終是無法規(guī)避泄漏的風(fēng)險(xiǎn),因?yàn)閼?yīng)用程序始終要進(jìn)行連接,在連接的時(shí)候要讀取配置,不管配置是從云端同步下來還是從本地讀取,只要是明文存儲密碼的就會存在安全問題。

          其實(shí)大多的數(shù)據(jù)庫連接池都有對數(shù)據(jù)庫訪問密碼加解密的功能,因此我們可以通過把數(shù)據(jù)庫訪問的密碼進(jìn)行加密來解決安全問題。

          下來我使用druid舉個(gè)例子,具體的看看如何使用,也可以查看druid官方?示例

          通過使用ConfigFilter為數(shù)據(jù)庫密碼提供加密功能

          <bean?id="dataSource"?class="com.alibaba.druid.pool.DruidDataSource"
          ????????destroy-method="close">

          ????.................
          ????
          ????<property?name="filters"?value="${filters}"?/>
          ????
          ????<property?name="filters"?value="stat,config"?/>?
          ????

          ????<property?name="connectionProperties"?value="config.decrypt=true;config.decrypt.key=${publickey}"?/>
          ????.................
          bean>


          filters=stat
          改為
          filters=stat,config

          jdbc.xxxx.password=123456
          改為
          jdbc.xxxx.password=加密后的值

          增加
          publickey=公鑰

          ps. 如果使用的是配置中心那么創(chuàng)建對應(yīng)的配置項(xiàng)即可。

          非對稱秘鑰對的生成方式有很多種,這里我給個(gè)在線生成的鏈接?加密后的密文是一段比較長的字符,例如下面這段示例

          jdbc.password=p9i+fChqlaYnfhI+NoJqmrGwTyWwlFZ1W7Vi7i2MGZ8agFkGxGr/kWU//yDvPyXZ6YwJwnMKQ4zXpTZnfxWaRjfqWIRG+JzxSdSYEMp/bRCiIvzF6y8FdVCqN/0m0eQeZFvMCdIf4wqhKF0QRCEOTysZ3oGg7t5o35CIMpV1A5Y=

          其他的jdbc連接池也都有類似的功能,但是不排除有一些沒有這個(gè)功能的就需要我們自己動手開發(fā)來增強(qiáng)這部分功能。

          首先我們需要了解數(shù)據(jù)庫連接加解密的思路,只要有思路實(shí)現(xiàn)都是很簡單的,其實(shí)數(shù)據(jù)庫連接加解密思路很簡單,在真正創(chuàng)建數(shù)據(jù)庫連接的時(shí)候讀取加密的密碼進(jìn)行解密后再進(jìn)行數(shù)據(jù)庫連接,那接下來我們給dbcp擴(kuò)展這個(gè)功能。

          import?java.sql.SQLFeatureNotSupportedException;
          import?java.util.Properties;
          import?java.util.logging.Logger;

          import?org.apache.commons.dbcp.BasicDataSource;
          import?org.slf4j.LoggerFactory;

          public?class?SecurityBasicDataSource?extends?BasicDataSource?{

          ????private?final?org.slf4j.Logger?logger?=?LoggerFactory.getLogger(SecurityBasicDataSource.class);

          ????@Override
          ????public?Logger?getParentLogger()?throws?SQLFeatureNotSupportedException?{
          ????????throw?new?SQLFeatureNotSupportedException();
          ????}

          ????@Override
          ????public?void?setPassword(String?password)?{
          ????????try?{
          ????????????//這里可以從任意地方讀取數(shù)據(jù)庫配置
          ????????????Properties?p?=?ConfigLoaderUtils.loadConfig("jdbc.properties");
          ????????????String?publickey?=?p.getProperty("publickey");
          ????????????//ConfigTools是實(shí)現(xiàn)私鑰、公鑰對加解密實(shí)現(xiàn)
          ????????????password?=?ConfigTools.decrypt(publickey,?password);
          ????????????super.setPassword(password);
          ????????}?catch(Exception?e)?{
          ????????????logger.error("解密password出錯(cuò)",?e);
          ????????}
          ????}

          }
          • 首先我們繼承dbcp數(shù)據(jù)源org.apache.commons.dbcp.BasicDataSource

          • 重寫setPassword

          • 設(shè)置密碼的時(shí)候通過公鑰和密文進(jìn)行解密

          這樣我們就給dbcp擴(kuò)展了數(shù)據(jù)庫連接加解密的功能,是不是很簡單。

          到這里我們就對數(shù)據(jù)庫連接密碼加密的方法介紹完畢,這樣做的好處有什么呢?假設(shè)當(dāng)應(yīng)用服務(wù)器被壞人俘虜后,他想通過應(yīng)用的配置信息輕松的獲取數(shù)據(jù)庫訪問密碼是不太可能,采用?公開密鑰加密?安全性還是很高的,它是一種非對稱加密算法想要了解更多的可以點(diǎn)開維基百科的連接查看。

          敏感數(shù)據(jù)加解密

          前面我們介紹完了數(shù)據(jù)庫連接上的安全問題以及如何解決,接下來我們繼續(xù)介紹數(shù)據(jù)庫中存儲的敏感數(shù)據(jù)應(yīng)該如何處理。

          我相信很多人都接觸過導(dǎo)出生產(chǎn)數(shù)據(jù)需要經(jīng)過?數(shù)據(jù)脫敏?,需要經(jīng)過數(shù)據(jù)脫敏的大多都是存儲的明文數(shù)據(jù),比如說用戶的手機(jī)號、詳細(xì)地址、銀行卡號、信用卡驗(yàn)證碼、用戶密碼、等。

          如果我們將這些敏感數(shù)據(jù)在存儲入庫的時(shí)候進(jìn)行加密,數(shù)據(jù)庫中存儲的是密文數(shù)據(jù),這樣及時(shí)被脫庫我相信也沒有那么容易破解,有人可能說密碼破解外界有?彩虹表?,彩虹表是一個(gè)用于加密散列函數(shù)逆運(yùn)算的預(yù)先計(jì)算好的表,常用于破解加密過的密碼散列,針對于用戶詳細(xì)地址、銀行卡號我相信彩虹表是無能為力的,如果使用暴力破解時(shí)間上的成本也是難以想象的,可能需要xxxxxx億年,哈哈哈。

          我們對數(shù)據(jù)加解密使用對稱加解密算法AESDES,為什么不使用非對稱的公開密鑰加密??

          雖然非對稱加解密算法安全性高,但是非對稱加解密算法加密后的值太長不利于存儲,所以我們需要使用固定長度或者可控長度的加解密算法,剛好對稱加解密算法符合要求,這里使用DES作為示例,當(dāng)然可以替換成任意的加解密算法。

          先說說數(shù)據(jù)落庫時(shí)的加解密實(shí)現(xiàn)思路,假設(shè)我們需要存儲用戶詳情,其中有姓名、電話、聯(lián)系地址、銀行卡號等信息,我們在持久化用戶詳情的時(shí)候?qū)γ舾凶侄芜M(jìn)行加密計(jì)算出密文,再將密文存入數(shù)據(jù)庫,當(dāng)查詢用戶詳情的時(shí)候,先從數(shù)據(jù)庫查詢出密文,通過對密文的解密和脫敏再返回給前臺,這樣我們就可以達(dá)到我們想要的效果,這里需要特殊說明一下,密文對模糊查詢不是很友好,但是也可以實(shí)現(xiàn)模糊查詢,具體的實(shí)現(xiàn)思路有很多種,這里我們就不多做介紹,感興趣的話我后面可以單獨(dú)出一篇支持模糊查詢的加解密算法,回到主題我們就以這個(gè)案例進(jìn)行實(shí)現(xiàn)。

          首先我們需要對敏感字段進(jìn)行打標(biāo)記,javaannotation可以幫助我們實(shí)現(xiàn)打標(biāo)

          import?java.lang.annotation.ElementType;
          import?java.lang.annotation.Retention;
          import?java.lang.annotation.RetentionPolicy;
          import?java.lang.annotation.Target;

          @Retention(RetentionPolicy.RUNTIME)
          @Target(ElementType.FIELD)
          public?@interface?Cipher?{
          }

          我們可以給用戶對象的敏感字段:手機(jī)號、銀行卡、詳細(xì)地址 上標(biāo)注@Cipher注釋,說明這幾個(gè)字段我們在保存、修改的時(shí)候需要加密,在查詢的時(shí)候需要解密。

          下來我們就要找一個(gè)公共的地方來統(tǒng)一的進(jìn)行加解密處理,作為一名合格的程序員需要想盡一切辦法來偷懶,并不是在所有CRUD的地方進(jìn)行加解密調(diào)用這樣會很傻很天真,作為被廣泛使用的orm框架之一的mybatis這里我使用它作為示例講解實(shí)現(xiàn)思路。

          mybatis提供攔截器機(jī)制,可以對執(zhí)行的CRUD進(jìn)行攔截處理操作,pagehelper?是一個(gè)分頁的mybatis插件,就是利用攔截的機(jī)制來擴(kuò)展分頁功能。

          我們剛才有說過我們需要對insert、update操作進(jìn)行加密,對select操作進(jìn)行解密,在mybatis的底層保存和修改都是update方法,查詢都是query方法,剛好我們就對這兩個(gè)方法進(jìn)行攔截處理。

          import?java.lang.reflect.Field;
          import?java.util.List;
          import?java.util.Properties;

          import?org.apache.commons.lang3.StringUtils;
          import?org.apache.ibatis.executor.Executor;
          import?org.apache.ibatis.mapping.MappedStatement;
          import?org.apache.ibatis.plugin.Interceptor;
          import?org.apache.ibatis.plugin.Intercepts;
          import?org.apache.ibatis.plugin.Invocation;
          import?org.apache.ibatis.plugin.Plugin;
          import?org.apache.ibatis.plugin.Signature;
          import?org.apache.ibatis.session.ResultHandler;
          import?org.apache.ibatis.session.RowBounds;
          import?org.apache.ibatis.session.defaults.DefaultSqlSession.StrictMap;
          import?org.slf4j.Logger;
          import?org.slf4j.LoggerFactory;

          @Intercepts({
          ????????@Signature(type?=?Executor.class,?method?=?"update",?args?=?{?MappedStatement.class,?Object.class?}),
          ????????@Signature(type?=?Executor.class,?method?=?"query",?args?=?{?MappedStatement.class,?Object.class,
          ????????????????RowBounds.class,?ResultHandler.class?})?})
          public?class?CipherHelper?implements?Interceptor?{

          ????private?final?Logger?logger?=?LoggerFactory.getLogger(CipherHelper.class);

          ????/**
          ?????*?加密密鑰br>
          ?為null,使用默認(rèn)密鑰進(jìn)行加解密br>

          ?????*/
          ????private?String?secureKey?=?null;
          ????/**
          ?????*?是否允許寬容處理br>
          ?寬容處理的話,使用原值,反之throw?{@link?CipherException}br>
          ?????*/
          ????private?boolean?lenient?=?false;

          ????@Override
          ????public?Object?intercept(Invocation?invocation)?throws?Throwable?{
          ????????String?methodName?=?invocation.getMethod().getName();
          ????????if?(methodName.equals("update")?||?methodName.equals("query"))?{
          ?????????????Object?parameter?=?invocation.getArgs()[1];
          ????????????if?(parameter?instanceof?List)?{
          ????????????????List?list?=?(List)?parameter;
          ????????????????for?(Object?obj?:?list)?{
          ????????????????????encrypt(obj);
          ????????????????}
          ????????????}?else?if(parameter?instanceof?StrictMap)?{
          ????????????????StrictMap?strictMap?=?(StrictMap)?parameter;
          ????????????????if?(strictMap.containsKey("list"))?{
          ????????????????????List?list?=?(List)?strictMap.get("list");
          ????????????????????for?(Object?obj?:?list)?{
          ????????????????????????encrypt(obj);
          ????????????????????}
          ????????????????}?else?if?(strictMap.containsKey("array"))?{
          ????????????????????Object[]?objects?=?(Object[])?strictMap.get("array");
          ????????????????????for?(Object?obj?:?objects)?{
          ????????????????????????encrypt(obj);
          ????????????????????}
          ????????????????}
          ????????????}?else?{
          ????????????????encrypt(parameter);
          ????????????}
          ????????}
          ????????Object?returnValue?=?invocation.proceed();
          ????????if?(methodName.equals("query"))?{
          ????????????if?(returnValue?instanceof?List)?{
          ????????????????List?list?=?(List)?returnValue;
          ????????????????for?(Object?obj?:?list)?{
          ????????????????????decrypt(obj);
          ????????????????}
          ????????????}?else?{
          ????????????????decrypt(returnValue);
          ????????????}
          ????????}
          ????????return?returnValue;
          ????}

          ????/**
          ?????*?加密處理
          ?????*?
          ?????*?@param?parameter
          ?????*?@throws?IllegalAccessException
          ?????*/

          ????private?void?encrypt(Object?parameter)?throws?IllegalAccessException?{
          ????????if?(parameter?==?null)?return;
          ????????Class?clazz?=?parameter.getClass();
          ????????if?(!clazz.getSimpleName().endsWith("Entity"))?{
          ????????????return;
          ????????}
          ????????for?(;?clazz?!=?Object.class;?clazz?=?clazz.getSuperclass())?{
          ????????????Field[]?fields?=?clazz.getDeclaredFields();
          ????????????for?(int?i?=?0;?i?????????????????if?(!fields[i].isAnnotationPresent(Cipher.class))?{
          ????????????????????continue;
          ????????????????}
          ????????????????if?(!fields[i].getType().equals(String.class))?{
          ????????????????????logger.debug("加密字段只支持String類型,當(dāng)前類型非String,跳過!");
          ????????????????????continue;
          ????????????????}
          ????????????????fields[i].setAccessible(true);
          ????????????????String?v?=?(String)?fields[i].get(parameter);
          ????????????????if?(StringUtils.isBlank(v))?{
          ????????????????????logger.debug("加密字段值為null,跳過!");
          ????????????????????continue;
          ????????????????}
          ????????????????try?{
          ????????????????????String?crypt?=?DESTools.encrypt(secureKey,?v);
          ????????????????????fields[i].set(parameter,?crypt);
          ????????????????????logger.debug("加密處理字段,{}",?fields[i].getName());
          ????????????????}?catch?(Exception?e)?{
          ????????????????????if?(lenient)?{
          ????????????????????????logger.warn("加密處理失敗,寬容處理使用原值");
          ????????????????????}?else?{
          ????????????????????????throw?new?CipherException("加密處理失敗,不允許寬容處理["+v+"]",?e);
          ????????????????????}
          ????????????????}
          ????????????}
          ????????}
          ????}

          ????/**
          ?????*?解密處理
          ?????*?
          ?????*?@param?obj
          ?????*?@throws?IllegalAccessException
          ?????*?@throws?Exception
          ?????*/

          ????private?void?decrypt(Object?obj)?throws?IllegalAccessException,?Exception?{
          ????????if?(obj?==?null)?return;
          ????????Class?clazz?=?obj.getClass();
          ????????if?(!clazz.getSimpleName().endsWith("Entity"))?{
          ????????????return;
          ????????}
          ????????for?(;?clazz?!=?Object.class;?clazz?=?clazz.getSuperclass())?{
          ????????????Field[]?fields?=?clazz.getDeclaredFields();
          ????????????for?(int?i?=?0;?i?????????????????if?(!fields[i].isAnnotationPresent(Cipher.class))?{
          ????????????????????continue;
          ????????????????}
          ????????????????if?(!fields[i].getType().equals(String.class))?{
          ????????????????????logger.debug("解密字段只支持String類型,當(dāng)前類型非String,跳過!");
          ????????????????????continue;
          ????????????????}
          ????????????????fields[i].setAccessible(true);
          ????????????????String?v?=?(String)?fields[i].get(obj);
          ????????????????if?(StringUtils.isBlank(v))?{
          ????????????????????logger.debug("解密字段值為null,跳過!");
          ????????????????????continue;
          ????????????????}
          ????????????????try?{
          ????????????????????String?crypt?=?DESTools.decrypt(secureKey,?v);
          ????????????????????fields[i].set(obj,?crypt);
          ????????????????????logger.info("解密處理字段,{}",?fields[i].getName());
          ????????????????}?catch?(Exception?e)?{
          ????????????????????if?(lenient)?{
          ????????????????????????logger.warn("解密處理失敗,寬容處理使用原值");
          ????????????????????}?else?{
          ????????????????????????throw?new?CipherException("解密處理失敗,不允許寬容處理["+v+"]",?e);
          ????????????????????}
          ????????????????}
          ????????????}
          ????????}

          ????}

          ????@Override
          ????public?Object?plugin(Object?target)?{
          ????????return?Plugin.wrap(target,?this);
          ????}

          ????@Override
          ????public?void?setProperties(Properties?properties)?{
          ????????if?(properties?!=?null?&&?StringUtils.isNotBlank(properties.getProperty("secureKey")))?{
          ????????????this.secureKey?=?properties.getProperty("secureKey");
          ????????}
          ????????if?(properties?!=?null?&&?StringUtils.isNoneBlank(properties.getProperty("lenient")))?{
          ????????????this.lenient?=?Boolean.parseBoolean(properties.getProperty("lenient"));
          ????????}

          ????}

          }

          通過mybatis的插件擴(kuò)展機(jī)制在執(zhí)行過程進(jìn)行攔截處理,plugin方法是插件的裝載方法,setProperties方法設(shè)置關(guān)鍵屬性,比如說密鑰串。

          接下來我們對每個(gè)方法進(jìn)行講解:

          encrypt:是加密方法,這里加密方法需要注意的是,mybatis參數(shù)支持Pojo?、Map、StrictMap、List、Array,我們使用注解@Cipher是用在類上的所以只對Pojo生效,如果是Map它天生的key,value格式無法支持打標(biāo),我們這里對Map類型進(jìn)行跳過不處理,如果非要處理Map也是有辦法的,需要固定加解密的key值,對特定的key進(jìn)行識別并加解密替換value,加密方法通過查找有注解@Cipher的字段進(jìn)行加密并且回填值。

          decrypt:是解密方法,主要用在查詢時(shí)的解密,這里需要注意的是查詢有可能返回特定的Pojo也可能返回List,所以這里解密的時(shí)候需要根據(jù)類型來分別處理,如果是List需要進(jìn)行很層次查找,如果是Pojo那就查找使用注解@Cipher的字段進(jìn)行解密并且回填值。

          intercept:是攔截方法,在update、query前后進(jìn)行攔截處理,在這個(gè)方法里需要進(jìn)行如下步驟:

          • 識別當(dāng)前執(zhí)行的methodupdate還是query

            • 如果是update那就進(jìn)行加密

            • 如果是query那就進(jìn)行解密

          • 識別參數(shù)類型是ListStrictMap、Pojo

            • 如果StrictMap里是list那就循環(huán)調(diào)用encrypt方法

            • 如果StrictMap里是array那就循環(huán)調(diào)用encrypt方法

            • 如果List里是Pojo那就循環(huán)調(diào)用encrypt方法

            • 如果List里是Map跳過處理,或者使用上面我們說的識別某些固定key進(jìn)行加密處理

            • 如果是List需要再深層次看一下List里是什么類型,這里建議使用遞歸方式

            • 如果是StrictMap需要再深層次看一下StrictMap里是什么類型,這里建議使用遞歸方式

            • 如果是Pojo那就調(diào)用encrypt方法

          • 執(zhí)行sql處理獲取返回值

          • 獲取返回值并且執(zhí)行的方法是query時(shí),進(jìn)行解密處理

            • 如果是List深層次查找內(nèi)部類型,這里建議使用遞歸方式

            • 如果是Pojo那就調(diào)用decrypt方法

            • 如果List里是Pojo那就循環(huán)調(diào)用decrypt方法

            • 如果List里是Map跳過處理,或者使用上面我們說的識別某些固定key進(jìn)行解密處理

            • 識別返回的類型是List還是Pojo

          到這里數(shù)據(jù)加解密的核心邏輯就介紹完了。

          這里我們回顧一下,我們先是對數(shù)據(jù)庫連接密碼進(jìn)行加解密,然后又對敏感數(shù)據(jù)落庫和查詢時(shí)進(jìn)行加解密,第一步連接密碼加密預(yù)防壞人即使攻擊拿到了應(yīng)用服務(wù)器的操作權(quán)限他也無法輕易的攻克我們的數(shù)據(jù)庫訪問密碼,第二步敏感數(shù)據(jù)加解密預(yù)防壞人即使攻克了我們的數(shù)據(jù)庫(俗稱脫庫)他也無法獲取用戶的隱私數(shù)據(jù),這樣就有效的保證了用戶隱私數(shù)據(jù)的安全性。

          到這里我們就對軟件程序?qū)用娴臄?shù)據(jù)安全防護(hù)手段介紹完畢,接下來我們再從人員訪問控制方面來看看有什么有效的手段。

          人員層面

          前面我們說了絕大多數(shù)的數(shù)據(jù)泄密都不是技術(shù)問題而是人員管理問題,我們要對人員進(jìn)行有效的管理與控制。

          開發(fā)或測試人員

          這類人一般對數(shù)據(jù)是有CRUD的訴求,針對這類人員的控制有如下幾個(gè)方面

          • 開發(fā)人員只能連接測試環(huán)境數(shù)據(jù)庫,不允許連接生產(chǎn)數(shù)據(jù)庫,即使連接vpn也不行。

          • 開發(fā)人員申請數(shù)據(jù)庫需要走運(yùn)維工單流程,運(yùn)維提供數(shù)據(jù)庫連接密碼時(shí)應(yīng)直接提供密文,或者運(yùn)維直接給配置到配置中心。

          • 配置文件或配置中心禁止存儲明文密碼,需要對jdbc等其他敏感密碼進(jìn)行脫敏處理。

          • 生產(chǎn)服務(wù)器需要通過跳板機(jī)訪問,禁止開發(fā)使用root直接操作,如果看應(yīng)用日志可以走日志平臺,實(shí)在沒有日志平臺可以給跳板機(jī)開通app用戶只給查看固定目錄日志的權(quán)限,如果要發(fā)布走devops平臺,如果沒有可以提供給運(yùn)維進(jìn)行發(fā)布。

          • 查詢生產(chǎn)數(shù)據(jù)走dms平臺,對敏感信息進(jìn)行脫敏或隱藏,對上線的sql和日常的查詢?nèi)罩咀龅?/span>dms可管控。

          • 提交到開放環(huán)境時(shí)需要注意以下幾點(diǎn)

            • 提交到開放的倉庫(github、gitlab、gitee等),需要對代碼進(jìn)行審核,避免有hardcode的公司服務(wù)器密碼、ip、端口、密鑰等。

            • 提交到開放的論壇(csdn、oschina、知乎、公眾號、社區(qū)分享等),需要對文章進(jìn)行審核,避免有不允許公開的技術(shù)細(xì)節(jié)或敏感信息。

          運(yùn)維或DBA人員

          這類人一般操作權(quán)限都很高,出問題概率最高的人員,有很多刪庫跑路或誤操作rm -rf的例子哈哈哈!所以這類人更要重點(diǎn)管控。

          • 需要搭建和處理運(yùn)維工單平臺,用于開發(fā)提出的運(yùn)維資源申請,尤其是數(shù)據(jù)庫密碼,直接提供加密后的密文和公鑰。

          • 需要搭建和處理數(shù)據(jù)庫管理工具dms,用于開發(fā)日常生產(chǎn)數(shù)據(jù)查詢和發(fā)版時(shí)SQL升級。

          • 需要提供跳板機(jī)和給跳板機(jī)提供不同等級的用戶,提供給特別需要的人訪問生產(chǎn)環(huán)境機(jī)器。

          • 需要提供devops平臺或者自動化發(fā)版工具,避免手動操作失誤帶來問題,對開發(fā)提供升級發(fā)布的流水線。

          • 對服務(wù)器密碼需要進(jìn)行加密存儲,可以借助密碼管理工具。

          • 運(yùn)維最好也不要使用root用戶操作服務(wù)器,使用特定權(quán)限的用戶操作。

          • dba最好也不要使用root用戶操作數(shù)據(jù)庫,使用特定權(quán)限的用戶操作。

          • 制定責(zé)任人機(jī)制,對應(yīng)的責(zé)任項(xiàng)必須到具體人,具體可以參考?責(zé)任分配矩陣RAM?。

          • 關(guān)鍵重要的操作需要至少兩個(gè)人在場,具體可以參考?責(zé)任分配矩陣RAM?。

          產(chǎn)品或業(yè)務(wù)人員

          這類人一般對數(shù)據(jù)有查詢和分析的訴求,有分析訴求就需要導(dǎo)出數(shù)據(jù),所以分析訴求統(tǒng)一走公司BI工具,也有少部分有修改的訴求。

          • 查詢分析數(shù)據(jù),統(tǒng)一接入BI工具,并且BI工具需要有功能和數(shù)據(jù)權(quán)限,并對敏感數(shù)據(jù)導(dǎo)出加以控制,導(dǎo)出走審批并脫敏。

          • 提交數(shù)據(jù)變更,統(tǒng)一接入dms平臺。

          • 產(chǎn)品的分析文件(word、excel、ppt)應(yīng)該進(jìn)行加密,這種一般依賴公司引入文檔安全的解決方案,要花錢的,如果不想花錢那就沒啥好辦法。

          總結(jié)

          到這里整篇也就差不多都介紹完了,我們現(xiàn)在回顧一下,首先我們介紹了數(shù)據(jù)安全的問題,并且說明了安全問題一般發(fā)生在兩個(gè)方面,一個(gè)是軟件程序,一個(gè)是人員管理。

          我們在軟件程序方面介紹了兩種預(yù)防數(shù)據(jù)安全的手段,一個(gè)是數(shù)據(jù)庫連接密碼加解密,一個(gè)是數(shù)據(jù)加解密,數(shù)據(jù)庫連接加密可以有效預(yù)防服務(wù)器被攻擊后通過翻找程序來進(jìn)一步攻擊數(shù)據(jù)庫,數(shù)據(jù)加解密可以有效預(yù)防數(shù)據(jù)庫被攻擊或脫庫后泄漏用戶及公司隱私數(shù)據(jù)。

          我們在人員方面首先對人員進(jìn)行了分類,針對每一類人的訴求談了管控的手段,說了這么多的控制手段,并不是說對員工不信任,這里說的控制并不等于限制,說了這么多的終極目標(biāo)是搭建一套有序的安全的管理機(jī)制,在安全的范圍內(nèi)給員工提供最大化的發(fā)揮空間,規(guī)避有心或無心的泄密。

          source: //ningyu1.github.io/20201229/datasource-security.html

          喜歡,在看

          瀏覽 55
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91高清无码免费看 | 欧美性猛交XXXX乱大交蜜桃 | 午夜精产品一区二区在线观看 | 狠狠撸天天撸 | 夏夏粉嫩黑鲍鱼大胆尤物P |