V-72925

Severity: Medium

Generated

2019-05-20 15:48:11.984914

Status

Passed

PostgreSQL must generate audit records showing starting and ending time for user access to the database(s).

NIST 800-53

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

Guidance

For completeness of forensic analysis, it is necessary to know how long a user’s (or other principal’s) connection to PostgreSQL lasts. This can be achieved by recording disconnections, in addition to logons/connections, in the audit logs. Disconnection may be initiated by the user or forced by the system (as in a timeout) or result from a system or network failure. To the greatest extent possible, all disconnections must be logged.

Check

Note: The following instructions use the PGDATA environment variable. See supplementary content APPENDIX-F for instructions on configuring PGDATA. First, log into the database with the postgres user by running the following commands: $ sudo su - postgres $ psql -U postgres Next, as the database administrator, verify the log for a connection audit trail: $ sudo su - postgres $ cat ${PGDATA?}/pg_log/postgresql-Tue.log < 2016-02-23 20:25:39.931 EST postgres 56cfa993.7a72 postgres: >LOG: connection authorized: user=postgres database=postgres < 2016-02-23 20:27:45.428 EST postgres 56cfa993.7a72 postgres: >LOG: AUDIT: SESSION,1,1,READ,SELECT,,,SELECT current_user;, < 2016-02-23 20:27:47.988 EST postgres 56cfa993.7a72 postgres: >LOG: disconnection: session time: 0:00:08.057 user=postgres database=postgres host=[local] If connections are not logged, this is a finding.

Fix

Note: The following instructions use the PGDATA environment variable. See supplementary content APPENDIX-F for instructions on configuring PGDATA. To ensure that logging is enabled, review supplementary content APPENDIX-C for instructions on enabling logging. If logging is enabled the following configurations must be made to log connections, date/time, username, and session identifier. First, as the database administrator (shown here as “postgres”), edit postgresql.conf by running the following: $ sudo su - postgres $ vi ${PGDATA?}/postgresql.conf Edit the following parameters: log_connections = on log_disconnections = on log_line_prefix = ‘< %m %u %c: >’ Where: * %m is the time and date * %u is the username * %c is the session ID for the connection Now, as the system administrator, reload the server with the new configuration: # SYSTEMD SERVER ONLY $ sudo systemctl reload postgresql-9.5 # INITD SERVER ONLY $ sudo service postgresql-9.5 reload

Test Results

  Result
Command: `sed -nre '/2019-05-16 08:11.*LOG:\s+starting tests for V-72925/,$p' /var/vcap/sys/log/postgresql/Thu.pg_log` stdout should match /2019-05-16 08:11.*LOG: +connection authorized:\s+user=crunchy +database=stig_test_db/ passed
Command: `sed -nre '/2019-05-16 08:11.*LOG:\s+starting tests for V-72925/,$p' /var/vcap/sys/log/postgresql/Thu.pg_log` stdout should match /2019-05-16 08:11.*LOG:\s+disconnection: session time:.*user=crunchy\s+database=stig_test_db\s+host=(localhost|127.0.0.1)/ passed

Code

control "V-72925" do
  title "PostgreSQL must generate audit records showing starting and ending time
  for user access to the database(s)."
  desc  "For completeness of forensic analysis, it is necessary to know how long
  a user's (or other principal's) connection to PostgreSQL lasts. This can be
  achieved by recording disconnections, in addition to logons/connections, in
  the audit logs.
  Disconnection may be initiated by the user or forced by the system (as in a
  timeout) or result from a system or network failure. To the greatest extent
  possible, all disconnections must be logged."
  impact 0.5
  tag "severity": "medium"
  tag "gtitle": "SRG-APP-000505-DB-000352"
  tag "gid": "V-72925"
  tag "rid": "SV-87577r1_rule"
  tag "stig_id": "PGS9-00-004700"
  tag "cci": "CCI-000172"
  tag "nist": ["AU-12 c", "Rev_4"]
  tag "check": "Note: The following instructions use the PGDATA environment
  variable. See supplementary content APPENDIX-F for instructions on configuring
  PGDATA.
  First, log into the database with the postgres user by running the following
  commands:
  $ sudo su - postgres
  $ psql -U postgres
  Next, as the database administrator, verify the log for a connection audit trail:
  $ sudo su - postgres
  $ cat ${PGDATA?}/pg_log/postgresql-Tue.log
  < 2016-02-23 20:25:39.931 EST postgres 56cfa993.7a72 postgres: >LOG: connection
  authorized: user=postgres database=postgres
  < 2016-02-23 20:27:45.428 EST postgres 56cfa993.7a72 postgres: >LOG:
  AUDIT: SESSION,1,1,READ,SELECT,,,SELECT current_user;,<none>
  < 2016-02-23 20:27:47.988 EST postgres 56cfa993.7a72 postgres: >LOG:
  disconnection: session time: 0:00:08.057 user=postgres database=postgres
  host=[local]
  If connections are not logged, this is a finding."
  tag "fix": "Note: The following instructions use the PGDATA environment
  variable. See supplementary content APPENDIX-F for instructions on configuring
  PGDATA.
  To ensure that logging is enabled, review supplementary content APPENDIX-C for
  instructions on enabling logging.
  If logging is enabled the following configurations must be made to log
  connections, date/time, username, and session identifier.
  First, as the database administrator (shown here as \"postgres\"), edit
  postgresql.conf by running the following:
  $ sudo su - postgres
  $ vi ${PGDATA?}/postgresql.conf
  Edit the following parameters:
  log_connections = on
  log_disconnections = on
  log_line_prefix = '< %m %u %c: >'
  Where:
  * %m is the time and date
  * %u is the username
  * %c is the session ID for the connection
  Now, as the system administrator, reload the server with the new configuration:
  # SYSTEMD SERVER ONLY
  $ sudo systemctl reload postgresql-9.5
  # INITD SERVER ONLY
  $ sudo service postgresql-9.5 reload"

  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}"

  time = Time.now
  timestamp = time.strftime('%Y-%m-%d %H:%M')
  host = PG_HOST == '127.0.0.1' ? "(localhost|#{PG_HOST})" : PG_HOST
  connection_message = "#{timestamp}.*LOG:\s+connection authorized:"\
    "\\s+user=#{PG_DBA}\s+database=#{PG_DB}"
  connection_regex = Regexp.new(connection_message)
  disconnection_message = "#{timestamp}.*LOG:\\s+disconnection: session time:"\
    ".*user=#{PG_DBA}\\s+database=#{PG_DB}\\s+host=#{host}"
  disconnection_regex = Regexp.new(disconnection_message)

  sql.query(message_sql, [PG_DB])

  sql.query('SELECT now();', [PG_DB])

  describe command(get_logs) do
    its('stdout') { should match connection_regex }
    its('stdout') { should match disconnection_regex }
  end
end