0

Possible Duplicate:
best way to determine if a URL is an image in PHP

Edited:

I have a script that copies remote files to my server using file_get_contents (which my host allows) to let users share pictures. To avoid abuse, however, I need code to check files for size, validity (and malicious code before allowing them on my server. So far, I've been unable to find a robust solution. Old articles that others have pointed to such as this one:

https://stackoverflow.com/questions/676949/best-way-to-determine-if-a-url-is-an-image-in-php

suggest possible approaches--checking file extension, mime type and using GD on files after they are on the server, but caution that none are foolproof. Yet countless sites allow remote uploading of files, suggesting there must be some better way to handle security.

File_get_upload is bare bones. Curl is gnarly but may have more functionality. GD's get_image_size function will return false if a file is not an image as in:

$imginfo_array = getimagesize($tempFile); 

However, my understanding is GD cannot process a file remotely.

Here is simple code using file_get_contents t this stage:

$url = 'http://example.com/image.php';
$img = '/my/folder/flower.gif';
file_put_contents($img, file_get_contents($url));

Here is curl version:

$ch = curl_init('http://example.com/image.php');
$fp = fopen('/my/folder/flower.gif', 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_exec($ch);
curl_close($ch);
fclose($fp);

Does anyone know the best practice to check file size and validity before they are on your server?

Community
  • 1
  • 1
user1260310
  • 2,229
  • 9
  • 49
  • 67

1 Answers1

1

I don't really think using stream_get_meta_data , header information or , extension or mime information is the best solution ... Why ?

Have created A fake PNG image and you would see

  • Fake Mime
  • Fake Creation date
  • Fake Modification Date
  • Fake File Extension

Missing Feature

  • Fake Output
  • Fake Size

Case 1

$fake = "https://i.stack.imgur.com/wbSmq.png";
$meta = stream_get_meta_data(fopen($fake, 'rb'));
var_dump($meta);

Output

array (size=10)
  'wrapper_data' => 
    array (size=12)
      0 => string 'HTTP/1.0 200 OK' (length=15)
      1 => string 'Accept-Ranges: bytes' (length=20)
      2 => string 'Cache-Control: max-age=315360000' (length=32)
      3 => string 'Content-Type: image/png' (length=23)
      4 => string 'Date: Mon, 03 Dec 2012 10:41:08 GMT' (length=35)
      5 => string 'ETag: "add48f1871182328f5d8ebe74c1df32d"' (length=40)
      6 => string 'Expires: Thu, 31 Dec 2037 23:58:38 GMT' (length=38)
      7 => string 'Last-Modified: Mon, 03 Dec 2012 10:29:40 GMT' (length=44)
      8 => string 'Server: ECAcc (cdg/44CF)' (length=24)
      9 => string 'X-Cache: HIT' (length=12)
      10 => string 'Content-Length: 167' (length=19)
      11 => string 'Connection: close' (length=17)
  'wrapper_type' => string 'http' (length=4)
  'stream_type' => string 'tcp_socket/ssl' (length=14)
  'mode' => string 'rb' (length=2)
  'unread_bytes' => int 167
  'seekable' => boolean false
  'uri' => string 'https://i.stack.imgur.com/wbSmq.png' (length=34)
  'timed_out' => boolean false
  'blocked' => boolean true
  'eof' => boolean false

From the above output there is nothing that suggest that the image is fake ?

Case 2

As far as I know I cannot use GD directly on a remote url.

That is not true getImageSize is a GD Function can works with remote URL and its much more reliable to identify fake images.

$fake = "https://i.stack.imgur.com/wbSmq.png";
$meta = getimagesize($fake);
var_dump($meta);

Output

array (size=6)
  0 => int 1                     |
  1 => int 1                     |=----------------- Looks Fake
  2 => int 3                     |
  3 => string 'width="1" height="1"' (length=20)
  'bits' => int 1   <------------------------------- fake
  'mime' => string 'image/png' (length=9) ---------- mime may be correct 

If The goal here is to let users share valid pictures up to a certain size as you have mentioned Using getImagesize a more reliable solution

Gunnar Thoreson
  • 313
  • 1
  • 7
Baba
  • 94,024
  • 28
  • 166
  • 217
  • I can't accept this as it doesn't really answer my question--whether to use get image size, curl etc. I said in the question I wanted to avoid downloading file and your answer is a way I already knew about that downloads the file. Neither does the 3 year old question that Deceze mentioned that doesn't take into account any advances in PHP. SO this question unfortunately remains unanswered. – user1260310 Dec 03 '12 at 23:37