Let’s write secure Drupal code!
Tatar Balazs Janos
Who am I?
Tatar Balazs Janos
@tatarbj
Works with Drupal since 2007
CTO @ Petend
Drupal Security Correspondent @ EC
Active mentor @ Mentoring community group
Provisional member @ Drupal Security Team
SecOSdreamer @ Secure Open Source day
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Are there site builders?
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Demo
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Gist
https://gist.github.com/tatarbj/bbd36b5722fd21199d1831663ff3ca59
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Are there developers/maintainers?
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Have you attended on a previous Let’s
write secure Drupal code! session?
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
DrupalCamp Antwerp 2017
DrupalCamp Ruhr 2018
DrupalDevDays 2018
Drupal Europe 2018
DrupalCamp Oslo 2018
DrupalCamp London 2019
Drupal Mountain Camp 2019
DrupalCamp Spain 2019
History
Trends in Security
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Types of vulnerabilities
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Cross Site Scripting
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Client side vulnerability
Unfiltered output
Never trust any user input.
We’ve seen the demo before ;)
Cross Site Scripting
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Html::escape() – plain text
Xss::filter() – html is allowed
Xss::filterAdmin() – text by admins
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Test
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Raise your red card if snippet has issues!
Raise your green card if code is secure!
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
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
DrupalCamp Spain2019
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
DrupalCamp Spain2019
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
DrupalCamp Spain2019
<?php print '<a href="/' . check_url($url) . '">'; ?>
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
<?php print '<a href="/' . check_url($url) . '">'; ?>
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
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
DrupalCamp Spain2019
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
DrupalCamp Spain2019
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
DrupalCamp Spain2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
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
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Access Bypass
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
User can access/do something.
Menu items can be defined to be
accessed/denied.
Many access systems: node, entity, field, views...
Access bypass
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Test II.
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
<?php
$query = db_select('node', 'n')
->fields('n', array('title', 'nid'))
->condition('type', 'article');
$result = $query->execute();
?>
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
<?php
$query = db_select('node', 'n')
->fields('n', array('title', 'nid'))
->condition('type', 'article');
$result = $query->execute();
?>
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
<?php
$query = db_select('node', 'n')
->fields('n', array('title', 'nid')
->condition('type', 'article')
->addTag('node_access');
$result = $query->execute();
?>
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
mymodule.not_found:
path: '/not-found'
defaults:
_controller: DrupalmymoduleControllerNotFoundController::build404
_title: 'Page not found'
requirements:
_access: 'TRUE'
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
mymodule.not_found:
path: '/not-found'
defaults:
_controller: DrupalmymoduleControllerNotFoundController::build404'
_title: 'Page not found'
requirements:
_access: 'TRUE'
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
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
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
SQL Injection
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Unauthorized access to database resources.
Do not trust any user input.
SA-CORE-2014-005 – Highly critical D7 SA
SQL Injection
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Test III.
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
<?php
$table = 'field_data_' . $field;
$sql = 'SELECT entity_id, bundle, ' . $field . '_linklabel FROM
{' . $table . '} WHERE ' . $field . '_normalized = :phoneno’;
$eid = db_query($sql, array(':phoneno' => $normalized))
->fetchAssoc();
?>
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
<?php
$table = 'field_data_' . $field;
$sql = 'SELECT entity_id, bundle, ' . $field . '_linklabel FROM
{' . $table . '} WHERE ' . $field . '_normalized = :phoneno’;
$eid = db_query($sql, array(':phoneno' => $normalized))
->fetchAssoc();
?>
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
<?php
$query = db_select('field_data_' . $field, 'fdf');
$query->fields('fdf', array('entity_id', 'bundle', $field .
'_linklabel'));
$query->condition('fdf.' . $field . '_normalized',
$normalized);
$eid = $query->execute()->fetchAssoc();
?>
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
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
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Test IV.
Ready for some other code?
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
<?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
DrupalCamp Spain2019
<?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
DrupalCamp Spain2019
<?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
DrupalCamp Spain2019
// 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
DrupalCamp Spain2019
// 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
DrupalCamp Spain2019
// 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
DrupalCamp Spain2019
// custom_module.routing.yml
custom_module.settings.form:
path: '/admin/config/custom/settings'
requirements:
_permission: 'administer site configuration'
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
// custom_module.routing.yml
custom_module.settings.form:
path: '/admin/config/custom/settings'
requirements:
_permission: 'administer site configuration'
TatarBalazsJanos
@tatarbj
DrupalCamp Spain2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Security Improvements
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
*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
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Learn by Advisories
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
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
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
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
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
SecOSday – Haarlem edition
11 May, 2019
Questions?
Tatar Balazs Janos - @tatarbj
DrupalCamp Spain 2019
Tatar Balazs Janos
@tatarbj
Thank you!

Let's write secure Drupal code! - DrupalCamp Spain 2019

  • 1.
    Let’s write secureDrupal code! Tatar Balazs Janos
  • 2.
    Who am I? TatarBalazs Janos @tatarbj Works with Drupal since 2007 CTO @ Petend Drupal Security Correspondent @ EC Active mentor @ Mentoring community group Provisional member @ Drupal Security Team SecOSdreamer @ Secure Open Source day
  • 3.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 4.
    Are there sitebuilders? Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 5.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 6.
    Demo Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 7.
  • 8.
    Are there developers/maintainers? TatarBalazs Janos - @tatarbj DrupalCamp Spain 2019
  • 9.
    Have you attendedon a previous Let’s write secure Drupal code! session? Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 10.
    DrupalCamp Antwerp 2017 DrupalCampRuhr 2018 DrupalDevDays 2018 Drupal Europe 2018 DrupalCamp Oslo 2018 DrupalCamp London 2019 Drupal Mountain Camp 2019 DrupalCamp Spain 2019 History
  • 11.
    Trends in Security TatarBalazs Janos - @tatarbj DrupalCamp Spain 2019
  • 12.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 13.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 14.
    Types of vulnerabilities TatarBalazs Janos - @tatarbj DrupalCamp Spain 2019
  • 15.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 16.
    Cross Site Scripting TatarBalazs Janos - @tatarbj DrupalCamp Spain 2019
  • 17.
    Client side vulnerability Unfilteredoutput Never trust any user input. We’ve seen the demo before ;) Cross Site Scripting Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 18.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 19.
    Html::escape() – plaintext Xss::filter() – html is allowed Xss::filterAdmin() – text by admins Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 20.
    Test Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 21.
    Raise your redcard if snippet has issues! Raise your green card if code is secure! TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 22.
    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 DrupalCamp Spain2019
  • 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 DrupalCamp Spain2019
  • 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 DrupalCamp Spain2019
  • 25.
    <?php print '<ahref="/' . check_url($url) . '">'; ?> TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 26.
    <?php print '<ahref="/' . check_url($url) . '">'; ?> TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 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 DrupalCamp Spain2019
  • 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 DrupalCamp Spain2019
  • 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 DrupalCamp Spain2019
  • 30.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 31.
    Use behat/automated tests. <script>alert('XSS')</script> <imgsrc="a" onerror="alert('title')"> Check your filters and user roles. Do not give too many options to untrusted users! Protection against Cross Site Scripting Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 32.
    Access Bypass Tatar BalazsJanos - @tatarbj DrupalCamp Spain 2019
  • 33.
    User can access/dosomething. Menu items can be defined to be accessed/denied. Many access systems: node, entity, field, views... Access bypass Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 34.
    Test II. Tatar BalazsJanos - @tatarbj DrupalCamp Spain 2019
  • 35.
    <?php $query = db_select('node','n') ->fields('n', array('title', 'nid')) ->condition('type', 'article'); $result = $query->execute(); ?> TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 36.
    <?php $query = db_select('node','n') ->fields('n', array('title', 'nid')) ->condition('type', 'article'); $result = $query->execute(); ?> TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 37.
    <?php $query = db_select('node','n') ->fields('n', array('title', 'nid') ->condition('type', 'article') ->addTag('node_access'); $result = $query->execute(); ?> TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 38.
    mymodule.not_found: path: '/not-found' defaults: _controller: DrupalmymoduleControllerNotFoundController::build404 _title:'Page not found' requirements: _access: 'TRUE' TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 39.
    mymodule.not_found: path: '/not-found' defaults: _controller: DrupalmymoduleControllerNotFoundController::build404' _title:'Page not found' requirements: _access: 'TRUE' TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 40.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 41.
    Visit node/nid andother 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 Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 42.
    SQL Injection Tatar BalazsJanos - @tatarbj DrupalCamp Spain 2019
  • 43.
    Unauthorized access todatabase resources. Do not trust any user input. SA-CORE-2014-005 – Highly critical D7 SA SQL Injection Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 44.
    Test III. Tatar BalazsJanos - @tatarbj DrupalCamp Spain 2019
  • 45.
    <?php $table = 'field_data_'. $field; $sql = 'SELECT entity_id, bundle, ' . $field . '_linklabel FROM {' . $table . '} WHERE ' . $field . '_normalized = :phoneno’; $eid = db_query($sql, array(':phoneno' => $normalized)) ->fetchAssoc(); ?> TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 46.
    <?php $table = 'field_data_'. $field; $sql = 'SELECT entity_id, bundle, ' . $field . '_linklabel FROM {' . $table . '} WHERE ' . $field . '_normalized = :phoneno’; $eid = db_query($sql, array(':phoneno' => $normalized)) ->fetchAssoc(); ?> TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 47.
    <?php $query = db_select('field_data_'. $field, 'fdf'); $query->fields('fdf', array('entity_id', 'bundle', $field . '_linklabel')); $query->condition('fdf.' . $field . '_normalized', $normalized); $eid = $query->execute()->fetchAssoc(); ?> TatarBalazsJanos @tatarbj DrupalCamp Spain2019
  • 48.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 49.
    Use always drupalDatabase 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 Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 50.
    Test IV. Ready forsome other code? Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 51.
    <?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 DrupalCamp Spain2019
  • 52.
    <?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 DrupalCamp Spain2019
  • 53.
    <?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 DrupalCamp Spain2019
  • 54.
    // custom_module.permissions.yml administer custommodule: 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 DrupalCamp Spain2019
  • 55.
    // custom_module.permissions.yml administer custommodule: 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 DrupalCamp Spain2019
  • 56.
    // custom_module.permissions.yml administer custommodule: 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 DrupalCamp Spain2019
  • 57.
  • 58.
  • 59.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 60.
    Security Improvements Tatar BalazsJanos - @tatarbj DrupalCamp Spain 2019
  • 61.
    *https://events.drupal.org/sites/default/files/slides/pwolanin-2017-09-ways-drupal8-d.pdf Many ways Drupal8 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 Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 62.
    Learn by Advisories TatarBalazs Janos - @tatarbj DrupalCamp Spain 2019
  • 63.
    Security advisories arefor  Only stable modules  No alpha, beta, dev  d.org hosted projects @Maintainers: If you are contacted, be supportive!  Drupal Security Team Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 64.
    Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 65.
    Hacked! Security review (simplytest.me) Passwordpolicy Encrypt Composer Security Checker Permission report Drop Guard Security Awareness programs + PHPCS Drupal BestPractice Sniff Security related projects Tatar Balazs Janos - @tatarbj DrupalCamp Spain 2019
  • 66.
    SecOSday – Haarlemedition 11 May, 2019
  • 67.
    Questions? Tatar Balazs Janos- @tatarbj DrupalCamp Spain 2019
  • 68.

Editor's Notes

  • #11 Einstein said: “insanity is when you do the same thing over and over again and expect different results”
  • #13 Owasp: open web application security project
  • #14 Reference for the XSS issue that was basically caused by a security misconfiguration.
  • #23 Hide enabled blocks from selector that are used Context update from this wednesday
  • #24 Hide enabled blocks from selector that are used Context update from this wednesday
  • #25 Hide enabled blocks from selector that are used Context update from this wednesday
  • #48 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!
  • #53 Mt_rand is not secure enough!
  • #54 Insecure randomness by Mass Password Reset (SA-CONTRIB-2018-043) by Greg Knaddison