+++ /dev/null
-<?php
-
-namespace Drupal\security_review\Checks;
-
-use Drupal\Core\Link;
-use Drupal\Core\Url;
-use Drupal\field\Entity\FieldConfig;
-use Drupal\security_review\Check;
-use Drupal\security_review\CheckResult;
-use Symfony\Component\Routing\Exception\RouteNotFoundException;
-
-/**
- * Checks for unsafe extensions in the allowed extensions settings of fields.
- */
-class UploadExtensions extends Check {
-
- /**
- * {@inheritdoc}
- */
- public function getNamespace() {
- return 'Security Review';
- }
-
- /**
- * {@inheritdoc}
- */
- public function getTitle() {
- return 'Allowed upload extensions';
- }
-
- /**
- * {@inheritdoc}
- */
- public function getMachineTitle() {
- return 'upload_extensions';
- }
-
- /**
- * {@inheritdoc}
- */
- public function run() {
- // If field is not enabled return with INFO.
- if (!$this->moduleHandler()->moduleExists('field')) {
- return $this->createResult(CheckResult::INFO);
- }
-
- $result = CheckResult::SUCCESS;
- $findings = [];
-
- // Check field configuration entities.
- foreach (FieldConfig::loadMultiple() as $entity) {
- /** @var FieldConfig $entity */
- $extensions = $entity->getSetting('file_extensions');
- if ($extensions != NULL) {
- $extensions = explode(' ', $extensions);
- $intersect = array_intersect($extensions, $this->security()->unsafeExtensions());
- // $intersect holds the unsafe extensions this entity allows.
- foreach ($intersect as $unsafe_extension) {
- $findings[$entity->id()][] = $unsafe_extension;
- }
- }
- }
-
- if (!empty($findings)) {
- $result = CheckResult::FAIL;
- }
-
- return $this->createResult($result, $findings);
- }
-
- /**
- * {@inheritdoc}
- */
- public function help() {
- $paragraphs = [];
- $paragraphs[] = $this->t(
- 'File and image fields allow for uploaded files. Some extensions are considered dangerous because the files can be evaluated and then executed in the browser. A malicious user could use this opening to gain control of your site. Review <a href=":url">all fields on your site</a>.',
- [':url' => Url::fromRoute('entity.field_storage_config.collection')->toString()]
- );
-
- return [
- '#theme' => 'check_help',
- '#title' => 'Allowed upload extensions',
- '#paragraphs' => $paragraphs,
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function evaluate(CheckResult $result) {
- $findings = $result->findings();
- if (empty($findings)) {
- return [];
- }
-
- $paragraphs = [];
- $paragraphs[] = $this->t('The following extensions are considered unsafe and should be removed or limited from use. Or, be sure you are not granting untrusted users the ability to upload files.');
-
- $items = [];
- foreach ($findings as $entity_id => $unsafe_extensions) {
- $entity = FieldConfig::load($entity_id);
- /** @var FieldConfig $entity */
-
- foreach ($unsafe_extensions as $extension) {
- $item = $this->t(
- 'Review @type in <em>@field</em> field on @bundle',
- [
- '@type' => $extension,
- '@field' => $entity->label(),
- '@bundle' => $entity->getTargetBundle(),
- ]
- );
-
- // Try to get an edit url.
- try {
- $url_params = ['field_config' => $entity->id()];
- if ($entity->getTargetEntityTypeId() == 'node') {
- $url_params['node_type'] = $entity->getTargetBundle();
- }
- $items[] = Link::createFromRoute(
- $item,
- sprintf('entity.field_config.%s_field_edit_form', $entity->getTargetEntityTypeId()),
- $url_params
- );
- }
- catch (RouteNotFoundException $e) {
- $items[] = $item;
- }
- }
- }
-
- return [
- '#theme' => 'check_evaluation',
- '#paragraphs' => $paragraphs,
- '#items' => $items,
- ];
- }
-
- /**
- * {@inheritdoc}
- */
- public function evaluatePlain(CheckResult $result) {
- $findings = $result->findings();
- if (empty($findings)) {
- return '';
- }
-
- $output = '';
- foreach ($findings as $entity_id => $unsafe_extensions) {
- $entity = FieldConfig::load($entity_id);
- /** @var FieldConfig $entity */
-
- $output .= $this->t(
- '@bundle: field @field',
- [
- '@bundle' => $entity->getTargetBundle(),
- '@field' => $entity->label(),
- ]
- );
- $output .= "\n\t" . implode(', ', $unsafe_extensions) . "\n";
- }
-
- return $output;
- }
-
- /**
- * {@inheritdoc}
- */
- public function getMessage($result_const) {
- switch ($result_const) {
- case CheckResult::SUCCESS:
- return $this->t('Only safe extensions are allowed for uploaded files and images.');
-
- case CheckResult::FAIL:
- return $this->t('Unsafe file extensions are allowed in uploads.');
-
- case CheckResult::INFO:
- return $this->t('Module field is not enabled.');
-
- default:
- return $this->t('Unexpected result.');
- }
- }
-
-}