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.
Upcoming SlideShare
What to Upload to SlideShare
What to Upload to SlideShare
Loading in …3
×
1 of 112

Let's write secure drupal code! - Drupal Camp Pannonia 2019

1

Share

Download to read offline

The 'Let's write secure drupal code!' session's slides given in Palic, Serbia at Drupal Camp Pannonia 2019.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

Let's write secure drupal code! - Drupal Camp Pannonia 2019

  1. 1. LET’S WRITE SECURE DRUPAL CODE! TATAR BALAZS JANOS DRUPAL CAMP PANNONIA PALIC, SERBIA – 02.08.2019
  2. 2. Who am I? Tatar Balazs Janos @tatarbj Working with Drupal since 2007 CTO @ Petend Drupal Security Correspondent @ European Commission Provisional member @ Drupal Security Team SecOSdreamer @ Secure Open Source days (SecOSdays) Active mentor @ Mentoring community group
  3. 3. TatarBalazsJanos - @tatarbj
  4. 4. Are there site builders? TatarBalazsJanos - @tatarbj
  5. 5. TatarBalazsJanos - @tatarbj
  6. 6. Demo TatarBalazsJanos - @tatarbj
  7. 7. Gist https://gist.github.com/tatarbj/52ef21d61e6b3d7ea1342275e98dcaa3 TatarBalazsJanos - @tatarbj
  8. 8. Are there developers/maintainers? TatarBalazsJanos - @tatarbj
  9. 9. Have you attended on a previous Let’s write secure Drupal code! session? TatarBalazsJanos - @tatarbj
  10. 10. DrupalCamp Antwerp 2017 DrupalCamp Ruhr 2018 DrupalDevDays 2018 Drupal Europe 2018 DrupalCamp Oslo 2018 DrupalCamp London 2019 Drupal Mountain Camp 2019 DrupalCamp Spain 2019 DrupalCamp Belarus 2019 DrupalCamp Kyiv 2019 DrupalCamp Poland 2019 DrupalCamp Pannonia 2019 History TatarBalazsJanos - @tatarbj
  11. 11. Trends in Security TatarBalazsJanos - @tatarbj
  12. 12. TatarBalazsJanos - @tatarbj
  13. 13. TatarBalazsJanos - @tatarbj
  14. 14. Types of vulnerabilities TatarBalazsJanos - @tatarbj
  15. 15. TatarBalazsJanos - @tatarbj
  16. 16. Cross Site Scripting TatarBalazsJanos - @tatarbj
  17. 17. Client side vulnerability Unfiltered output Never trust any user input. We’ve seen the demo before ;) Cross Site Scripting TatarBalazsJanos - @tatarbj
  18. 18. TatarBalazsJanos - @tatarbj
  19. 19. Html::escape() – plain text Xss::filter() – html is allowed Xss::filterAdmin() – text by admins TatarBalazsJanos - @tatarbj
  20. 20. Bingo TatarBalazsJanos - @tatarbj
  21. 21. Everyone has a bingo card (check your bag!) If you answer well, mark the number! Wrong answer = no number! First who shouts BINGO! wins the price! Rules and etiquette TatarBalazsJanos - @tatarbj
  22. 22. Round 1 TatarBalazsJanos - @tatarbj
  23. 23. function custom_field_formatter_view(...) { foreach ($items as $key => $value) { //... $element[$key] = array( '#type' => 'markup', '#markup' => t('<img src="!src" alt="@alt" />', array('!src' => $value['src'], '$alt' => $value['alt'])), ); //... } return $element; } TatarBalazsJanos - @tatarbj
  24. 24. function custom_field_formatter_view(...) { foreach ($items as $key => $value) { //... $element[$key] = array( '#type' => 'markup', '#markup' => t('<img src="!src" alt="@alt" />', array('!src' => $value['src'], '$alt' => $value['alt'])), ); //... } return $element; } TatarBalazsJanos - @tatarbj
  25. 25. function custom_field_formatter_view(...) { foreach ($items as $key => $value) { //... $element[$key] = array( '#type' => 'markup', '#markup' => t('<img src="@src" alt="@alt" />', array('@src' => $value['src'], '$alt' => $value['alt'])), ); //... } return $element; } TatarBalazsJanos - @tatarbj
  26. 26. 12 TatarBalazsJanos - @tatarbj
  27. 27. 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; TatarBalazsJanos - @tatarbj
  28. 28. 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; TatarBalazsJanos - @tatarbj
  29. 29. 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; TatarBalazsJanos - @tatarbj
  30. 30. 23 TatarBalazsJanos - @tatarbj
  31. 31. In Drupal 7 check_url() calls check_plain() to sanitize bad protocols properly. ? TatarBalazsJanos - @tatarbj
  32. 32. In Drupal 7 check_url() calls check_plain() to sanitize bad protocols properly. ? TatarBalazsJanos - @tatarbj
  33. 33. In Drupal 7 check_url() calls drupal_strip_dangerous_protocols() to sanitize bad protocols properly. ? TatarBalazsJanos - @tatarbj
  34. 34. 25 TatarBalazsJanos - @tatarbj
  35. 35. Drupal 8 allows Full HTML to be used by authenticated and administrator users. ? TatarBalazsJanos - @tatarbj
  36. 36. Drupal 8 allows Full HTML to be used by authenticated and administrator users. ? TatarBalazsJanos - @tatarbj
  37. 37. 17 TatarBalazsJanos - @tatarbj
  38. 38. TatarBalazsJanos - @tatarbj
  39. 39. 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 TatarBalazsJanos - @tatarbj
  40. 40. Access Bypass TatarBalazsJanos - @tatarbj
  41. 41. User can access/do something. Menu items can be defined to be accessed/denied. Many access systems: node, entity, field, views... Access bypass TatarBalazsJanos - @tatarbj
  42. 42. Round 2 TatarBalazsJanos - @tatarbj
  43. 43. <?php $query = db_select('node', 'n') ->fields('n', array('title', 'nid')) ->condition('type', 'article'); $result = $query->execute(); ?> TatarBalazsJanos - @tatarbj
  44. 44. <?php $query = db_select('node', 'n') ->fields('n', array('title', 'nid')) ->condition('type', 'article'); $result = $query->execute(); ?> TatarBalazsJanos - @tatarbj
  45. 45. <?php $query = db_select('node', 'n') ->fields('n', array('title', 'nid') ->condition('type', 'article') ->addTag('node_access'); $result = $query->execute(); ?> TatarBalazsJanos - @tatarbj
  46. 46. 29 TatarBalazsJanos - @tatarbj
  47. 47. mymodule.not_found: path: '/not-found' defaults: _controller: 'DrupalmymoduleControllerNotFoundController::build404' _title: 'Page not found' requirements: _access: 'TRUE' TatarBalazsJanos - @tatarbj
  48. 48. mymodule.not_found: path: '/not-found' defaults: _controller: 'DrupalmymoduleControllerNotFoundController::build404' _title: 'Page not found' requirements: _access: 'TRUE' TatarBalazsJanos - @tatarbj
  49. 49. 16 TatarBalazsJanos - @tatarbj
  50. 50. Restricted permissions make Drupal sites more secure by calling restrict_permission() method. ? TatarBalazsJanos - @tatarbj
  51. 51. Restricted permissions make Drupal sites more secure by calling restrict_permission() method. ? TatarBalazsJanos - @tatarbj
  52. 52. Restricted permissions make Drupal sites more secure by raising attention on the permission page. ? TatarBalazsJanos - @tatarbj
  53. 53. 6 TatarBalazsJanos - @tatarbj
  54. 54. A standard Drupal 8 allows users to mistype their passwords 10 times. ? TatarBalazsJanos - @tatarbj
  55. 55. A standard Drupal 8 allows users to mistype their passwords 10 times. ? TatarBalazsJanos - @tatarbj
  56. 56. A standard Drupal 8 allows users to mistype their passwords 5 times. ? TatarBalazsJanos - @tatarbj
  57. 57. 9 TatarBalazsJanos - @tatarbj
  58. 58. TatarBalazsJanos - @tatarbj
  59. 59. 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 TatarBalazsJanos - @tatarbj
  60. 60. SQL Injection TatarBalazsJanos - @tatarbj
  61. 61. Unauthorized access to database resources. Do not trust any user input. SA-CORE-2014-005 – Highly critical D7 SA SQL Injection TatarBalazsJanos - @tatarbj
  62. 62. Round 3 TatarBalazsJanos - @tatarbj
  63. 63. <?php $result = Drupal::database() ->delete('people') ->condition('name', '%_' . $_GET['param'], 'LIKE'); ->execute(); ?> TatarBalazsJanos - @tatarbj
  64. 64. <?php $result = Drupal::database() ->delete('people') ->condition('name', '%_' . $_GET['param'], 'LIKE'); ->execute(); ?> TatarBalazsJanos - @tatarbj
  65. 65. <?php $database = Drupal::database(); $result = $database ->delete('people') ->condition('name', $database->escapeLike($_GET['param']), 'LIKE'); ->execute(); ?> TatarBalazsJanos - @tatarbj
  66. 66. 31 TatarBalazsJanos - @tatarbj
  67. 67. A highly critical Drupal 7 core update remediated a Remote code execution vulnerability in 2014. ? TatarBalazsJanos - @tatarbj
  68. 68. A highly critical Drupal 7 core update remediated a Remote code execution vulnerability in 2014. ? TatarBalazsJanos - @tatarbj
  69. 69. A highly critical Drupal 7 core update remediated an SQL injection vulnerability in 2014. ? TatarBalazsJanos - @tatarbj
  70. 70. 15 TatarBalazsJanos - @tatarbj
  71. 71. TatarBalazsJanos - @tatarbj
  72. 72. 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 TatarBalazsJanos - @tatarbj
  73. 73. Round 4 Ready for some other code? TatarBalazsJanos - @tatarbj
  74. 74. <?php function _generate_password($length = 8) { $pass = ’’; for ($i = 0; $i < $length; $i++) { // Each iteration, pick a random character from the // allowable string and append it to the password: $pass .= $allowable_characters[mt_rand(0, $len)]; } } ?> TatarBalazsJanos - @tatarbj
  75. 75. <?php function _generate_password($length = 8) { $pass = ’’; for ($i = 0; $i < $length; $i++) { // Each iteration, pick a random character from the // allowable string and append it to the password: $pass .= $allowable_characters[mt_rand(0, $len)]; } } ?> TatarBalazsJanos - @tatarbj
  76. 76. <?php function _generate_password($length = 8) { $pass = ’’; for ($i = 0; $i < $length; $i++) { do { // Find a secure random number within the range needed. $index = ord(drupal_random_bytes(1)); } while ($index > $len); $pass .= $allowable_characters[$index]; } } ?> TatarBalazsJanos - @tatarbj
  77. 77. 8 TatarBalazsJanos - @tatarbj
  78. 78. // custom_module.permissions.yml administer custom module: title: 'Bypass access control' description: 'Allows a user to bypass access control.’ // custom_module.routing.yml custom_module.settings.form: path: '/admin/config/custom/settings' requirements: _permission: 'administer custom module' TatarBalazsJanos - @tatarbj
  79. 79. // custom_module.permissions.yml administer custom module: title: 'Bypass access control' description: 'Allows a user to bypass access control.’ // custom_module.routing.yml custom_module.settings.form: path: '/admin/config/custom/settings' requirements: _permission: 'administer custom module' TatarBalazsJanos - @tatarbj
  80. 80. // custom_module.permissions.yml administer custom module: title: 'Bypass access control' description: 'Allows a user to bypass access control.’ restrict access: TRUE // custom_module.routing.yml custom_module.settings.form: path: '/admin/config/custom/settings' requirements: _permission: 'administer custom module' TatarBalazsJanos - @tatarbj
  81. 81. 20 TatarBalazsJanos - @tatarbj
  82. 82. // contrib_module.routing.yml contrib_module.settings.form: path: '/admin/config/contrib/settings' requirements: _permission: 'administer site configuration' TatarBalazsJanos - @tatarbj
  83. 83. // contrib_module.routing.yml contrib_module.settings.form: path: '/admin/config/contrib/settings' requirements: _permission: 'administer site configuration' TatarBalazsJanos - @tatarbj
  84. 84. 26 TatarBalazsJanos - @tatarbj
  85. 85. CSRF stands for Cross Site Remote Fallout vulnerability. ? TatarBalazsJanos - @tatarbj
  86. 86. CSRF stands for Cross Site Remote Fallout vulnerability. ? TatarBalazsJanos - @tatarbj
  87. 87. CSRF stands for Cross Site Request Forgery vulnerability. ? TatarBalazsJanos - @tatarbj
  88. 88. 32 TatarBalazsJanos - @tatarbj
  89. 89. SQL Injection is a server side vulnerability. ? TatarBalazsJanos - @tatarbj
  90. 90. SQL Injection is a server side vulnerability. ? TatarBalazsJanos - @tatarbj
  91. 91. 13 TatarBalazsJanos - @tatarbj
  92. 92. Cross Site Scripting vulnerability is in the TOP3 of OWASP list from 2017. ? TatarBalazsJanos - @tatarbj
  93. 93. Cross Site Scripting vulnerability is in the TOP3 of OWASP list from 2017. ? TatarBalazsJanos - @tatarbj
  94. 94. Cross Site Scripting vulnerability is not in the TOP3 of OWASP list from 2017, but was in 2013. ? TatarBalazsJanos - @tatarbj
  95. 95. 5 TatarBalazsJanos - @tatarbj
  96. 96. In case of no winner, extra numbers are coming! ! TatarBalazsJanos - @tatarbj
  97. 97. 18 TatarBalazsJanos - @tatarbj
  98. 98. 27 TatarBalazsJanos - @tatarbj
  99. 99. 30 TatarBalazsJanos - @tatarbj
  100. 100. 1 TatarBalazsJanos - @tatarbj
  101. 101. 11 TatarBalazsJanos - @tatarbj
  102. 102. 33 TatarBalazsJanos - @tatarbj
  103. 103. TatarBalazsJanos - @tatarbj
  104. 104. Security Improvements TatarBalazsJanos - @tatarbj
  105. 105. *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 session always in 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 TatarBalazsJanos - @tatarbj
  106. 106. Learn by Advisories TatarBalazsJanos - @tatarbj
  107. 107. Security advisories are for  Only stable modules  No alpha, beta, dev  d.org hosted projects @Maintainers: If you are contacted, be supportive!  Drupal Security Team TatarBalazsJanos - @tatarbj
  108. 108. TatarBalazsJanos - @tatarbj
  109. 109. Hacked! Security review (simplytest.me) Password policy Encrypt Composer Security Checker Permission report Drop Guard Security Awareness programs + PHPCS Drupal BestPractice Sniff Security related projects TatarBalazsJanos - @tatarbj
  110. 110. SecOSdays 25-26 October 2019 – Sofia, Bulgaria https://secosday.eu Call For Sessions and Sponsors are open! Tatar Balazs Janos - @tatarbj
  111. 111. Questions? TatarBalazsJanos - @tatarbj
  112. 112. Tatar Balazs Janos @tatarbj Thank you!

Editor's Notes

  • Einstein said: “insanity is when you do the same thing over and over again and expect different results”
  • Owasp: open web application security project
  • Reference for the XSS issue that was basically caused by a security misconfiguration.
  • Hide enabled blocks from selector that are used
    Context update from this wednesday
  • Hide enabled blocks from selector that are used
    Context update from this wednesday
  • Hide enabled blocks from selector that are used
    Context update from this wednesday
  • Not because of having db_query deprecated, but: The $field param is used to derive various table and field names, but in each case the Database API automatically escapes these values. Note that the API does not do this for all arguments!
  • Not because of having db_query deprecated, but: The $field param is used to derive various table and field names, but in each case the Database API automatically escapes these values. Note that the API does not do this for all arguments!
  • Not because of having db_query deprecated, but: The $field param is used to derive various table and field names, but in each case the Database API automatically escapes these values. Note that the API does not do this for all arguments!
  • Mt_rand is not secure enough!
  • Insecure randomness by Mass Password Reset (SA-CONTRIB-2018-043) by Greg Knaddison
  • ×