沙漠綠洲

          ----駱駝之行

           

          轉 Web應用的輸入攻擊及其防范

          來自:http://www.vbyte.com/blog/detail.asp?blog_id=1&content_id=3&cat_id=7

          一、攻擊者繞過身份驗證的方法?

            設想有這樣一個簡單的用戶登錄程序:它通過表單獲取用戶名字和密碼,然而把這些數據發送到服務器端,服務器端程序查找數據庫并驗

          證用戶身份。這種用戶身份驗證方法非常常見。檢查用戶名字和密碼時,許多開發者使用的是類如下面的代碼:?


          <HTML>
          <%@language=javascript....%>
          <%
          if?(isPasswordOK(Request.form("name"),Request.form("pwd")))?{
          Response.write("身份驗證通過!");
          //?其他操作
          }?else?{
          Response.write("拒絕訪問!");
          }

          function?isPasswordOK(strName,?strPwd)?{
          var?fAllowLogon?=?false;
          try?{
          var?oConn?=?new?ActiveXObject("ADODB.Connection");
          var?strConnection="Provider=Microsoft.Jet.OLEDB.4.0;Data
          Source=c:\\auth\\auth.mdb;"
          oConn.Open(strConnection);
          var?strSQL?=?"SELECT?count(*)?FROM?client?WHERE?"?+
          "(name='"?+?strName?+?"')?"?+?
          "?and?"?+
          "(pwd='"?+?strPwd?+?"')";
          var?oRS?=?new?ActiveXObject("ADODB.RecordSet");
          oRS.Open(strSQL,oConn);
          fAllowLogon?=?(oRS(0).Value?>?0)???true?:?false;
          oRS.Close();
          delete?oRS;
          oConn.Close();
          delete?oConn;
          }?catch(e)?{
          fAllowLogon?=?false;
          }

          return?fAllowLogon;
          }
          %>
          </HTML>



            注意,在上面的代碼中,程序從表單數據中提取出用戶名字和密碼,然后直接傳遞給了進行驗證的函數isPasswordOK。查詢數據庫的SQL命

          令直接利用表單輸入數據構造,這是一個不安全的過程。假設用戶名字是“mikey”,密碼是“&y-)4Hi=Qw8”,則實際查詢數據庫的SQL命令是

          :?


          SELECT?count(*)?FROM?client?WHERE?(name='mikey')?and
          (pwd='&y-)4Hi=Qw8')



            當查詢結果中count(*)返回合適的數值時,用戶“mikey”的身份驗證通過。如果count(*)返回的結果是0,則查詢未能找到匹配的記錄,

          用戶被拒絕訪問。?

            那么,攻擊者如何繞過這個驗證過程呢?首先,攻擊者會假定驗證過程使用上面這種SQL命令進行驗證,然后他們就發送偽造的用戶名字和

          密碼,改變SQL命令的判斷邏輯。例如,如果攻擊者輸入的用戶名字是“x'?or?1)?or?('1”,密碼是“anyoldpassword”,則實際查詢數據庫

          的SQL命令將變成:?


          SELECT?count(*)?FROM?client?WHERE?(name='x'?or?1)?or?('1')
          and?(pwd='anyoldpassword')



            可以看出,這個查詢選出的行數量總是大于或等于1,即count(*)的返回結果總是1或者更大。由此,雖然攻擊者并不知道合法的用戶名字

          和密碼,他總是能夠通過身份驗證!?

            注意下面5點有助于防止攻擊者繞過Web應用的身份驗證過程。?

          二、防止錯誤信息泄密?


            不要向瀏覽器返回帶有出錯SQL命令的錯誤信息。出現腳本錯誤時,默認情況下IIS會返回一個500-100錯誤信息。事實上,返回不帶調試信

          息的錯誤信息更有利于安全。例如,當我們在登錄表單輸入偽造的用戶名字和密碼時,服務器返回的錯誤信息可能如下:?


          Error?Type:
          Microsoft?JET?Database?Engine?(0x80040E14)
          Syntax?error?(missing?operator)?in?query?expression?
          '(name='x'?or?1)?or?('1')?and?(pwd=''p')'.
          /login.asp,?line?24



            可以看到,錯誤信息中包含了部分SQL命令,它會幫助攻擊者改正原先的錯誤,為攻擊者快速構造出雖然偽造、但在SQL命令中合法的用戶

          名字和密碼帶來了方便。?

            要減少服務器返回的錯誤信息量,最簡單的方法是修改%winnt%\help\iisHelp\500-100.asp;或者創建一個新的文件,同時設置IIS,使得

          500.100錯誤出現時服務器返回這個新的文件。設置IIS服務器的步驟如下:?


          1.打開IIS管理工具?
          2.右擊要設置的Web服務器?
          3.選擇“屬性”?
          4.選擇定制錯誤的選項卡?
          5.輸入定制的500.100錯誤頁面文件的名字?
            對于安全來說,錯誤信息中最好永遠不要出現服務器上的物理路徑。例如,返回“不能在c:\wwwroot\secretlocation目錄下找到foo.doc

          文件”這種錯誤信息并不有利于安全,一個簡單的404提示已經足夠了。?

          三、確定合法性規則?

            利用VBscript....、Jscript....以及Perl語言的正則表達式,我們可以為用戶輸入數據定義合法性規則。不要去分析哪些輸入數據非法,因為攻擊

          者會找出繞過非法數據檢查規則的辦法。例如,假設為了防止用戶向網站發送HTML數據,我們要替換輸入數據中的“<”和“>”符號:?


          strInput?=?strInput.replace(/[<>]/,"");?



            上面這個語句把“<”和“>”符號替換成空字符串。那么,是否這樣一來攻擊者所發送的HTML就不能再發送到服務器上了呢?答案是否定

          的。攻擊者只需把“<”和“>”替換為相應的HTML實體符號,上述分析用戶輸入的代碼就不能再找出HTML。由此我們認識到,正確的方法應該

          是先確定什么是合法的,然后驗證用戶輸入的合法性,拒絕所有不符合合法性規則的輸入:?


          if?(strName.search(/[^A-Za-z?0-9]/)?!=?-1)?return?false;?



            這行代碼搜索strName,如果strName包含除了大寫字母、小寫字母、數字和空白字符之外的(這就是^的含義)字符,則輸入數據被拒絕。?


            進行輸入檢驗時還要注意偽造的文件名字。攻擊者可能嘗試把數據發送到某些敏感的位置,或者可能發出請求試圖得到源文件,等等。下

          面這個正則表達式對文件名字作嚴格的限制。合法文件名字的規則描述如下:?


          ●一個或者多個0-9a-zA-Z或_,再加上?

          ●一個或者多個0-9a-zA-Z、-、\、/和_,再加上?

          ●一個句點,再加上?

          ●’’、’txt’、’jpg’、’jpeg’、’gif’、’htm’、’html’、’png’、’bmp’或’zip’?

            所有不符合上述規則的文件名字都非法。這個文件名字規則非常嚴格,但確實有效。你可以看到,文件名字不能以斜杠開頭,因為斜杠是

          磁盤的根目錄。除了攻擊者之外,另外還有誰需要從磁盤的根目錄開始訪問呢?所有對文件的訪問都應該相對于Web網站的根進行:?


          var?strInput?=?Request.form("filename");?

          var?re?=?/^[\w]{1,}[\w\-\/\\]{1,}\.(txt|jpg|jpeg|gif|htm|html|png|bmp|zip)?

          {0,1}$/i;?

          var?fIsFilenameValid?=?(re.test(strInput))???true?:?false;?

          四、正確處理引號?

            引號有時候很難處理,因為它們會干擾SQL命令。如本文開頭的例子,攻擊者利用引號改變SQL命令的邏輯,使得不具備合法用戶名字和密

          碼的人也能夠登錄系統。防止利用引號攻擊的另外一種方法是事先轉義引號字符。下面這個正則表達式將把所有單引號和雙引號分別替換為兩

          個單引號和兩個雙引號。替換得到的SQL命令完全合乎SQL語法,而且它使得許多攻擊更難進行。?


          strPwd?=?strPwd.replace(/([\’\"])/g,"$1$1");?



            這個語句可以替換前面加上的正則表達式。但也可以兩者一起使用,加強防衛力量!?

          五、檢查SQL查詢返回的數據?

            一種完全防止這類攻擊的方法是停止使用只能表示“贊成、反對”的count(*),改為檢查用戶名字、密碼是否和SQL命令返回的用戶名字、

          密碼匹配。具體代碼如下所示:?


          var?strSQL?=?"SELECT?name,?pwd?FROM?client?WHERE?"?+?

          "(name=’"?+?strName?+?"’)?"?+?

          "?and?"?+?

          "(pwd=’"?+?strPwd?+?"’)";?

          var?oRS?=?new?ActiveXObject("ADODB.RecordSet");?

          oRS.Open(strSQL,oConn);?

          fAllowLogon?=?(oRS(0).Value?==?strName?&&?oRS(1).Value?==?strPwd)?

          ??true?:?false;?



            如果SQL查詢沒有返回數據,程序將觸發一個異常,隨后這個異常就被catch()捕獲。?


          六、禁用父路徑?

            確保文件名字中沒有出現“..”。按照如下步驟禁用父路徑:?


          右擊Web網站的根,從菜單選擇“屬性”。?

          ●選擇“主目錄”選項卡。?

          ●點擊“配置”。?

          ●點擊“應用程序選項”。?

          ●取消“啟用父路徑”。?

            如果要從命令行禁用父路徑,請執行如下命令:?


          cscript....?adsutil.vbs?set?w3svc/1/root/AspEnableParentPaths?false?



            要真正做到對輸入攻擊的全面防范,你必須有一切輸入數據都可能有危險的心理準備。檢查合法的輸入,而不是檢查不合法的輸入,因為

          攻擊者很快就可以找出突破不合法規則的辦法。同時,學習并正確地運用正則表達式。記住了這幾點,你就能夠大大減少Web應用被侵入的機會。?

          posted on 2006-07-23 17:43 小澗流水 閱讀(242) 評論(0)  編輯  收藏 所屬分類: 信息安全

          導航

          統計

          公告

          Free Counter
          Free Web

          常用鏈接

          留言簿(1)

          隨筆分類(43)

          隨筆檔案(48)

          文章檔案(1)

          收藏夾(12)

          網絡

          計算機圖形學

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 峨边| 黔江区| 上栗县| 六枝特区| 威宁| 通山县| 介休市| 理塘县| 左云县| 营山县| 海安县| 南阳市| 甘洛县| 桃园县| 平潭县| 株洲市| 天全县| 偏关县| 如皋市| 绥棱县| 灵璧县| 开平市| 桂阳县| 徐闻县| 渑池县| 黎城县| 科尔| 博罗县| 浮山县| 墨竹工卡县| 吉木萨尔县| 三河市| 册亨县| 浦江县| 甘孜县| 房山区| 北安市| 通江县| 皮山县| 沽源县| 博罗县|