From 49eed7b8ed98895a47388935d7aca3e0d74ab128 Mon Sep 17 00:00:00 2001 From: sfuerte <16941995+sfuerte@users.noreply.github.com> Date: Tue, 10 Mar 2020 14:48:41 -0600 Subject: [PATCH 1/2] input vars vs hardcoded values; extra checks --- README.md | 6 ++ controls/tomcat.rb | 220 +++++++++++++++++++++++++++++++++------------ 2 files changed, 168 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 0e35d79..762135d 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,12 @@ You can also execute the profile directly from Github: $ inspec exec https://github.com/T-Systems-MMS/tomcat-baseline ``` +It also can be executed inside Docker image with overridden default values. Here is an example for default Tomcat 9 ([`9-jdk11-openjdk-slim`](https://hub.docker.com/_/tomcat)) settings: + +```bash +inspec exec tomcat-baseline/ --input catalina_home=/usr/local/tomcat tomcat_conf=/usr/local/tomcat/conf tomcat_libs=/usr/local/tomcat/lib tomcat_logs=/usr/local/tomcat/logs tomcat_cache=/usr/local/tomcat/temp logging_filehandler=AsyncFileHandler tomcat_service=disable +``` + ## License and Author * Author: Sebastian Gumprich diff --git a/controls/tomcat.rb b/controls/tomcat.rb index 6132b42..dbf5729 100644 --- a/controls/tomcat.rb +++ b/controls/tomcat.rb @@ -1,19 +1,42 @@ +input('tomcat_service', value: 'enable') +input('tomcat_user', value: 'tomcat') +input('tomcat_group', value: 'tomcat') +input('catalina_home', value: '/usr/share/tomcat') +input('tomcat_conf', value: '/etc/tomcat') +input('tomcat_libs', value: '/var/lib/tomcat') +input('tomcat_logs', value: '/var/log/tomcat') +input('tomcat_cache', value: '/var/cache/tomcat') +input('logging_filehandler', value: 'FileHandler') + control 'tomcat.dedicated_user' do + impact 1.0 tag 'ID: 3.10-5/2.1' title 'The application server must run under a dedicated (operating-system) account that only has the permissions required for operation.' - describe service('tomcat') do - it { should be_installed } - it { should be_enabled } - it { should be_running } - end - describe user('tomcat') do + describe user(input('tomcat_user')) do it { should exist } end - describe group('tomcat') do + describe group(input('tomcat_group')) do it { should exist } end +end + +control 'tomcat.dedicated_service' do + impact 1.0 + tag 'ID: 3.10-5/2.1-1' + title 'If not containerized, the application service must be installed properly.' + describe service('tomcat') do + before do + skip if input('tomcat_service') == "disable" + end + it { should be_installed } + it { should be_enabled } + it { should be_running } + end describe processes('tomcat') do - its('users') { should eq ['tomcat'] } + before do + skip if input('tomcat_service') == "disable" + end + its('users') { should eq [input('tomcat_user')] } end end @@ -24,9 +47,10 @@ # end control 'tomcat.shutdownport' do + impact 1.0 tag 'ID: 3.39-2/2.2' title 'If the shutdown port is not needed, it must be deactivated.' - describe file('/etc/tomcat/server.xml') do + describe file(input('tomcat_conf') + "/server.xml") do its('content') { should match '' } + its('content') { should match '' } end end end control 'tomcat.ip_whitelisting' do + impact 1.0 tag 'ID: 3.39-7/2.2' title 'Access to the application server must only be possible from approved IP addresses (IP whitelisting).' - describe file('/etc/tomcat/server.xml') do + describe file(input('tomcat_conf') + '/server.xml') do # mit der xml resource testen! its('content') { should match 'allow=".*"' } end @@ -112,78 +142,152 @@ # end control 'tomcat.logging' do + impact 1.0 tag 'ID: 3.10-8/2.1' title 'Access to the application server must be logged.' - describe file('/usr/share/tomcat/conf/logging.properties') do - its('content') { should match '.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler' } - its('content') { should match '1catalina.org.apache.juli.FileHandler.level = FINE' } - its('content') { should match '2localhost.org.apache.juli.FileHandler.level = FINE' } + describe file(input('tomcat_conf') + '/logging.properties') do + its('content') { should match '.handlers = 1catalina.org.apache.juli.' + input('logging_filehandler') + ', java.util.logging.ConsoleHandler' } + its('content') { should match '1catalina.org.apache.juli.' + input('logging_filehandler') + '.level = FINE' } + its('content') { should match '2localhost.org.apache.juli.' + input('logging_filehandler') + '.level = FINE' } its('content') { should match 'java.util.logging.ConsoleHandler.level = FINE' } its('content') { should match '.level = INFO' } end - describe directory('/usr/share/tomcat/logs') do + describe file(input('tomcat_conf') + '/server.xml') do + its('content') { should match 'org.apache.catalina.valves.AccessLogValve' } + end + describe directory(input('tomcat_logs')) do it { should exist } it { should be_directory } its('mode') { should cmp '0750' } - it { should be_owned_by 'tomcat' } + it { should be_owned_by input('tomcat_user') } end end control 'tomcat.directories' do + impact 1.0 title 'Check for existence and correct permissions of tomcat directories' - describe directory('/usr/share/tomcat') do + describe directory(input('catalina_home')) do it { should be_directory } - its('owner') { should eq 'tomcat' } - its('group') { should eq 'tomcat' } + its('owner') { should eq input('tomcat_user') } + its('group') { should eq input('tomcat_group') } its('mode') { should cmp '0750' } end - describe directory('/etc/tomcat') do + describe directory(input('tomcat_conf')) do it { should be_directory } - its('owner') { should eq 'tomcat' } - its('group') { should eq 'tomcat' } + its('owner') { should eq input('tomcat_user') } + its('group') { should eq input('tomcat_group') } its('mode') { should cmp '0750' } end - describe directory('/var/log/tomcat') do + describe directory(input('tomcat_logs')) do it { should be_directory } - its('owner') { should eq 'tomcat' } - its('group') { should eq 'tomcat' } + its('owner') { should eq input('tomcat_user') } + its('group') { should eq input('tomcat_group') } its('mode') { should cmp '0750' } end - describe directory('/var/lib/tomcat') do + describe directory(input('tomcat_libs')) do it { should be_directory } - its('owner') { should eq 'tomcat' } - its('group') { should eq 'tomcat' } + its('owner') { should eq input('tomcat_user') } + its('group') { should eq input('tomcat_group') } its('mode') { should cmp '0750' } end - describe directory('/var/cache/tomcat') do + describe directory(input('tomcat_cache')) do it { should be_directory } - its('owner') { should eq 'tomcat' } - its('group') { should eq 'tomcat' } + its('owner') { should eq input('tomcat_user') } + its('group') { should eq input('tomcat_group') } its('mode') { should cmp '0750' } end end control 'tomcat.files' do + impact 1.0 title 'Check for existence and correct permissions of tomcat files' - describe file('/usr/share/tomcat/conf/web.xml') do + describe file(input('tomcat_conf') + '/web.xml') do it { should exist } it { should be_file } - its('owner') { should eq 'tomcat' } - its('group') { should eq 'tomcat' } + its('owner') { should eq input('tomcat_user') } + its('group') { should eq input('tomcat_group') } its('mode') { should cmp '0640' } end - describe file('/usr/share/tomcat/conf/context.xml') do + describe file(input('tomcat_conf') + '/context.xml') do it { should exist } it { should be_file } - its('owner') { should eq 'tomcat' } - its('group') { should eq 'tomcat' } + its('owner') { should eq input('tomcat_user') } + its('group') { should eq input('tomcat_group') } its('mode') { should cmp '0640' } end - describe file('/usr/share/tomcat/conf/server.xml') do + describe file(input('tomcat_conf') + '/server.xml') do it { should exist } it { should be_file } - its('owner') { should eq 'tomcat' } - its('group') { should eq 'tomcat' } + its('owner') { should eq input('tomcat_user') } + its('group') { should eq input('tomcat_group') } its('mode') { should cmp '0640' } end end + +control 'tomcat.listeners' do + impact 1.0 + title 'Checking enabled listeners' + describe file(input('tomcat_conf') + '/server.xml') do + its('content') { should match '' } + its('content') { should match '' } + its('content') { should match '' } + its('content') { should match '' } + its('content') { should match '' } + end +end + +control 'tomcat.lock_out_realm' do + impact 1.0 + title 'Use the LockOutRealm to prevent attempts to guess user passwords via a brute-force attack' + describe file(input('tomcat_conf') + '/server.xml') do + its('content') { should match '' } + end +end + +control 'tomcat.stuck_thread_detection' do + impact 1.0 + title 'Detect requests that take a long time to process' + describe file(input('tomcat_conf') + '/server.xml') do + its('content') { should match '' } + end +end + +control 'tomcat.logging_error_reporting' do + impact 1.0 + title 'Verify that stack traces and server info are not reported' + describe file(input('tomcat_conf') + '/server.xml') do + its('content') { should match 'showReport="false"' } + its('content') { should match 'showServerInfo="false"' } + end +end + +control 'tomcat.crawler_session_manager' do + impact 1.0 + title 'Ensuring that crawlers are associated with a single session' + describe file(input('tomcat_conf') + '/server.xml') do + its('content') { should match 'hostAware="true"' } + its('content') { should match 'contextAware="true"' } + end +end + +control 'tomcat.health_status' do + impact 1.0 + title 'Health checks must be disabled' + describe file(input('tomcat_conf') + '/server.xml') do + its('content') { should_not match 'org.apache.catalina.valves.HealthCheckValve' } + end +end + +control 'tomcat.http_headers' do + impact 1.0 + title 'Verifying HTTP headers security (see https://securityheaders.com)' + describe file(input('tomcat_conf') + '/web.xml') do + its('content') { should match 'hstsEnabled' } + # X-Frame-Options + its('content') { should match 'antiClickJackingEnabled' } + # X-Content-Type-Options & X-XSS-Protection: 1; mode=block + its('content') { should match 'blockContentTypeSniffingEnabled' } + # HttpOnly flag to cookies + its('content') { should match 'true' } + end +end From 4605b9bf4ec2ad851dc71ca0b7a4d5afd16e33ab Mon Sep 17 00:00:00 2001 From: sfuerte <16941995+sfuerte@users.noreply.github.com> Date: Wed, 11 Mar 2020 15:47:35 -0600 Subject: [PATCH 2/2] lint fixes --- controls/tomcat.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/controls/tomcat.rb b/controls/tomcat.rb index dbf5729..dc01890 100644 --- a/controls/tomcat.rb +++ b/controls/tomcat.rb @@ -24,9 +24,9 @@ impact 1.0 tag 'ID: 3.10-5/2.1-1' title 'If not containerized, the application service must be installed properly.' - describe service('tomcat') do + describe service('tomcat') do before do - skip if input('tomcat_service') == "disable" + skip if input('tomcat_service') == 'disable' end it { should be_installed } it { should be_enabled } @@ -34,7 +34,7 @@ end describe processes('tomcat') do before do - skip if input('tomcat_service') == "disable" + skip if input('tomcat_service') == 'disable' end its('users') { should eq [input('tomcat_user')] } end @@ -50,7 +50,7 @@ impact 1.0 tag 'ID: 3.39-2/2.2' title 'If the shutdown port is not needed, it must be deactivated.' - describe file(input('tomcat_conf') + "/server.xml") do + describe file(input('tomcat_conf') + '/server.xml') do its('content') { should match '