Modern and Secure PHP (SoutheastPHP 2018)

Modern and Secure PHP (SoutheastPHP 2018)

This is not the PHP of old. Learn what's changed in the PHP world over the last few years. Classes, objects, statics, traits, unit testing, composer, password hashing, standards; it's a whole new ballgame.

22f21d5c22b930fd35dd98f25dedf6a4?s=128

Ben Edmunds

August 17, 2018
Tweet

Transcript

  1. PHP modern & secure

  2. Who is this guy? Ben Edmunds Open Source Author PHP

    Town Hall Podcast CTO at Mindfulware
  3. Who is this guy? Ben Edmunds @benedmunds http://benedmunds.com

  4. Welcome to the Future

  5. Great Scott!

  6. Welcome to the Future PDO Closures Namespaces

  7. Welcome to the Future Anonymous Classes Traits Interfaces

  8. Welcome to the Future Null Coalescing Scalar Type Hints Return

    Type Declarations
  9. Welcome to the Future Variadic Functions Authentication Password Hasing

  10. Welcome to the Future SQL Injection HTTPS

  11. Welcome to the Future Common Hacks

  12. Legit Tools Built-in Server Composer Unit Testing

  13. Standards PHP-FIG PSRs

  14. Exceptions

  15. None
  16. Exceptions try { //your code goes here } catch (Exception

    $e) { die($e->getMessage()); }
  17. Exceptions try { //your code goes here } catch (Exception

    $e) { die($e->getMessage()); }
  18. Errors Exception implements Throwable Error implements Throwable

  19. Errors try { //error thrown here } catch (Error $e)

    { die($e->getMessage()); }
  20. Errors try { //error thrown here } catch (Error $e)

    { die($e->getMessage()); } catch (Exception $e) { die($e->getMessage()); }
  21. Errors try { //err or excpt thrown here } catch

    (Throwable $t) { die($t->getMessage()); }
  22. Errors try { //error or excpt thrown here } catch

    (Error | Exception $e) { die($e->getMessage()); }
  23. Namespaces

  24. None
  25. Namespaces namespace Illuminate\Console; class Command { //…

  26. Namespaces use Illuminate\Console\Command; namespace Illuminate\Console; class Command { //…

  27. Namespaces use Illuminate\Console\Command; namespace Illuminate\Console; class Command { //…

  28. PDO

  29. None
  30. PDO Cross System Safe Binding

  31. PDO $stmt = $db->prepare(‘ SELECT * FROM users WHERE id=:id

    ’); $stmt->bindParam(‘:id’, $id); $stmt->execute();
  32. Traits

  33. Traits // grouping without // strict inheritance trait baseUser {

    function getName() { return ‘Jon Snow’; } }
  34. Traits class adminUser { use baseUser; }

  35. Traits $adminUser = new adminUser; echo $adminUser->getName(); //output = ‘Jon

    Snow’
  36. Traits trait Loggable { function log($msg) { echo $msg; }

    }
  37. Traits class Post { function get($id) { return $this->db->get($id); }

    }
  38. Traits class Post { use Loggable; function get($id) { $this->log('Getting

    post ' . $id); return $this->db->get($id); } }
  39. Traits $postModel = new Post; $myPost = $postModel->get(1); //output =

    ‘Getting post 1’
  40. Traits class Post extends Model { use SoftDeletes; }

  41. Interfaces

  42. Interface Class myLogger { public function log($msg) { echo $msg;

    } }
  43. Interface interface Logger { public function log($msg); }

  44. Interface Class myLogger implements Logger { public function log($msg) {

    echo $msg; } }
  45. Closures

  46. None
  47. Closures Route::get(‘/', function(){ return View::make(‘index'); });

  48. Closures Route::get(‘/', function(){ return View::make(‘index'); });

  49. Closures $input = [1, 2, 3, 4, 5, 6, 7,

    8]; $output = array_filter($input, function($v){ return $v > 5; }); // [6,7,8]
  50. Closures $input = [1, 2, 3, 4, 5, 6, 7,

    8]; $output = array_map(function($n){ return number_format($n * 10, 2) . '%'; }, array_filter($input, function($v){ return $v > 5; })); // ['60.00%', '70.00%', '80.00%']
  51. Anonymous Classes

  52. Anonymous Classes trait Loggable { function log($msg) { echo $msg;

    } }
  53. Anonymous Classes interface Logger { public function log($msg); }

  54. Anonymous Classes trait Loggable { protected $logger; function setLogger(Logger $logger)

    { $this->logger = $logger; } function log($msg) { $this->logger->log($msg); } }
  55. Anonymous Classes class Post { use Loggable; } $post =

    new Post;
  56. Anonymous Classes class Post { use Loggable; } $post =

    new Post; $post->setLogger( new class implements Logger { public function log($msg) { echo date('m/d G:i') . ': ' .$msg; } });
  57. Anonymous Classes $postModel = new Post; $myPost = $postModel->get(1); //output

    = ‘09/08 16:20: Getting post 1’
  58. Null Coalescing Operator

  59. Null Coalescing $val = isset($_GET[‘val’]) ? $_GET[‘val’] : 'default';

  60. Null Coalescing $val = $_GET['val'] ?? 'default';

  61. Null Coalescing $val = $_GET['val'] ?? 'default';

  62. Types!

  63. None
  64. Scalar Type Hinting

  65. Types declare(strict_types=1); function addNums(float $a, float $b) { return $a

    + $b; }
  66. Types declare(strict_types=1); function addNums(float $a, float $b) { return $a

    + $b; } addNums(2, "1 week"); // Fatal error: Uncaught TypeError: Argument 2 passed to addNums() must be of the type float, string given
  67. Types function addNums(float $a, float $b) addNums(2, "1 week”); //

    Fatal error: Uncaught TypeError: Argument 2 passed to addNums() must be of the type float, string given
  68. Types try { addNums(2, "1 week”); } catch(TypeError $e) {}

  69. Types try { addNums(2, 1); } catch(TypeError $e) {} //3

  70. Types class/interface array callable bool float int string object

  71. Return Type Declarations

  72. Types function addNums(float $a, float $b) : int { return

    $a + $b; }
  73. Types function addNums(float $a, float $b) : int { return

    $a + $b; }
  74. Types function addNums($a, $b) : int { return $a +

    $b; } addNums(1.5, 1); // Fatal error: Uncaught TypeError: Return value of addNums() must be of the type integer, float returned
  75. Types function addNums(float $a, ?float $b) : int { return

    $a + $b??0; } addNums(1, null); // int(1)
  76. Types function addNums(float $a, ?float $b) : ?int { return

    $a + $b??0; } addNums(1, null); // int(1)
  77. Types public function log($msg) : void { Logger::write($msg); }

  78. Variadic Functions

  79. Scalar Types function addNums(float $a, float $b) : int {

    return $a + $b; }
  80. Variadic Functions function addNums(...$numbers) : int { return array_sum($numbers); }

    addNums(1, 2, 3, 4); // int(10)
  81. Variadic Functions function addNums(float …$numbers) : int { return array_sum($numbers);

    } addNums(1, 2, 3, 4); // int(10)
  82. Security

  83. None
  84. HTTPS

  85. HTTPS Encrypts traffic across the wire Trusted send and receiver

    Required by OAUTH 2
  86. HTTPS https://letsencrypt.org/

  87. Authentication

  88. Security //authentication - access control if (!$user->inGroup(‘admin’)) { return ‘ERROR

    YO’; }
  89. Security //authentication - brute force if ($user->loginAttempts > 5) {

    return ‘CAUGHT YA’; }
  90. Passwords

  91. Passwords //safe password hashing password_hash($_POST['pass'], ALGO);

  92. Passwords //safe password hashing password_hash($_POST['pass'], ALGO); //password verification password_verify($_POST['pass'], $u->pass);

  93. Passwords //safe password hashing password_hash($_POST['pass'], ALGO); //password verification password_verify($_POST['pass'], $u->pass);

    //password rehashing password_needs_rehash($u->pass, ALGO);
  94. Passwords if (password_verify($_POST['pass'], $u->pass)) { if (password_needs_rehash( $u->pass, PASSWORD_DEFAULT ))

    { $u->pass = password_hash( $_POST['pass'], PASSWORD_DEFAULT ); $u->save();
  95. Safe Defaults

  96. Security //safe defaults class Your Controller { protected $var1 =

    ‘default value’; function __construct() { … } }
  97. Security //safe defaults $something = false; foreach ($array as $k

    => $v) { $something = $v->foo; if ($something == ‘bar’) { … } }
  98. Security function addNums(float $a, float $b) : int { return

    $a + $b; } $something = []; foreach ($array as $v) { $something[] = addNums($v[0], $v[1]) }
  99. Common Hacks

  100. Security //Non-Persistent XSS http://www.yourSite.com/ ?page_num=2&per_page=50 Send the link to someone,

    boom
  101. Security //Persistent XSS Same idea, except with data that is

    saved to the server and re-displayed
  102. Security //escaping input $stmt->bindParam(‘:id’, $id);

  103. Security //escaping input $stmt->bindParam(‘:id’, $id); //escaping output htmlentities($_POST[‘name’]);

  104. Security //escaping input Class myModel extend Model { function save($id)

    { $stmt = $this->query->insert(); $stmt->bindParam(‘:id’, $id); $stmt->execute(); } }
  105. Security //escaping output <h1>Title</h1> Hello <?=htmlentities($name)?>

  106. Security //Cross Site Request Forgery //(CSRF) http://yourSite.com/ users/12/delete

  107. Security //CSRF Protection POST / PUT / UPDATE / DELETE

    behind forms with one-time use tokens
  108. Security //CSRF Protection function generateCsrf() { $token = mcrypt_create_iv( 16,

    MCRYPT_DEV_URANDOM); Session::flash('csrfToken', $token); return $token; }
  109. Security //CSRF Protection function generateCsrf() { $token = bin2hex(random_bytes(16)); Session::flash('csrfToken',

    $token); return $token; }
  110. Security //CSRF Protection if ( $_POST['token'] == Session::get(‘csrfToken') ) {

    … }
  111. Legit Tools

  112. None
  113. Built-in Web Server

  114. Built-in Server $ php -S localhost:8000 PHP 5.7.0 Development Server

    started… Listening on localhost:8000 Document root is /home/ben/htdocs Press Ctrl-C to quit
  115. Composer

  116. Another Package Manager!?

  117. Composer Sane Package Management Autoloading via PSR4

  118. Composer / composer.json { "require": { "stripe/stripe-php": "dev-master", "twilio/sdk": "dev-master"

    } }
  119. Composer $ php composer.phar install -> composer.lock

  120. Composer $ php composer.phar install -> composer.lock Commit it ^

  121. Composer $ php composer.phar install /composer.lock

  122. Composer $ php composer.phar update /composer.json

  123. Composer $client = new Services_Twilio($sid, $tkn); $client->account ->messages ->sendMessage(…)

  124. Unit Testing

  125. None
  126. Unit Testing PHPUnit Behat Mink Selenium CodeCeption PHPSpec

  127. Unit Testing class ApiAuthTest extends PHPUnit_Framework_TestCase { public function testVerify()

    { $auth = new apiAuth(); $this->assertTrue($auth->verify());
  128. Unit Testing class ApiAuthTest extends PHPUnit_Framework_TestCase { public function testVerify()

    { $auth = new apiAuth(); $this->assertTrue($auth->verify());
  129. Unit Testing $ phpunit tests PHPUnit 3.3.17 by Sebastian Bergmann.

    Time: 0.01 seconds OK (1 tests, 1 assertions)
  130. Standards

  131. None
  132. Standards PHP-FIG Framework Interop Group

  133. Standards Member Projects Zend Symfony CakePHP Magento Joomla Drupal

  134. Standards PSRs PHP Standards Recommendation

  135. Standards PSRs Autoloading Interfaces Style Guides

  136. Standards PSRs PSR-4: Autoloading PSR-1: Basic Coding Standards PSR-2: Coding

    Style Guide PSR-7: HTTP Message Interface PSR-6: Caching Interface PSR-3: Logger Interface
  137. Resources

  138. None
  139. Resources PHP.net

  140. Resources Modern Frameworks Laravel Symfony2 SlimPHP Cake PHP

  141. Resources leanpub.com/ phptherightway PHPtheRightWay.com

  142. Resources Give Me $$$ SecuringPhpApps.com SecuringNodeApps.com

  143. Q/A TIME! https://joind.in/talk/83929 Ben Edmunds @benedmunds