>> Also, you *SHOULD* force the file to be saved on your server >> with the correct extension. If a user can upload a JPEG with >> .php on the end, or worse, with php in the middle of the >> filename, and then your server puts that file in the web tree or >> otherwise allows it to be executed, *YOU* (and your server >> admin) screwed up your security, not PHP. > > Trusting the name provided by the client is certainly a bad practice, but > I wouldn't consider "php" in the middle of a filename to be worse than > extension manipulation. I'm not sure what gave you that idea, but it's > just not true. The original article, in another newsgroup/list, referenced a server seen by that author, where the SysAdmin had configured the server to use PHP to parse any file whose name contained 'php'. Not ending in '.php' ('.php$') Nor even ending in 'php' ('php$') But containing 'php' ('.*php.*'). phplogo.jpg, when surfed to, went through PHP. Real-life problem. Yes, that's a horribly-configured server. No, I don't think you'd have that on your server. But I'd bet at least one reader on this list misunderstands the Apache Files directive (with and without the ~) badly enough that they've got this gaping hole on their server. Now combine that with putting uploaded JPEGs in the web tree, and what have you got? My grammar in my post incorrectly put the 'or worse' near 'php in the middle' when it should have been near 'your server ... allows it to be executed' The real culprit, is, of course, the mis-configured server. But it takes two to tango, here, and throwing the JPEGs in the web tree should not be done unless you *NEED* to do that, for performance, after due consideration and a security audit to be *SURE* that the JPEGs cannot ever possibly get executed as PHP. >> Under *NO* circumstances should a file uploaded by an >> untrusted user be put into your web tree. You should *KEEP* it >> outside the web tree, and use PHP to http://php.net/readfile it >> when it needs to be displayed. Since you are using PHP's >> readfile function to *READ* the file, Apache won't have any >> chance to get fooled into thinking it's supposed to be a PHP file >> and be parsed by PHP. > > This is misleading. It is fine to put uploaded files within document root, > and in fact many applications may require this. Using readfile() is not > realistic except for small sites - the performance penalty alone makes > this a poor approach, since it provides very little value. > > That being said, it's true that you should not trust the name provided by > the client (or anything provided by the client), but this is much > different than blind paranoia. If this perspective were applied to HTML > forms, no one could use them. You don't take raw data from HTML forms and save the field values into your web tree do you? You scrub the incoming data from the web form and make sure, as much as possible for the given field, that it is benign, right? And you certainly don't http://php.net/eval that untrusted data from a user, do you? Then why in the world would you take an untrusted, unscrubbable, binary file and shove it into your web-tree?! Can you be 100% certain that <?php /* bad code here */ ?> is not embedded in the JPEG? How? getimagesize() will tell you the JPEG headers are kosher, but not confirm that the JPEG itself is really really just JPEG data. Even viewing it would only, at best, show you an ugly JPEG. You could egrep for <?php.*?>, and assume that that's not valid in any JPEG, but it probably actually *IS* valid in at least one real JPEG -- And if you allow JPEG comments, it would be trivial to have a zillion JPEGs that would pass any automated validation of JPEG-ness that have PHP code in the comment. What's to stop the bad guy from taking a valid JPEG, cramming PHP code into it, and then surfing to the image directly in such a way that the PHP code gets executed? Sure, your server configuration almost for sure doesn't have .jpg files going through the PHP parser. But if they can find a way to force that to happen: Altering an .htaccess file somewhere, or forcing one to be uploaded. Finding an old cgi-bin setup on the server. Getting the CLI PHP to execute the JPG as a script. It's hard to imagine that last one without them being able to just TYPE a PHP script, mind you, but some whack 'sudo' setup might do it. Think every SysAdmin who uses sudo really understands sudo completely? Hopefully, none of these things can be done on your server. If you are 100% certain that none of these could ever possibly occur, then you are confident that the JPEGs with PHP embedded will only be ugly JPEGs. But if there is any doubt in your mind that a malicious user could manage to get the JPEG to be passed through PHP (or Perl or ...) then you've got a risk there that may not be obvious to the casual Reader/Sysadmin/Programmer. Busy servers may have a performance problem with using the readfile solution -- But that's no excuse to expose that busy server by just throwing an unscrubbed binary file into the web tree. I targetted my post at the MAJORITY of users, who are not on busy server, who *can* easily and trivially use the readfile solution. If readfile then becomes a bottle-neck the reader can make the decision what to do about it. And, perhaps, after a thorough security audit of the risks/benefits involved, for a busy server with a Security team and auditing and the kind of budget that goes with that, tossing your JPEGs in the web tree could be the right solution. But it's not something I believe you, or I, should recommend as a best practice for the majority of PHP users. Do you? I'd be ecstatic to hear of a performance-viable solution that doesn't involve putting the binary file into the web tree. I simply don't consider that a viable solution from a security standpoint for the MAJORITY of readers, however. This is just my opinion, and I know you're way more versed in security than I. Perhaps I'm missing some crucial fact here -- Been known to happen. But I'd rather have slower JPEGs than risk a bone-headed move in an .htaccess file turning my server over to the bad guys. Just me. [shrug] PS: Just what percentage of performance loss are looking at, on average, for PHP/readfile to spew out a JPEG instead of Apache to spew out a JPEG? Can PHP's readfile really be that much slower than Apache's 'readfile'? The both have to find the file, fopen it, suck in the data, and spew it out. You're not, like, throwing in a database connection to lookup the filename or something like that, are you? Cuz, yeah, that's gonna slow you down a whole whole whole lot. Don't do that. :-) Or using test data from the old[er] PHP readfile where it was dog-slow? That's gonna lose big-time. But readfile got way more faster at some point in PHP's history. Just to be sure I wasn't completely out of line, I ran a crude benchmark just now. My admittedly crude tests with "time wget" on: SunOS 5.8 Generic_117350-12 sun4u sparc SUNW,UltraAX-i2 for a 2 Meg JPEG showed only a 2% difference between the average of five trials (each) for: time wget http://example.com/readfile_bench.php time wget http://example.com/test.jpg where readfile_bench.php is just: <?php header("Content-type: image/jpeg"); readfile('/usr/home/rlynch/public_html/id/test.jpg'); ?> Data Analysis: PHP readfile: Seconds MB/s 0.23 12.63 0.233 12.2 0.244 12.64 0.223 12.8 0.255 11.04 === average === 0.237 12.262 Raw URL: Seconds MB/s 0.253 10.58 0.226 11.7 0.235 11.32 0.254 10.1 0.246 11.2 === average === 0.2428 10.98 2% <---- (0.2428-0.237)/0.2428 For a 2% loss, compared to the risk of a goofball .htaccess setting plus malicious JPEG upload, I'll stick with readfile for my needs. YMMV. -- Like Music? http://l-i-e.com/artists.htm -- PHP General Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php