SlideShare uma empresa Scribd logo
1 de 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.

Mais conteúdo relacionado

Mais procurados

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
 

Mais procurados (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
 

Semelhante a 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
 

Semelhante a 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
 

Último

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Victor Rentea
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 

Último (20)

Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024Finding Java's Hidden Performance Traps @ DevoxxUK 2024
Finding Java's Hidden Performance Traps @ DevoxxUK 2024
 
Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)Introduction to Multilingual Retrieval Augmented Generation (RAG)
Introduction to Multilingual Retrieval Augmented Generation (RAG)
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
AI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by AnitarajAI in Action: Real World Use Cases by Anitaraj
AI in Action: Real World Use Cases by Anitaraj
 
Platformless Horizons for Digital Adaptability
Platformless Horizons for Digital AdaptabilityPlatformless Horizons for Digital Adaptability
Platformless Horizons for Digital Adaptability
 
JohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptxJohnPollard-hybrid-app-RailsConf2024.pptx
JohnPollard-hybrid-app-RailsConf2024.pptx
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
DBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor PresentationDBX First Quarter 2024 Investor Presentation
DBX First Quarter 2024 Investor Presentation
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
Apidays New York 2024 - Passkeys: Developing APIs to enable passwordless auth...
 
Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..Understanding the FAA Part 107 License ..
Understanding the FAA Part 107 License ..
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 

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.