漠漠孤雲盡成雨---淺談CGI指令碼安全(轉)

worldblog發表於2007-09-18
漠漠孤雲盡成雨---淺談CGI指令碼安全(轉)[@more@]

  很多朋友告訴我一定要去不斷總結自己學的東西,並且不要吝嗇拿出來與人分享,這樣才有一個很好的沉澱和交流,還有彼此的促進。於是自己把自己一部分學習筆記整理了一下。還有一些自己平時總結的一些學習經驗,希望對大家有所幫助。

  CGI指令碼是在網路伺服器上解釋執行的,然後將執行的結果返回給客戶端(就是我們的瀏覽器)。因為perl的強大功能、他的靈活性和對所有流行的作業系統的支援,當然還有它的“價格”(純免費)。使其受到了很多CGI程式設計者的青睞。我們知道任何語言本身是無安全性可言的,安全只是存在於使用他的人的身上。所以如果在編寫指令碼時,沒有安全的意識,那麼編寫出的程式碼也就沒有安全的"功能"了。

  一、注意對變數的處理

  1、使用者的輸入是不可信任的,當談到安全程式設計的時候,比爾蓋茲先生對他的員工說了一句非常經典的話:All input is invalid.(所有的使用者輸入都是有害的,具體是不是他第一個說的,有待考察)

  一切使用者輸入的地方都是我們應當注意的地方。大家知道美國最著名的電子商務網站e***.com吧,他在1999年就被駭客用以下的方法入侵了。我們的新浪網站也被用同一種方法攻了進去,並且還被人截了圖。。。。

  來看一段程式碼吧:

  -----------Code Start------------

  #unsafecodz.cgi

  01 $filepath="f://myhome//bbs//"

  ......

  ......

  13 $filename=$query -> param( page );

  14 if ($filename eq "")

  15 { $filename="error.html";

  16 die("對不起,檔名不能為空!");

  17 }

  18 else{

  19 $filename="$filepath/".$filename;

  20 open(FILE,$filename);

  21 while()

  22 {

  23 print $_;

  24 }

  25 close(FILE)

  ......

  -----------Code Ends-------------

  這段程式碼基本上沒有作太多改動,因為我演示是在自己的機子上,所以把路徑改了一下,我們在這裡回放一下曾經的過程。

  這段程式碼是網站用來瀏覽的其他網頁的,如:,就會瀏覽something.html這個檔案,這裡的$filename用param提取page中使用者輸入的內容,$filename其實是使用者間接輸入的內容,而程式碼對$filename並沒有做嚴格的審查只是檢查是否為空,如果惡意使用者直接在瀏覽器中指定其他檔案,如cgi,asp或者任何檔案,則返回的是檔案的原始碼,如:。

  看到unsafecodz.cgi的原始碼了,透過簡單的瀏覽其他的頁面,我們可以基本上可以得到所有檔案的原始碼。我們也可以透過"../"來切換到其他的目錄下。

  這還不是最糟糕的,如果你的系統是Linux或者UNIX,那麼更過分的在這裡呢!。結果顯而易見,可以看到了主機的使用者名稱和密碼文件。

  這也不是最遭的,如果利用open函式加管道符執行任意命令的後果會怎麼樣?利用open函式執行命令的技術很老了,我就不廢筆墨了。

  後來有人對程式碼進行加固,將第19行改成 $filename="$filepath/".$filename.".html" 他限定後面4位為html,但是這樣的加固似乎起不到什麼作用,因為它忽略了NULL字元。提交如下請求依然可以繞過他的限定:

  /myhome/bbs/unsafecodz.cgi?page=unsafecodz.cgi%00.html

  還是這個問題,還有人這麼加固程式碼,它在將19行改了之後,又將第14行改成:

  if (($filename eq "") || (-e $filename))

  他在這裡檢查檔案是否存在,如果不存在就不去進行後面的操作,我們這麼依然提交:

  /myhome/bbs/unsafecodz.cgi?page=unsafecodz.cgi%00.html

  你會發現我們依然可以成功。

  他還是忽略了什麼,他忽略了什麼呢?他忽略了null字元是可以繞開-e的檢查,也就是說(-e $filename)將會認為檔案是存在的,因為%00後面的東西在-e中會被忽略。

  ok,這裡我們停一下,我們應該能注意到剛才是什麼改變了程式本來的流程。就是那個null字元(),想想還有什麼我們可以用來改成程式的流程呢? , ,x0B, ,空格。這些字元都很有用,大家記住它並要學會如何自由運用這些東西。大家是否還記得前不久的dvbbs論壇漏洞,就是由於上傳中的null字元所引起的。很多時候你會發現技術突破不過就是你的技術積累沉澱後的爆發。

  ##關鍵詞:使用者輸入的變數

  ##檢查:是否做過有效過濾

  2、隱式輸入的危害

  使用者的輸入分為兩種,顯示輸入和隱式輸入。上面的例子沒有注意到使用者的輸入導致問題的出現。因為那是使用者直接輸入的,算是顯示輸入吧。現在很多程式設計師都會下意識的去保護自己程式的安全性或者他們本身就瞭解一些安全的重要性,都會加一些有用或者沒用的限制,使用者直接輸入可利用的部分越來越少,於是隱式輸入就開始受到關注。這裡說的並不僅僅是perl cgi,包括現在一大幫人玩的asp注入攻擊,還有本來是n年前的技術現在才浮出水面的php注入還有一些其他的攻擊手段。仔細回顧一下你就會發現很多都是隱式輸入所引起。隱式輸入都是不被程式設計師注意或者容易被忽略的地方。

  cookie應該算是隱式輸入中比較典型的例子,我們就用cookie來說事兒吧......

  -----------Code Start------------

  #unsafecodz2.cgi

  ......

  18 $filename=$query->cookie("namecookie");#**********#

  19 $filename="$filepath/".$filename;

  20 open(FILE,$filename);

  21 while()

  22 {

  23 print $_;

  24 }

  25 close(FILE)

  -----------Code Ends------------

  注意打星號的那一行,這只是提取cookie而已,這的確不是使用者的直接輸入,但這卻是使用者可以間接控制的。如果惡意使用者透過nc提交如下東東,後果是什麼呢?

  GET /myhome/unsafecodz2.cgi HTTP/1.1

  Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, */*

  Accept-Language: zh-cn

  Accept-Encoding: gzip, deflate

  User-Agent: Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)

  Host: 127.0.0.1

  Connection: Keep-Alive

  Cookie: namecookie=/../../../../../ect/passwd

  我們看到這行中

  Cookie: namecookie=/../../../../../ect/passwd

  一般隱式輸入都不容易被注意。

  這裡攻擊者可以透過構造cookie來控制網站,結果就是和上面的一樣。說到這裡其實都是一句話:All input is invalid。作為程式碼的編寫者要注意所有使用者可以直接或間接控制的地方。

  這裡你可能覺得你似乎明白了,但我敢說其實你並沒有真的明白,cookie的控制是裡面最簡單的一個例子。隱式輸入很多時候,不要說寫程式碼的人了,就連很多WEB安全的高手都不見得能夠非常容易的找到,他們更多的是憑自己的經驗和直覺。你可能覺得我言過其實了,其實並沒有,簡單的連傻瓜都能看出來的隱式輸入,當然容易找到。但是許多的危害更大的,並不那麼容易發現,所以這個時候多是憑藉自己的經驗和對漏洞"味道"靈敏的嗅覺。

  ##關鍵詞:沒有

  ##檢查:是否做過有效過濾

  解決方法其實很簡單,就是嚴格控制使用者的輸入。所謂嚴格控制並不只是過濾,因為過濾難免有漏網之魚。限定要比過濾來得輕巧和嚴格。把使用者的輸入控制在你規定的範圍內,可以用一個正規表示式來給使用者劃一個範圍,指定使用者可以輸入的字元或者數字,如果使用者輸入與你的規定的不匹配,則不與透過。

  至於如何做限定,用正規表示式會很簡單。我用email的例子說明:

  if (email !~/^[w.-]+@[w.-]+$))#如果不和裡面的規定字元匹配則報錯

  {

  &error"輸入不正確,難道您就是傳說中的駭客?"

  }

  else

  {

  #輸入正確,繼續操作。

  ......

  email的一般格式是fakename@fakename.org。我們只希望使用者輸入字元、數字、@、"."、“-”、“_”這些東東。永遠不要幻想使用者會按照你所希望的輸入,除非你給他們劃定範圍。在這裡用以一個簡單的正規表示式。在這個正規表示式中,要求使用者只能輸入英文大小寫字元,數字和“@”,"-","_""."這幾個字元,如果輸入其他的,則報錯。

  二、注意幾個危險函式在程式碼中的使用和特殊字元過濾。

  1、有幾個危險函式在程式中用得越少越安全(這麼說好像有點不嚴格,呵呵)。因為很多都是駭客的突破口。這些函式是:system(),open(),exec()。

  system()和exec都可以執行系統命令,如system("del f:myhome$filname"),如果$filename也是透過表單從使用者那裡得到的,如果我們在$filename處輸入1.txt;del f:myhome。我們就刪除了整個目錄。我們現在可以刪除任意檔案。如果你用管道運算子的話也可以。

  其實system()函式可以執行系統命令,如果對其中變數缺少嚴格限制容易引起安全問題,程式設計師們或多或少的知道一些,但是由於快速開發或者專案給的時間緊,為了應付差事,往往不會理會。

  ##關鍵詞:system()、exec()

  ##檢查:函式中是否有可控制的變數,是否可利用

  open()函式也是我們應當留意的地方,大家不要誤會,open函式本身是沒有什麼的,而是裡面的使用者輸入的資料導致的問題集中到了open()函式上。open()函式本來是用來開啟一些檔案,我們看到我們的第一個程式就是因為open函式引起的洩漏原始碼。我們還可以透過“>”,"

  

·上一篇:

·下一篇:
 
     最新更新
·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·

·


| | | | | | |

Copyright © 2004 - 2007 All Rights Reserved

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-969899/,如需轉載,請註明出處,否則將追究法律責任。

漠漠孤雲盡成雨---淺談CGI指令碼安全(轉)
請登入後發表評論 登入
全部評論

相關文章