中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
C、C++ 和 Java安全編碼實(shí)踐提示與技巧
文 / Gwyn Fisher
      對(duì)于所有類型環(huán)境中的開(kāi)發(fā)人員來(lái)說(shuō),安全性正成為一個(gè)越來(lái)越重要的主題,即便過(guò)去一直認(rèn)為安全性不成問(wèn)題的嵌入式系統(tǒng)也是如此。本文將介紹幾種類型的編碼漏洞,指出漏洞是什么、如何降低代碼被攻擊的風(fēng)險(xiǎn)、如何更好地找出代碼中的此類缺陷。

注入攻擊
      通過(guò)將信息注入正在運(yùn)行的流程,攻擊者可以危害進(jìn)程的運(yùn)行狀態(tài),以反射到開(kāi)發(fā)人員無(wú)法保護(hù)的某種最終目標(biāo)。例如,攻擊者可能會(huì)通過(guò)堆棧溢出(stack corruption)將代碼注入進(jìn)程,從而執(zhí)行攻擊者選定的代碼。此外,攻擊者也可能嘗試將數(shù)據(jù)注入數(shù)據(jù)庫(kù),供將來(lái)使用;或?qū)⑽词鼙Wo(hù)的字符串注入數(shù)據(jù)庫(kù)查詢,獲取比開(kāi)發(fā)人員更多的信息。無(wú)論出于怎樣的目的,注入總是一件壞事,總是需要謹(jǐn)慎對(duì)待的。
      最惡劣的注入攻擊形式也許是代碼注入——將新代碼置入正在運(yùn)行的進(jìn)程的內(nèi)存空間,隨后指示正在運(yùn)行的進(jìn)程執(zhí)行這些代碼。此類攻擊如果成功,則幾乎可以進(jìn)行任何操作,因?yàn)檎谶\(yùn)行的進(jìn)程完全被劫持,可執(zhí)行攻擊者希望執(zhí)行的任何代碼。
      此類攻擊最著名的示例之一就是 Windows 動(dòng)畫(huà)光標(biāo)攻擊,這正是本文要討論的模式。攻擊者利用一個(gè)簡(jiǎn)單的 Web 頁(yè)面將形式不當(dāng)?shù)膭?dòng)畫(huà)光標(biāo)文件下載到查看者的 PC 中,導(dǎo)致瀏覽器調(diào)用此動(dòng)畫(huà)光標(biāo),動(dòng)畫(huà)光標(biāo)調(diào)用時(shí)可能發(fā)生任意代碼的注入。實(shí)際上,這是一個(gè)完美的攻擊載體:因?yàn)樗灰髮?duì)被攻擊機(jī)器的任何實(shí)際訪問(wèn)、最終用戶根本意識(shí)不到任何可能發(fā)生的麻煩;此外,如果攻擊效果的惡意也是適度的,則對(duì)最終用戶的外部影響幾乎是零。
      考慮示例 1(a),當(dāng)然,這改寫自 Windows 攻擊,它構(gòu)成了此類攻擊載體的基礎(chǔ)。這里的開(kāi)發(fā)人員對(duì)于傳入流的可靠性做出了基本的假設(shè)。信任流和并相信一切都沒(méi)問(wèn)題。使用基于堆棧的將被非串形化(deserialized)的類型調(diào)用函數(shù),未知數(shù)據(jù)流和代碼注入肯定會(huì)在某個(gè)時(shí)間點(diǎn)出現(xiàn)。
(a)
void LoadTypeFromStream(unsigned char* stream, SOMETYPE* typtr)
{
  int len;
  // Get the size of our type's serialized form
  memcpy(&len, stream, sizeof(int));
  // De-serialize the type
  memcpy(typtr, stream + sizeof(int), len);
}
(b)
void foo(unsigned char* stream)
{
  SOMETYPE ty;
  LoadTypeFromStream(stream, &ty);
}
(c)
void LoadTypeFromStream
      (unsigned char* stream, SOMETYPE* typtr)
{
    int len;
    // Get the size of our type's serialized form
    memcpy(&len, stream, sizeof(int));
    // GUARD
    if( len < 0 || len > sizeof(SOMETYPE) )
        throw TaintedDataException();
    // De-serialize the type
    memcpy(typtr, stream + sizeof(int), len);
}
示例1 注入攻擊。
      這是怎樣發(fā)生的?假設(shè)您調(diào)用示例 1(b)中的函數(shù)。我們就得到了一個(gè)易于利用的攻擊載體。這里的問(wèn)題在于 SOMETYPE 在編譯時(shí)的大小是固定的。假設(shè)此類型在內(nèi)存中使用 128 個(gè)字節(jié)表示。再假設(shè)您構(gòu)建傳入流時(shí),使前 4 個(gè)字節(jié)(要非串形化的內(nèi)容的長(zhǎng)度)的讀數(shù)為 256?,F(xiàn)在,您沒(méi)有檢查正在處理的內(nèi)容的有效性,而是將 256 個(gè)字節(jié)復(fù)制到了僅為 128 個(gè)字節(jié)的保留堆棧空間內(nèi)。
      考慮到發(fā)布模式堆棧的典型布局,您顯然遇到了麻煩。查看堆棧,了解原因所在。每個(gè)被調(diào)用的函數(shù)都會(huì)將其本地?cái)?shù)據(jù)布設(shè)到堆棧的一個(gè)幀內(nèi),通常是通過(guò)在輸入時(shí)從堆棧指針減去本地?cái)?shù)據(jù)的已知大?。由咸幚碚{(diào)用鏈本身所需的任何管理數(shù)據(jù))實(shí)現(xiàn)的。編譯器發(fā)出的理想函數(shù) prolog(偽代碼)如下所示:
 .foo
 sub sp, 128  ; sizeof SOMETYPE

      隨后,對(duì)可利用函數(shù)的調(diào)用應(yīng)如下所示:
push sp   ; push the SOMETYPE 
  local variable
push ap   ; push the stream 
  pointer (comes from 1st argument)
call LoadTypeFromStream
ret
      在調(diào)用 foo() 時(shí),調(diào)用方將流地址以及返回地址(作為使用調(diào)用指令或平臺(tái)上可用的同等部分的隱式效果)壓入堆棧,使堆棧內(nèi)容中有 128 個(gè)字節(jié)是為我們的類型保留的,且緊鄰返回給 foo() 調(diào)用方的返回地址,參見(jiàn)圖 1。
      現(xiàn)在,LoadTypeFromStream 執(zhí)行,并將 256 個(gè)字節(jié)寫入所提供的地址,也就是在我們調(diào)用函數(shù)之前堆棧指針(SP)的值。這會(huì)覆蓋應(yīng)該使用的 128 個(gè)字節(jié)(本例中位于地址 0x1000 處),加上隨后的 128 個(gè)字節(jié),包括傳入的參數(shù)指針、返回地址以及堆棧中隨后 128 個(gè)字節(jié)內(nèi)存儲(chǔ)的其他任何信息。
      那么攻擊者怎樣利用這樣的漏洞呢?并不簡(jiǎn)單,需要經(jīng)過(guò)反復(fù)的試錯(cuò)。實(shí)際上,攻擊者要安排攻擊,使覆蓋的返回地址將控制權(quán)移交給攻擊者,而非預(yù)期調(diào)用方函數(shù)。因而,攻擊者需要準(zhǔn)確了解要利用哪些數(shù)據(jù)結(jié)構(gòu),這樣的數(shù)據(jù)結(jié)構(gòu)在要攻擊的任意版本的操作系統(tǒng)或應(yīng)用程序上有多大、周邊有哪些內(nèi)容(以便正確設(shè)定偽造的返回地址)、如何有意義地插入足夠的信息以使返回地址和其他效果能夠?qū)崿F(xiàn)某種惡意操作。
      這一切做起來(lái)并不簡(jiǎn)單,但多種多樣的攻擊表明,總是有人有太多的空閑時(shí)間。
      應(yīng)如何防范此類攻擊?這是一次攻擊還是多重攻擊?所寫入的代碼是否真的像這里所顯示的這樣笨拙?現(xiàn)代編譯器是否會(huì)對(duì)堆棧幀布局做一些特殊處理,以避免此類問(wèn)題?
      總而言之,模糊處理就等于沒(méi)有防御。我們都認(rèn)識(shí)到,程序員將攻擊預(yù)想得越簡(jiǎn)單,攻擊出現(xiàn)的可能性就越高。然而,即便是復(fù)雜的代碼,若未進(jìn)行合理防御,也遲早會(huì)受到攻擊。這種利用被污染的數(shù)據(jù)流和非?;镜木彌_溢出漏洞的攻擊,多年以來(lái)這一直是熱門的研究課題,但每年仍然會(huì)出現(xiàn)大量此類攻擊。
      防范此類攻擊的效果甚微,因?yàn)楣粜问綇?fù)雜——注意您的數(shù)據(jù)假設(shè)。只要在示例1(a)中添加一行簡(jiǎn)單的代碼,就會(huì)使其更加安全,參見(jiàn)示例1(c)。顯然,隨著流交互變得更加復(fù)雜,保護(hù)的要求也隨之復(fù)雜化,但基本上說(shuō)代碼注入是編碼中“不可饒恕”的過(guò)失,因?yàn)榉婪端姆椒ㄊ悄菢悠占昂秃?jiǎn)單。

SQL 注入
      此外還存在其他一些類型的 SQL 注入,可能會(huì)給以數(shù)據(jù)庫(kù)為中心的應(yīng)用程序造成嚴(yán)重的問(wèn)題。在某些情況下,攻擊者只是嘗試訪問(wèn)更多的內(nèi)容。在另一些情況下,攻擊者關(guān)注的則是在數(shù)據(jù)庫(kù)中存儲(chǔ)新信息,以便使應(yīng)用程序此后在不知情的前提下使用此類信息,入侵最終用戶的會(huì)話。
      基于查詢的攻擊關(guān)注的是一種普遍應(yīng)用的反模式,使用字符串串聯(lián)構(gòu)建查詢。這種類型的漏洞常常出現(xiàn)在面向 Web 的應(yīng)用程序中,在所有常用頁(yè)面產(chǎn)品——包括 PHP、ASP、JSP 等及其后備控制器邏輯中同樣常見(jiàn)。
      這種漏洞的核心是開(kāi)發(fā)人員使用直接查詢執(zhí)行,而非利用查詢準(zhǔn)備來(lái)運(yùn)行數(shù)據(jù)庫(kù)交互。考慮以下登錄驗(yàn)證查詢示例:
SELECT ID FROM USERS WHERE NAME= 'user' AND PWD='password'
      用戶將看到一個(gè)簡(jiǎn)單的 HTML 表單,該表單包含兩個(gè)輸入框并使用了這種反模式。從表單傳入的參數(shù)(無(wú)論所討論的頁(yè)面產(chǎn)品是怎樣接收到這些參數(shù)的)都將通過(guò)串聯(lián)直接代入查詢的字符串形式。
考慮攻擊者提供的一組參數(shù):
NAME:   x
PWD:    x' OR '1' = '1
      運(yùn)行串聯(lián),結(jié)果將得到被利用的查詢:
SELECT ID FROM USERS WHERE NAME=
  'x' AND PWD='x' OR '1' = '1'
      如果登錄僅檢查該語(yǔ)句執(zhí)行成功與否(而未考慮結(jié)果行),攻擊者即可迅速獲得該應(yīng)用程序所處理的任意用戶記錄可提供的任意訪問(wèn)權(quán)限。很多應(yīng)用程序的用戶表的第一行都是為超級(jí)用戶保留的,攻擊此類應(yīng)用程序輕而易舉。
      利用未謹(jǐn)慎處理數(shù)據(jù)庫(kù)語(yǔ)句內(nèi)代入字符串的應(yīng)用程序,攻擊者可實(shí)現(xiàn)多種其他形式的攻擊。這種反模式極為常見(jiàn)(參見(jiàn)最近的 Microsoft 公告和其他內(nèi)容了解其普遍性),緩解方法也同樣簡(jiǎn)單,并可置于基本數(shù)據(jù)庫(kù) API 之中:使用準(zhǔn)備好的語(yǔ)句而非字符串串聯(lián)。
      例如,考慮示例2 中的錯(cuò)誤實(shí)現(xiàn)。此函數(shù)嚴(yán)格遵循反模式,還通過(guò)拋出包含傳入(未過(guò)濾)數(shù)據(jù)(即用戶名)的異常而執(zhí)行了另外一項(xiàng)重要的 no-no 操作。如果以響應(yīng)的形式為用戶呈現(xiàn)此數(shù)據(jù),您就很可能遇到某些惡意利用,特別是可能遭遇跨站腳本攻擊。
public void validateUser(String user, String pwd, Connection db)
    throws InvalidUserException
{
  Statement stmt = null;
  ResultSet rs = null;
  try
  {
      // Create the statement
      stmt = db.createStatement();
      String sql = "select id from users where user='" + user +
                   "' and pwd='" + pwd + "'";
      // Execute it, process the result
      rs = stmt.executeQuery(sql);
      if( rs == null || rs.next() == null )
          throw new InvalidUserException(user);
  }
  catch( SQLException e )
  {
      throw new InvalidUserException(user);
  }
  finally
  {
    try { if( rs != null ) rs.close(); } catch( Exception e ) { }
    try { if( stmt != null ) stmt.close(); } catch( Exception e ) { }
  }
}
示例2 錯(cuò)誤實(shí)現(xiàn)。
      為了修正此代碼,不應(yīng)動(dòng)態(tài)構(gòu)建 SQL 查詢,而是直接構(gòu)建準(zhǔn)備好的語(yǔ)句,并使用它來(lái)代替?zhèn)魅雲(yún)?shù)。
我們將準(zhǔn)備的語(yǔ)句會(huì)為參數(shù)保留空間,并且不易受此類攻擊利用,原因就在于它的詞匯方面并不像字符串串聯(lián)那樣脆弱。
      考慮以下語(yǔ)句(準(zhǔn)備該語(yǔ)句的目的與前面提到的串聯(lián)字符串相同):
SELECT ID FROM USERS WHERE USER=?
   AND PWD=?
      我使用這個(gè)準(zhǔn)備好的語(yǔ)句代入了 user 和 pwd 參數(shù)的傳入數(shù)據(jù)。如果我們將之前被利用的字符串作為輸入,結(jié)果將是查詢代入過(guò)程出錯(cuò),因?yàn)椴荒軐瑔我?hào)等特殊字符的參數(shù)提供給準(zhǔn)備好的查詢。
      其他可能出現(xiàn)的利用也能在不同階段捕捉到,但如示例3 所示,新實(shí)現(xiàn)的創(chuàng)建與原實(shí)現(xiàn)一樣簡(jiǎn)單,但安全性要高得多(我們也從拋出的異常中刪除了用戶名,這樣可以避免在未經(jīng)過(guò)濾的情況下將其公開(kāi)給調(diào)用方的危險(xiǎn))。
public void validateUser(String user, String pwd, Connection db)
    throws InvalidUserException
{
  PreparedStatement stmt = null;
  ResultSet rs = null;
  try
  {
      // Prepare the statement, rather than concatenating it
      String sql = "select id from users where user=? and pwd=?");
      stmt = db.prepareStatement(sql);
      // Substitute our incoming parameters into the query
      stmt.setString(1, user);
      stmt.setString(2, pwd);
      // Execute the query and process the results as before
      rs = stmt.executeQuery();
      if( rs == null || rs.next() == null )
          throw new InvalidUserException();
  }
  catch( SQLException e )
  {
      throw new InvalidUserException();
  }
  finally
  {
    try { if( rs != null ) rs.close(); } catch( Exception e ) { }
    try { if( stmt != null ) stmt.close(); } catch( Exception e ) { }
  }
}
示例3  示例2 的較為安全的版本。
      總體而言,無(wú)論是處理查詢還是DML,在處理來(lái)自最終用戶的數(shù)據(jù)時(shí),始終應(yīng)使用準(zhǔn)備好的語(yǔ)句來(lái)利用數(shù)據(jù)庫(kù)本身內(nèi)置的過(guò)濾和解析功能。

跨站點(diǎn)腳本攻擊(XSS)
      在早期的瀏覽器版本中,對(duì)于JavaScript 施加的第一項(xiàng)限制就是為頁(yè)面內(nèi)容建立一種邊界,使一個(gè)站點(diǎn)提供的一個(gè)框架內(nèi)執(zhí)行的腳本無(wú)法訪問(wèn)其他站點(diǎn)提供的框架中的內(nèi)容。因而,跨站點(diǎn)腳本攻擊這種攻擊模式關(guān)注的是使來(lái)自一個(gè)站點(diǎn)(攻擊者站點(diǎn))的腳本能夠訪問(wèn)其他站點(diǎn)的內(nèi)容(例如,用戶的銀行賬戶站點(diǎn))。
      為此,用戶通常必然要訪問(wèn)一個(gè)惡意或不可信的網(wǎng)站,而社會(huì)工程的眾多試驗(yàn)已經(jīng)顯示,用戶可能會(huì)被最古怪的站點(diǎn)吸引。
      在此類漏洞中,最常見(jiàn)的形式就是簡(jiǎn)單的反射漏洞,在一次服務(wù)器請(qǐng)求中將未經(jīng)過(guò)濾的 HTML 參數(shù)(通常是表單參數(shù))反射給用戶。這種攻擊載體的標(biāo)準(zhǔn)形式首先是通過(guò)搜索引擎結(jié)果頁(yè)面顯示出來(lái)的,通常會(huì)在頁(yè)面標(biāo)題中反射用戶的查詢關(guān)鍵詞。如果未經(jīng)過(guò)濾,這種反射回的查詢關(guān)鍵詞很可能包含一些編碼不當(dāng)?shù)?HTML 標(biāo)記,但可被接收方瀏覽器解釋為有效的 HTML。
      實(shí)際上,未經(jīng)過(guò)濾的傳入數(shù)據(jù)的任何反射都會(huì)造成問(wèn)題,因?yàn)?XSS數(shù)量和種類始終在增加,參見(jiàn)示例4。
public void doGet(HttpServletRequest req, HttpServletResponse res)
{
    string title = req.getParameter("searchTerm");
    res.getOutputStream().write(title.getBytes("UTF-8"));
}
示例4 未經(jīng)過(guò)濾的傳入數(shù)據(jù)本身就存在問(wèn)題。
      XSS反射的表現(xiàn)十分簡(jiǎn)單,而解決此問(wèn)題的方法也極為簡(jiǎn)單——將從傳入請(qǐng)求中讀取的一切內(nèi)容編碼,之后再回發(fā)給瀏覽器即可。盡管我們?cè)谶@里的示例中使用了Java,但包括HTML編碼機(jī)制的所有常見(jiàn)頁(yè)面產(chǎn)品均可用以避免此類漏洞。例如,下面這條 ASP 語(yǔ)句就可能被利用:
Response.Write Request.Form("username""
      反之,以下語(yǔ)句則不能被利用:
Response.Write Server.HTMLEncode( Request.Form("username"))
      盡管仍然沒(méi)有內(nèi)置對(duì)象可用于執(zhí)行標(biāo)準(zhǔn)轉(zhuǎn)換,但也可在 Java 中進(jìn)行類似轉(zhuǎn)換,以避免此類利用。也就是說(shuō),可輕松編寫一個(gè)類似的 String 轉(zhuǎn)換程序。對(duì)于尋找“現(xiàn)成”產(chǎn)品包的用戶,JTidy 項(xiàng)目(jtidy.sourceforge.net)是一個(gè)理想的起點(diǎn)。
      其他更加復(fù)雜的 XSS 表現(xiàn)形式以未過(guò)濾用戶輸入的持久存儲(chǔ)為中心,此類輸入內(nèi)容會(huì)在隨后用于提供響應(yīng)內(nèi)容。這是一類更難以診斷的 XSS,因?yàn)楣裟J讲粌H依賴于所存儲(chǔ)的未經(jīng)過(guò)濾的用戶輸入,還依賴于此后對(duì)其他用戶可用的存儲(chǔ)數(shù)據(jù)。
      在早期Web發(fā)展階段,不可信任的論壇提供的軟件包特別易受此類攻擊模式的影響。即便是現(xiàn)在,在數(shù)據(jù)庫(kù)(或文件)中存儲(chǔ)未經(jīng)過(guò)濾的傳入數(shù)據(jù)并隨后將所存儲(chǔ)的數(shù)據(jù)發(fā)送給用戶的應(yīng)用程序也易于受到此類持久形式的 XSS 的攻擊。
      同樣,解決方法非常簡(jiǎn)單,只需通過(guò)編程,在存儲(chǔ)信息之前將信息編碼或在將信息從持久存儲(chǔ)發(fā)送給用戶之前編碼即可。總而言之,在存儲(chǔ)之前編碼數(shù)據(jù)總是更加安全,這種方式可以保證未來(lái)對(duì)此類數(shù)據(jù)的使用免遭XSS 攻擊。

查找漏洞
      本文介紹的問(wèn)題的規(guī)避方法易于實(shí)現(xiàn),但對(duì)于嘗試控制現(xiàn)有代碼庫(kù)或新建代碼庫(kù)的安全性的開(kāi)發(fā)人員或開(kāi)發(fā)組織而言,所面臨的最大挑戰(zhàn)就是找到漏洞所在。毫無(wú)疑問(wèn),可以利用手動(dòng)代碼檢查的方法,但我可以確定地說(shuō),圍坐在桌邊、查看大量代碼并嘗試找出可能成為漏洞的內(nèi)容絕非樂(lè)事。
      靜態(tài)源代碼分析為此類問(wèn)題提供了一種可行的解決方案,這種方法關(guān)注代碼中現(xiàn)有的潛在漏洞或弱點(diǎn),而不是像傳統(tǒng)安全性應(yīng)用程序或滲透測(cè)試工具那樣嘗試找到現(xiàn)有漏洞或攻擊載體 。利用 SCA 工具可顯著減少查找并緩解此類問(wèn)題所需的時(shí)間和工作量。
      目前有多種開(kāi)源和商業(yè)工具可用,分別具有不同的功能。Klocwork(我目前效力的企業(yè))就提供了這樣一種商業(yè)靜態(tài)源代碼分析產(chǎn)品套件,主要關(guān)注 C、C++ 和 Java,為開(kāi)發(fā)人員提供了快速、準(zhǔn)確的運(yùn)行缺陷和安全漏洞分析,并且能夠集成在您所選擇的 IDE 之中。■
原文鏈接:http://www.ddj.com/cpp/210602504
作者簡(jiǎn)介:
Gwyn是Klocwork的首席技術(shù)官,他有著20多年的全球技術(shù)經(jīng)驗(yàn)。在Klocwork,Gwyn從事的工作仍然圍繞他最初的愛(ài)好——編譯器理論,他致力于將靜態(tài)源代碼分析推向更高級(jí)別。
(本文來(lái)自《程序員》0902期)
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
java連接mysql數(shù)據(jù)庫(kù)詳細(xì)步驟解析
某郵件管理系統(tǒng)代碼審計(jì)
從數(shù)據(jù)庫(kù)中讀出圖片并顯示的示例代碼
mysql基本的JDBC概念
Spring中模板模式和回調(diào)模式的講解
原理分析之一:從JDBC到Mybatis
更多類似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服