首頁  >  文章  >  後端開發  >  PHP安全-檔案系統跨越

PHP安全-檔案系統跨越

黄舟
黄舟原創
2017-02-21 09:15:151443瀏覽



 檔案系統跨越

  無論你用什麼方法使用文件,你都要在某個地方指定文件名。在許多情況下,檔案名稱會作為fopen()函數的一個參數,同時其它函數會呼叫它所傳回的句柄:

<?php
 
  $handle = fopen(&#39;/path/to/myfile.txt&#39;, &#39;r&#39;);
 
  ?>


 

  當你把被污染資料當作檔案名稱的一部分時,漏洞就產生了:

 

  <?php
 
  $handle =
fopen("/path/to/{$_GET[&#39;filename&#39;]}.txt", &#39;r&#39;);
 
  ?>


 

  由於在本例中路徑和檔案名稱的前後兩部分無法由攻擊者所操縱,攻擊的可能性受到了限制。可是,需要緊記的是有些攻擊會使用NULL(在URL中表示為%00)來使字串終止,這樣就能繞過任何檔案副檔名的限制。在這種情況下,最危險的攻擊手段是透過使用多個../來方問上級目錄,以達到檔案系統跨越的目的。例如,想像一下filename的值被指定如下:

 

  http://www.php.cn/ ... nother/path/to/file

 

  與許多攻擊的情況相同,在構造一個字符串時如果使用了被污染數據,就會給攻擊者以機會來更改這個字符串,這樣就會造成你的應用以你不希望方式運行。如果你養成了只使用已過濾資料來建立動態字串的習慣,就可以防止許多類型包括許多你不熟悉的漏洞的出現。

  由於fopen()所呼叫的檔案名稱前導的靜態部分是/path/to,所以上面的攻擊中向上跨越目錄的次數比所需的更多。因為攻擊者在發動攻擊前無法察看原始碼,所以典型的策略是過多次重複../字符串。 ../字符串使用太多次並不會破壞上面的攻擊效果,所以攻擊者沒有必要猜測目錄的深度。

 

  在上面的攻擊中使fopen()調用以你不希望方式運行,它簡化後等價於:

  <?php
 
  $handle = fopen(&#39;/another/path/to/file.txt&#39;,
&#39;r&#39;);
 
  ?>


 

  在意識到這個問題或遭遇攻擊後,許多開發者都會犯下試圖糾正潛在的惡意資料的錯誤,有時根本不會先對資料進行檢查。如第一章所述,最好的方法把過濾看成檢查過程,同時迫使使用者遵守你所製定的規則。例如,如果合法的檔案名稱只包含字母,則下面的程式碼能加強這個限制:

 

<?php
 
  $clean = array();
 
  if (ctype_alpha($_GET[&#39;filename&#39;]))
  {
    $clean[&#39;filename&#39;] = $_GET[&#39;filename&#39;];
  }
  else
  {
    /* ... */
  }
 
  $handle =
fopen("/path/to/{$clean[&#39;filename&#39;]}.txt", &#39;r&#39;);
 
  ?>


 

  並沒有必要對filename值進行轉義,這是因為這些資料只用在PHP函數而不會傳送到遠端系統。

 

basename( )函數在檢查是否有不必要的路徑時非常有用:

<?php
 
  $clean = array();
 
  if (basename($_GET[&#39;filename&#39;]) ==
$_GET[&#39;filename&#39;])
  {
    $clean[&#39;filename&#39;] = $_GET[&#39;filename&#39;];
  }
  else
  {
    /* ... */
  }
 
  $handle =
fopen("/path/to/{$clean[&#39;filename&#39;]}.txt", &#39;r&#39;);
 
  ?>


 

  這個流程比只允許檔案名稱是字母的安全性要差了一些,但你不太可能要求那麼嚴格。比較好的深度防範流程是綜合上面的兩種方法,特別是你在用正規表示式檢查程式碼合法性時(而不是用函數ctype_alpha( ))。

  當檔案名稱的整個尾部是由未過濾資料組成時,一個高風險漏洞就產生了:

 <?php
 
  $handle = fopen("/path/to/{$_GET[&#39;filename&#39;]}",
&#39;r&#39;);
 
  ?>


 

  給予攻擊者更多的彈性意味著更多的漏洞。在這個例子中,攻擊者能操縱filename參數指向檔案系統中的任何文件,而不管路徑和檔案副檔名是什麼,這是因為檔案副檔名是$_GET['filename']的一部分。一旦WEB伺服器具有能讀取該檔案的權限,處理就會轉向這個攻擊者所指定的檔案。

  如果路徑的前導部分使用了被污染資料的話,這一類的漏洞會變得更龐大。這也是下一節的主題。

以上就是PHP安全-檔案系統跨越的內容,更多相關內容請關注PHP中文網(www.php.cn)!


陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn