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! - DrupalCamp Oslo, 2018

91 views

Published on

Slides of the Drupal security related session at DrupalCamp Oslo - 10 November 2018.

Published in: Software
  • Be the first to comment

  • Be the first to like this

Let's write secure Drupal code! - DrupalCamp Oslo, 2018

  1. 1. Let’s write secure Drupal code! Balazs Janos Tatar DrupalCamp Oslo 2018
  2. 2. Thanks Sponsors!
  3. 3. Who am I? Tatar Balazs Janos @tatarbj Hungarian, lives in Brussels Works with Drupal since 2007 Provisional Member of Drupal Security Team IT Security Analyst, Drupal Security Correspondent @ EC... And a cat-gif addict
  4. 4. Are there site builders?
  5. 5. Demo
  6. 6. Gist http://bit.ly/oslo_writes_secure_drupal_code
  7. 7. Are there developers/maintainers?
  8. 8. Trends in Security
  9. 9. Types of vulnerabilities
  10. 10. Cross Site Scripting
  11. 11. Client side vulnerability Unfiltered output Never trust any user input. We’ve seen the demo before ;) Cross Site Scripting
  12. 12. Html::escape() – plain text Xss::filter() – html is allowed Xss::filterAdmin() – text by admins
  13. 13. Test
  14. 14. Raise your green card if snippet is secure! Raise your red card if code has issues!
  15. 15. <?php print '<tr><td>' . check_plain($title) . '</td></tr>'; ?>
  16. 16. <?php print '<tr><td>' . check_plain($title) . '</td></tr>'; ?>
  17. 17. <?php print '<a href="/' . check_plain($url) . '">'; ?>
  18. 18. <?php print '<a href="/' . check_plain($url) . '">'; ?>
  19. 19. <?php print '<a href="/' . check_url($url) . '">'; ?>
  20. 20. 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;
  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 = [ '#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;
  23. 23. 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
  24. 24. Access Bypass
  25. 25. User can access/do something. Menu items can be defined to be accessed/denied. Many access systems: node, entity, field, views... Access bypass
  26. 26. Test II.
  27. 27. <?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; } ?>
  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 $query = db_select('node', 'n') ->fields('n', array('title', 'nid') ->condition('type', 'article'); $result = $query->execute(); ?>
  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') ->addTag('node_access'); $result = $query->execute(); ?>
  32. 32. mymodule.not_found: path: '/not-found' defaults: _controller: DrupalmymoduleControllerNotFoundController::build404 _title: 'Page not found' requirements: _access: 'TRUE'
  33. 33. mymodule.not_found: path: '/not-found' defaults: _controller: DrupalmymoduleControllerNotFoundController::build404' _title: 'Page not found' requirements: _access: 'TRUE'
  34. 34. 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
  35. 35. SQL Injection
  36. 36. Unauthorized access to database resources. Do not trust any user input. SA-CORE-2014-005 – Highly critical D7 SA SQL Injection
  37. 37. Test III.
  38. 38. <?php $results = db_query("SELECT uid, name, mail FROM {users} WHERE name LIKE '%%$user_search%%'"); ?>
  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", array(':user_search' => '%' . db_like($user_search))); ?>
  41. 41. 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
  42. 42. Security Improvements
  43. 43. *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
  44. 44. Learn by Advisories
  45. 45. 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
  46. 46. 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
  47. 47. Questions?
  48. 48. Tatar Balazs Janos @tatarbj Thank you!

×