I just starting out learning PHP, I've been developing web apps in ASP.Net for a long time. I was wondering if there are any PHP specific security mistakes that I should be looking out for.
So, my question is what are the top security tips that every PHP developer should know?
Please keep it to one tip per answer so people can vote up/down effectively.
(In no particular order)
Always check that register globals are OFF
Always check that magic quotes are OFF
Make sure you understand SQL injection attacks
Turn OFF error reporting in production
EDIT: For the "newbies" out there this is a basic why (and since I have time to explain this):
Register globals is an aberration. It's the ultimate security hole ever. For example, if register_globals is on, the url http://www.yourdomain.com/foo.php?isAdmin=1 will declare $isAdmin as a global variable with no code required. I don't know why this "feature" has made it's way to PHP, but the people behind this should have the following tattooed on their forehead: "I invented PHP Register Globals" so we can flee them like pest when we see them!
Magic quotes is another dumb idea that has made it's way to PHP. Basically, when ON PHP will escape quotes automatically (' become \' and " become \") to help with SQL injection attacks. The concept is not bad (help avoid injection attacks), but escaping all GET, POST and COOKIE values make your code so much complex (for example, have to unescape everytime when displaying and data). Plus if one day you switch this setting OFF without doing any change to your code, all your code and/or data is broken and (even more) vulnerable to injection attacks (yes even when ON you are vulnerable).
Your databse data is your most valuable thing on your site. You don't want people to mess with it, so protect yourself and read things about it and code with this in mind.
Again this can lead to security concerns. The error message can give hints to hackes on how your code works. Also these messages don't mean anything to your visitors, so why show them?
Avoid using register_globals.
Warning: This feature has been DEPRECATED as of PHP 5.3.0 and REMOVED as of PHP 5.4.0.
Cross Site Scripting (XSS) Wiki, Google
Cross Site Request Forgery (XSRF/CSRF) Wiki, Google (thanks Rook)
Session Fixation Wiki, Google
SQL Injection (SQLi) Wiki, Google
Turn off error messages in Production environments
Keep any "include" code in a directory that is not web-accessible (either deny access or keep it outside of the webroot)
Here's an article I wrote about storing passwords in a secure way, and if you don't feel like taking my word for it, check the links at the bottom.
Also linked in my article, but given its own separate link here, is a paper published by M.I.T. called The DOs and DON'Ts of Client Authentication on the Web [PDF]. While some of its info (recommendation to use MD5 hash, for one) is somewhat out of date simply because of what-we-know-now versus what-we-knew-then, the overall principles are very strong and should be considered.
One of Rooks' links reminded me of another important set of restrictions
Turn off Register Globals (This is the default now, so I hadn't mentioned it before)
When dealing with file uploads, be sure to use is_uploaded_file() to validate that a file was uploaded and move_uploaded_file() instead of copy() or rename().
Read this section of the PHP Manual if you need to know why (and you do).
Since I've now mentioned him twice, check out Rooks's Answer (https://stackoverflow.com/questions/2275771/what-are-the-most-important-safety-precautions-that-a-php-developer-needs-to-know#2275788) as it includes a link to a document which contains (Non-PHP-Specific) information on the most important security concerns (and this therefore probably the right answer).
here is a link of good PHP security programming practices.
http://phpsec.org/
Most of the security issues revolve around user input (naturally) and making sure they don't screw you over. Always make sure you validate your input.
http://htmlfixit.com/cgi-tutes/tutorial_PHP_Security_Issues.php
Always sanitize and validate data passed from the page
In conjunction with #1, always properly escape your output
Always turn display_errors off in production
If using a DB backend use a driver that supports/emulates prepared statements and use without prejudice :-)
don't use "Register Global Variables" and filter user input for xss and injections
Language Vs Programmer. You can write the most serious vulnerability and you won't get a warning or error message. Vulnerabilities can be as simple as adding or removing 2 characters in your code. There are hundreds of different types of vulnerabilities that affect PHP applications. Most people think of XSS and Sql Injection because they are the most popular.
Read the OWASP top 10.
If you're using a mysql database make sure you call mysql_real_escape_string when sending data to the database
There are tons of safety precautions. I can recommend a book Chris Shiflett: PHP and Web Application Security.
http://phpsecurity.org/
Have a look at the Suhosin Hardening Patch, and check out the security vulnerabilities that it addresses.
The PHPSec Guide gives a good overview.
Most of the security issues related to PHP come from using unparsed "outside" (GET/POST/COOKIE) variables. People put that kind of data directly into file paths or sql queries, resulting in file leakage or sql injections.
OWASP provides a lot of insight into security issues that are the biggest problems in applications today. It is nice to see that they have a PHP dedicated page available
http://www.owasp.org/index.php/PHP_Top_5
Always Close you SQL Connection.
Always Release SQL results.
Always Scrub all variables your putting into a database.
When deleteing or dropping from sql use limit 1 just in case.
When developing make sure you have a lock on things to keep the undesirable out. If its open and you know not to load the page right now because it could break something, doesn't mean other people do.
Never use Admin or Root as your server log in name.
Whenever possible, use prepared statements (tutorial. It's almost a must whenever dealing with user input (I say "almost" because there are a few use cases where they don't work), and even when not dealing with input, they keep you in the habit. Not to mention they can lead to better performance, and are a LOT easier, once you get into the swing of things, than piecemeal sanitizing.
Often introductory tutorials don't talk at all about checking data from users. Like all programming environments, never trust the data you get from users. Learn to use functions like is_numeric(), isset(), and mysql_real_escape_string() to protect your system.
There are also features that allow you to access remote files, and other creative things. I'd avoid those until you have a good understand of how and when they work (often they are disabled for security reasons).
Use POST method for data passing from one page to another.
Use trim while getting data like trim($_POST).
Also, use strip_tags for variables before you passing into the queries.
I am suggesting you use any framework link Codeigniter, Laravel, YII, Cake PHP because they maid framework with all securities
I suggest Codeigniter for small projects and Laravel for big projects.
Always use POST and not GET for important Data...
Related
I'm finishing up my first "real" PHP application and I am trying to make sure it is secure. I'm kind of afraid that since I'm not an "expert" PHP programmer that I might be missing something huge, so I would like to give you some information about my application and hopefully you can tell me whether or not that is the case. So here we go:
I'm using a CMS to handle user authentication, so I don't have to
worry about that.
After discovering PDO shortly after starting work
on my application, I ported all of my code over to using prepared
statements with PDO.
I am escaping all form and database data (even stuff I think is safe) which is being output with htmlentities().
My application does use a session variable and cookie variable, but the function of both is very unimportant.
I have designed my form processing functions in such a way that it doesn't matter if the form were somehow altered, or submitted from off-server (i.e. I always check the data submitted to ensure it's valid).
I have done my best to make all error messages and exception messages polite but very obscure.
I'm forcing pages with sensitive information (such as the login page) to be served over https.
When I first starting writing my application, I didn't know about prepared statements, which is kind of a huge deal. Have I missed anything else?
OWASP maintains a list of the Top 10 Most Critical Web Application Security Risks (warning, PDF download). This is from 2010, but I think it still applies, perhaps even moreso now.
Injection and XSS are the top two, but you should certainly be aware of the other 8. If you are using an existing CMS, many of these may already be considered, but the more popular the CMS the more you risk running into vulnerabilities because of black hats trying to find holes in it.
If you are not storing critical data like credit cards, order history, addresses, and even emails, then I wouldn't worry too much about your site being affected as long as you are taking the basic precautionary measures (and it sounds like you are).
If you are concerned about security issues, a good resource is the OWASP - Top 10 Application Security Risks
The most important thing to take care in web applications(specially PHPs') is Data Validation of all the inputs taken from the user which are further saved in your database.
For a secure application, all the transactions should be done on HTTPS. For a secure cookie management Secure and HTTPOnly cookie should be implemented.
Some more points I don't see mentioned yet. Most of these are not related to code - I am not sure if you only wished for things related to code, but I'll mention them anyway.
Backups (user data). should be self-evident
Version control. If you have a big bug, you want to have access to the previous version.
Audit trail, alarms and logging. If you do get into trouble, how will you find out? Are you able to track down what happened? if you know something is wrong but don't fully know what, are you able to diagnoze the issue?
Hosting. Where are you hosting? Do you have adequade bandwidth and monitoring? What happens if you get DOSed? Are you able to block out unwanted traffic?
Caching. Can you change it if needed?
There's always one thing left. Availability :) There are three aspects of security:
Confidentiality (Noone can read what they don't have access to)
Integrity (Noone can change any data what they should have to and you have to be able to detect if it happened even so)
Availability (The data, application whatever has to be available)
You pretty much did a nice job and took care of the first two (credentials, prepared statements, htmlentities...) but none of them will help against a DoS attack. You should be able to detect if someone slaps your site and ban the attackers ip from your server. Although this can be done in PHP (still much better to kick the attacker at the first line of php than let them initialize the framework, database connections etv.) it can be done mre effectively in lower layers (for example: nginx/apache, iptables, snort).
However what you're asking for that usually comes to the matter of risk management. In a real application you're not able to be prepared for all the possible attacks, edge cases etc. What you need to do is classify all the risks by the probability and the impact ( http://www.jiscinfonet.ac.uk/InfoKits/infokit-related-files/Resources/Images/risk-matrix ). With this you can focus on the most important (highest) risks first and probably you can completely ignore the lower bottom part.
SQL Injection and XSS are the most prominent Hacking methods.
You are covered from SQL Injections if you use prepared statements.
Also, if htmlentities() on everywhere you display HTML you should be safe.
So I have a website that given a users input it will generate a /home/content/s/a/m/p/l/e/users/profile/index.php. My real question is, is this safe? This is what I do to try to sanitize the users input, if there is more, please let me know.
strip_tags(html_entity_decode($mysqli->real_escape_string($title)), ALLOWED_TAGS);
ALLOWED_TAGS = "<br><p><b><i><hr>";
Since I am relatively new to this website development, I am wondering if this is a good approach, because it takes the strain off using the database to get the same information over and over again, instead just have a static page with the information on it, or is this a HUGE security hole? I do not know! :) I do not know if they could do some sort of XSS attack with what I have setup here. Please help!
Michael
P.S. If you have any answers or suggestions, could you please give me some insight into why it is. I have a degree in computer science so I am curious on how it works, not just the quick and dirty solution. Thanks.
This is a PHP security checklist I compiled for my company's internal knowledgebase. May be it helps.
Do not use deprecated functions and practices
Always validate user input
Use place holders when using variable values in an SQL query.
Always escape variables used in SQL queries.
Set proper directory permissions
Always regenerate session id when the user logs in each time. (To avoid session id hijacking)
Never store passwords in plain text. Store only their hashed values.
When outputting user input in a web page, always check for html special characters. (HTML tags like may be used for XSS attacks)
Know the specs of your deployment server before you move to it
Protect directories where log entries are saved.
Set register_globals to off
PHP safe mode can be useful, but it is deprecated since version 5.3
If not used in the code, disable the functions system and exec using the disable_functions setting in php.ini
Set display_errors to off in production/live servers.
Validate Cookie Data
This XSS input validation is awful. An html_entity_decode() is the opposite of what you need. Further more some of these tags, such as the <p> tag allow you to execute JavaScript in an event handler. So in short this code doesn't do shit to stop xss.
You should use htmlspecialchars($var,ENT_QUOTES); or htmlpurifer. If you go the htmlpurifer route make sure you keep that shit up to date, it gets bypassed every couple of weeks, oah and htmlpurifer very computationally expensive because it uses THOUSANDS of regex's.
I just read this article about piggy backing in PHP.
I googled it but not so much information there.
Can anyone tell me more details how to prevent this kind of attack, what kind of code practices are vulnable and what we should do?
Thanks in advance.
That article seems to refer to a vulnerable web application, not anything specific to PHP.
This previous thread provides some useful information regarding writing secure PHP code:
What security issues should I look out for in PHP
If we take the "They used these vulnerabilities to inject PHP code into the site" part of the article literally, then the developers likely used user input with include/require statements or eval
The article isn't particularly clear, but my guess is that they just used SQL injection and, to try to avoid detection, they inserted a script that didn't actually change the behavior of the site normally unless the visitor came from Google using a relevant search term, and the author is calling the redirection in that situation "piggybacking".
So: escape and validate all user input.
First link really on the general subject should give you some overview.
Second link is PHP / SQL - specific and should lead you to enlightenment.
The BBC news article is talking about "persistent xss". Leave it to the news to talk about hacking without mentioning anything about vulnerabilities. But that could be that the bbc.co.uk dosen't know what an xss vulnerability is, because if they did they would patch their own damn site!.
There are many ways to achieve remote code execution against a PHP web application. No one should ever call this "PHP Injection", if they call it this then they don't know what they are talking about. A Study In Scarlet is an excellent paper that details many different methods that an attacker can use to obtain remote code execution against a PHP application. This paper is intended for malicious hackers, not developers.
XSS is by far the easiest and most common method to nefariously palace advertisements on somebody's site.
I just wanted to know what are some basic PHP security techniques I should use when creating a web page that accepts articles?
I'm fairly new to PHP and was wondering what will hold the fort down until I'm a security expert?
There are two fronts to consider when accepting user-generated text that will later be displayed.
First off, you need to protect your database from injection attacks. There's a simple PHP function for this: mysql_real_escape_string() will usually suffice to protect your database from injection when passing this string in to store as a field value.
From there, you have to be careful about your display, as a user who is allowed to upload HTML code can do nasty things to other users when that code gets displayed. If you're doing plaintext articles, you can simply htmlspecialchars() the resulting text. (you'll also probably want to convert newlines to tags.) If you're using a formatting solution, such as the Markdown engine used on this site, those solutions will usually provide HTML sanitization as a function of the engine, but be sure to read the documentation and make sure.
Oh, make sure you're also verifying your GET/POST variables used to submit the articles. That goes without saying, and the verification performed is going to need to be tailored to what your site is doing with its logic.
This is to broad, maybe you should try to narrow it a bit.
What kind of security?
For passwords?
Do you want to restrict some stuff?
SQL Injection?
HTML Injection?
Cross domain security?
Well, as mentioned in the other answers, there are a number of different fronts in which your PHP scripts can be compromised.
Here are just a couple:
SQL Injection
Cross site scripting
There are a number of ways to deal with each. Here are some things to look at:
Suhosin
eval()
There is a lot to know, and you should start as soon as you can.
For one, if you accept articles (and probably use a WYSIWYG and are accepting HTML), use something to parse the content and strip out things that could leave you vulnerable to XSS and the like.
An example is HTML Purifier.
It might be wise to start by using a framework like Drupal or CakePHP. That way you can both learn from the way they've implemented security and take advantage of the fact that it's already been done. The learning curve is steep enough without having to roll your own authentication mechanisms etc.
maybe two tips could help you get more secure websites
create two users in your database, read only account to make only selects and counts, and write account when you have to do updates, inserts or deletes.
when you have to insert into database or delete, sanitize inputs, use mysql prepared statements or assert values that arrive via post or get this way :
if(!empty($_GET["integer_like_id_value"]){
$integer_id_value = (int)$_GET["integer_like_id_value"];
}else{
// that stuff seems not to be legit, die application, log error ? whatever
die();
}
Top 7 PHP Security Blunders
When your project is ready for public usage, it is generally a good idea to set error_reporting(0);
It won't provide more security, but it makes it lot harder (usually) for bad guys to find possible security problems with your site.
I'm a PHP/MySQL noob who knows nothing about online security.
Could you point me to some resources that will aid in my knowledge? (Beginner level, please!)
I'll suggest two things:
Make sure Register_globals is off.
Use prepared statements.
This question is well-answered and covers MySQL injection attacks (one of the more common concerns.
This question is also well documented and covers XSS (cross site scripting) attacks well.
Lastly, learn about PHP.INI and how to set it up and what is actually open/closed and on/off. A good host will, for example, never turn on register globals, but you should at least know what it is and why to check it. PHP Security has resources on that and many other PHP security concerns.
PHP might not be the best start. Especially if you're largely hand-rolling your own code. It doesn't exactly hold your hand with security issues. (fd: I wish PHP would go away for a variety of reasons.)
But some general rules:
Don't trust anything that comes from the outside. Always assume the user is some jerk trying to break your app. Most of them won't be, of course, but there will eventually be one who is. Just because you gave the browser a <select> containing a, b, and c doesn't mean you'll get one of those back. Javascript isn't a guarantee of anything. Referers can be easily faked. POST data can be easily faked. Textboxes can contain any character, not just the ones you expect.
Don't copy-paste others' code into production if you aren't sure how it works. You have no idea how much of an eye the author has for security. In my experience, PHP copypasta in particular seems to be less reliable but more frequently blindly reused.
Don't trust yourself to perform the same ritual in dozens of different places. Yes, mysql_real_escape_string() will fix SQL injection, but then you have to remember to use it everywhere. This creates a lot of places where you might make a mistake and forget your escaping ritual. Use prepared statements instead, and the problem vanishes entirely. Another example: Pylons (a Python framework) rigs its templates so any variable is HTML-escaped unless you explicitly ask otherwise. XSS is no longer a problem, and I never have to worry about manually escaping everything I print.
Chris Shiflett is the go-to guy on PHP programming and security:
http://phpsecurity.org/ for his book "Essential PHP Security"
http://shiflett.org/ for his website, blog, etc.
He is Speaking at PHP CodeWorks in Sept/Oct.
If you have some time, you could take a look at the slides used by Stefan Esser during his conference at the Dutch PHP Conference a few months ago, which title was "PHP Security Crash Course for beginners".
There are a couple of PDF :
Part I - Introduction
Part II - XSS
Part III -CSRF
Part IV - SQL Security
Part V - Session Management Security
Part VI + VII - PHP Code Inclusion and PHP Code Evaluation
Those could be helpful.
Then, don't hesitate to search a bit for non-PHP-specific informations : some security problems (like XSS, SQL Injections, CSRF, ...) are not specific to PHP : only the technical means to avoid them are specific ; so, you could find plenty of informations on sites like Wikipedia, or the OWASP website