• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      代碼安全性審查方法研究

      2018-11-15 09:08:40賀江敏相里朋
      信息安全研究 2018年11期
      關(guān)鍵詞:緩沖區(qū)靜態(tài)代碼

      賀江敏 相里朋

      (工業(yè)和信息化部電子第五研究所 廣州 510610)

      我們知道,軟件從誕生的一刻起就伴隨著各種各樣的缺陷,這是因?yàn)檐浖际怯扇碎_發(fā)的,只要是有人參與的活動(dòng)就不可避免會(huì)引入缺陷,而原因也是五花八門,如軟件需求不明確、開發(fā)人員技術(shù)水平不一致、團(tuán)隊(duì)協(xié)作缺乏默契等.軟件中的缺陷可能會(huì)導(dǎo)致嚴(yán)重的后果,如系統(tǒng)崩潰、財(cái)產(chǎn)損失甚至是人員傷亡.于是,人們又研究出了軟件測(cè)試方法來發(fā)現(xiàn)軟件中存在的缺陷.

      軟件測(cè)試從測(cè)試類型上分為功能測(cè)試、性能測(cè)試、可靠性測(cè)試、接口測(cè)試、界面測(cè)試等;從開發(fā)過程來看,可分為單元測(cè)試、集成測(cè)試、系統(tǒng)測(cè)試等;從是否執(zhí)行代碼來看,可分為靜態(tài)測(cè)試和動(dòng)態(tài)測(cè)試;從軟件的內(nèi)部結(jié)構(gòu)又可分為白盒測(cè)試、黑盒測(cè)試和灰盒測(cè)試.在實(shí)踐中,人們根據(jù)測(cè)試的目的選擇不同的測(cè)試類型及測(cè)試方法.對(duì)于一些非常重要的軟件或者軟件中存在的缺陷可能帶來十分嚴(yán)重的危害時(shí),為了更加徹底地發(fā)現(xiàn)軟件中存在的缺陷,往往需要對(duì)軟件的源代碼進(jìn)行分析,一般采用的是白盒的靜態(tài)測(cè)試方法,代碼審查就是其中一種常見的方法.

      1 代碼審查

      代碼審查以軟件源代碼為輸入,是采用人工的方式,對(duì)其中可能存在的缺陷、違反開發(fā)標(biāo)準(zhǔn)及其他可能存在的問題進(jìn)行審查,一般采用的方法有代碼檢查單、代碼走查、軟件開發(fā)規(guī)范一致性檢查、工具靜態(tài)分析等[1].代碼審查的目的是檢查代碼和設(shè)計(jì)的一致性、代碼執(zhí)行標(biāo)準(zhǔn)的情況、代碼邏輯表達(dá)的正確性、代碼結(jié)構(gòu)的合理性以及代碼的可讀性[2].

      代碼審查依據(jù)其目的可以分為代碼質(zhì)量審查和代碼安全性審查.代碼質(zhì)量審查主要對(duì)代碼的質(zhì)量進(jìn)行度量,包括編程規(guī)則的違反情況、代碼的圈復(fù)雜度、節(jié)點(diǎn)數(shù)、注釋行、運(yùn)行時(shí)錯(cuò)誤等.代碼質(zhì)量審查主要用于對(duì)實(shí)時(shí)性、可用性要求較高的軟件或模塊,這類軟件失效時(shí)可能造成嚴(yán)重的經(jīng)濟(jì)損失或人員傷害,多用于嵌入式軟件;代碼安全性審查主要對(duì)代碼中存在的安全漏洞進(jìn)行分析,如SQL注入、跨站腳本、緩沖區(qū)溢出等.軟件中的安全漏洞一旦被非法利用可能導(dǎo)致敏感信息泄露、數(shù)據(jù)篡改、拒絕服務(wù)攻擊等,多針對(duì)信息安全要求高的軟件或系統(tǒng),以信息系統(tǒng)居多.

      代碼審查依據(jù)審查方法又可分為人工走查及工具靜態(tài)分析.人工走查就是采用人工的方式對(duì)源代碼逐行進(jìn)行審查,人工走查可以最大限度地發(fā)現(xiàn)軟件中存在的問題,但是費(fèi)時(shí)費(fèi)力,同時(shí)又和代碼審查人員的技術(shù)水平相關(guān).若軟件的代碼量十分巨大,對(duì)所有代碼進(jìn)行人工走查往往是不現(xiàn)實(shí)的,這時(shí)往往對(duì)系統(tǒng)中十分重要的核心模塊進(jìn)行人工走查.人工走查主要采用檢查單的形式,就是對(duì)照一份錯(cuò)誤列表來檢查代碼是否存在常見錯(cuò)誤[3].代碼質(zhì)量審查和代碼安全性審查由于其目的不同,審查的重點(diǎn)往往不一樣,表1以對(duì)比的方式列出了部分審查內(nèi)容:

      表1 代碼走查檢查單

      工具靜態(tài)分析就是采用專門的代碼審查工具對(duì)軟件源代碼進(jìn)行掃描,并對(duì)掃描的結(jié)果進(jìn)行人工分析.靜態(tài)分析的目的是通過對(duì)源程序分析、目測(cè),但不執(zhí)行程序,找出源代碼中可能的錯(cuò)誤和缺陷[4].工具靜態(tài)分析可以代替人工發(fā)現(xiàn)代碼中存在的通用性缺陷,并且速度快、效率高,但是針對(duì)特定領(lǐng)域相關(guān)的邏輯缺陷是無法發(fā)現(xiàn)的,比如嵌入式軟件對(duì)寄存器的賦值錯(cuò)誤、軟件運(yùn)行狀態(tài)錯(cuò)誤等.因此即使采用工具對(duì)源代碼進(jìn)行分析具有如此多的優(yōu)點(diǎn),但也不能完全取代代碼人工走查.在實(shí)際的工程中,往往是這2種測(cè)試方法相結(jié)合,以達(dá)到更好的效果.目前市面上的代碼靜態(tài)分析工具也主要分成2類:針對(duì)代碼質(zhì)量的靜態(tài)分析工具和針對(duì)代碼安全性的靜態(tài)分析工具.針對(duì)代碼質(zhì)量的靜態(tài)分析工具如testbed,logiscope,C++test等,其主要功能有復(fù)雜度分析、靜態(tài)數(shù)據(jù)流分析、交叉索引分析、信息流和數(shù)據(jù)對(duì)象分析、運(yùn)行時(shí)錯(cuò)誤檢測(cè)等.針對(duì)代碼安全性的靜態(tài)分析工具如Fortify SCA,Checkmarx CxSuite,Armorize CodeSecure等.有的靜態(tài)分析工具2種缺陷都可以檢測(cè),如Klocwork在對(duì)代碼質(zhì)量進(jìn)行分析的同時(shí)也可以檢測(cè)一些諸如注入、緩沖區(qū)溢出、拒絕服務(wù)等常見的安全問題.每種代碼靜態(tài)分析工具都有自己的特點(diǎn),有的測(cè)試類型比較廣泛,有的針對(duì)某個(gè)領(lǐng)域做得比較完善,在實(shí)際中,可以根據(jù)測(cè)試的內(nèi)容、關(guān)心的方向等有目的的選擇.

      2 代碼安全性審查

      隨著網(wǎng)絡(luò)上每年爆出大量的安全事件,如軟件漏洞、蠕蟲病毒、木馬、黑客攻擊、用戶信息泄露等,人們開始越來越重視軟件的安全性.在《GBT 16260.1—2006 軟件工程 產(chǎn)品質(zhì)量 第1部分:質(zhì)量模型》中,軟件的安全保密性是屬于軟件6性(功能性、可靠性、易用性、效率、維護(hù)性、可移植性)中功能性的子特性,而在《GBT 25000.10—2016 系統(tǒng)與軟件工程 系統(tǒng)與軟件質(zhì)量要求和評(píng)價(jià)(SQuaRE) 第10部分:系統(tǒng)與軟件質(zhì)量模型》中,軟件的產(chǎn)品質(zhì)量特性被劃分為8個(gè)特性:功能性、性能效率、兼容性、易用性、可靠性、信息安全性、維護(hù)性和可移植性,信息安全性已被單獨(dú)提出成為軟件質(zhì)量特性之一,并劃分為保密性、完整性、抗抵賴性、可核查性、真實(shí)性、信息安全的依從性6個(gè)子特性.可見軟件的安全性測(cè)試已成為軟件測(cè)試中非常重要的部分.對(duì)于軟件的安全性可以通過黑盒的測(cè)試方法,如安全功能測(cè)試、滲透測(cè)試等,也可以通過白盒的測(cè)試方法如代碼安全性審查進(jìn)行評(píng)估.前面已經(jīng)對(duì)代碼安全性審查的概念作了描述,下面分別從人工走查和工具靜態(tài)分析量2方面對(duì)代碼安全性審查的方法進(jìn)行研究.

      2.1 代碼安全性人工走查

      本文主要針對(duì)目前常見的軟件安全漏洞進(jìn)行分析.

      2.1.1SQL注入

      SQL注入(SQL injection)是一種代碼注入(code injection)攻擊,其根源是用戶輸入等不可信數(shù)據(jù)未經(jīng)充分凈化、過濾就被數(shù)據(jù)庫引擎當(dāng)作SQL代碼片段執(zhí)行[5],這樣攻擊者就可以注入任何SQL語句實(shí)現(xiàn)數(shù)據(jù)庫的查詢、修改,甚至是通過存儲(chǔ)過程或調(diào)用外部命令實(shí)現(xiàn)對(duì)操作系統(tǒng)的操作.以下就是一個(gè)存在SQL注入漏洞代碼的例子:

      public class test{

      public ResultSet getArticleData(ServletRequest req, Connection con) throws SQLException {

      String id=request.getParameter(″id″);

      String query=″SELECT * FROM articles WHERE id=′″+id+″′″;

      Statement stmt=con.createStatement();

      ResultSet rs=stmt.execute(query);

      return rs;

      }

      }

      這段代碼的功能為:服務(wù)器接收客戶端瀏覽器通過post或get方法傳遞過來的id參數(shù),以id參數(shù)為輸入,形成查詢字符串,查找數(shù)據(jù)庫articles表中以id為指定值的文章相關(guān)內(nèi)容并返回.可以看出,代碼中的查詢字符串是由一個(gè)基本的查詢語句和用戶輸入的字符串采用拼接字符串的方式組成的,如果攻擊者為id輸入字符串“100′ OR ′a′=′a”那么構(gòu)建的查詢語句就變成:

      SELECT * FROM articles WHERE id=′100′ OR ′a′=′a′;

      由于OR ′a′=′a′是恒成立的,于是構(gòu)建的查詢語句就等效為

      SELECT * FROM articles;

      這時(shí)返回的是articles表中的所有條目,而不是指定id的條目,當(dāng)然也可以通過構(gòu)建的SQL語句來執(zhí)行更加復(fù)雜的操作,比如在支持采用分割符一次性執(zhí)行多條SQL語句的數(shù)據(jù)庫中,若攻擊者為id輸入字符串“100′; DELETE FROM articles; --”那么構(gòu)建的查詢語句就變成:

      SELECT * FROM articles WHERE id=′100′;

      DELETE FROM articles;

      查詢語句變?yōu)?個(gè),在執(zhí)行完第1個(gè)查詢語句后會(huì)執(zhí)行第2個(gè)查詢語句,直接刪除articles表.

      具有安全意識(shí)的程序員會(huì)采用參數(shù)化的SQL指令來進(jìn)行SQL查詢,通過占位符進(jìn)行參數(shù)捆綁,以便區(qū)分哪些是命令的一部分哪些只是輸入的數(shù)據(jù),捆綁的參數(shù)只會(huì)當(dāng)作輸入的數(shù)據(jù),即使里面帶有SQL指令也不會(huì)執(zhí)行.因此,參數(shù)化SQL可以防止篡改上下文,有效避免SQL注入攻擊.在Java語言中,采用PreparedStatement進(jìn)行預(yù)編譯,提供占位符實(shí)現(xiàn)參數(shù)化功能,如下所示:

      public class test {

      public ResultSet getArticleData(ServletRequest req, Connection con) throws SQLException {

      String id=request.getParameter(″id″);

      String query=″SELECT * FROM articles WHERE id=?″;

      PreparedStatement stmt=

      con.prepareStatement (query);

      stmt.setString(1, id);

      ResultSet rs=stmt.execute();

      return rs;

      }

      }

      當(dāng)以上這種方式進(jìn)行數(shù)據(jù)庫查詢時(shí)便不會(huì)產(chǎn)生SQL注入的問題.

      2.1.2緩沖區(qū)溢出

      緩沖區(qū)溢出是一種十分危險(xiǎn)的漏洞,這是由于向內(nèi)存區(qū)塊中填寫的數(shù)據(jù)超過了區(qū)塊本身的大小,導(dǎo)致數(shù)據(jù)覆蓋了指定區(qū)域之外的內(nèi)存區(qū)域,經(jīng)過精心構(gòu)建的填充數(shù)據(jù)可以覆蓋并重寫函數(shù)的返回地址,當(dāng)函數(shù)返回時(shí)直接跳轉(zhuǎn)到攻擊者指定的緩沖區(qū),并執(zhí)行攻擊者想要執(zhí)行的任意代碼.即使是任意填充的隨機(jī)數(shù)據(jù)也會(huì)使函數(shù)返回到未知的地址,最終導(dǎo)致程序的崩潰,造成拒絕服務(wù)攻擊.緩沖區(qū)溢出漏洞常出現(xiàn)在采用C語言編寫的代碼中,經(jīng)常與危險(xiǎn)的字符串函數(shù)的使用相關(guān),標(biāo)準(zhǔn)C庫中有很多不進(jìn)行自變量檢查的字符串操作函數(shù),在使用這類函數(shù)時(shí)一定要對(duì)操作字符串的數(shù)目進(jìn)行限制[6],如gets(),scanf(),strcpy(),sprintf().內(nèi)存分配函數(shù)malloc()的使用也要十分謹(jǐn)慎,若沒有對(duì)分配的內(nèi)存大小進(jìn)行判斷,很可能會(huì)引起緩沖區(qū)溢出漏洞,在進(jìn)行代碼人工走查時(shí),以上都是需要重點(diǎn)關(guān)注的地方.下面是一個(gè)緩沖區(qū)溢出的例子:

      void test()

      {

      char a[10]=″Hello Tom″;

      char b[20]=″This is a example″;

      strcpy(a,b);

      }

      這段代碼中,字符數(shù)組變量a的長(zhǎng)度為10,字符數(shù)組變量b的長(zhǎng)度為20,通過函數(shù)strcpy將b的內(nèi)容覆蓋變量a,由于變量b中的內(nèi)容長(zhǎng)度大于變量a的長(zhǎng)度,當(dāng)變量a的10個(gè)字節(jié)覆蓋完成后會(huì)繼續(xù)覆蓋其分配的內(nèi)存空間之外的地址,這就形成了緩沖區(qū)溢出.

      針對(duì)緩沖區(qū)溢出漏洞有以下2種解決辦法:

      1) 人工通過代碼對(duì)上限進(jìn)行判斷,如下所示:

      void test()

      {

      char a[10]=″Hello Tom″;

      char b[20]=″This is a example″;

      if (strlen(b) > (sizeof(a)-1)){

      print(″e(cuò)rror ″);

      return;

      }

      strcpy(a,b);

      }

      2) 將無界字符串操作函數(shù)strcpy(dest,src),替換成對(duì)應(yīng)的有界字符串操作函數(shù)strncpy(dest,src,n),strncpy將src中的內(nèi)容復(fù)制到dest,復(fù)制的大小由n決定,如下所示:

      void test()

      {

      char a[10]=″Hello Tom″;

      char b[20]=″This is a example″;

      strncpy(a,b,sizeof(a)-1);

      }

      這樣就可以避免緩沖區(qū)溢出的問題.

      2.1.3資源未釋放

      資源未釋放一般分為2種情況:一種是文件流資源未釋放;另一種是數(shù)據(jù)庫連接資源未釋放.文件流資源未釋放就是當(dāng)打開一個(gè)文件流,對(duì)文件進(jìn)行讀寫操作后卻忘記了釋放這個(gè)文件流.數(shù)據(jù)庫連接資源未釋放就是建立了一個(gè)數(shù)據(jù)庫連接,對(duì)數(shù)據(jù)庫進(jìn)行增、刪、改、查操作后忘記釋放數(shù)據(jù)庫連接.資源未釋放會(huì)被惡意攻擊者利用,大批量并發(fā)的資源打開操作而又不釋放資源,很容易導(dǎo)致資源的耗盡從而引發(fā)拒絕服務(wù)攻擊.一個(gè)典型的文件流資源未釋放的例子如下:

      private void test(String fileName) throws IOException {

      try

      {

      Int len=0;

      FileInputStream fis=new FileInputStream(fileName);

      byte[] Array=new byte[SIZE];

      while((len=fis.read(Array))!=-1){

      System.out.println(new String(Array,0,len));

      }

      }

      catch (IOException e)

      {

      e.printStackTrace();

      }

      }

      該代碼建立一個(gè)文件流,讀取文件中的內(nèi)容并打印出來,最后卻沒有關(guān)閉該文件流.雖然Java有垃圾回收機(jī)制,但是垃圾收集器需要確認(rèn)對(duì)象是否符合回收條件,而且什么時(shí)候回收是由系統(tǒng)自動(dòng)判斷的,這就不能保證資源的釋放,導(dǎo)致內(nèi)存使用過大.

      有的程序員會(huì)在try模塊中釋放資源,如下所示:

      private void test(String fileName) throws IOException {

      try

      {

      Int len=0;

      FileInputStream fis=new FileInputStream(fileName);

      byte[] Array=new byte[SIZE];

      while((len=fis.read(Array))!=-1){

      System.out.println(new String(Array,0,len));

      }

      if(fis!=null)

      {

      fis.close();

      }

      }

      catch (IOException e)

      {

      e.printStackTrace();

      }

      }

      這在大多數(shù)情況下沒有什么問題,但是一旦程序發(fā)生異常則會(huì)跳過后續(xù)代碼的執(zhí)行,資源便得不到釋放.正確的做法是在finally模塊中釋放資源,這樣,即使發(fā)生了異常也能保證資源可以得到釋放,如下所示:

      private void test(String fileName) throws IOException {

      try

      {

      Int len=0;

      FileInputStream fis=new FileInputStream(fileName);

      byte[] Array=new byte[SIZE];

      while((len=fis.read(Array))!=-1){

      System.out.println(new String(Array,0,len));

      }

      }

      catch (IOException e);

      {

      e.printStackTrace();

      }

      finally

      {

      if(fis!=null)

      {

      fis.close();

      }

      }

      }

      2.1.4路徑操縱

      當(dāng)對(duì)文件進(jìn)行操作時(shí),若文件路徑由用戶可以操作的變量組成,而程序又沒有對(duì)用戶提交的參數(shù)進(jìn)行過濾就會(huì)導(dǎo)致路徑操縱漏洞,通過路徑操縱漏洞,惡意用戶可能訪問操作系統(tǒng)中任意文件[7].

      String fileName=request.getParameter(″fileName″);

      test(fileName);

      public void test(String filename){

      try

      {

      amt=fis.read(Array);

      out.println(Array);

      }

      catch(…){

      }

      }

      因此需要限制用戶輸入的字符,只允許輸入規(guī)定的字符,如下所示:

      String fileName=request.getParameter(″fileName″);

      test(fileName);

      public void test(String filename){

      try

      {

      String regex=″∧[A-Za-z0-9]+.[a-z]+$″;

      if(filename.matches(regex)){

      red=fis.read(Array);

      out.println(Array);

      }

      }

      catch(…){

      }

      }

      這樣若用戶提交的文件名和正則表達(dá)式不匹配則不能進(jìn)行文件讀取的操作,防止了用戶讀取操作系統(tǒng)上的任意文件.

      2.1.5不安全的密碼算法

      一些密碼算法在其誕生之初是安全的,但隨著技術(shù)的發(fā)展現(xiàn)在已經(jīng)不再安全,比如DES算法,其密鑰長(zhǎng)度只有56 b,在云計(jì)算、并行計(jì)算及計(jì)算機(jī)運(yùn)算速度發(fā)展的今天,破解其密鑰只需要很短的時(shí)間.對(duì)于散列算法,像MD5,SHA-1都已經(jīng)實(shí)現(xiàn)了碰撞,不再安全,應(yīng)使用現(xiàn)在公認(rèn)還比較安全的散列算法如SHA-256,SM3等.

      public void encrypt(String str){

      Cipher encryptCipher=

      Cipher.getInstance(″DES″);

      KeyGenerator keygen=

      KeyGenerator.getInstance(″DES″);

      SecretKey deskey=keygen.generateKey();

      encryptCipher.init(Cipher.ENCRYPT_MODE, deskey);

      byte[] src=str.getBytes();

      byte[] cipherByte=

      encryptCipher.doFinal(src);

      }

      以上代碼采用DES加密方式對(duì)輸入的字符串進(jìn)行加密,由于DES加密算法已經(jīng)不安全,需要將其改為AES加密算法,AES加密算法可以使用256 b長(zhǎng)度的密鑰,以現(xiàn)在的技術(shù)在可承受的時(shí)間范圍內(nèi)破解是不可能的.當(dāng)然隨著技術(shù)的發(fā)展,如量子計(jì)算,將來的某一天,也許AES加密算法也不再安全,但至少現(xiàn)在暫時(shí)還是安全的,為了修復(fù)該問題,只需要將以上代碼修改為如下代碼:

      public void encrypt(String str, String

      password){

      Cipher encryptCipher=Cipher.getInstance(″AES″);

      KeyGenerator keygen=

      KeyGenerator.getInstance(″AES″);

      keygen.init(256, new

      SecureRandom(password.getBytes()));

      SecretKey orikey=keygen.generateKey();

      byte [] raw=orikey.getEncoded();

      SecretKey deskey=new SecretKeySpec(raw, ″AES″);

      encryptCipher.init(Cipher.ENCRYPT_MODE, deskey);

      byte[] src=str.getBytes();

      byte[] cipherByte=encryptCipher.doFinal(src);

      }

      2.2 代碼安全性工具靜態(tài)分析

      通過工具對(duì)源代碼的安全性進(jìn)行靜態(tài)分析并不是用工具跑一遍得出結(jié)果就可以了,我們知道只要是采用工具就有2個(gè)不可避免的問題:漏報(bào)率和誤報(bào)率.漏報(bào)率可以通過人工走查的方式降低,要降低誤報(bào)率,采用靜態(tài)分析工具對(duì)源程序進(jìn)行編碼規(guī)則檢查,對(duì)于工具報(bào)出的問題再由人工進(jìn)行進(jìn)一步的分析以確認(rèn)軟件問題,是一種比較有效的方法[8].

      目前各種代碼安全性靜態(tài)分析工具都比較成熟,所采用的分析方法一般有:數(shù)據(jù)流分析、語義分析、結(jié)構(gòu)分析、控制流分析、配置分析等.

      2.2.1數(shù)據(jù)流分析

      數(shù)據(jù)流分析就是跟蹤程序中數(shù)據(jù)的傳遞,從而發(fā)現(xiàn)存在的安全問題.比如數(shù)據(jù)從一個(gè)變量傳遞給另一個(gè)變量,或者數(shù)據(jù)通過調(diào)用函數(shù)傳遞到函數(shù)內(nèi)部,處理后再返回給另一個(gè)變量等.下面舉一個(gè)SQL注入漏洞數(shù)據(jù)流分析的例子,如圖1所示:

      圖1 數(shù)據(jù)流傳遞示意圖

      圖1在getRawParameter()函數(shù)中用戶提交的數(shù)據(jù)通過request.getParameterValues()傳遞到服務(wù)器,接著數(shù)據(jù)返回到createContent()函數(shù)內(nèi)部,并形成SQL語句,執(zhí)行查詢操作.數(shù)據(jù)流在從用戶提交到SQL語句執(zhí)行的整個(gè)傳遞過程都可以很清楚看到.經(jīng)過分析,在數(shù)據(jù)流的整個(gè)傳遞過程中都沒有對(duì)數(shù)據(jù)進(jìn)行過濾,在最終的執(zhí)行階段也沒有采用預(yù)編譯的方式通過占位符參數(shù)綁定防止SQL注入,因此,這是一個(gè)SQL注入漏洞.

      通過數(shù)據(jù)流分析可以很容易發(fā)現(xiàn)通過數(shù)據(jù)的傳遞引發(fā)的安全漏洞,但是由于其只對(duì)數(shù)據(jù)流進(jìn)行跟蹤,對(duì)于數(shù)據(jù)流之外的防護(hù)手段是無法發(fā)現(xiàn)的,這就可能出現(xiàn)誤報(bào),因此還需要進(jìn)行額外的人工分析以消除這些誤報(bào).比如采用了全局過濾器,這時(shí)在web.xml配置文件中會(huì)有如下代碼:

      SqlInjectionfilter

      com.filter.SqlInjectionfilter

      SqlInjectionfilter

      同時(shí),我們還需要檢查其對(duì)應(yīng)的過濾函數(shù)是否有效,查看classescomfilter目錄下的SqlInjectionfilter.java文件

      public class SqlInjectionfilter implements Filter {

      public void destroy() {

      }

      public void init(FilterConfig arg0) throws ServletException {

      }

      public void doFilter(ServletRequest args0, ServletResponse args1, FilterChain chain) throws IOException, ServletException {

      過濾代碼

      }

      }

      對(duì)于asp代碼,可以通過在文件頭引用具有SQL過濾功能的代碼對(duì)提交的數(shù)據(jù)進(jìn)行過濾,如下所示:

      SqlInjectionfilter.asp文件是對(duì)提交數(shù)據(jù)進(jìn)行過濾的代碼,如:

      <%

      If Request.QueryString<>″″ Then

      For Each Get_Data In Request.QueryString

      對(duì)通過GET方式提交的參數(shù)進(jìn)行過濾…

      Next

      End If

      If Request.Form<>″″ Then

      For Each Post_Data In Request.Form

      對(duì)通過POST方式提交的參數(shù)進(jìn)行過濾…

      next

      end if

      %>

      這種過濾方法同樣是在數(shù)據(jù)流之外,通過數(shù)據(jù)流分析的方法無法識(shí)別,因此需要人工審查并進(jìn)行剔除.

      2.2.2語義分析

      語義分析就是分析代碼中不安全函數(shù)、API或不安全方法的使用,這對(duì)一些緩沖區(qū)溢出及格式化字符串問題十分有效,比如下面這段代碼:

      char a[10]″;

      char b[10]″;

      strcat(a,b);

      由于使用了危險(xiǎn)的函數(shù)strcat(),可能造成緩沖區(qū)溢出漏洞.

      再舉一例,比如以下代碼:

      public final static String

      DATABASE_PASSWORD=″cp8gc6ka″;

      將密碼直接寫到源代碼中,這是一種不安全的做法,稱為密碼硬編碼.因?yàn)橐坏┸浖l(fā)布以后就不能修改這些密碼,除非發(fā)布新的版本,而通過對(duì)軟件進(jìn)行動(dòng)態(tài)調(diào)試或二進(jìn)制分析也可能找到這些密碼,因此應(yīng)對(duì)密碼進(jìn)行加密并存儲(chǔ)在外部的配置文件中.

      2.2.3結(jié)構(gòu)分析

      結(jié)構(gòu)分析就是通過對(duì)程序結(jié)構(gòu)的上下文進(jìn)行分析,并找出其中的安全問題,比如下面的代碼:

      public class test extends HttpServlet {

      String name;

      protected void doPost (HttpServletRequest req,HttpServletResponse res) {

      username=req.getParameter(″username″);

      out.println(″Hello″+username);

      }

      }

      該段代碼將用戶名變量放置在成員變量中,從結(jié)構(gòu)上看,這個(gè)變量在“類”中,“方法”外.當(dāng)一個(gè)用戶進(jìn)行訪問時(shí),這段代碼是沒有什么問題的,但當(dāng)2個(gè)用戶同時(shí)訪問時(shí),由于Servlet是單實(shí)例多線程的并發(fā)處理模式,會(huì)導(dǎo)致第2個(gè)用戶的用戶名覆蓋第1個(gè)用戶的用戶名,從而在執(zhí)行到顯示用戶名的代碼時(shí),將第2個(gè)用戶的用戶名顯示給第1個(gè)用戶,形成競(jìng)爭(zhēng)條件問題.

      另外一個(gè)典型的結(jié)構(gòu)問題是函數(shù)在finally中返回,如下所示:

      public int test(int Num) {

      int rt;

      try

      {

      }

      catch (Exception e)

      {

      }

      finally

      {

      return rt;

      }

      }

      函數(shù)在finally中返回會(huì)導(dǎo)致從try塊中拋出的異常丟失,這樣便無法處理可能出現(xiàn)的異常情況.

      2.2.4控制流分析

      控制流分析根據(jù)指令的執(zhí)行可定義多個(gè)不同的狀態(tài),不同的狀態(tài)通過控制流的路徑連接起來,主要是在代碼解析的基礎(chǔ)上,分析過程內(nèi)語句之間的控制依賴關(guān)系,提取程序的控制流信息[9].基本的控制語法,如if,while,case等根據(jù)狀態(tài)的不同引導(dǎo)控制流的走向,如果某一條控制流最后的狀態(tài)是一個(gè)錯(cuò)誤狀態(tài),那么這就有可能是一個(gè)漏洞.

      State state=null;

      switch (Fg) {

      case 1:

      state=state1;

      break;

      case 2:

      state=state2;

      case 3:

      state=state3;

      }

      state.dosomething ();

      在以上代碼中,若Fg不為1,2,3中的任何一個(gè)值,那么state就不會(huì)賦值,仍為null狀態(tài),這時(shí)若對(duì)state進(jìn)行操作就有可能觸發(fā)null引用問題,導(dǎo)致程序崩潰,當(dāng)然若state在賦值狀態(tài),程序是沒有問題的.

      2.2.5配置分析

      配置分析就是對(duì)配置文件的內(nèi)容進(jìn)行分析,找出其中可能存在的安全問題,如敏感信息、不安全的配置等.比如在application.properties配置文件中有如下配置:

      jdbc.driver=

      oracle.jdbc.driver.OracleDriver

      jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:orcl

      jdbc.username=test

      jdbc.password=uuikx0k6

      該配置文件描述了應(yīng)用程序通過jdbc連接oracle數(shù)據(jù)庫的連接字符串,包括連接的用戶名和密碼,可以看到密碼采用了明文方式存儲(chǔ),任何可以訪問該配置文件(包括使用非法手段)的人都可以獲得數(shù)據(jù)庫的訪問密碼,從而訪問數(shù)據(jù)庫,因此需要對(duì)配置文件中存儲(chǔ)的密碼進(jìn)行加密.

      需要注意的是,工具并不能區(qū)分出密碼字符串是否經(jīng)過加密,比如下面的配置:

      zJQDik2PenVdnh6IZA0cqW9kX7Nz53oc=

      工具仍可能會(huì)認(rèn)為這可能是一個(gè)存儲(chǔ)在配置文件中的未加密的密碼,因此需要對(duì)工具分析出的結(jié)果進(jìn)行人工分析.

      另外一些看上去好像是加密的密碼實(shí)際上并沒有加密,如下所示:

      jdbc.password=MTIzNDU2Nzg5MA==

      這實(shí)際上只是對(duì)密碼明文進(jìn)行了Base64的編碼,并不是加密,可以很容易還原成明文,以上都是在對(duì)工具靜態(tài)分析結(jié)果進(jìn)行確認(rèn)時(shí)需要注意的地方.

      3 結(jié)束語

      在軟件安全測(cè)試領(lǐng)域,經(jīng)過多年的發(fā)展,測(cè)試方法和測(cè)試手段已經(jīng)多元化,有的側(cè)重于安全功能的實(shí)現(xiàn),有的側(cè)重于外部環(huán)境的影響,還有的需要從整個(gè)系統(tǒng)層面進(jìn)行考量.對(duì)于特別重要的軟件系統(tǒng),如涉及人民生命財(cái)產(chǎn)安全、重要數(shù)據(jù)、甚至可能影響到國家安全的軟件及信息系統(tǒng),代碼安全性審查就是一個(gè)十分必要的手段.雖然目前還存在人工成本大、耗時(shí)長(zhǎng)、工具分析存在誤報(bào)和漏報(bào)等不足,但是隨著云計(jì)算、大數(shù)據(jù)、人工智能等技術(shù)的發(fā)展,若將其應(yīng)用到對(duì)軟件源代碼的安全分析方面,代碼安全性審查的效率將大大提高,時(shí)間和成本也會(huì)大幅度降低,成本的降低將帶來技術(shù)的普及,這將為更多、更廣范圍的軟件帶來安全性的保障.

      猜你喜歡
      緩沖區(qū)靜態(tài)代碼
      嵌入式系統(tǒng)環(huán)形緩沖區(qū)快速讀寫方法的設(shè)計(jì)與實(shí)現(xiàn)
      靜態(tài)隨機(jī)存儲(chǔ)器在軌自檢算法
      創(chuàng)世代碼
      創(chuàng)世代碼
      創(chuàng)世代碼
      創(chuàng)世代碼
      關(guān)鍵鏈技術(shù)緩沖區(qū)的確定方法研究
      機(jī)床靜態(tài)及動(dòng)態(tài)分析
      具7μA靜態(tài)電流的2A、70V SEPIC/升壓型DC/DC轉(zhuǎn)換器
      50t轉(zhuǎn)爐靜態(tài)控制模型開發(fā)及生產(chǎn)實(shí)踐
      上海金屬(2013年6期)2013-12-20 07:57:59
      淮南市| 睢宁县| 光山县| 舟山市| 罗源县| 栾城县| 兖州市| 永兴县| 英德市| 武鸣县| 孟津县| 原阳县| 翁源县| 郴州市| 沂水县| 炉霍县| 金塔县| 河曲县| 祁东县| 南岸区| 宽甸| 长春市| 惠东县| 玉山县| 恩平市| 镇沅| 筠连县| 赤水市| 娄底市| 宝坻区| 丰城市| 阳朔县| 诏安县| 阿瓦提县| 察哈| 山丹县| 纳雍县| 民勤县| 诏安县| 乐山市| 普格县|