Welcome to WebmasterWorld Guest from 18.204.48.199

Forum Moderators: coopster & jatar k

Message Too Old, No Replies

A Security Checklist

Please post your top tips for security in php

     
8:37 pm on Jun 30, 2003 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


I'm starting this thread hopefully so that people new to PHP can become aware of the important security issues - something that the hack-a-script school of php tends to neglect.

1 - Ensure register_globals is firmly OFF, it will stop you making some of the most common scripting mistakes involving people overwriting session variables etc using the url

2 - Use mysql_escape_string() on EACH AND EVERY user submitted string you put into your SQL statements.

3 - For reasonable security, use sessions, and check the value of a variable (eg $userstatus) on every page - try not to use it as true/false, but use an exact number, such as logged in is ($userstatus==74) - this is a great defense against many of the most common forms of attack

4 - Whenever you store a password, only store the md5() hash of the password - that way _if_ someone gets into your database, they don't have a password they can use. To check passwords of later logins, test md5($login_password)==$stored_md5_password

5 - If you use .inc files, set your .htaccess so that php parses them - that way they won't return the source code if someone sneakily guesses/finds out the URL and enters it into their browser.

10:35 pm on June 30, 2003 (gmt 0)

Administrator

WebmasterWorld Administrator jatar_k is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:July 24, 2001
posts:15756
votes: 0


how do you figure you need to use sessions? If you have nothing to track then why the session? Though if you mean only in "logged in" situations then I would say I agree.

#5 is always good advice or just don't use inc extensions at all or .inc.php works too.

Error Handling/Trapping - check all data and disallow variations or use default cases or catch alls to trap exceptions.

11:19 pm on June 30, 2003 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


need to use sessions

Yes, I was meaning logged in cases.

I'll add another one:
place @ before every function likely to give an error - i'm going for database calls and file handling, especially from external sites here - the default error it spews out not only looks bad for your site - but it reveals your actual server path - and possibly your mySql username.

11:23 pm on June 30, 2003 (gmt 0)

Administrator

WebmasterWorld Administrator jatar_k is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:July 24, 2001
posts:15756
votes: 0


place @ before every function

only once you are putting it live, I know that's what you mean vincevincevince but I just want to make sure everyone is clear.

The @ symbol will suppress error messages and when the site is still in some form of development you will run yourself ragged chasing errors you suppressed.

11:27 pm on June 30, 2003 (gmt 0)

Full Member

10+ Year Member

joined:Mar 18, 2002
posts:309
votes: 0


5 - If you use .inc files, set your .htaccess so that php parses them - that way they won't return the source code if someone sneakily guesses/finds out the URL and enters it into their browser.

I store my includes below the document root. Is that safe?

12:01 am on July 1, 2003 (gmt 0)

Administrator

WebmasterWorld Administrator jatar_k is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:July 24, 2001
posts:15756
votes: 0


Yes it is, I forgot about that.
12:05 am on July 1, 2003 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Feb 13, 2003
posts:775
votes: 0


This is a great thread.

place @ before every function likely to give an error - i'm going for database calls and file handling, especially from external sites here - the default error it spews out not only looks bad for your site - but it reveals your actual server path - and possibly your mySql username.

I'm no expert on this but I think it might be worth it to do this in the php.ini file ... see [php.net...] . You can turn off displaying errors and have everything log to a text file. This way you don't have to track down every function.

2:53 am on July 1, 2003 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lorax is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Mar 31, 2002
posts:7577
votes: 4


I place my uname, pwd, and mysql_connect call in an include file in a directory outside of my webspace.

Not really directly related to PHP but if you're using an Admin area use SSL - if it's available - to wrap it up.

9:25 am on July 1, 2003 (gmt 0)

Senior Member from ES 

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month

joined:July 24, 2002
posts:1129
votes: 2


good to read the bit about checking all data jatar_k,

i find myself going round the bend if()-ing and else()-ing and ereg()-ing to check all possible GET $vars - nice to know that it is worth the extra trouble!

10:06 am on July 1, 2003 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Dec 6, 2001
posts:2213
votes: 0


Re Number 5

Care to elaborate. I just looked for some of my inlcudes and nothing showed when snooping around.

security has me worried sometimes. This sort of stuff is interesting.

6:51 pm on July 1, 2003 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Sept 12, 2002
posts:885
votes: 0


2 - Use mysql_escape_string() on EACH AND EVERY user submitted string you put into your SQL statements.

Might want to gheck the value of magic_quotes_gpc first - escaping twice is safer than not at all, but can still screw up your site.

5 - If you use .inc files, set your .htaccess so that php parses them - that way they won't return the source code if someone sneakily guesses/finds out the URL and enters it into their browser.

Or put them in a directory outside the web root, so there is no URL for them.

8:44 pm on July 1, 2003 (gmt 0)

Junior Member

10+ Year Member

joined:Oct 8, 2002
posts:65
votes: 0


Never ever trust any input from anywhere. Forms (GET and POST), etc - hell, I don't even trust sessions.

I always code so that unless I state the variable myself in the code, I don't trust it. Probably a little over the top, but it hasn't been too much of a problem yet.

9:14 pm on July 1, 2003 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


Another I remembered:

Always delete (possibly after backup) any installation scripts supplied with ready made systems, typically install.php or setup.php.

Asandir...

How about a very very commonly used function - taking an email address to save as part of a registration / post to a site / email to. I'll be impressed when you can do that without reading form data :-)

Or did I miss the point?

12:40 am on July 2, 2003 (gmt 0)

New User

10+ Year Member

joined:Aug 23, 2002
posts:25
votes: 0


Also, if you're taking user data on one page and displaying it on another page you should run it through htmlentities() or one of the similar functions at some stage too. Otherwise you/your users could be vulnerable to cross-site scripting attacks and cookie hijacking.
3:01 am on July 2, 2003 (gmt 0)

Junior Member

10+ Year Member

joined:Oct 8, 2002
posts:65
votes: 0


I meant that I don't trust the input. Not that I don't use input. =)

Every bit of data coming from outside of "my" system gets treated as if it is "hostile" - every bit of data from a form, for example, would all be treated as if they were SQL injects, etc.

What you said in post #1, point 2, really.

7:40 am on July 2, 2003 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Dec 6, 2001
posts:2213
votes: 0


I was told to remove phpinfo, I think that is what it is called as it gives all the server variables for a potential attack.
1:33 pm on July 2, 2003 (gmt 0)

Senior Member from US 

WebmasterWorld Senior Member lorax is a WebmasterWorld Top Contributor of All Time 10+ Year Member Top Contributors Of The Month

joined:Mar 31, 2002
posts:7577
votes: 4


>> I was told to remove phpinfo, I think that is what it is called as it gives all the server variables

phpinfo() is actually a function that produces a page with all of those variables. It can be added to a file named what ever you want but yes - if someone were to guess the name of that file, they would have access to all of the server info.

2:27 pm on July 2, 2003 (gmt 0)

Senior Member from MY 

WebmasterWorld Senior Member vincevincevince is a WebmasterWorld Top Contributor of All Time 10+ Year Member

joined:Apr 1, 2003
posts:4847
votes: 0


phpinfo can be disabled - which is a very good idea security wise - but it makes it very hard to find bugs if you are using lots of server variables and such. Another function to disable is mail(), if you are security paranoid - but then you can't send email easily through php.

the disabling of phpinfo and mail are recommended only for where you will let a third party run php on your service - for example you are a host with virtual php enabled domains.

5:22 am on July 5, 2003 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Apr 3, 2003
posts:1633
votes: 0


And delete your phpinfo.php from your production box :)

According to Google, 16,900 webmasters haven't.

8:28 am on July 5, 2003 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Feb 13, 2003
posts:775
votes: 0


And delete your phpinfo.php from your production box :)
According to Google, 16,900 webmasters haven't.

Make that 16,899... blush.

9:31 am on July 5, 2003 (gmt 0)

New User

10+ Year Member

joined:July 5, 2003
posts:3
votes: 0


"And delete your phpinfo.php from your production box"

changing the name should be enough, if someone can figure out phpinf0234.php then they will not need the information supplied by it.

10:22 am on July 5, 2003 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Mar 27, 2003
posts:664
votes: 0


Thanks to all; these are valuable tips. My contribution:

If you take form input, put some sort of flood control on it, such as minimum time between posting from the same IP = 5 minutes; to stop an automated process flooding you.

9:21 pm on July 5, 2003 (gmt 0)

New User

10+ Year Member

joined:July 5, 2003
posts:3
votes: 0


"...such as minimum time between posting from the same IP = 5 minutes; to stop an automated process flooding you."

If guest posting is disabled and you have a limit on post sizes/subject sizes then it is easy to delete posts by user. Minimum delays can piss your members off. The functions to watch out for are anything that sends email, like lost password, registration etc, or any function that works the CPU like Search. As I said, you can always delete posts by user, but the emailer and search use CPU resources which will eventually completely bog the server.

If you have your website virtually hosted, then the host will eventually drop your site to release CPU resources.

Dealing with sessions tables filling is another issue too.

7:47 am on July 6, 2003 (gmt 0)

Senior Member

WebmasterWorld Senior Member 10+ Year Member

joined:Mar 27, 2003
posts:664
votes: 0


Whoops! I forgot my manners... Welcome to WebmasterWorld, Komodo.

Not sure I agree with your views, though. You can reduce user irritation by making the delay appropriate for the particular audience. For example, WebmasterWorld uses 15s I think.

You raise good points about controlling the server load, but flood control is important for other reasons too. Here are a few examples:

  • For example, to prevent a vandal from setting up an automated process to submit lots of posts. True, a forum can be moderated, but why get the moderators to work harder than they already do when there are some things that can be automated. Also, there are other applications besides discussion groups/fora.
  • Another example is searching a product database. In this case you want to prevent automated flooding of requests even if it doesn't use much CPU resources. You want to prevent a competitor from downloading your entire database using an automated process.
  • In a similar vein, you want to prevent other sites from using your site as an information portal where they simply serve your content but brand it as their own. Sure, after a while you'll get wise and tighten up your htaccess, but you might as well stop it before it starts.

Shawn

10:07 am on July 6, 2003 (gmt 0)

Senior Member from MT 

WebmasterWorld Senior Member 10+ Year Member

joined:Apr 1, 2003
posts:1843
votes: 0


But for usabilities sake don't just have a fixed delay between two posts.

I often have competitors try to extract my database. I even once got a funny email from a microsoft employee complaining he didn't manage to extract my databasse and if I could please send it to him (what ARE they thinking?).

What I did for my ant-hammering is to hae a minimum time before it kicks in, for example 5mins, and then have a threshold of hits/second that will trigger a timed ban, so perhaps a user can do maybe 1 or two hits per second, or perhaps 30 perminute or less. Should stop most extraction spiders. Of course have t obe carefull not to hit any search engines (was easy in my case, I only affected IPs from my country which doesn't host any SEs)

SN

11:25 am on July 6, 2003 (gmt 0)

New User

10+ Year Member

joined:July 5, 2003
posts:3
votes: 0


"True, a forum can be moderated, but why get the moderators to work harder than they already do when there are some things that can be automated."

Well if the forums are set up to run reports like 'delete all posts by user', then it is not a biggy. My comments are based on the preferred denial of service attacks on PHP websites. Whether forums or not, attackers first preferences are always functions that sapp server CPU resources. i.e. anything that dispatches email, registration scripts, then the search scripts etc.

Disabling attacks of that nature means creating a sessions include script that will more accurately determine if it is indeed a browser that is requesting/posting, or a attack script.

Look at the way browers deal with cookies. For instance, 99% of attack apps cannot store cookie data and then return them on future requests from a given proxy/IP.

So create a session based on the requesting IP, which allows it to have persistant data even if the requester is not giving back the PHPSESSID via cookie or URL.

Create a hash based on several different persistant pieces of information, sends it to the requester as a cookie, then have them re-request the document... meaning it ensures the user has the correct cookie before allowing access to any document.

Another way to deal with post floods, is rather than arbitarily forcing delays between posting is to start a counter which would allow say 10 consecutive post requests of say less than 20 seconds apart, if that counter gets past 10, a message tells them they've been blocked to prevent spamming. If that counter gets past 40, then that IP is banned via .htaccess

So each time a document is requested, a random hash would need to be sent to them as a cookie. Whenever they perform a POST operation, it makes sure the cookie they send matches the last hash that was sent.

This will effectively stop attacks made from applications that employ huge anonymous proxy lists.