PCI DSS req 10: Auditing, accounting, and histories

Title:Linux PCI DSS req 10
Author:Douglas O’Leary <dkoleary@olearycomputers.com>
Description:How to configure auditing on linux systems.
Disclaimer:Standard: Use the information that follows at your own risk. If you screw up a system, don’t blame it on me...


PCI DSS requirement 10 covers tracking and monitoring individual access to the system resources and cardholder data. This can be appropriately handled on a budget by implementing auditing for systems that actually house cardholder data, accounting, and updating the shell history naming convention.


PCI DSS requirement 10.2.1 requires that all individual access to PCI data is logged. Unfortunately, that means configurating auditing as I know of no way, in UNIX, to track individual access to files and directories outside of the auditing system. That is unfortunate as the raw audit logs have the most obtuse, arcane syntax that I’ve seen since assembly language. The good thing, though, is that it’s gotten significantly easier to manage and to get useful reports than it used to be.

So, with that in mind, here are details:

  • auditing should come standard with any major Linux variant. If it’s not installed, use the package manager of choice to look for the file: auditctl
  • The PCI_DSS standard requires auditing on any directories that have PCI data in them and any audit files themselves. So, on any system that needs auditing, there should be at least four rules: three for the audit directories and files and at least one more for the PCI data.
# auditctl -l
LIST_RULES: exit,always dir=/var/log/audit (0xe) perm=rwxa key=Audit          # audit directory
LIST_RULES: exit,always watch=/etc/auditd.conf perm=rwxa key=Audit            # audit conf file
LIST_RULES: exit,always watch=/etc/audit.rules perm=rwxa key=Audit            # audit rules
LIST_RULES: exit,always dir=/mnt/pci_audit_test (0x13) perm=rwxa key=PCI_test # PCI data
  • The syntax for the audit.rules file is very easy: effectively the command arguments given to auditctl. See the man page for auditctl for more information, particularly on the perms flag.
# tail -5 /etc/audit/audit.rules
# Feel free to add below this line. See auditctl man page
-w /var/log/audit -k Audit
-w /etc/auditd.conf -p rxwa -k Audit
-w /etc/audit.rules -p rxwa -k Audit
-w /mnt/pci_audit_test -k PCI_test
  • Please notice the key entries (-k argument) on the rules themselves. After configuring auditing, you generally shouldn’t have to do much with the audit processes themselves. However, if you ever have to dive into the details, having these keys added ahead of time will greatly aid your work. These keys are pre-defined search strings. So, instead of running ausearch and grep’ing for the audit files or directories, for instance, you can run have the ausearch command pull those out directly:
# ausearch -k Audit
[[358 lines snipped]]
  • The aureport command is used to translate the raw audit data into reasonably useful information. The aureport command is very useful and well worth the read of the man page. There are quite a few things that it can report. For instance:
# aureport -f -ts 9/14/2012 08:08:30
File Report
# date time file syscall success exe auid event
1. 09/14/2012 08:08:32 /var/log/audit 2 yes /sbin/aureport 0 56686
2. 09/14/2012 08:08:32 /var/log/audit/audit.log 2 yes /sbin/aureport 0 56687
3. 09/14/2012 08:08:32 /var/log/audit/audit.log.2 2 yes /sbin/aureport 0 56688
4. 09/14/2012 08:08:32 /var/log/audit/audit.log.1 2 yes /sbin/aureport 0 56689
5. 09/14/2012 08:08:32 /var/log/audit/audit.log 2 yes /sbin/aureport 0 56690
6. 09/14/2012 08:08:47 /var/log/audit/audit.log 2 yes /sbin/aureport 0 56692
7. 09/14/2012 08:08:47 /var/log/audit/audit.log.2 2 yes /sbin/aureport 0 56693
8. 09/14/2012 08:08:47 /var/log/audit/audit.log.1 2 yes /sbin/aureport 0 56694
9. 09/14/2012 08:08:47 /var/log/audit/audit.log 2 yes /sbin/aureport 0 56695
10. 09/14/2012 08:08:47 /var/log/audit 2 yes /sbin/aureport 0 56691

Those 10 lines of audit report easily encompass at least 100 lines of raw audit data...

  • Another very useful feature with Linux auditing is the capability of forwarding the events to syslog which can be then stored locally or forwarded to a Security Information and Event Monitor (SIEM). This functionality is enabled by editing the /etc/audisp/plugins.d/syslog.conf file and changing active to yes.
active = yes
direction = out
path = builtin_syslog
type = builtin
args = LOG_INFO
format = string
  • service auditd restart and your auditing is configured.
  • Note that the PCI standards also require daily log monitoring. With the unholy amount of data that the audit subsystem generates, that’s all but impossible to do manually. If you’re not using a SIEM, I suggest some type of script to automate the collection of aureport commands that are sent to a named individual(s) for review and sign off.


The PCI_DSS requirement 10.2.2 states that any action taken by anyone with access to root, as root or any other administrative account, has to be logged. The way I typically answer that requirement on PCI/SOX audits is to refer them to the shell history which I generally reconfigure from the default. More on that in a bit. While it’s not been a problem on the audits, the security issue with that answer is that the history file is basically a text file to which the user has direct access. So, if I wanted to hide some, but not all, of my actions, I could edit that file, remove the incriminating lines, and no one would be the wiser.

Turning on the accounting subsystem is the answer for the audits. The accounting system satisfies the letter of the requirement - the shell histories satisfy the spirit.

# chkconfig psacct on
# service psacct start

From there, any commands anyone runs will be logged to /var/account/psacct and logrotate will rotate the logs daily.

Please note, however, that this is more of a feel-good solution. It legitimately answers the requirements of the PCI DSS standard but, unfortunately, doesn’t really provide any actionable information. For instance:

# lastcomm -f ./pacct-20120914 dkoleary
bash                  X dkoleary  __         0.05 secs Thu Sep 13 14:25
sshd              SF    dkoleary  __         0.03 secs Thu Sep 13 14:25
bash               F    dkoleary  pts/3      0.00 secs Thu Sep 13 14:32
bash               F    dkoleary  pts/3      0.00 secs Thu Sep 13 14:31
cp                      dkoleary  pts/3      0.00 secs Thu Sep 13 14:31
cat                     dkoleary  pts/3      0.00 secs Thu Sep 13 14:30
ls                      dkoleary  pts/3      0.00 secs Thu Sep 13 14:30
ls                      dkoleary  pts/3      0.00 secs Thu Sep 13 14:30

The accounting subystem tells you the exact commands that were being executed - not what they were being executed on or why. For that, you need to go back to the shell history.

# tail ~dkoleary/.bash_history
ls -la
ssh-keygen -t dsa
ls -la
cd .ssh
ls -l
cat id_dsa.pub
cp id_dsa.pub /etc/sshkeys/authorized_keys.dkoleary

So, while the accounting subsystem will satisfy the requirements of PCI_DSS, it’s not overly useful for figuring out what someone was doing after the fact. For that, you need to go back to the shell history.

Shell histories

Third, shell histories: I strongly recommend that the shell history naming convention be changed from the default. This is easily done and circumvents a number of problems:

  1. If you have more than one window open, using the default shell history, each window is writing to the same file so the last command you executed in one window may not be the last command in the shell history.
  2. This issue is compounded if more than one person is logged in as root at the same time. Now, you have two more more people writing to the same file which can cause someone working quickly to inadvertently run the wrong command (experience talking there...).
  3. Lastly, changing the default shell history will allow you to keep your shell histories longer. One perfect example is you spend several hours working out how to do something particularly intensive. If you forget to write the process down, you can go back to the previous shell history to remind yourself how it was done. With the default history, the data will eventually scroll off the history file after 2048 lines.

So, how to change the history file location: as one of the first command sets in either ~/.bash_profile or ~/.bashrc, add these lines:

[[ ! -d ~/history ]] && mkdir -p -m 700 ~/history
Dts=$(date +%y%m%d_%H:%m:%S)

If you ssh in directly as root, your shell history will be: /root/history/.sh_history_root_120914_08:09:37; if you log in as yourself, and su to root, your shell history will be: /root/history/.sh_history_dkoleary_120914_08:09:15

Notice that there is a date/time stamp as part of the filename. If you log in using a separate window or if someone else logs in, you will have separate shell histories and won’t be clobbering each other’s commands. Also, the files will be retained making research into past activities much easier as well as convincing auditors that you can find out what someone was doing...


This document covers configuring auditing, turning on accounting, and reconfiguring the shell history file names. These actions will satisfy a good portion of PCI DSS requirement 10. Installing a file integrity monitoring tool like tripwire or OSSEC will satisfy most of the rest of req 10. Those topics, though, are beyond the scope of this doc.

Doug O’Leary