A note from the HTS.org staff:
The advice in this article should not be followed, read the comments to learn why. The article is being left here as a warning to others.
Secure PHP websites
Hello my fellow PHP writers!
As you all might know, it can be quite a tricky to make sure that your website is 100% injection protected. Of course, you could sanitize every single time the visitor has the possibility of submitting an input. However, I believe to have found an easier way.
Only 1 term must be met in order for this to work:
.htaccess with mod_rewrite must be available at your host
It most often is, but if it is not, this article will be useless to you. I'm sorry.
--------------------------------------
So! Ready for the coding ??
The system consist of the following two parts:
1. A .htaccess redirection for all PHP pages
2. A sanitizing PHP script which every PHP page will be forced to execute
Part 1 - The .htaccess
Copy this code to into a new document (or your existing .htaccess) and name it .htaccess (no file name - .htaccess as extension, Google it if you're new to it)
The script redirects all php, htm and html pages to our sanitizing script. The %{QUERY_STRING} is there to preserve GET input and the %{SCRIPT_FILENAME} is there to tell the sanitizing script which file you were trying to access. POST will automatically be preserved.
NOTICE: The redirected extensions may be changed if needed. Furthermore, the script redirects to the file /scripts/sanitize.php - this may, of cause, be changed too. Just make sure to change both lines!
BONUS: This script might be used to make an image viewer - just change the extensions to image ones and your will force images to open the entered PHP-script in stead of just showing...
Thats the .htaccess... No big troubles, huh? Good, then let's contionue to the sanitizing script.
Part 2 - The sanitizing script
This is the really fun part. This might be done in a hundred of ways in order to meet your specific demands. However, here goes a basic template for the script:
Our primary target is to eliminate injection vulnerabilities, and therefore we will start by sanitizing the POST and GET input:
CODE :
<?PHP
foreach($_POST as $name=>$value){
$_POST[$name] = htmlspecialchars($value);
}
foreach($_GET as $name=>$value){
$_GET[$name] = htmlspecialchars($value);
}
?>
This code snippet will loop through everything submitted and sanitize it using the htmlspecialchars()-function.
This might changed, but I like it this way - not too much sanitizing nor too little.
NOTICE: This will sanitize the filename of the requested file too. This shouldn't be any problem using this sanitizing, however, keep it in mind if you do your own one...
Thats all for sanitizing! Now all we need to do is to display the file originally meant to be displayed. That is done like this:
The reason why i do the file_exists check is because this redirection will make the ErrorDocument .htaccess command inactive. The "errors/404.php" is the path to the error document (change it to your own 404 location - or just make a script to display random quotes etc.??)
Thats it! Every PHP document on this domain will now be sanitized and you won't have to think about sanitizing input ever again! Delightful, huh?
For you who might want to just copy-paste this, here goes the full PHP script:
CODE :
<?PHP
foreach($_POST as $name=>$value){
$_POST[$name] = htmlspecialchars($value);
}
foreach($_GET as $name=>$value){
$_GET[$name] = htmlspecialchars($value);
}
This way will, with a optimized sanitizing script, help you secure your website. Beside sanitizing, this principle might be used for session initializing, header applying etc. too. Though, please keep in mind, that EVERY PHP-script will be handled by this scrip. Even scripts executed by include() or require()-functions, which might lead to unwanted header applying.
I hope you found this helpful. I apologize any spelling/grammar mistakes as English is not my primary language.
Cast your vote on this article *Note: the order of the votes has been reversed.
I am sorry that i overlooked this vulnerability, but would you agree that this fixes it??
FrederikVds - 04:59 pm Thursday October 02nd, 2008
A couple of problems with this article:
First, local included and required scripts of course won't include this sanitizing script, which is good, but you're writing something else.
But there's something worse! You're ignoring the backslash! At least you should've done mysql_real_escape_string, or your site is still vulnerable (less obviously vulnerable, but still vulnerable).
Also the whole idea is dumb. This assumes that everything the user inputs will be outputted as html. Users better don't have any special chars in their password! Magic Quotes has been disabled by default just for this reason. Also, if you change servers and forget to move your .htaccess file, this leaves your whole site vulnerable to attacks.
Also, this leads to bad coding practice in general.
It couldn't be simpler though. Before inserting anything into a database, use mysql_real_escape_string. And yes I mean anything, not just user input, also things read from files, from databases, and other things your script doesn't escape. And before outputting as html, use htmlspecialchars. Again for everything, not just user input. As I said, a script like this leads to a bad coding style where you don't think about things like that.
Also, you're forgetting cookies, which could also be used to attack.
Sorry for being so harsh, I just want to warn you about the security problems related to a seemingly secure script like this.
--quote:
You are right that this script is
vulnerable... However, I believe that
this vulnerability could be removed by
adding the strings:
str_replace("http://","",$_GET['file']);
str_replace("..","",$_GET['file']);
to the sanitizing part of the script...
--end of quote
How about https:// and all the other protocol handlers, mate? Not a good solution at all.
@oohal:
Wouldn't it be an RFI? (leading to remote code execution)
According to php.net, file_exists() should work on URLs as of PHP 5.0.
HOWEVER, I belive this method holds some posibilities if the sanitizing part was optimezed...
I posted this to provide people with a possibility of collecting sanitizing in one script in stead of the old "everytime you submit something remember to sanitize it".
I never said this method was perfect, only that it holds possibilities, and that it is the most effective way I ever came across.
And all the security flaws you are pointing out - these could easily be corrected with some optimizing!
Vulnerabilities aside, it's a fucking stupid idea. Period.
Not every bit of user submitted data is going to be echoed back. Which means, you're running functions that don't need to be ran. Stupid.
That can be ignored, somewhat. But what about inserting data into a database? You shouldn't insert 'html entitie'd' code. It should only be quote escaped.
What if someone manages to bypass your filtering system and ends up XSS'ing your site. How are you going to patch that? You don't know what the vector was...
tl;dr it's a stupid idea.
Oct 02 16:48:51 <Kane> http://www.hackthissite.org/articles/read/989 <-- That's a terrific way to teach bad coding. Who ever allowed that, yikes.
Oct 02 16:49:07 <Nines9> faith
It doesn't hold any possibilities. It's a stupid idea. Better alternative? Escape data that needs to be escaped when it's supposed to be escaped. There.
It shouldn't of been accepted as an article. At one stage, HTS was supposed to be 'filtering out shit articles' to set a better standard. Letting in stuff like this, that teaches bad coding, is proving that idea is clearly being forgotten about.
@GBHis
Probably, iirc suhosin (which you should be using) disables remote includes so I discounted it.
@MrKnox
Since you asked for a better alternative. A lot of sites will have some sort of global include which sets up DB connections, etc. Put your escaping code there and use a class like HTSv4's safestring (which can be found here: http://beta.hackthissite.org/wsvn/HTSv4/trunk/core/class.safestring.php ). Of course you still have the overhead of escaping everything, even if it doesn't need to be, but that's the price you pay.
Kane is probably going to complain this encourages bad coding practice, but since safestring forces you to be explicit in escaping data it's ok IMO.
I have been trying to track down that safestring script for a long time now, I had lost it, so thanks.
This site is the collective work of the
HackThisSite staff. Please don't reproduce in part or whole without permission.
Page Generated: Mon, 01 Dec 2008 23:26:50 -0500 Exec:
11 Page loaded in 0.12171 seconds!
Nice article, two thumbs up!