0

I need to check if an uploaded file is a favicon type and I need do it in a secure way.

If I upload a favicon file through an input file and print the $_FILES variable, I can see that the variable has the following type value:

image/vnd.microsoft.icon

I know that I can check if that value matches that, but I think that the user can dumper it. If someone could give me some tip I'd be grateful

Kevin Gravell
  • 499
  • 2
  • 7
  • 20
  • Use `Fileinfo` to get the mime type and then compare that to your desired mime type. http://php.net/Fileinfo – Charlotte Dunois Aug 07 '16 at 15:12
  • Thanks for your comment. And is it a secure way to do check it? I want to be sure that user doesn't tamper it. If so, you can leave me your comment as answer and I will mark it as right answer @CharlotteDunois – Kevin Gravell Aug 07 '16 at 15:18
  • 2
    `The functions in this module try to guess the content type and encoding of a file by looking for certain magic byte sequences at specific positions within the file. While this is not a bullet proof approach the heuristics used do a very good job.` It's much better than relying on `$_FILES[...]['mime']` – Charlotte Dunois Aug 07 '16 at 15:19

3 Answers3

2

You can use various tools:

FileInfo

You can use FileInfo directly from PHP:

$finfo = finfo_open(FILEINFO_MIME_TYPE);
echo finfo_file($finfo, 'the_file_to_check.ico');
// Should print something like 'image/x-icon'
finfo_close($finfo);

If FileInfo is setup on your system, this is probably the easiest way to go.

ImageMagick

ImageMagick goes a step further by actually decoding the content of the file, listing the embedded images:

$ identify favicon.ico
favicon.ico[0] ICO 16x16 16x16+0+0 32-bit sRGB 15.1KB 0.000u 0:00.000
favicon.ico[1] ICO 32x32 32x32+0+0 32-bit sRGB 15.1KB 0.000u 0:00.000
favicon.ico[2] ICO 48x48 48x48+0+0 32-bit sRGB 15.1KB 0.000u 0:00.000

(called from the command line in this example)

I don't know how FileInfo works with ICO files, but ImageMagick is probably safer as it really has to decode a significant part of the file.

As ImageMagick supports a lot of formats, it's important to check its output and not simply its return code (it also succeeds with JPG, SVG, etc).

IcoUtils

As a lightweight alternative to ImageMagick, IcoUtils can do the trick:

$ icotool -l favicon.ico
--icon --index=1 --width=16 --height=16 --bit-depth=32 --palette-size=0
--icon --index=2 --width=32 --height=32 --bit-depth=32 --palette-size=0
--icon --index=3 --width=48 --height=48 --bit-depth=32 --palette-size=0

$ icotool -l not_a_favicon.svg
favicon.svg: not an icon or cursor file (reserved non-zero)

Unfortunately its return code is always 0, forcing you to actually check its output.

It can be installed on Ubuntu with:

sudo apt-get install icoutils
philippe_b
  • 38,730
  • 7
  • 57
  • 59
1

If you want avoid using any external tools, https://github.com/lordelph/icofileloader provides a native PHP method for parsing .ico files

$loader = new Elphin\IcoFileLoader\IcoFileService;
try {
    /** @var Elphin\IcoFileLoader\Icon $icon */
    $icon = $loader->fromFile('/path/to/icon.ico');

    //perform further inspection or render the icon as an image here...

} catch (\Exception $e) {
    //not an .ico file
}
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
-1
  1. Use a tool to convert your png to a ico file. You can search "favicon generator" and you can find many online tools.
  2. Place the ico address in the head with a link-tag:

    <link rel="shortcut icon" href="http://sstatic.net/stackoverflow/img/favicon.ico">