Tutorials

PHP Security

by Daniel Egeberg on Jun 30, 2008 12:40:06 PM

4. Cross Site Scripting

Cross-Site Scripting, abbreviated XSS, is another common security issue. This issue is relevant whenever content that comes from the user will be redisplayed on the screen. It is essentially when Javascript is injected into the HTML source. We could for instance imaging a forum. On a forum users will be able to post messages that will be displayed for other users. We want the users to be able to format their messages and HTML is just perfect for that, right? There is just a minor problem... Not all users are equally nice. The same kind of people that might want to drop the school's student table from the previous section might also want to do something here. Specifically what they might want to do is insert Javascript into the source. This might be for various purposes. It could be simply for annoying by creating an infinite loop of alert messages which would force the user to shutdown the browser or it could be redirecting the users to websites such as goatse or tubgirl (you might not want to check what it is if you do not already know). Other, more sofisticated attacks, could be writing a keylogger that logs and sends keystrokes (such as passwords) to an external website or the injected Javascript could be retrieving the users' cookies (more on the latter later in this tutorial).

4.1. XSS Protection

As a matter of fact, this is rather easy to protect yourself from as well. PHP has a nifty function that is useful in this instance which is called htmlentities(). It will simply convert characters which have a meaning in HTML to their corresponding entities. For instance, HTML tags start with a lower-than sign and that particular character will be converted to <. If you care about validation of your HTML (and you should!) then this will also help along with that.

We just have one problem. Our original example was a forum system and we wanted to give the users the opportunity to format their posts. However, the fix we just implemented removed this opportunity so we need to give them an alternate one. One with which we can control what they may do and not do. A common feature is called bbcodes. It has a syntax very similar to HTML and I am quite sure you are familiar with it if you have ever frequented any forum. Be aware though! You might get some additional XSS security holes with some tags.

A common bbcode tag is the URL tag. We could imagine that someone entered

[url=http://www.phpfreaks.com]The best PHP website[/url]

which would be converted to:

<a href="http://www.phpfreaks.com">The best PHP website</a>

. At first glance there is no issue with allowing that. However, URLs like javascript:alert('Hi') are also allowed and they will, obviously, execute the entered Javascript. Similarly, in some lower versions of Internet Explorer (IE6 and below) that URL format is allowed and will execute Javascript so we have to take care of that as well.

For both the two before mentioned instances we might want to check that the protocol is one we would allow. It would be better to create a white-list of allowed protocols instead of creating a black-list of disallowed protocols. Simply select the protocols you want (e.g. http, https and ftp) and disallow all other.

Finally, this XSS cheatsheet might be useful to you. Both when learning about XSS as well as testing that your application is secure.

Comments

You wrote a very nice tutorial here. I'm going to keep all these security advices in mind.

1. John McKenzie on Jun 30, 2008 4:07:27 PM

a great article,
definitely bookmarked.

2. HoTDaWg on Jul 1, 2008 9:46:22 PM

I actually created a post in the Forums asking where to find a good tutorial on PHP security: it was right here on the home page!

3. rupertrealbear on Jul 2, 2008 6:40:55 PM

Great tutorial - explains alot of technical stuff definately recommended

4. Wasim Ilyas on Jul 11, 2008 8:36:42 AM

about the mysql injection, how would such a user find out the name of the table/structure of the table so they could put something to damage the database?

is there a way of stopping them finding out the database/table structure?

5. Flames on Jul 24, 2008 8:36:44 AM

Flames: It could be guesswork, but there are also queries that will allow you to see how the tables are laid out. It could also be an open source app, and it that case it would be as simple as checking the source.

6. Daniel Egeberg on Jul 24, 2008 10:00:29 AM

k, i've been trying to stop mysql injection and although its taken time i finally got it to work without random apostrophes being put in places :D.

7. Flames on Jul 24, 2008 11:07:42 AM

Views: 17435 lol

8. dezkit on Jul 26, 2008 9:14:19 PM

One part is missing, security problems related to emails.

9. Hervé Thouzard on Jul 27, 2008 3:11:32 AM

good stuff!

10. libertyct on Jul 28, 2008 10:44:46 AM

Im happy I found this tutorial - dont understand lots of stuff but will re-read so that it sits.

11. Dorothy Wegmueller on Aug 5, 2008 6:14:18 PM

Well, feel free to ask in the forums if there is anything specific in the tutorial you need help with :)

12. Daniel Egeberg on Aug 5, 2008 7:53:32 PM

Very nice tutorial indeed. It is very helpful for newbie's like me.

13. cyberbuff on Aug 11, 2008 4:57:40 AM

Excellent tutorial. I've had experience with other scripting languages and decided to try PHP. This is really a great start what to look out for and how to design with these dangers in mind.

One question about the include(), mostly for db access. Some showed using a config.pm that would contain passwords to the db.

Would you consider this secure?

mkdir public_html/secure
chmod 711 public_html/secure
create the config.pm containing the db access

in the php script, I add
include('../secure/config.pm');

Would it be better to not be in the document root at all?
I notice in the tree, the config dir is in the system root, not doc root.

Thanks

14. budman85 on Aug 12, 2008 8:11:32 PM

The safest way would be to not place it within document root at all.

15. Daniel Egeberg on Aug 13, 2008 11:10:32 AM

Daniel, great article, was a good read and learned a lot (implementing some of this stuff as I'm writing this.) In doing so, I've noticed that the error_reporting and error_log statements in .htaccess files seem to not work unless they are preceeded by php_value, and not php_flag as stated in the article. Feel free to correct me if I'm wrong, I just thought I'd point it out in case anyone else ran into the issue.

Thanks again :)

16. vnums on Aug 15, 2008 11:15:05 AM

the pdf article for download just gets a 404

17. Brad Floyd on Sep 17, 2008 11:13:51 PM

Ooops... sorry about that. It's back up now.

18. Daniel Egeberg on Sep 18, 2008 1:25:08 PM

cool :-) Just thought I'd point it out since security is one aspect people need to pay more attention to I agree

19. Brad Floyd on Sep 18, 2008 7:34:22 PM

However, wouldn't RFI only be an issue if PHP - Register globals is turned on?

Note some shared hosts has it disabled by default.

20. BlueBoden on Nov 11, 2008 4:20:41 AM
Login or register to post a comment.