Skip navigation


This is not a complete article on how to create a secure PHP application but rather, the outline for a talk I’ve been planning for some time. Yes, there have been talks on this topic in the past but they either had flaws or were missing some essential pieces. My goal was to provide a complete list of application security concerns and explain how you go about dealing with them in PHP. Of course, much of the context is missing but it wouldn’t be a very good talk if I wrote it all down, now would it? I’ve decided to publish it in hopes that it will force me to give the talk sometime soon.

This list is very extensive, so it’s possible that I missed something. If you happen to read through it and notice something, please leave a comment.

  1. Introduction
    1. Remember, layers
    2. Simpler is easier to test
    3. Don’t make assumptions
    4. Vulnerable browser = game over
  2. Explicit Coding and Quality Assurance
    1. Don’t rely on the server configuration; Set ini directives in your bootstrap
    2. Don’t use global constants / variables / registries
    3. Don’t use function parameter defaults
    4. Use === instead of == whenever possible
    5. Use constants for *possible* values
    6. Use wrappers for super-gloabals ($_GET, $_REQUEST, $_SESSION, etc.)
    7. Code should read like a book
    8. Simulate “Strong/Static” types
    9. Use Code sniffer and PHPMD
    10. Unit testing / TDD
    11. Continuous Integration
  3. Lock Down the Environment
    1. Implement ACLs
    2. Web server user should only be able to read from web root
    3. Web server user should only be able to write to cache directories and log files
    4. Cache and log directories should not be publicly accessible; Bonus: store them on a separate sever
    5. Implement MAC / SELinux
    6. Don’t rely on Safe Mode, Suhosin, or any other “automatic” protection
    7. Configure web server process/thread limits
    8. PHPMyAdmin bypasses MySQL host filtering
  4. Error Handling
    1. Exceptions are okay in PHP
    2. Install a custom error handler which can catch any code-level error or exception
    3. Error handler should be able to easily switch between “production” and “development” mode
    4. Production systems should not expose error content, including HTTP status codes
    5. Development systems should display ALL error content
    6. When calling any method that accepts sensitive information (e.g. PDO instantiation),  wrap the call in a try-catch block because any resulting exception stack trace will contain sensitive information; The exception message can be re-thrown from within the catch block
    7. Install a separate “message” handler for dealing with business-logic errors and converting code-level errors into user-friendly errors
  5. Input Validation & Sanitizing and Output Sanitizing
    1. Validation means checking, reporting, and then stopping execution
    2. Sanitizing means automatically converting data into the expected format
    3. Validation and sanitizing MUST be done in the server-side code
    4. Front-end JavaScript is only for improving the user experience
    5. Don’t accept include file names as input
    6. Don’t read or write files identified via input
    7. Don’t accept session or cookie data as input
    8. Business logic validation should happen first
    9. Validate every parameter of every method
    10. Sanitize all data before attempting to store it (e.g. SQL injection)
    11. Use database connection libraries which support bound parameters and correct encoding (PDO)
    12. Sanitize all data before it is sent to the output (e.g. Cross-site scripting)
    13. Use quickly-expiring HMAC signatures to authenticate requests from trusted sources
    14. Only allow input-controlled redirects to do so locally
  6. User Authentication
    1. Use SSL
    2. Don’t set arbitrary password limitations
    3. Use a key derivation function for password hashing (scrypt, bcrypt, PBKDF2, or S/I S2K; in that order)
    4. Control how often your key derivation function can be executed
    5. Pay VERY close attention to how sessions are managed (next section)
  7. Sessions & Cookies
    1. Session does not equal authenticated
    2. Explicitly manage association of session IDs with authentication states
    3. session_destroy() is not enough; the session probably still exists
    4. Regenerate the session id immediately after authentication and only associate the new session with the authentication state
    5. Re-authenticate when the user moves to a higher security zone
    6. NEVER store logic data in the session (e.g. admin = 1), even if it is encrypted
    7. Only use session and cookie storage for display purposes
  8. AJAX, Forms, and API handlers
    1. Each local action should have a unique nonce associated with it in the session
    2. Use quickly-expiring HMAC signatures to authenticate requests from trusted sources
    3. Perform access control checks in every single server-side action
  9. Data Encryption
    1. Don’t bother, you’ll probably do it wrong
    2. No, seriously, if you need encryption, hire an expert to build it
    3. Then hire Matasano to show you what a terrible job the “expert” did
    4. If you’re not offended, there’s a very slim chance you might be qualified to build your own
    5. Either way, encryption is WAY beyond the scope of this talk

Background

As mentioned by some of the more well-known PHP talking heads in their responses, there has been quite a bit of PHP smashing going around lately. Each of them provided great reasons for using PHP. And while they came close, they didn’t quite cover the reasons I continually choose it over others. Or at least, they expressed it differently.

The first thing I’ll explain is that my development realm is the web. I develop web applications for a living. There are infinitely better languages for developing applications for other platforms but for the purposes of this article, I’m talking about web applications.

So, I’ll just come out and say what many others won’t: I’m a huge PHP advocate.

But wait, it gets worse:  1) I love security 2) I love software craftsmanship

Yeah, I know you’re thinking, “Wait, a supposed security guys who loves PHP? This guy has no idea what he’s talking about.”

Bear with me.

The reasons I choose PHP boil down to

  • It’s as secure as any other web platform
  • It’s fast, reliable, and mature yet continually improving
  • It’s syntactically pretty
  • The community & php.net


So, lets cover these items.

The security of PHP

I get a lot of flack from my friends at security events whenever I remind them that I’m a proud PHP developer. The most common response to the idea that a PHP application can easily be developed to be as secure as any other platform is a scoff. But of course, not many of them are programmers, so it’s not even worth going into the details. Lets cover those details now.

First off, no language does security for you and application security is difficult regardless of the language you’re using. Every language has frameworks and libraries to help with this problem, including PHP. But don’t forget the essential requirement that developers understand what these tools are doing for them. I don’t mean that they should be able to build those tools themselves but they should understand what is being done and why.

You could argue about the “security” of compilers and interpreters but I have looked and and I have never seen any definitive research on this. The one bit of research I’ve seen that affects the potential security of PHP was a comparison of statically and dynamically typed code. The research showed that static typing produces superior code. Luckily, there are libraries available for simulating static typing in PHP and it’s something I advocate. I’ll be writing an article on that next.

So, I’ll lump compiler and interpreter “security” this into the same category as operating system security where the most unbiased assurance ratings we can get are from Common Criteria. Windows has consistently scored better than Max OSX for as long as I can remember but everyone swears that OSX is “more secure”. If we’re talking about published vulnerabilities in the interpreter, I can assure you that I’ve never had to rush a PHP upgrade on a production system because of a published vulnerability. The PHP manual is generally very good at providing best practice guidelines for pretty much everything at the language level. In most cases of published vulnerabilities, if you were following best practices, you were safe from them.

Many interpreted (scripting) languages do have a run-time configuration which alters the behavior of the language and PHP is one of these. In PHP’s past, it had some default behaviors which caused problems for the uninformed but those have since been removed. Some of those features have been removed entirely as PHP has evolved. It’s common to see magic quotes cited as a terrible PHP feature. And while yes, I agree, those of us who had to tolerate it simply added a run-time check to the database abstraction layer. If it was enabled, we replaced those back-slashed quotes with regular quotes and went on to our SQL injection checks. So, while it wasn’t a great solution, it didn’t actually cause any security problems.

So, lets just drop the idea that the “language” is less secure. Lets just agree that all languages are more-or-less equal where security is concerned. Application security is hard regardless of the language you’re using.

I have been working on a talk on how to build “secure” PHP applications for some time (work and family keep me busy) because the existing examples are lacking in key areas. I’ll be publishing the outline shortly which will hopefully force me to give the talk so we can end this argument.

PHP is a fast and reliable scripting language

Associated with the security argument is the pervasive idea that PHP itself is a terribly written interpreter and there is nothing you can do about that. It’s just not true. Sure, it has some pitfalls you need to watch out for but this is programming, not Lego©s. The PHP interpreter itself is certainly not made of the most elegant code but it does what it does very well and it is the fastest scripting language in nearly every regard except for large arrays.

As the manual says, “An array in PHP is actually an ordered map”. It then goes on to explain a whole lot about what you can do with them; pretty much any kind of list. The unfortunate side effect of this flexibility is that they can be really slow. Some PHP array operations are documented to be as slow as O(n). I’ve been told that they can be as slow as O(n²) but I haven’t seen any proof.

Fortunately, a slow array implementation isn’t really a problem for most web applications because we have database engines on which we can rely for this sort of functionality.

Overall, I think PHP has struck a good balance. I like the fact that primitives are not objects. I like the way error handling works. The inconsistencies in argument orders and function names have never bothered me. Code written in PHP is very easy to understand because there are so few variations in syntax for accomplishing the same thing. And finally, references work in exactly the way you would want them to work in a web application.

So, yes, PHP is quirky. But honestly, every language is. The most important thing to consider is what the language was designed to do. PHP was designed to facilitate building web applications and it does that job very well.

PHP is mature

PHP has been in continuous development since 1995 and has evolved into a language which can truly hold its own against any of the other languages out there. Did you realize that the list of languages released to the public around the same time includes ASP “classic”, ColdFusion, Java, Python, and Ruby? (and probably others)

Sure, there have been problems along the way; but it has been the same for all of the languages I mentioned. The important thing to note is that we have all learned from these problems.

I think the things that truly set PHP apart from the others were, cross-platform support, open source/free to use, and php.net. The first two are significant enough accomplishments but I believe PHP’s true genius was php.net.

The community and php.net

For as long as I can remember, php.net has been there in pretty much its present form. I’ve used a lot of languages over the years but I’ve never encountered another with documentation that was as well-organized and accessible as this. Top top that off, anyone can leave moderated comments directly on the manual page for any given function or feature. I think the interactive element of the manual is what really encouraged the growth of the PHP community and improvement of the language. If you were a PHP user, you used php.net, and you knew what everyone else knew.

The one major thing php.net didn’t provide was design guidelines. For instance, there was no common document you could visit which explained a good architecture for implementing database connections. So, what ended up happening was, new users would need particular features, access the individual manual sections for them, copy the remedial examples intended to explain essential implementation details, and piece them together until they had a functional application.

Sometime around 2005, a significant movement in the PHP community aimed at software craftsmanship, quality assurance, and security, began. Unfortunately, it was not directly associated with php.net so new users don’t know about it. These new users ended up going through the same old cycle and the same old results are produced. Sadly, this is something we’re still battling.

While the documentation and comments on php.net are indispensable for learning which functions are available and how each works, they are certainly not the way to go about learning how to create entire PHP applications. Fortunately, progress is being made in this area. People like me are writing articles like this one and talks are being presented at local user groups. As a result, we are starting to see sites like phptherightway.com crop up. I’m not affiliated with that site in any way and I don’t completely agree with the message being delivered, but it’s a start.

I’m hoping to see something similar done in in the spirit of php.net where there is a pre-defined structure but anyone is allowed to contribute in a moderated way. I think the only way it will make an impact, though, is if it is blatantly referenced on php.net. A quick tactic I can think of would be to add a link to “Database connection implementation recommendations” on any database related manual pages. That way, when new people visit the site, they are encouraged to consider their overall implementations.

PHP has an extensive collection of great frameworks, libraries, and information out there but there is still a lot of work to be done in making these things known.

Conclusion

So hopefully, I’ve explained all of it in a clear and rational way. I don’t expect the PHP bashing to go away because some people will believe what they want to believe. In the end, I wrote this article to explain why *I* choose PHP as a software security and craftsmanship advocate.

Remember to keep an eye out for my outline on how to develop “secure” PHP applications.

Thanks for stopping by.


Background

After accepting the fact that Git is likely going to supplant SVN, I decided to hunker down and figure out how to actually USE the tool rather than fight with it every time I had to interact with it. Well, my foray into Git has often reminded me of a very similar experience I had when learning Vim: utter frustration. Each time I dug into Git’s man pages and internals, I felt more confused than when I started and told myself, “just live with it”. Well, as with Vim, as time has gone by, I’ve learned things which have made Git infinitely easier to live with and I want to share them with you.

DISCLAIMER: I am by NO means a Git expert. I am still far more comfortable with SVN. My goal here is to provide the information I’ve found helpful in my transition.

So, I’m going to start posting some very simple tips targeted at seasoned SVN users. I’m not going to explain the functionality behind each item in order to keep it simple and make the answers easy to find. So, here we go.

Log Output

In this post, I’ll cover log output. If you’re a long-time SVN user who has recently switched to Git for whatever reason, you may, like I was, be continually frustrated by the log output. It never gives me the information I want! Well, here are some tips on how to get that information:

How do I make Git output to STDOUT by default?

Either execute the following command:

$ git config --unset-all core.pager

Or add the following lines to your ~/.gitconfig file

[core]
   pager =

What is the Git equivalent to svn log --limit 5?

$ git log --name-status -n 5

What is the Git equivalent to svn info?

It’s not exact, but most of that information can be shown by executing the following commands:

$ git config --local --list && git log -n 1

Okay, that’s it for now; just some simple tips to help you get by.

Thanks for stopping by!


Some hype has been going around the web lately related to the use of Bcrypt and how it opens you up to denial-of-service attacks. Now, to the seasoned developer, this is a completely ridiculous notion. As developers, we think about how and when resources will be consumed on a daily basis.

To be fair, one of the videos I saw was targeting “inexperienced developers” and didn’t offer many solutions to the issue. I wanted to chime in with some simple measures to implement which will help deter attackers from using your derivation function against you:

  1. Check for a valid user record before hashing the password
  2. Store the last log-in attempt time-stamp for each user
  3. Store the number of failed log-in attempts for each user
  4. Write the following time delay function into your log-in routine before the password is hashed:
    • If failed log-in attempts > 1
      • Wait until (failed log-in attempts ^ 2) seconds after the last failed log-in attempt before allowing the password to be hashed again
  5. Reset the number of failed log-in attempts after each successful log-in

That’s it. Simple.

Thanks for stopping by.


Often, I’m utterly depressed by the state my industry (software development) and then human nature in general. Then, every once once in a while, I’ll run across a group or a study, see what they are trying to accomplish, and it renews my enthusiasm.

This week, the number of instances of the later has been greater than the number of instances of the former :)

Here are the examples:

  1. http://manifesto.softwarecraftsmanship.org
  2. http://www.slideshare.net/stubbornella/dont-feed-the-trolls
  3. https://implicit.harvard.edu/implicit/Study?tid=-1

It doesn’t get a whole lot better than this.

image

Except it does! Shortly after I posted this, my wife accompanied my 2-year-old daughter out who brought me a chocolate chip muffin :)


In anticipation of the upcoming move, I scrubbed our kitchen floor on my hands and knees with a sponge. It’s amazing how much cleaner it gets as opposed to a mop or a Swiffer. The most intriguing aspect of the whole thing was the distinct odor of garlic being released as I moved across the floor. Now it smells like I just got done cooking!


Oh, which could it be?

Fireworks Or Sea Life? - Preview

Click here for a larger version.


Okay, it’s time. I’ve been putting off posting photos for so long because I keep going off on tangents with my photo gallery functionality. I follow a few photographers who publish one or two photos in a dedicated post and I’ve decided that I like that format. It means that instead of making users wade through my entire collection, I have to chose my favorite(s) and post them individually. So here goes.

This photo is of a bird who posed for me at the Brevard Zoo in Melbourne, Florida, while I was there visiting family in the area.

Bird On A Post - Preview

Click here for a larger version.


President Obama,

I know that you have heard the aguments for Patriot Act reform time-and-time again. So there is little point in my going on at length other than to add my voice to the chorus, in the hope that you might recognize that The People are being misrepresented on this front.

Stop this nonsense of spying on American citzens under the guise of terrorism prevention. Our right to privacy is being trampled as if the Bill of Rights had never been written. The blance of power between The Government and The People
is leaning too heavily in the Government’s favor.

We have seen the proof of government agencies exploiting their powers, and yet, the government moves to grant them more power? You and I know well that very few agents of the government are ethically pure. How long will it be before the
increased powers and reduced transparency are exploited for financial gain?

Sincerely,
Bryan C. Geraghty