SlideShare une entreprise Scribd logo
1  sur  24
Explicit Code & QA
So, who are you, anyway?

                  Bryan C. Geraghty
          Security Consultant at Security PS
                     @archwisp

  I’m a Sr. PHP developer with a systems and security
   engineering background - turned application security
                       consultant
Remember, layers
Simpler is easier to test
Don’t make assumptions
Compromised browser = game over
These are not specifically security activities but they produce more
stable code
Don’t rely on the server’s configuration
  Your bootstrap should       Absolute Minimum
  set the defaults for any     Include paths
  PHP core functionality       Error reporting
  that your application is
                               Time zones
  using.
  These must be
  customizable for every
  environment
  e.g. (dev, staging, live)
Example Bootstrap
<?php

// All environment configuration for this application is done from this file

ini_set('display_errors', 0);
ini_set('error_reporting', -1);

date_default_timezone_set('UTC');

$rootPath = dirname(__FILE__);

set_include_path(sprintf(
   '%s%s%s%s',
   $rootPath, PATH_SEPARATOR, $rootPath, '/third-party'
));

require_once('MindFrame2/AutoLoad.php');
MindFrame2_AutoLoad::install();
Don’t use global constants, variables, or registries

 You can’t be certain that nobody else will ever use the
  same global constant name
 Tracking down where a value is assigned to a global
  variable is usually very difficult
 Global variables remove control of that variable from the
  current scope
 Global registries are really just fancy global variables and
  the same problems apply
Value Reference Rules
 Values should only be referenced in one of the following
  ways:
   A direct reference in the current scope:
    $limit = $this->_objectPool->getConfig()-
      >getDefaultLimit();
   A parameter:
    public function getUsers($limit) {
      return $this->_objectPool-
      >getMapper(‘User’)->fetchAll($limit);
    }
Don’t use function parameter defaults
   "There should be one-- and preferably only one --
   obvious way to do it." - Tim Peters

 Reduces understanding from the caller perspective
 Often add unnecessary complexity
 Represents the most common use-case
 Other use-cases are often ignored entirely
 Changing the default breaks all implementations
 Adding parameters breaks default implementations
Default parameter example
class User
{
   public function __construct($name, $email, $status = self::STATUS_ACTIVE) {
          $this->_name = $name;
          $this->_email = $email;
          $this->_status = $status;
   }
}

function createUser($name, $email, $status) {
   $user = new User($name, email);
   return $this->_objectPoool->getMapper(‘User’)->create($user);
}
Use explicit operators whenever possible
This was actual production code.
if ($sincedate && (int)$sincedate) {
 $param["UpdatedSinceDate"] =
    date("Y-m-d H:i:s", strtotime(time() - ((int)$sincedate)*60*60);
} elseif ($sincedate && strtotime($sincedate)) {
 $param["UpdatedSinceDate"] =
    date("Y-m-d H:i:s", strtotime($sincedate));
} elseif(!isset($param["UpdatedSinceDate"])) {
 exit ("Invalid param UpdatedSinceDate");
}



Do you think this code worked as the author intended when $sincedate was set to
'2011-05-31'?
Use constants for possible values
Constants cannot be re-defined, so using a constant for configuration limits your code
to only ever be able to run in one configuration in a given stack.


// Bad: This code cannot execute differently in the same stack
define(‘PDO_FETCH_MODE’, 2);
$dbi->fetchAll(PDO_FETCH_MODE);

// Better: The value can change but this literal value means nothing without
// referencing the documentation
$dbi->fetchAll(2);

// Best: Implemented using a meaningful constant which represents a *possible* value
$dbi->fetchAll(PDO::FETCH_ASSOC);
Use wrappers for super-globals
 $_REQUEST, $_GET, $_SESSION, and $_FILES are the most
  commonly used PHP super-globals but there are others
 It’s easy to create some serious security problems
 It’s best to use a wrapper for interacting with these
  variables
Simulate strong/static types
PHP is dynamically typed, so we cannot do true strong or static typing but we can
put controls in place which provide the same protection.

private function _buildSelectDatabaseTableSql($database_name, $table_name,
     array $select_data, array $order_by_columns, $offset, $limit)
  {
     MindFrame2_Core::assertArgumentIsNotBlank($database_name, 1, 'database_name');
     MindFrame2_Core::assertArgumentIsNotBlank($table_name, 2, 'table_name');
     MindFrame2_Core::assertArgumentIsInt($offset, 5, 'offset');
     MindFrame2_Core::assertArgumentIsInt($limit, 6, 'limit');

      $skel = "SELECTn   %snFROMn   %s.%sn%s%s%s%s;";

      $sql = sprintf($skel,
         $this->_buildSelectTableSqlFieldClause($table_name),
         $this->getSharedModule()->escapeDbElementName($database_name),
         $this->getSharedModule()->escapeDbElementName($table_name),
         $this->_buildSelectTableSqlJoinClause(
            $this->getSharedModule()->getDatabase()->getName(), $table_name),
         $this->_buildSelectTableSqlWhereClause($table_name, $select_data),
         $this->_buildSelectTableSqlOrderByClause(
            $table_name, $order_by_columns),
         $this->_buildSelectTableSqlLimitClause($offset, $limit));

      return $sql;
  }
Example Typing Assertions
public static function assertArgumentIsInt($value, $position, $name)
{
   if (!is_int($value)) {
      $skel = 'Expected integer value for argument #%d (%s), %s given';
      $message = sprintf($skel, $position, $name, gettype($value));
      throw new InvalidArgumentException($message);
   }
}

public static function assertArgumentIsNotBlank($value, $position, $name)
{
   if (trim($value) === '') {
      $skel = 'Argument #%d (%s) cannot be blank';
      $message = sprintf($skel, $position, $name);

        throw new InvalidArgumentException($message);
    }
}
Use PHPMD & CodeSniffer
This is the ./bin/codecheck script in MindFrame2
#!/bin/bash

WD="`/usr/bin/dirname $0`/../";
echo Changing to working directory: $WD;
cd $WD;

if [ -z $1 ]; then
     DIR='.';
else
     DIR=$1;
fi

phpmd --exclude coverage $DIR text codesize,unusedcode,naming,design
phpcs --ignore=coverage --standard=`pwd`/Standards/MindFrame2 $DIR
phpcs --ignore=coverage --report=source --standard=`pwd`/Standards/MindFrame2 $DIR
Example PHPMD Output
bryan@ubuntu-virtual ~/Code/MindFrame2 [130] $ ./bin/codecheck Dbms/Dbi
Changing to working directory: ./bin/../

/home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:128         Avoid unused local
variables such as '$partner'.
/home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:185         Avoid unused local
variables such as '$data'.
/home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:199         Avoid unused local
variables such as '$index'.
/home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:240         Avoid unused private
methods such as '_buildReplicaDatabaseSuffix'.
/home/bryan/Code/MindFrame2/Dbms/Dbi/Single.php:25       This class has too many
methods, consider refactoring it.
/home/bryan/Code/MindFrame2/Dbms/Dbi/Single.php:150      Avoid unused parameters such as
'$options'.
Example PHPCS Output
FILE: /home/bryan/Code/MindFrame2/Dbms/Dbi/Single.php
--------------------------------------------------------------------------------
FOUND 6 ERROR(S) AFFECTING 6 LINE(S)
--------------------------------------------------------------------------------
  39 | ERROR | Public member variables ("_connection") are forbidden
  62 | ERROR | Whitespace found at end of line
 144 | ERROR | Whitespace found at end of line
 160 | ERROR | Line exceeds maximum limit of 80 characters; contains 97
     |       | characters
 195 | ERROR | Whitespace found at end of line
 298 | ERROR | Line exceeds maximum limit of 80 characters; contains 81
     |       | characters
--------------------------------------------------------------------------------
Unit testing / TDD
 Test critical functionality at a minimum
 Add edge cases to regression tests as they are discovered
 Test-driven development only works if the entire team is
  dedicated to it
 I personally don’t trust code that isn’t regression-tested;
  even if it was written by me
Continuous Integration
 Automated system for code analysis and regression
  testing
 There are a lot of continuous integration systems for PHP
 If your tests aren’t automated, very few people will know
  or care when they break
Deployment
 Manually copying files is riddled with problems
 Tagging releases and re-deploying is a complicated and
  time-consuming process
 Deployment systems automate the build and deployment
  process
ACLs
MAC
Thread limits
Unwanted services
If you’re interested in an application security career, come talk with
me.

Contenu connexe

Tendances

Beginning PHPUnit
Beginning PHPUnitBeginning PHPUnit
Beginning PHPUnit
Jace Ju
 
Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8
PrinceGuru MS
 
The Joy of Smartmatch
The Joy of SmartmatchThe Joy of Smartmatch
The Joy of Smartmatch
Andrew Shitov
 
The Art Of Readable Code
The Art Of Readable CodeThe Art Of Readable Code
The Art Of Readable Code
Baidu, Inc.
 
Introduction to Twig
Introduction to TwigIntroduction to Twig
Introduction to Twig
markstory
 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 Integration
Jonathan Wage
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
Kang-min Liu
 

Tendances (20)

Beginning PHPUnit
Beginning PHPUnitBeginning PHPUnit
Beginning PHPUnit
 
Php security3895
Php security3895Php security3895
Php security3895
 
Functional Structures in PHP
Functional Structures in PHPFunctional Structures in PHP
Functional Structures in PHP
 
Dsl
DslDsl
Dsl
 
Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4Can't Miss Features of PHP 5.3 and 5.4
Can't Miss Features of PHP 5.3 and 5.4
 
Perl6 in-production
Perl6 in-productionPerl6 in-production
Perl6 in-production
 
Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8Corephpcomponentpresentation 1211425966721657-8
Corephpcomponentpresentation 1211425966721657-8
 
The Joy of Smartmatch
The Joy of SmartmatchThe Joy of Smartmatch
The Joy of Smartmatch
 
The Art Of Readable Code
The Art Of Readable CodeThe Art Of Readable Code
The Art Of Readable Code
 
Text in search queries with examples in Perl 6
Text in search queries with examples in Perl 6Text in search queries with examples in Perl 6
Text in search queries with examples in Perl 6
 
Introduction to Twig
Introduction to TwigIntroduction to Twig
Introduction to Twig
 
Improving Dev Assistant
Improving Dev AssistantImproving Dev Assistant
Improving Dev Assistant
 
(Parameterized) Roles
(Parameterized) Roles(Parameterized) Roles
(Parameterized) Roles
 
Zend Certification Preparation Tutorial
Zend Certification Preparation TutorialZend Certification Preparation Tutorial
Zend Certification Preparation Tutorial
 
Symfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 IntegrationSymfony2 and Doctrine2 Integration
Symfony2 and Doctrine2 Integration
 
Smarty
SmartySmarty
Smarty
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
The art of readable code (ch1~ch4)
The art of readable code (ch1~ch4)The art of readable code (ch1~ch4)
The art of readable code (ch1~ch4)
 
Perl6 grammars
Perl6 grammarsPerl6 grammars
Perl6 grammars
 
Making the most of 2.2
Making the most of 2.2Making the most of 2.2
Making the most of 2.2
 

Similaire à Creating "Secure" PHP Applications, Part 1, Explicit Code & QA

Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
Michelangelo van Dam
 
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
smueller_sandsmedia
 

Similaire à Creating "Secure" PHP Applications, Part 1, Explicit Code & QA (20)

Building Testable PHP Applications
Building Testable PHP ApplicationsBuilding Testable PHP Applications
Building Testable PHP Applications
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
Fatc
FatcFatc
Fatc
 
PHP Unit Testing
PHP Unit TestingPHP Unit Testing
PHP Unit Testing
 
Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8Unit testing after Zend Framework 1.8
Unit testing after Zend Framework 1.8
 
Unit testing with zend framework tek11
Unit testing with zend framework tek11Unit testing with zend framework tek11
Unit testing with zend framework tek11
 
Unit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBeneluxUnit testing with zend framework PHPBenelux
Unit testing with zend framework PHPBenelux
 
Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12Workshop quality assurance for php projects tek12
Workshop quality assurance for php projects tek12
 
Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012Quality Assurance for PHP projects - ZendCon 2012
Quality Assurance for PHP projects - ZendCon 2012
 
Quality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStormQuality assurance for php projects with PHPStorm
Quality assurance for php projects with PHPStorm
 
Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13Load Testing with PHP and RedLine13
Load Testing with PHP and RedLine13
 
Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
Kicking off with Zend Expressive and Doctrine ORM (PHPNW2016)
 
OWASP Top 10 - DrupalCon Amsterdam 2019
OWASP Top 10 - DrupalCon Amsterdam 2019OWASP Top 10 - DrupalCon Amsterdam 2019
OWASP Top 10 - DrupalCon Amsterdam 2019
 
Prepared Statement 올바르게 사용하기
Prepared Statement 올바르게 사용하기Prepared Statement 올바르게 사용하기
Prepared Statement 올바르게 사용하기
 
Zend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_ToolZend Framework 1.9 Setup & Using Zend_Tool
Zend Framework 1.9 Setup & Using Zend_Tool
 
Automated code audits
Automated code auditsAutomated code audits
Automated code audits
 
Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)Best Practices in Plugin Development (WordCamp Seattle)
Best Practices in Plugin Development (WordCamp Seattle)
 
Php unit the-mostunknownparts
Php unit the-mostunknownpartsPhp unit the-mostunknownparts
Php unit the-mostunknownparts
 
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnitinternational PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
international PHP2011_Bastian Feder_The most unknown Parts of PHPUnit
 
PHPunit and you
PHPunit and youPHPunit and you
PHPunit and you
 

Dernier

CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
giselly40
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
vu2urc
 

Dernier (20)

The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Tech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdfTech Trends Report 2024 Future Today Institute.pdf
Tech Trends Report 2024 Future Today Institute.pdf
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 

Creating "Secure" PHP Applications, Part 1, Explicit Code & QA

  • 2. So, who are you, anyway? Bryan C. Geraghty Security Consultant at Security PS @archwisp I’m a Sr. PHP developer with a systems and security engineering background - turned application security consultant
  • 3. Remember, layers Simpler is easier to test Don’t make assumptions Compromised browser = game over
  • 4. These are not specifically security activities but they produce more stable code
  • 5. Don’t rely on the server’s configuration Your bootstrap should Absolute Minimum set the defaults for any  Include paths PHP core functionality  Error reporting that your application is  Time zones using. These must be customizable for every environment e.g. (dev, staging, live)
  • 6. Example Bootstrap <?php // All environment configuration for this application is done from this file ini_set('display_errors', 0); ini_set('error_reporting', -1); date_default_timezone_set('UTC'); $rootPath = dirname(__FILE__); set_include_path(sprintf( '%s%s%s%s', $rootPath, PATH_SEPARATOR, $rootPath, '/third-party' )); require_once('MindFrame2/AutoLoad.php'); MindFrame2_AutoLoad::install();
  • 7.
  • 8. Don’t use global constants, variables, or registries  You can’t be certain that nobody else will ever use the same global constant name  Tracking down where a value is assigned to a global variable is usually very difficult  Global variables remove control of that variable from the current scope  Global registries are really just fancy global variables and the same problems apply
  • 9. Value Reference Rules  Values should only be referenced in one of the following ways:  A direct reference in the current scope: $limit = $this->_objectPool->getConfig()- >getDefaultLimit();  A parameter: public function getUsers($limit) { return $this->_objectPool- >getMapper(‘User’)->fetchAll($limit); }
  • 10. Don’t use function parameter defaults "There should be one-- and preferably only one -- obvious way to do it." - Tim Peters  Reduces understanding from the caller perspective  Often add unnecessary complexity  Represents the most common use-case  Other use-cases are often ignored entirely  Changing the default breaks all implementations  Adding parameters breaks default implementations
  • 11. Default parameter example class User { public function __construct($name, $email, $status = self::STATUS_ACTIVE) { $this->_name = $name; $this->_email = $email; $this->_status = $status; } } function createUser($name, $email, $status) { $user = new User($name, email); return $this->_objectPoool->getMapper(‘User’)->create($user); }
  • 12. Use explicit operators whenever possible This was actual production code. if ($sincedate && (int)$sincedate) { $param["UpdatedSinceDate"] = date("Y-m-d H:i:s", strtotime(time() - ((int)$sincedate)*60*60); } elseif ($sincedate && strtotime($sincedate)) { $param["UpdatedSinceDate"] = date("Y-m-d H:i:s", strtotime($sincedate)); } elseif(!isset($param["UpdatedSinceDate"])) { exit ("Invalid param UpdatedSinceDate"); } Do you think this code worked as the author intended when $sincedate was set to '2011-05-31'?
  • 13. Use constants for possible values Constants cannot be re-defined, so using a constant for configuration limits your code to only ever be able to run in one configuration in a given stack. // Bad: This code cannot execute differently in the same stack define(‘PDO_FETCH_MODE’, 2); $dbi->fetchAll(PDO_FETCH_MODE); // Better: The value can change but this literal value means nothing without // referencing the documentation $dbi->fetchAll(2); // Best: Implemented using a meaningful constant which represents a *possible* value $dbi->fetchAll(PDO::FETCH_ASSOC);
  • 14. Use wrappers for super-globals  $_REQUEST, $_GET, $_SESSION, and $_FILES are the most commonly used PHP super-globals but there are others  It’s easy to create some serious security problems  It’s best to use a wrapper for interacting with these variables
  • 15. Simulate strong/static types PHP is dynamically typed, so we cannot do true strong or static typing but we can put controls in place which provide the same protection. private function _buildSelectDatabaseTableSql($database_name, $table_name, array $select_data, array $order_by_columns, $offset, $limit) { MindFrame2_Core::assertArgumentIsNotBlank($database_name, 1, 'database_name'); MindFrame2_Core::assertArgumentIsNotBlank($table_name, 2, 'table_name'); MindFrame2_Core::assertArgumentIsInt($offset, 5, 'offset'); MindFrame2_Core::assertArgumentIsInt($limit, 6, 'limit'); $skel = "SELECTn %snFROMn %s.%sn%s%s%s%s;"; $sql = sprintf($skel, $this->_buildSelectTableSqlFieldClause($table_name), $this->getSharedModule()->escapeDbElementName($database_name), $this->getSharedModule()->escapeDbElementName($table_name), $this->_buildSelectTableSqlJoinClause( $this->getSharedModule()->getDatabase()->getName(), $table_name), $this->_buildSelectTableSqlWhereClause($table_name, $select_data), $this->_buildSelectTableSqlOrderByClause( $table_name, $order_by_columns), $this->_buildSelectTableSqlLimitClause($offset, $limit)); return $sql; }
  • 16. Example Typing Assertions public static function assertArgumentIsInt($value, $position, $name) { if (!is_int($value)) { $skel = 'Expected integer value for argument #%d (%s), %s given'; $message = sprintf($skel, $position, $name, gettype($value)); throw new InvalidArgumentException($message); } } public static function assertArgumentIsNotBlank($value, $position, $name) { if (trim($value) === '') { $skel = 'Argument #%d (%s) cannot be blank'; $message = sprintf($skel, $position, $name); throw new InvalidArgumentException($message); } }
  • 17. Use PHPMD & CodeSniffer This is the ./bin/codecheck script in MindFrame2 #!/bin/bash WD="`/usr/bin/dirname $0`/../"; echo Changing to working directory: $WD; cd $WD; if [ -z $1 ]; then DIR='.'; else DIR=$1; fi phpmd --exclude coverage $DIR text codesize,unusedcode,naming,design phpcs --ignore=coverage --standard=`pwd`/Standards/MindFrame2 $DIR phpcs --ignore=coverage --report=source --standard=`pwd`/Standards/MindFrame2 $DIR
  • 18. Example PHPMD Output bryan@ubuntu-virtual ~/Code/MindFrame2 [130] $ ./bin/codecheck Dbms/Dbi Changing to working directory: ./bin/../ /home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:128 Avoid unused local variables such as '$partner'. /home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:185 Avoid unused local variables such as '$data'. /home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:199 Avoid unused local variables such as '$index'. /home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:240 Avoid unused private methods such as '_buildReplicaDatabaseSuffix'. /home/bryan/Code/MindFrame2/Dbms/Dbi/Single.php:25 This class has too many methods, consider refactoring it. /home/bryan/Code/MindFrame2/Dbms/Dbi/Single.php:150 Avoid unused parameters such as '$options'.
  • 19. Example PHPCS Output FILE: /home/bryan/Code/MindFrame2/Dbms/Dbi/Single.php -------------------------------------------------------------------------------- FOUND 6 ERROR(S) AFFECTING 6 LINE(S) -------------------------------------------------------------------------------- 39 | ERROR | Public member variables ("_connection") are forbidden 62 | ERROR | Whitespace found at end of line 144 | ERROR | Whitespace found at end of line 160 | ERROR | Line exceeds maximum limit of 80 characters; contains 97 | | characters 195 | ERROR | Whitespace found at end of line 298 | ERROR | Line exceeds maximum limit of 80 characters; contains 81 | | characters --------------------------------------------------------------------------------
  • 20. Unit testing / TDD  Test critical functionality at a minimum  Add edge cases to regression tests as they are discovered  Test-driven development only works if the entire team is dedicated to it  I personally don’t trust code that isn’t regression-tested; even if it was written by me
  • 21. Continuous Integration  Automated system for code analysis and regression testing  There are a lot of continuous integration systems for PHP  If your tests aren’t automated, very few people will know or care when they break
  • 22. Deployment  Manually copying files is riddled with problems  Tagging releases and re-deploying is a complicated and time-consuming process  Deployment systems automate the build and deployment process
  • 24. If you’re interested in an application security career, come talk with me.