V-72969

Severity: Medium

Generated

2019-05-20 15:48:11.984914

Status

Passed

PostgreSQL must generate audit records when unsuccessful attempts to execute privileged activities or other system-level access occur.

NIST 800-53

STIG # Description Result
AU-12 AU-12: Audit Generation failed

Guidance

Without tracking privileged activity, it would be difficult to establish, correlate, and investigate the events relating to an incident or identify those responsible for one. System documentation should include a definition of the functionality considered privileged.

A privileged function in this context is any operation that modifies the structure of the database, its built-in logic, or its security settings. This would include all Data Definition Language (DDL) statements and all security-related statements. In an SQL environment, it encompasses, but is not necessarily limited to:

CREATE ALTER DROP GRANT REVOKE

Note: That it is particularly important to audit, and tightly control, any action that weakens the implementation of this requirement itself, since the objective is to have a complete audit trail of all administrative activity. To aid in diagnosis, it is necessary to keep track of failed attempts in addition to the successful ones.

Check

As the database administrator (shown here as “postgres”), create the role bob by running the following SQL: $ sudo su - postgres $ psql -c “CREATE ROLE bob”

Next, change the current role to bob and attempt to execute privileged activity: $ psql -c “CREATE ROLE stig_test SUPERUSER” $ psql -c “CREATE ROLE stig_test CREATEDB” $ psql -c “CREATE ROLE stig_test CREATEROLE” $ psql -c “CREATE ROLE stig_test CREATEUSER”

Now, as the database administrator (shown here as “postgres”), verify that an audit event was produced (use the latest log): $ sudo su - postgres $ cat ${PGDATA?}/pg_log/

< 2016-02-23 20:16:32.396 EST postgres 56cfa74f.79eb postgres: >ERROR: must be superuser to create superusers < 2016-02-23 20:16:32.396 EST postgres 56cfa74f.79eb postgres: >STATEMENT: CREATE ROLE stig_test SUPERUSER; < 2016-02-23 20:16:48.725 EST postgres 56cfa74f.79eb postgres: >ERROR: permission denied to create role < 2016-02-23 20:16:48.725 EST postgres 56cfa74f.79eb postgres: >STATEMENT: CREATE ROLE stig_test CREATEDB; < 2016-02-23 20:16:54.365 EST postgres 56cfa74f.79eb postgres: >ERROR: p ermission denied to create role < 2016-02-23 20:16:54.365 EST postgres 56cfa74f.79eb postgres: >STATEMENT: CREATE ROLE stig_test CREATEROLE; < 2016-02-23 20:17:05.949 EST postgres 56cfa74f.79eb postgres: >ERROR: must be superuser to create superusers < 2016-02-23 20:17:05.949 EST postgres 56cfa74f.79eb postgres: >STATEMENT: CREATE ROLE stig_test CREATEUSER; If audit records are not produced, this is a finding.

Fix

Configure PostgreSQL to produce audit records when unsuccessful attempts to execute privileged SQL. All denials are logged by default if logging is enabled. To ensure that logging is enabled, review supplementary stdout APPENDIX-C for instructions on enabling logging.

Test Results

  Result
Command: `sed -nre '/2019-05-16 08:11.*LOG:\s+starting tests for V-72969/,$p' /var/vcap/sys/log/postgresql/Thu.pg_log` stdout should match /ERROR:\s+must be superuser to create superusers/ passed
Command: `sed -nre '/2019-05-16 08:11.*LOG:\s+starting tests for V-72969/,$p' /var/vcap/sys/log/postgresql/Thu.pg_log` stdout should match /ERROR:\s+permission denied to create role/ passed
Command: `sed -nre '/2019-05-16 08:11.*LOG:\s+starting tests for V-72969/,$p' /var/vcap/sys/log/postgresql/Thu.pg_log` stdout should match /STATEMENT:\s+SET ROLE inspec_v72969_role; CREATE ROLE stig_test SUPERUSER;/ passed
Command: `sed -nre '/2019-05-16 08:11.*LOG:\s+starting tests for V-72969/,$p' /var/vcap/sys/log/postgresql/Thu.pg_log` stdout should match /STATEMENT:\s+SET ROLE inspec_v72969_role; CREATE ROLE stig_test CREATEDB;/ passed
Command: `sed -nre '/2019-05-16 08:11.*LOG:\s+starting tests for V-72969/,$p' /var/vcap/sys/log/postgresql/Thu.pg_log` stdout should match /STATEMENT:\s+SET ROLE inspec_v72969_role; CREATE ROLE stig_test CREATEROLE;/ passed
Command: `sed -nre '/2019-05-16 08:11.*LOG:\s+starting tests for V-72969/,$p' /var/vcap/sys/log/postgresql/Thu.pg_log` stdout should match /STATEMENT:\s+SET ROLE inspec_v72969_role; CREATE ROLE stig_test CREATEUSER;/ passed

Code

control "V-72969" do
  title "PostgreSQL must generate audit records when unsuccessful attempts to
  execute privileged activities or other system-level access occur."
  desc  "Without tracking privileged activity, it would be difficult to
  establish, correlate, and investigate the events relating to an incident or
  identify those responsible for one.
  System documentation should include a definition of the functionality
  considered privileged.

  A privileged function in this context is any operation that modifies the
  structure of the database, its built-in logic, or its security settings. This
  would include all Data Definition Language (DDL) statements and all
  security-related statements. In an SQL environment, it encompasses, but is not
  necessarily limited to:

  CREATE
  ALTER
  DROP
  GRANT
  REVOKE

  Note: That it is particularly important to audit, and tightly control, any
  action that weakens the implementation of this requirement itself, since the
  objective is to have a complete audit trail of all administrative activity.
  To aid in diagnosis, it is necessary to keep track of failed attempts in
  addition to the successful ones."

  impact 0.5
  tag "severity": "medium"
  tag "gtitle": "SRG-APP-000504-DB-000355"
  tag "gid": "V-72969"
  tag "rid": "SV-87621r1_rule"
  tag "stig_id": "PGS9-00-006500"
  tag "cci": "CCI-000172"
  tag "nist": ["AU-12 c", "Rev_4"]

  tag "check": "As the database administrator (shown here as \"postgres\"),
  create the role bob by running the following SQL:
    $ sudo su - postgres
    $ psql -c \"CREATE ROLE bob\"

  Next, change the current role to bob and attempt to execute privileged activity:
    $ psql -c \"CREATE ROLE stig_test SUPERUSER\"
    $ psql -c \"CREATE ROLE stig_test CREATEDB\"
    $ psql -c \"CREATE ROLE stig_test CREATEROLE\"
    $ psql -c \"CREATE ROLE stig_test CREATEUSER\"

  Now, as the database administrator (shown here as \"postgres\"), verify that
  an audit event was produced (use the latest log):
    $ sudo su - postgres
    $ cat ${PGDATA?}/pg_log/<latest_log>

  < 2016-02-23 20:16:32.396 EST postgres 56cfa74f.79eb postgres: >ERROR: must be
  superuser to create superusers
  < 2016-02-23 20:16:32.396 EST postgres 56cfa74f.79eb postgres: >STATEMENT:
  CREATE ROLE stig_test SUPERUSER;
  < 2016-02-23 20:16:48.725 EST postgres 56cfa74f.79eb postgres: >ERROR:
  permission denied to create role
  < 2016-02-23 20:16:48.725 EST postgres 56cfa74f.79eb postgres: >STATEMENT:
  CREATE ROLE stig_test CREATEDB;
  < 2016-02-23 20:16:54.365 EST postgres 56cfa74f.79eb postgres: >ERROR: p
  ermission denied to create role
  < 2016-02-23 20:16:54.365 EST postgres 56cfa74f.79eb postgres: >STATEMENT:
  CREATE ROLE stig_test CREATEROLE;
  < 2016-02-23 20:17:05.949 EST postgres 56cfa74f.79eb postgres: >ERROR: must be
  superuser to create superusers
  < 2016-02-23 20:17:05.949 EST postgres 56cfa74f.79eb postgres: >STATEMENT:
  CREATE ROLE stig_test CREATEUSER;
  If audit records are not produced, this is a finding."

  tag "fix": "Configure PostgreSQL to produce audit records when unsuccessful
  attempts to execute privileged SQL.
  All denials are logged by default if logging is enabled. To ensure that
  logging is enabled, review supplementary stdout APPENDIX-C for instructions
  on enabling logging."

  sql = postgres_session(PG_DBA, PG_DBA_PASSWORD, PG_HOST)
  log_directory_query = sql.query('SHOW log_directory;', [PG_DB])
  log_directory = log_directory_query.output
  current_log_command = "ls -1t #{log_directory}/*.pg_log | head -1"
  current_log = command(current_log_command).stdout.strip
  control = File.basename(__FILE__, File.extname(__FILE__))
  message = "starting tests for #{control}"
  message_sql = "DO language plpgsql $$ BEGIN "\
    "RAISE LOG '#{message}'; END $$;"
  start = Time.now.strftime('%Y-%m-%d %H:%M')
  get_logs = "sed -nre '/#{start}.*LOG:\\s+#{message}/,$p' #{current_log}"

  create_role = 'CREATE ROLE bob;'
  set_role = 'SET ROLE bob;'
  drop_role = 'DROP ROLE bob;'
  create_role_superuser = "#{set_role} CREATE ROLE stig_test SUPERUSER;"
  create_role_createdb = "#{set_role} CREATE ROLE stig_test CREATEDB;"
  create_role_createrole = "#{set_role} CREATE ROLE stig_test CREATEROLE;"
  create_role_createuser = "#{set_role} CREATE ROLE stig_test CREATEUSER;"
  permission_denied_error = 'permission denied to create role'
  must_be_superuser_error = 'must be superuser to create superusers'

  sql.query(message_sql, [PG_DB])
  sql.query(create_role, [PG_DB])
  sql.query(create_role_superuser, [PG_DB])
  sql.query(create_role_createdb, [PG_DB])
  sql.query(create_role_createrole, [PG_DB])
  sql.query(create_role_createuser, [PG_DB])
  sql.query(drop_role, [PG_DB])

  describe command(get_logs) do
    its('stdout') { should match /ERROR:\s+#{must_be_superuser_error}/ }
    its('stdout') { should match /ERROR:\s+#{permission_denied_error}/ }
    its('stdout') { should match /STATEMENT:\s+#{create_role_superuser}/ }
    its('stdout') { should match /STATEMENT:\s+#{create_role_createdb}/ }
    its('stdout') { should match /STATEMENT:\s+#{create_role_createrole}/ }
    its('stdout') { should match /STATEMENT:\s+#{create_role_createuser}/ }
  end
end