It's really rather simple. Run all uploaded images through an image filter that is known to be safe. If it kicks back with a "Not an image error", you have shenanigans. (A simple example would be an identity transform, or a JPEG quality normalization technique.) An important point, tho', is to actually use the output from the filter, not the original file.
As you mentioned, there's another question that addresses the issue. The author notes that he should be safe as long as he only accepts genuine image files and keeps down the filesize, which is about the only thing you can do. Check extension and MIME type and reject anything that does not match the formats you want. There's still RFI (well, more like LFI here), but as long as you aren't haphazardly including files without performing sanity checks, you should be good to go.
Things you need to consider and watch out for:
File extensions: Webservers use the file extension to determine the MIME-Type sent to the client. You should use a whitelisting of extensions that you allow. In your case this would be image extensions.
LFI: As already mentioned by Matchu, local file inclusion can be an issue. If your application has dynamic includes that allow you to include an arbitrary file, eg. include($_GET['myfile']);
it can lead to arbitrary PHP execution. So you need to secure such includes by using basename(). This can even happen with images, since they can contain embedded comments.
MIME-Type-Detection: This is actually not very well known, and there's not much information about it. IE<8 has a feature called MIME-Type-Detection which will, if the Content-Type does not match with the content, try to guess the type by looking at the first 256 bytes. This means, if you have a PNG file called image.gif with a comment at the top that reads <script>alert('hello');</script>
, then IE<8 will think it is HTML and execute the JavaScript, leading to an XSS attack.
To prevent this issue for images you can use the approach mentioned by Williham Totland. I would suggest using getimagesize() to detect if the image is valid and to ensure that the extension matches the type.
$image_filename = 'uploaded_image.gif';
$image_extension = substr(strrchr($image_filename, '.'), 1);
$mime_mapping = array('png' => 'image/png', 'gif' => 'image/gif', 'jpg' => 'image/jpeg', 'jpeg' => 'image/jpeg');
$info = getimagesize($image_filename);
if (!$info) {
exit('not an image');
}
if ($info['mime'] != $mime_mapping[$image_extension]) {
exit('wrong extension given');
}
// all checks passed
// image can be saved now
There is an article written about this issue here.