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.

Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany

325 views

Published on

Slides of the 'Let's write secure Drupal code!' session in Darmstadt, Germany at Drupal Europe in 2018.

Published in: Technology
  • Be the first to comment

Let's write secure Drupal code! - 13.09.2018 @ Drupal Europe, Darmstadt, Germany

  1. 1. www.drupaleurope.org
  2. 2. Let’s write secure Drupal code! Balazs Janos Tatar
  3. 3. Drupal + Technology 17/3/2018 TRACK SUPPORTED BY
  4. 4. Who am I? Tatar Balazs Janos @tatarbj Hungarian, lives in Brussels Works with Drupal since 2007 Provisional Member of Drupal Security Team Technical PM and former QA Lead @ EC-DIGIT
  5. 5. Are there site builders?
  6. 6. Demo
  7. 7. Gist https://gist.github.com/tatarbj/85d85cc934792ba78196393267fd0443
  8. 8. Are there developers/maintainers?
  9. 9. Trends in Security
  10. 10. Types of vulnerabilities
  11. 11. Cross Site Scripting
  12. 12. Client side vulnerability Unfiltered output Never trust any user input. We’ve seen the demo before ;) Cross Site Scripting
  13. 13. Html::escape() – plain text Xss::filter() – html is allowed Xss::filterAdmin() – text by admins
  14. 14. Test
  15. 15. Raise your green card if snippet is secure! Raise your red card if code has issues!
  16. 16. <?php print '<tr><td>' . check_plain($title) . '</td></tr>'; ?>
  17. 17. <?php print '<tr><td>' . check_plain($title) . '</td></tr>'; ?>
  18. 18. <?php print '<a href="/' . check_plain($url) . '">'; ?>
  19. 19. <?php print '<a href="/' . check_plain($url) . '">'; ?>
  20. 20. <?php print '<a href="/' . check_url($url) . '">'; ?>
  21. 21. foreach ($items as $delta => $item) { $id = $item->getValue()['target_id']; $content = Drupal::entityTypeManager() ->getStorage($entity_type_id) ->load($id); $body = $content->get('body_field')->getValue()[0]['value']; } $elements[$delta] = array( '#theme' => 'something_custom', '#body' => $body, ); return $elements;
  22. 22. foreach ($items as $delta => $item) { $id = $item->getValue()['target_id']; $content = Drupal::entityTypeManager() ->getStorage($entity_type_id) ->load($id); $body = $content->get('body_field')->getValue()[0]['value']; } $elements[$delta] = array( '#theme' => 'something_custom', '#body' => $body, ); return $elements;
  23. 23. foreach ($items as $delta => $item) { $id = $item->getValue()['target_id']; $content = Drupal::entityTypeManager() ->getStorage($entity_type_id) ->load($id); $body = [ '#type' => 'processed_text', '#text' => $content->get('body_field')->getValue()[0]['value'], '#format' => $content->get('body_field')->getValue()[0]['format'], ]; } $elements[$delta] = array( '#theme' => 'something_custom', '#body' => $body, ); return $elements;
  24. 24. Use behat/automated tests. <script>alert(‘XSS’)</script> <img src=“a” onerror=“alert(’title’)”> Check your filters and user roles. Do not give too many options to untrusted users! Protection against Cross Site Scripting
  25. 25. Access Bypass
  26. 26. User can access/do something. Menu items can be defined to be accessed/denied. Many access systems: node, entity, field, views... Access bypass
  27. 27. Test II.
  28. 28. <?php function mymodule_menu() { $items['admin/mymodule/settings'] = array( 'title' => 'Settings of my module', 'page callback' => 'drupal_get_form', 'page arguments' => array('mymodule_setting_form'), 'access arguments' => array('administer mymodule'), 'type' => MENU_LOCAL_ACTION, ); return $items; } ?>
  29. 29. <?php function mymodule_menu() { $items['admin/mymodule/settings'] = array( 'title' => 'Settings of my module', 'page callback' => 'drupal_get_form', 'page arguments' => array('mymodule_setting_form'), 'access arguments' => array('administer mymodule'), 'type' => MENU_LOCAL_ACTION, ); return $items; } ?>
  30. 30. <?php $query = db_select('node', 'n') ->fields('n', array('title', 'nid') ->condition('type', 'article'); $result = $query->execute(); ?>
  31. 31. <?php $query = db_select('node', 'n') ->fields('n', array('title', 'nid') ->condition('type', 'article'); $result = $query->execute(); ?>
  32. 32. <?php $query = db_select('node', 'n') ->fields('n', array('title', 'nid') ->condition('type', 'article') ->addTag('node_access'); $result = $query->execute(); ?>
  33. 33. mymodule.not_found: path: '/not-found' defaults: _controller: DrupalmymoduleControllerNotFoundController::build404 _title: 'Page not found' requirements: _access: 'TRUE'
  34. 34. mymodule.not_found: path: '/not-found' defaults: _controller: DrupalmymoduleControllerNotFoundController::build404' _title: 'Page not found' requirements: _access: 'TRUE'
  35. 35. Visit node/nid and other urls Visit anything/%node Use behat/automated tests. node_access, entity_access Menu definitions user_access for permissions $query->addTag('node_access') Protection against Access bypass
  36. 36. SQL Injection
  37. 37. Unauthorized access to database resources. Do not trust any user input. SA-CORE-2014-005 – Highly critical D7 SA SQL Injection
  38. 38. Test III.
  39. 39. <?php $results = db_query("SELECT uid, name, mail FROM {users} WHERE name LIKE '%%$user_search%%'"); ?>
  40. 40. <?php $results = db_query("SELECT uid, name, mail FROM {users} WHERE name LIKE '%%$user_search%%'"); ?>
  41. 41. <?php $results = db_query("SELECT uid, name, mail FROM {users} WHERE name LIKE :user_search", array(':user_search' => '%' . db_like($user_search))); ?>
  42. 42. Use always drupal Database API! db_query with :placeholder (deprecated in D8, in D9 will be removed) Filter parameters Check the queries in code. username' AND 1=1 POST requests by curl Protection against SQL Injection
  43. 43. Security Improvements
  44. 44. *https://events.drupal.org/sites/default/files/slides/pwolanin-2017-09-ways-drupal8-d.pdf Many ways Drupal 8 is more secure! Twig templates for HTML generation Removed PHP format Site configuration exportable, versionable User content entry and filtering improvements User session and sessio always n ID handling Automated CSRF token protection Trusted host patterns enforced for requests Single statement execution for SQL Clickjacking protection Content security policy compatibility with Core Javascript API
  45. 45. Learn by Advisories
  46. 46. Security advisories are for Only stable modules No alpha, beta, dev d.org hosted modules @Maintainers: If you are contacted, be supportive!  Drupal Security Team
  47. 47. Hacked! Security review (simplytest.me) Password policy Encrypt Drop Guard Composer Security Checker Permission report Text format reported + PHPCS Drupal BestPractice Sniff Security related contribs
  48. 48. Become a Drupal contributor Friday from 9am ● First timers workshop ● Mentored contribution ● General contribution
  49. 49. Questions?
  50. 50. Tatar Balazs Janos @tatarbj Thank you!

×