• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    Perl CGI編程安全點滴

    發布: 2007-7-04 20:04 | 作者: admin | 來源:  網友評論 | 查看: 9次 | 進入軟件測試論壇討論

    領測軟件測試網 ◆Perl CGI編程安全點滴(作者:backend)

      CGI在現在的互聯網應用越來越廣泛,CGI編程的安全問題也得到越來越多的
    重視。Perl作為CGI編程的主要語言之一,其安全性也受到很大的關注。在 W3C
    組織的 "WWW Security FAQ" 之 "CGI Scripts"一章中,Perl安全編程就整整占
    了一節。由此可見 Perl CGI 安全編程的重要性。
       這里我不會重復 "WWW Security FAQ" 的內容,而是根據一直以來對 Perl
    免費/商業程序包的源代碼的研究,得出一些較易被忽略的編程漏洞,在此將幾個
    最常見的(主要是變量字符過濾方面)寫出來,供廣大程序員作為參考。
       如果你對本文的內容有不同意見或任何建議,請告訴我。如果你發現了其它
    Perl CGI 編程漏洞,也請告訴我。如果你也發表了關于這方面的文章,當然也
    請告訴我。:-)

    ---------------------
    1、“有毒”的NULL字符
    ---------------------

      如果我說:"root"=="root",相信沒有什么人反對。但同時我也這樣說:
    "root"!="root"!還有多少人會認為我是個“正常人”?:)
       但在各種不同的編程語言中,確實存在著這種情況。
       對于每一個希望發現CGI漏洞的安全專家或黑客來說,最常用的方法之一是
    通過傳遞特殊字符(串),繞過CGI限制以執行系統級調用或程序。如果你仔細
    留意的話,或許也會發現NULL字符確實有它的“妙用”。:)
       閱讀以下例子:

    # parse $user_input
    $database="$user_input.db";
    open(FILE "<$database");

    這個例子用于打開客戶端指定的數據庫文件。例如客戶端輸入"backend",則系
    統將打開"backend.db"文件考只讀方式)。(注:在這里我們暫且不討論"../"
    的安全問題。)這種處理方式在互聯網中是很常見的。
       現在,讓我們在客戶端輸入"backend%00",在該PERL程序中$database=
    "backend.db",然后調用open函數打開該文件。但結果是什么呢?系統會打
    開"backend"文件(,如果該文件存在)!
       出現這種情況的原因是由于PERL允許在字符串變量中使用NULL空字符,而
    在C語言中字符串則不允許包含空字符。因此,也就有了"root"!="root"(在
    PERL中)和"root"="root"(在C語言中)。由于系統內核/調用等都是使用C
    語言編寫,因此當PERL將"backend.db"字符串傳遞到(C語言的)鏈接庫/程序
    時,空字符以后的字符將被忽略?(或許還有利用價值?我還沒發現。:))
       這種編程缺陷的影響可大可小。試想一下,如果利用以上編程原理編寫一個
    給系統其他管理員修改除了root外的其他用戶口令的PERL程序:

    $user=$ARGV[1] # user the jr admin wants to change
    if ($user ne "root"){
    # do whatever needs to be done for this user }

    那么,聰明的你應該知道如何繞過這個限制修改root用戶口令了吧?對了,只要
    使 $user="root",則PERL會執行上面程序中花括號內的語句。除非所有處理
    過程均使用PERL,否則一旦該變量傳遞給系統,則會造成安全問題。如修改root
    用戶口令等。
       也許你認為很難遇到這種會造成嚴重安全問題的情況,那么我們能否將它作
    為一種尋找網站源程序漏洞的間接手段呢?;-)
       不知你有沒有經常遇到這種類型的CGI程序,該程序用于打開客戶端(提交
    的表單中)要求的頁面?如:

    page.cgi?page=1

    然后網站是否返回頁面"1.html"呢?;-) 好,現在將其改為:

    page.cgi?page=page.cgi%00 (%00 == '' escaped)

    這樣,我們就可以得到我們感興趣的文件內容了!這種方法連PERL的"-e"參數也
    可繞過:

    $file="/etc/passwd.txt.whatever.we.want";
    die("hahaha! Caught you!) if($file eq "/etc/passwd");
    if (-e $file){
    open (FILE, ">$file");}

    繞過這段程序的后果你應該想像得到吧?:)
       解決方法?最簡單地,過濾NULL空字符。在PERL程序中,

    $insecure_data=~s///g;

    ------------------------
    2、漏網之魚--反斜杠()
    ------------------------

      對于每一個關心CGI安全的人,也許都看過 W3C 的 WWW Security FAQ 中關
    于CGI安全編程一節。其中列出了建議過濾的字符:

    &;`'"|*?~<>^()[]{}$nr

    但我在很多時候發現反斜杠()往往被遺忘了。以下是正確的過濾表達式:

    s/([&;`'\|"*?~<>^()[]{}$nr])/\$1/g;

    但在很多商業的CGI程序中反斜杠卻沒有被包含進去,這可能是程序員們寫程序
    時被這些過濾用的匹配表達式搞迷糊了?
       那么,沒有過濾反斜杠會造成安全問題嗎?試想一下,如果向你的程序中發
    送如下一行內容:

    user data `rm -rf /`

    大多數情況下,程序員編寫的程序會將以上內容過濾為:

    user data `rm -rf /`

    從而保護了系統。但如果PERL程序中忘記過濾了反斜杠,當客戶端向該程序提交
    如下內容時:

    user data `rm -rf / `

    經過匹配表達式后為:

    user data \`rm -rf / \`

    怎么樣,看出危險了嗎?由于兩個反斜杠經系統解釋后為一個字符"",但`字符
    卻因此沒有被過濾掉,`rm -rf / `將被系統執行!不過,由于其中還含有一個
    反斜杠字符,執行時系統會出錯。你自己想辦法繞過這個限制吧?;-)
       利用反斜杠的另一個應用--繞過系統目錄進入限制。請看以下表達式:

    s/..//g;

    這個匹配表達式的作用非常簡單,就是過濾字符串中的".."。當輸入為:

    /usr/tmp/../../etc/passwd

    將被過濾為:

    /usr/tmp///etc/passwd

    這樣,你將無法訪問/etc/passwd文件。(注:*nix系統允許///,試一下'ls -l
    /etc////passwd'命令就知道了。)
       現在,讓我們的“好伙伴”反斜杠來幫忙。將輸入改為:

    /usr/tmp/../../etc/passwd

    則由于反斜杠的存在而不符合過濾表達式。當PERL中存在如下程序段時,

    $file="/usr/tmp/.\./.\./etc/passwd";
    $file=s/..//g;
    system("ls -l $file");

    當運行到執行系統調用時,執行的命令會是"ls -l /usr/tmp/../../etc/
    passwd"。想知道會得到什么輸出嗎?自己在機器上試試吧。;-)
       然而,以上方法只適用于系統調用或``命令中。無法繞過PERL中的'-e'命令
    和open函數(非管道)。如下程序:

    $file="/usr/tmp/.\./.\./etc/passwd";
    open(FILE, "<$file") or die("No such file");

    執行時將顯示"No such file"并退出。我還沒有找出繞過這個限制的方法。:(

      解決方法:只要別忘了過濾反斜杠字符(),就已足夠了。

    --------------------------------
    3、暢通無阻的“管道”--字符"|"
    --------------------------------

      在PERL的open函數中,如果在文件名后加上"|",則PERL將會執行這個文件,
    而不是打開它。即:

    open(FILE, "/bin/ls")

    將打開并得到/bin/ls的二進制代碼,但

    open(FILE, "/bin/ls|")

    將執行/bin/ls命令!
       以下過濾表達式

    s/(|)/\$1/g

    可以限制這個方法。PERL會提示"unexpected end of file"。如果你找到繞過這
    個限制的方法,請告訴我。:-)

    綜合應用

      現在讓我們綜合以上幾種編程安全漏洞加以利用。先舉個例子,$FORM是客
    戶端需要提交給CGI程序的變量。而在CGI程序中有如下語句:

    open(FILE, "$FORM")

    那我們可以將"ls|"傳遞給$FORM變量來獲得當前目錄列表,F在讓我們考慮如下
    程序段:

    $filename="/safe/dir/to/read/$FORM"
    open(FILE, $filename)

    如何再執行"ls"命令呢?只要能使$FORM="../../../../bin/ls|"即可。如果系
    統對目錄操作加入了".."過濾,則可利用反斜杠的漏洞繞過它。
       在這段程序中,我們還可以在命令中加入參數。如"touch /backend|",將
    建立/backend文件。(但我不會使用這個文件名,因為它是我的名字。:-))
       現在,讓我們在程序段中加入更多的安全限制:

    $filename="safe/dir/to/read/$FORM"
    if(!(-e $filename)) die("I don't think so!")
    open(FILE, $filename)

    這樣我們還需要繞過"-e"的限制。由于我們在$FORM變量中使用了"|"字符,當
    "-e"運算符檢查"ls|"文件時,因為不存在此文件而退出程序。如何當"-e"檢查
    時去掉管道符,而調用open函數時又含有管道符呢?回憶一下在前面談到的NULL
    字符的利用,我們就知道應該如何做了。只要使$FORM="ls|"(注:在客戶端
    提交的表單中為"ls%00|")即可。其中的原理復習一下前面提到的內容就會明白
    了。
       需要說明的是,以上程序段中,我們無法象再上一段程序那樣執行帶參數的
    命令,這是因為"-e"運算符的限制所致。舉例如下:

    $filename="/bin/ls /etc|"
    open(FILE, $filename)

    將顯示/etc目錄下文件列表。

    $filename="/bin/ls /etc|"
    if(!(-e $filename)) exit;
    open(FILE, $filename)

    將導致因不存在文件而退出。

    $filename="/bin/ls /etc|"
    if(!(-e $filename)) exit;
    open(FILE, $filename)

    將只顯示當前目錄下文件列表。

    延伸閱讀

    文章來源于領測軟件測試網 http://www.kjueaiud.com/


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>