如何檢查上傳圖檔

網站如果要開放讓使用者上傳圖檔,通常都在上傳介面中先做副檔名檢查,做第一層的篩選。但基於資安的考量,還是無法相信使用者上傳的圖檔是沒問題的。尚須對這些上傳到伺服器上的圖檔做檢查。

我們假設圖檔可能會有下列的狀況,要能檢查出來
  1. 圖檔的附檔名是否符合檔案實際格式?
    如,將 .zip 改名為 .png
  2. 圖檔是否被塞入其他資訊?
    如,利用愛的機器,做出加工的圖檔
最基本的判斷方式,莫過於讀取圖檔head內的資訊來做判斷與檢查。

以php而言,最簡單的方式可以採用getimagesize()來取得圖檔相關資訊來做判斷。以上述第一個狀況而言,getimagesize()會回傳FALSE,就可以檢查出來。

不過,第二個狀況就檢查不出來,因為他算是合法的圖檔。使用getimagesize()會得到如下的資訊…
  1. array  
  2.   0 => int 120  
  3.   1 => int 92  
  4.   2 => int 3  
  5.   3 => string 'width="120" height="92"' (length=23)  
  6.   'bits' => int 8  
  7.   'mime' => string 'image/png' (length=9)  
要能檢測出第二個項目或類似的狀況,除了head內的資訊外,尚須配合實際讀取圖檔內容來比對。此時,可以利用getID3

誠如getID3官方網站上的自我介紹 『getID3() is a PHP script that extracts useful information from MP3s & other multimedia file formats』。我們藉由getID3讀取出圖檔的相關資訊,然後做判斷、檢查圖檔是否正常。

getID3的使用非常簡單,以官方的範例程式 demo.basic.php 舉例,三行程式碼就可以取得 /tmp/upload/lovemachine00.png 的圖檔資訊了。簡單吧!
  1. // include getID3() library (can be in a different directory if full path is specified)  
  2. require_once('../getid3/getid3.php');  
  3.   
  4. // Initialize getID3 engine  
  5. $getID3 = new getID3;  
  6.   
  7. // Analyze file and store returned data in $ThisFileInfo  
  8. $ThisFileInfo = $getID3->analyze('/tmp/upload/lovemachine00.png');  
如果被檢查的圖檔有異常,getID3回傳的array中,會有['warning']。因此,可以利用此資訊做判斷上的參考。接下來的判斷與應用,就看各自發揮了…

我也曾做個測試,亂改正常圖檔的binary內容,再利用getID3分析,也會有['warning']。

最後,附上以var_dump呈現getID3回傳的內容。請注意第28行處['warning']的內容!
附註:原始資訊太多,內容我有做些刪除與調整
  1. array  
  2.   'GETID3_VERSION' => string '1.9.1-20110810' (length=14)  
  3.   'filesize' => int 521399  
  4.   'filename' => string 'lovemachine00.png' (length=17)  
  5.   'filepath' => string '/tmp/upload/ (length=16) 
  6.   'filenamepath' => string '/tmp/upload/lovemachine00.png' (length=34) 
  7.   'avdataoffset' => int 0 
  8.   'avdataend' => int 521399 
  9.   'fileformat' => string 'png' (length=3) 
  10.   'video' =>  
  11.     array 
  12.       'dataformat' => string 'png' (length=3) 
  13.       'lossless' => boolean false 
  14.       'resolution_x' => int 120 
  15.       'resolution_y' => int 92 
  16.       'bits_per_sample' => int 8 
  17.       'compression_ratio' => float 47.228170289855 
  18.   'tags' =>  
  19.     array 
  20.       'png' =>  
  21.         array 
  22.           'Title' =>  
  23.             array 
  24.               ... 
  25.           'Software' =>  
  26.             array 
  27.               ... 
  28.   'warning' =>  
  29.     array 
  30.       0 => string 'Unhandled chunk type: r60=' (length=26) 
  31.   'encoding' => string 'UTF-8' (length=5) 
  32.   'mime_type' => string 'image/png' (length=9) 
  33.   'png' =>  
  34.     array 
  35.       'IHDR' =>  
  36.         array 
  37.           'header' =>  
  38.             array 
  39.               ... 
  40.           'width' => int 120 
  41.           'height' => int 92 
  42.           'raw' =>  
  43.             array 
  44.               ... 
  45.           'compression_method_text' => string 'deflate/inflate' (length=15) 
  46.           'color_type' =>  
  47.             array 
  48.               ... 
  49.       'PLTE' =>  
  50.         array 
  51.           'header' =>  
  52.             array 
  53.               ... 
  54.           0 => int 2629661 
  55.           1 => int 12559029 
  56.           2 => int 9390909 
  57.           3 => int 14665142 
  58.           4 => int 3878976 
  59.           5 => int 14723760 
  60.           6 => int 14928859 
  61.           7 => int 11834011 
  62.           8 => int 14665936 
  63.           9 => int 6435882 
  64.           10 => int 14459822 
  65.           124 => int 15458279 
  66.           125 => int 15453903 
  67.           126 => int 15190999 
  68.           more elements... 
  69.       'tEXt' =>  
  70.         array 
  71.           'header' =>  
  72.             array 
  73.               ... 
  74.           'keyword' => string 'Software' (length=8) 
  75.           'text' => string 'ViX' (length=3) 
  76.       'comments' =>  
  77.         array 
  78.           'Title' =>  
  79.             array 
  80.               ... 
  81.           'Software' =>  
  82.             array 
  83.               ... 
  84.       'IDAT' =>  
  85.         array 
  86.           0 =>  
  87.             array 
  88.               ... 
  89.       'IEND' =>  
  90.         array 
  91.           'header' =>  
  92.             array 
  93.               ... 
  94.       'r60=' =>  
  95.         array 
  96.           'header' =>  
  97.             array 
  98.               ... 
  99.       'encoding' => string 'UTF-8' (length=5) 
  100.   'tags_html' =>  
  101.     array 
  102.       'png' =>  
  103.         array 
  104.           'Title' =>  
  105.             array 
  106.               ... 
  107.           'Software' =>  
  108.             array 
  109.               ... 
  110.   'comments' =>  
  111.     array 
  112.       'Title' =>  
  113.         array 
  114.           0 => string 'ishiguro04.png' (length=14) 
  115.       'Software' =>  
  116.         array 
  117.           0 => string 'ViX' (length=3) 
  118.   'comments_html' =>  
  119.     array 
  120.       'Title' =>  
  121.         array 
  122.           0 => string 'ishiguro04.png' (length=14) 
  123.       'Software' =>  
  124.         array 
  125.           0 => string 'ViX' (length=3)  

留言