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.

Introduction

  1. Remember, layers
  2. Simpler is easier to test
  3. Don’t make assumptions
  4. Vulnerable browser = game over

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
  12. Deployment

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

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

Input Validation, Bounds Checking, & Output Encoding

  1. Validation means checking, reporting, and then stopping execution
  2. Bounds checking means ensuring that the input is smaller than the maximum allowable size
  3. Encoding means automatically converting data into the expected format
  4. Validation and encoding MUST be done in the server-side code
  5. Front-end JavaScript is only for improving the user experience
  6. Don’t accept include file names as input
  7. Don’t read or write files identified via input
  8. Don’t accept session or cookie data as input
  9. Business logic validation should happen first
  10. Validate every parameter of every method
  11. Sanitize all data before attempting to store it (e.g. SQL injection)
  12. Use database connection libraries which support bound parameters and correct encoding (PDO)
  13. Sanitize all data before it is sent to the output (e.g. Cross-site scripting)
  14. Use quickly-expiring HMAC signatures to authenticate requests from trusted sources
  15. Only allow input-controlled redirects to do so locally

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)

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

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

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

One Comment

  1. It’s a really very informative information. It’s very useful and knowledgeable for me. i was stuck while coding this. I will bookmark this page for coding help.


Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">