Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Explicit Code & QA
So, who are you, anyway?                  Bryan C. Geraghty          Security Consultant at Security PS                   ...
Remember, layersSimpler is easier to testDon’t make assumptionsCompromised browser = game over
These are not specifically security activities but they produce morestable code
Don’t rely on the server’s configuration  Your bootstrap should       Absolute Minimum  set the defaults for any     Incl...
Example Bootstrap<?php// All environment configuration for this application is done from this fileini_set(display_errors, ...
Don’t use global constants, variables, or registries You can’t be certain that nobody else will ever use the  same global...
Value Reference Rules Values should only be referenced in one of the following  ways:   A direct reference in the curren...
Don’t use function parameter defaults   "There should be one-- and preferably only one --   obvious way to do it." - Tim P...
Default parameter exampleclass User{   public function __construct($name, $email, $status = self::STATUS_ACTIVE) {        ...
Use explicit operators whenever possibleThis was actual production code.if ($sincedate && (int)$sincedate) { $param["Updat...
Use constants for possible valuesConstants cannot be re-defined, so using a constant for configuration limits your codeto ...
Use wrappers for super-globals $_REQUEST, $_GET, $_SESSION, and $_FILES are the most  commonly used PHP super-globals but...
Simulate strong/static typesPHP is dynamically typed, so we cannot do true strong or static typing but we canput controls ...
Example Typing Assertionspublic static function assertArgumentIsInt($value, $position, $name){   if (!is_int($value)) {   ...
Use PHPMD & CodeSnifferThis is the ./bin/codecheck script in MindFrame2#!/bin/bashWD="`/usr/bin/dirname $0`/../";echo Chan...
Example PHPMD Outputbryan@ubuntu-virtual ~/Code/MindFrame2 [130] $ ./bin/codecheck Dbms/DbiChanging to working directory: ...
Example PHPCS OutputFILE: /home/bryan/Code/MindFrame2/Dbms/Dbi/Single.php-------------------------------------------------...
Unit testing / TDD Test critical functionality at a minimum Add edge cases to regression tests as they are discovered T...
Continuous Integration Automated system for code analysis and regression  testing There are a lot of continuous integrat...
Deployment Manually copying files is riddled with problems Tagging releases and re-deploying is a complicated and  time-...
ACLsMACThread limitsUnwanted services
If you’re interested in an application security career, come talk withme.
Creating "Secure" PHP Applications, Part 1, Explicit Code & QA
Upcoming SlideShare
Loading in …5
×

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

2,430 views

Published on

Published in: Technology
  • Be the first to comment

  • Be the first to like this

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

  1. 1. Explicit Code & QA
  2. 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. 3. Remember, layersSimpler is easier to testDon’t make assumptionsCompromised browser = game over
  4. 4. These are not specifically security activities but they produce morestable code
  5. 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. 6. Example Bootstrap<?php// All environment configuration for this application is done from this fileini_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. 7. 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
  8. 8. 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); }
  9. 9. 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
  10. 10. Default parameter exampleclass 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);}
  11. 11. Use explicit operators whenever possibleThis 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 to2011-05-31?
  12. 12. Use constants for possible valuesConstants cannot be re-defined, so using a constant for configuration limits your codeto only ever be able to run in one configuration in a given stack.// Bad: This code cannot execute differently in the same stackdefine(‘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);
  13. 13. 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
  14. 14. Simulate strong/static typesPHP is dynamically typed, so we cannot do true strong or static typing but we canput 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; }
  15. 15. Example Typing Assertionspublic 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); }}
  16. 16. Use PHPMD & CodeSnifferThis is the ./bin/codecheck script in MindFrame2#!/bin/bashWD="`/usr/bin/dirname $0`/../";echo Changing to working directory: $WD;cd $WD;if [ -z $1 ]; then DIR=.;else DIR=$1;fiphpmd --exclude coverage $DIR text codesize,unusedcode,naming,designphpcs --ignore=coverage --standard=`pwd`/Standards/MindFrame2 $DIRphpcs --ignore=coverage --report=source --standard=`pwd`/Standards/MindFrame2 $DIR
  17. 17. Example PHPMD Outputbryan@ubuntu-virtual ~/Code/MindFrame2 [130] $ ./bin/codecheck Dbms/DbiChanging to working directory: ./bin/..//home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:128 Avoid unused localvariables such as $partner./home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:185 Avoid unused localvariables such as $data./home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:199 Avoid unused localvariables such as $index./home/bryan/Code/MindFrame2/Dbms/Dbi/Distributed.php:240 Avoid unused privatemethods such as _buildReplicaDatabaseSuffix./home/bryan/Code/MindFrame2/Dbms/Dbi/Single.php:25 This class has too manymethods, consider refactoring it./home/bryan/Code/MindFrame2/Dbms/Dbi/Single.php:150 Avoid unused parameters such as$options.
  18. 18. Example PHPCS OutputFILE: /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--------------------------------------------------------------------------------
  19. 19. 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
  20. 20. 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
  21. 21. 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
  22. 22. ACLsMACThread limitsUnwanted services
  23. 23. If you’re interested in an application security career, come talk withme.

×