orange08 Posted June 25, 2009 Share Posted June 25, 2009 hi, guys i would like to know how you guys prevent this remote file inclusion in your php site? i did read some prevention way online, but still read some others that claim that those are actually not enough to prevent it, so just wanna to know how you guys deal with it... thanks for sharing! Quote Link to comment Share on other sites More sharing options...
Psycho Posted June 25, 2009 Share Posted June 25, 2009 It isn't all that hard. It isn't like the vulnarability magically happens. For RFI to occur the code has to allow a file inclusion which is in some way affected by user input. So, if you had something like this include('myfile.php'); there is little to no risk as the include file is hard coded (see note at end). However, if you had something like $page = $_GET['page']; include($page.'.php'); That is trouble waiting to happen. Whenever there is a need to use user input to decide on an include page it should ALWAYS be validated. If for instance you know that the $page value will only consist of three possibilities you could test the value against a white list of those values. If the passed value is not in that list have error handling or choose a default. $pages = array('pageone', 'pagetwo', 'pagethree'); $page = $_GET['page']; if(!in_array($page, $pages) { $page = $pages[0]; } include($page.'.php'); Of course, the actual implementation could be more complex than a simple hard coded list. But, you should still have some way to validate that the values being passed are what you expect. The bottom line is NEVER trust anything the user sends you. For example, one common misconception I see is that POST data from a select list doesn't need to be validated because the user can only select a value from that list. That's not true, and again, should always be validated. Regarding the previous statment that a hard-coded include is relatively safe, there are instances where it could be unsafe. But again, they are easily mitigated by a little thought. An example would be where the include() is on a page which itself is included so that the path to the include file is relative to the parent script. It would be possible to have the page include a file with the same name if it was accessed directly. But, that would only be if the user has the ability to upload a file to that specific path relative to the calling page. Some basic good file file structure would prevent this possibility. Quote Link to comment Share on other sites More sharing options...
orange08 Posted June 25, 2009 Author Share Posted June 25, 2009 Regarding the previous statment that a hard-coded include is relatively safe, there are instances where it could be unsafe. But again, they are easily mitigated by a little thought. An example would be where the include() is on a page which itself is included so that the path to the include file is relative to the parent script. It would be possible to have the page include a file with the same name if it was accessed directly. But, that would only be if the user has the ability to upload a file to that specific path relative to the calling page. Some basic good file file structure would prevent this possibility. sorry, not too understand with this part...can give example? thanks! Quote Link to comment Share on other sites More sharing options...
Psycho Posted June 25, 2009 Share Posted June 25, 2009 Let's assume you have the following directory structure and files. ROOT/ - index.php ROOT/USER_FILES/ - uploader.php ROOT/INCLUDES/ - foobar.php[code] The application allows users to create their own personal folder in the "USER_FILES" directory to put their personal files. Now, let's assume that index.ph and uploader.php have content such as follows: index.php [code]include('USER_FILES/uploader.php'); uploader.php include('INCLUDES/foobar.php') When index.php is called it will include uploader.php. Then the include is called in uploader.php the path is relative and it will be relative from the parent script. So the path 'INCLUDES/foobar.php' will point to the intended file as expected. OK, there are problems with that structure above. Let's suppose a user creates their personal folder and names it 'INCLUDES' (ROOT/USER_FILES/INCLUDES). Then the user creates a file called foobar.php with malicious code. If the user can then directly call the uploader file, when it sees include('INCLUDES/foobar.php') it will be relative to the uploader.php file since it is the parent script and it will then include the malicious file the user created and uploaded. Now, all of this assumes that the developer did a LOT of things wrong. A couple are: - User files should be stored in a protected area outside of any application files and definitely not in a web accessible directory. - If a file is only supposed to be included by another file (such as uploader.php in the example above) there should be some code at the top of the script to prevent direct running of the file and/or put in a directory that is not web accessible Quote Link to comment Share on other sites More sharing options...
orange08 Posted June 25, 2009 Author Share Posted June 25, 2009 Let's assume you have the following directory structure and files. ROOT/ - index.php ROOT/USER_FILES/ - uploader.php ROOT/INCLUDES/ - foobar.php[code] The application allows users to create their own personal folder in the "USER_FILES" directory to put their personal files. Now, let's assume that index.ph and uploader.php have content such as follows: index.php [code]include('USER_FILES/uploader.php'); uploader.php include('INCLUDES/foobar.php') When index.php is called it will include uploader.php. Then the include is called in uploader.php the path is relative and it will be relative from the parent script. So the path 'INCLUDES/foobar.php' will point to the intended file as expected. OK, there are problems with that structure above. Let's suppose a user creates their personal folder and names it 'INCLUDES' (ROOT/USER_FILES/INCLUDES). Then the user creates a file called foobar.php with malicious code. If the user can then directly call the uploader file, when it sees include('INCLUDES/foobar.php') it will be relative to the uploader.php file since it is the parent script and it will then include the malicious file the user created and uploaded. Now, all of this assumes that the developer did a LOT of things wrong. A couple are: - User files should be stored in a protected area outside of any application files and definitely not in a web accessible directory. - If a file is only supposed to be included by another file (such as uploader.php in the example above) there should be some code at the top of the script to prevent direct running of the file and/or put in a directory that is not web accessible but, if my site didn't allow user to create folder and upload their files, then no such worry, right? Quote Link to comment Share on other sites More sharing options...
Richard Posted June 25, 2009 Share Posted June 25, 2009 In addition to what mjdamato has posted, there is also an option allow_url_fopen in your php.ini file that if disabled will not allow functions like include(), require(), file_get_contents() and so on to be able to retrieve data from remote locations. Quote Link to comment Share on other sites More sharing options...
Psycho Posted June 25, 2009 Share Posted June 25, 2009 but, if my site didn't allow user to create folder and upload their files, then no such worry, right? I'm not saying that is the only risk. I was only giving one possible risk. All it takes is a little thought to look at how your files are used and to prevent malicious use. Quote Link to comment Share on other sites More sharing options...
orange08 Posted June 25, 2009 Author Share Posted June 25, 2009 In addition to what mjdamato has posted, there is also an option allow_url_fopen in your php.ini file that if disabled will not allow functions like include(), require(), file_get_contents() and so on to be able to retrieve data from remote locations. yup, i did read it online and set it already... how about this: Here we check our query string for http://, https:// or ftp:// RewriteCond %{QUERY_STRING} (.*)(http|https|ftp):\/\/(.*) If you are using this rewrite within a .htaccess all you have left is to deny access from all matching requests. RewriteRule ^(.+)$ - [F] If you have access to your vhost you could also log those requests like this: <IfModule mod_rewrite.c> RewriteEngine on RewriteCond %{QUERY_STRING} (.*)(http|https|ftp):\/\/(.*) RewriteRule ^(.+)$ - [env=rfi:true] </IfModule> CustomLog /path/to/logs/rfi.log combined env=rfi You will also have to deny access from requests that have been caught by the above rewrite Deny from env=rfi get from http://www.phpfreaks.com/tutorial/preventing-remote-file-include-attacks-with-mod-rewrite as i don't understand the code, so don't know which part should be modified and put in my .htaccess...can give a bit guidance here? thanks! Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.