From b146b7f8542db825314785c91765ddb051ec072c Mon Sep 17 00:00:00 2001 From: Tim Clifford Date: Wed, 27 Jan 2021 15:38:03 +0000 Subject: [PATCH 1/5] Adding database dump exposure policy --- Policies/database_exposure.policy.yml | 34 +++++ Profiles/algm_security.profile.yml | 3 +- Profiles/algm_sla_site_beta.profile.yml | 4 +- src/Audit/DatabaseExposure.php | 158 ++++++++++++++++++++++++ 4 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 Policies/database_exposure.policy.yml create mode 100644 src/Audit/DatabaseExposure.php diff --git a/Policies/database_exposure.policy.yml b/Policies/database_exposure.policy.yml new file mode 100644 index 0000000..acbb006 --- /dev/null +++ b/Policies/database_exposure.policy.yml @@ -0,0 +1,34 @@ +title: "Database exposure check" +class: \Drutiny\algm\Audit\DatabaseExposure +name: Security:DatabaseExposure +tags: + - Drupal 8 + - Drupal 7 + - Security +description: | + A policy that will check for database dumps that are publically exposed and readable by the web server. +remediation: | + Due to the severity of this, the following databases were removed: + + {{#cleaned}} + - {{ . }} + {{/cleaned}} +failure: | + Sensitive database{{ plural }} found: {{ results.found }} + + {{#results.findings}}{{ markdown_display }}{{/results.findings}} +success: No leaked/exposed databases were found +parameters: + root: + default: "%root" + filetypes: + default: + - sql + - sql.gz + description: 'Database file extensions to look for.' + type: string + exclude: + default: + - core + description: 'Directories to exclude from find' +severity: 'critical' diff --git a/Profiles/algm_security.profile.yml b/Profiles/algm_security.profile.yml index 1f3cd3a..7515ce7 100644 --- a/Profiles/algm_security.profile.yml +++ b/Profiles/algm_security.profile.yml @@ -1,4 +1,5 @@ title: 'ALGM Security audit' description: 'This profile is for sites which contain security policies that need to be rolled out ad-hoc' policies: - 'Security:DoubleFileExtension': { severity: critical } \ No newline at end of file + 'Security:DoubleFileExtension': { severity: critical } + 'Security:DatabaseExposure': { severity: critical } diff --git a/Profiles/algm_sla_site_beta.profile.yml b/Profiles/algm_sla_site_beta.profile.yml index eff88ea..f90e1b1 100644 --- a/Profiles/algm_sla_site_beta.profile.yml +++ b/Profiles/algm_sla_site_beta.profile.yml @@ -9,5 +9,7 @@ policies: 'algm:SSLChecker': { severity: high } 'algm:StageFileProxy': { severity: medium } 'algm:StorageSpace': { severity: medium } - 'algm:CdnCheck': { severity: high } 'algm:DevModulesEnabled': { severity: high} + # Security + 'Security:DatabaseExposure': { severity: critical } + 'algm:CdnCheck': { severity: high } diff --git a/src/Audit/DatabaseExposure.php b/src/Audit/DatabaseExposure.php new file mode 100644 index 0000000..648704f --- /dev/null +++ b/src/Audit/DatabaseExposure.php @@ -0,0 +1,158 @@ +getParameter('root', '%root'); + $stat = $sandbox->drush(['format' => 'json'])->status(); + $root = strtr($root, $stat['%paths']); + + $command = ['find', $root]; + + $filepathConditions = []; + foreach ($sandbox->getParameter('exclude', []) as $filepath) { + $filepath = strtr($filepath, $stat['%paths']); + $format = "-path %s/%s"; + $filepathConditions[] = sprintf($format, $root, $filepath); + } + + $filepathConditions = '\( ' . implode(' -o ', $filepathConditions) . ' \)'; + + $command[] = sprintf("-type d %s", $filepathConditions); + + $command[] = "-prune -false -o -type f"; + + $types = $sandbox->getParameter('filetypes', []); + + if (!empty($types)) { + $conditions = []; + foreach ($types as $type) { + $format = '-iname \*.%s'; + $conditions[] = sprintf($format, $type); + } + + $command[] = '\( ' . implode(' -o ', $conditions) . ' \) -readable 2> /dev/null'; + } + + $command = implode(' ', $command); + $sandbox->logger()->info('[' . __CLASS__ . '] ' . $command); + + // Execute + $output = $sandbox->exec($command); + + if (empty($output)) { + return TRUE; + } + + $matches = array_filter(explode(PHP_EOL, $output)); + $matches = array_map(function ($line) { + return [ + 'file' => $line, + 'permission' => 'readable' + ]; + }, $matches); + + // Filters + // $matches = array_filter($matches, function($line) { + // return !strpos($line['file'], '\/core\/') !== false; + // }); + + $results = [ + 'found' => count($matches), + 'findings' => $matches, + 'filepaths' => array_values(array_unique(array_map(function ($match) use ($stat) { + return str_replace($stat['%paths']['%root'], '', $match['file']); + }, $matches))) + ]; + + //TODO: Add a conditional check for Markdown format + $columns = ['File', 'Permission']; + $rows = []; + foreach ($results['findings'] as $key => $file) { + $rows[] = [$file['file'], $file["permission"]]; + } + + $md_table = new MarkdownTableGenerator($columns, $rows); + $results['findings'] = ['markdown_display' => $md_table->render()]; + + $sandbox->setParameter('results', $results); + $sandbox->setParameter('plural', count($results) > 1 ? 's' : ''); + + if (empty($matches)) { + Audit::SUCCESS; + } + return Audit::FAIL; + } + + // This remediation step is run if the audit fails/returns false. + public function remediate(Sandbox $sandbox) { + $root = $sandbox->getParameter('root', '%root'); + $list = $sandbox->getParameter('results'); + + $stat = $sandbox->drush(['format' => 'json'])->status(); + $root = strtr($root, $stat['%paths']); + + $output = ''; + if (!empty($list['filepaths'])) { + foreach ($list['filepaths'] as $file) { + $fileToRemove = sprintf('%s%s', $root, $file); + $output = $sandbox->exec('rm -rf ' . $fileToRemove); + } + + $sandbox->setParameter('cleaned', $list['filepaths']); + } + + return $this->audit($sandbox); + } +} From 9a33c292fb80374a41ddb71c627ab201bd6b73b6 Mon Sep 17 00:00:00 2001 From: Tim Clifford Date: Wed, 27 Jan 2021 15:48:08 +0000 Subject: [PATCH 2/5] Update Policies/database_exposure.policy.yml Co-authored-by: Dan Lemon --- Policies/database_exposure.policy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Policies/database_exposure.policy.yml b/Policies/database_exposure.policy.yml index acbb006..45e45ef 100644 --- a/Policies/database_exposure.policy.yml +++ b/Policies/database_exposure.policy.yml @@ -6,7 +6,7 @@ tags: - Drupal 7 - Security description: | - A policy that will check for database dumps that are publically exposed and readable by the web server. + A policy that will check for database dumps that are publicly exposed and readable by the web server. remediation: | Due to the severity of this, the following databases were removed: From f105177e6d68f652a73041e9abe0b492d737c42f Mon Sep 17 00:00:00 2001 From: Tim Clifford Date: Wed, 27 Jan 2021 15:48:14 +0000 Subject: [PATCH 3/5] Update src/Audit/DatabaseExposure.php Co-authored-by: Dan Lemon --- src/Audit/DatabaseExposure.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Audit/DatabaseExposure.php b/src/Audit/DatabaseExposure.php index 648704f..ac040ec 100644 --- a/src/Audit/DatabaseExposure.php +++ b/src/Audit/DatabaseExposure.php @@ -56,7 +56,7 @@ class DatabaseExposure extends Audit implements RemediableInterface { public function audit(Sandbox $sandbox) { $root = $sandbox->getParameter('root', '%root'); $stat = $sandbox->drush(['format' => 'json'])->status(); - $root = strtr($root, $stat['%paths']); + $root = strtr($root, $stat['%paths']); $command = ['find', $root]; From b9ab8de1b0fb1e509b160657dc7d5c1479400247 Mon Sep 17 00:00:00 2001 From: Tim Clifford Date: Wed, 27 Jan 2021 15:48:23 +0000 Subject: [PATCH 4/5] Update src/Audit/DatabaseExposure.php Co-authored-by: Dan Lemon --- src/Audit/DatabaseExposure.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Audit/DatabaseExposure.php b/src/Audit/DatabaseExposure.php index ac040ec..9fec4d7 100644 --- a/src/Audit/DatabaseExposure.php +++ b/src/Audit/DatabaseExposure.php @@ -141,7 +141,7 @@ public function remediate(Sandbox $sandbox) { $list = $sandbox->getParameter('results'); $stat = $sandbox->drush(['format' => 'json'])->status(); - $root = strtr($root, $stat['%paths']); + $root = strtr($root, $stat['%paths']); $output = ''; if (!empty($list['filepaths'])) { From 84f3b60bb3bded019fb1d84e56b71195d32618c7 Mon Sep 17 00:00:00 2001 From: Tim Clifford Date: Wed, 27 Jan 2021 15:48:30 +0000 Subject: [PATCH 5/5] Update src/Audit/DatabaseExposure.php Co-authored-by: Dan Lemon --- src/Audit/DatabaseExposure.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Audit/DatabaseExposure.php b/src/Audit/DatabaseExposure.php index 9fec4d7..34b6f8b 100644 --- a/src/Audit/DatabaseExposure.php +++ b/src/Audit/DatabaseExposure.php @@ -130,7 +130,7 @@ public function audit(Sandbox $sandbox) { $sandbox->setParameter('plural', count($results) > 1 ? 's' : ''); if (empty($matches)) { - Audit::SUCCESS; + return Audit::SUCCESS; } return Audit::FAIL; }