Re: Draft copy of how to write good events

Richard Guy Briggs
2014-09-04T22:04:23Z

[-- Attachment #1: Type: text/plain, Size: 919 bytes --]

On 14/09/03, Steve Grubb wrote:
> Hello,

Hi Steve,

> People have mentioned a couple times that they would like to know more about
> what is expected of well written events. I put together a draft document
> located here:
>
> http://people.redhat.com/sgrubb/audit/audit-events.txt

Thanks for pulling this together and posting it.

> The intention is to add this to the kernel documentation after people have had
> a chance to review it and send feedback. Any and all comments are welcome.

I assume the mix of new-, new_, old- and old_ are there due to
historical raisins and changing them would break userspace...

Here's a unified diff of a few obvious minor cleanups...

> -Steve

- RGB

--
Richard Guy Briggs <rbriggs@redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

[-- Attachment #2: audit-events-rgb1.txt --]
[-- Type: text/plain, Size: 15516 bytes --]

Guide to writing well formed audit events
=========================================

Background
----------
The audit system is a security subsystem that monitors the activities of
users based on admin defined rules to ensure compliance with organizational
security policies. The events should contain enough information that a
security officer can figure out what is happened on a system later. For
example, there may be a policy where access to files in a specific directory
are on a "need to know" basis. The security officer would restrict access
and allow intended access through group permissions or posix ACLs. But how
would he know if the intended security policy is working? The audit system
can be configured to watch who accesses those files and provide the
information. The security officer can then run reports periodically to make
sure no unusual access has occurred.

Events
------
An audit event is all records that have the same host (node), timestamp, and
serial number. Each event on a host (node) has a unique timestamp and serial
number. The serial number separates events that occur during the same
millisecond. An event may be composed of multiple records which have
information about different aspects of an audit event.

The audit system has been designed to be able to answer the question, "who did
what to whom and what was the result." These pieces of information have names.
The 'who' is the subject. This is the thing doing the action. It is usually
a process that is running on a user's behalf. The what is generally described
by the audit event type or a key (this is an admin defined name for the event).
It let's you know if we are dealing with a file access, login, system shutdown,
etc. The 'to whom' is called the object. The object is what is being acted
upon such as a file, socket, user account, or process. The result is either
success or fail. It either did or did not complete.

When writing events, the author will need to list several attributes so that
no doubt can be left as to what is being recorded. For example, if we are
recording the subject, you would naturally assume we are speaking of the
current uid, which is after all the user. Because of things like sudo or
su, users can change accounts sometimes. The audit system has a concept of
loginuid which is the account originally used to login. To perform an
action, the user invokes a process, so we likely want to show which process
is acting on the user's behalf. Is pid alone useful when reconstructing
events? Probably not, so we should record the executable name. It
turns out that if the user invoked a script, the executable is the interpreter,
so we also need the command name, too. Because users can log into multiple
sessions at the same time, we should also disambiguate which session they are
in with the sessionid. To summarize, we may need to record: uid, auid, pid,
exec, comm, ses fields just to specify exactly who the subject is. Some cases
may require more fields.

The same kind of process needs to be thought about when recording the object.
Suppose the object was a file. Files are located by an inode on a device.
However, it could be edited and the inode changes. So, we need to record the
path. But if the path could be relative, we need to also record the current
working directory. The inode could contain different kind of file objects like
a fifo, directory, socket, or a regular file, so that needs to be included. But
in case there is a question about whether access should have been allowed, we
should also gather attributes such as owner and access modes.

The event writer should always think about whether there has been enough information
recorded so that later a security officer knows what the event means.

Fields
------
An audit record is composed of multiple fields. Information recorded in these
fields is held by a name/value pair that contains an '=' between them
(name=value). Each field is separated from one another by a space.

The value recorded is typically numeric. No attempt should be made to interpret
the meaning of the value. For example, if uid=0 is being recorded, it is not
necessary to say that it's the root account. That can be looked up in post
processing.

If the value side is not numeric and user space can influence the
value (such as file names, unauthenticated acct names, process names, etc.)
then certain precautions will need to be taken. It may turn out that a clever
user may wish to trick naive parsing to pin blame on another account or to
make it look like something else was being accessed.

The established convention in this case is to scan the value string to see if
it has control characters. If it does not, the value is enclosed by a double
quote '"'. If it contains a control character, then the characters are
convertered to a hex character encoding so that parsing the field is
unmistakable. This can also be used for recording data structures if it were
ever needed. Hex encoding doubles the number of bytes needed to represent the
value. This is only done when recording a non-numeric value that user space can
control.

Field Names
-----------
Fields names in a record should be consistent so that the parser can make
sense of the value associated with a field. When writing events, always use
a known field name and don't make one up. If nothing fits, take a guess and
make sure you check with the linux-audit mail list to see if it's acceptable.
The value associated with the field needs to have the same formatting as
listed here or translations of the values can have errors. The following
list enumerates known field names:

a? - numeric, the arguments to a syscall
acct - encoded, a user's account name
addr - the remote address that the user is connecting from
arch - numeric, the elf architecture flags
argc - numeric, the number of arguments to an execve syscall
audit_backlog_limit - numeric, audit system's backlog queue size
audit_enabled - numeric, audit systems's enable/disable status
audit_failure - numeric, audit system's failure mode
auid - numeric, login user id
banners - alphanumeric, banners used on printed page
capability - numeric, posix capabilities
cap_fi - numeric, file inherited capability map
cap_fp - numeric, file permitted capability map
cap_fver - numeric, file system capabilities version number
cap_pe - numeric, process effective capability map
cap_pi - numeric, process inherited capability map
cap_pp - numeric, process permitted capability map
cipher - alphanumeric, name of crypto cipher selected
code - numeric, seccomp action code
comm - encoded, command line program name
cmd - encoded, command being executed
cwd - encoded, the current working directory
data - encoded, TTY text
default-context - alphanumeric, default MAC context
dev - numeric, in path records, major and minor for device
dev - in avc records, device name as found in /dev
device - encoded, device name
dir - encoded, directory name
direction - alphanumeric, direction of crypto operation
egid - numeric, effective group id
enforcing - numeric, new MAC enforcement status
entries - numeric, number of entries in the netfilter table
euid - numeric, effective user id
exe - encoded, executable name
exit - numeric, syscall exit code
family - numeric, netfilter protocol
fd - numeric, file descriptor number
file - encoded, file name
flags - numeric, mmap syscall flags
fe - numeric, file assigned effective capability map
fi - numeric, file assigned inherited capability map
fp - numeric, file assigned permitted capability map
fp - alphanumeric, crypto key finger print
format - alphanumeric, audit log's format
fsgid - numeric, file system group id
fsuid - numeric, file system user id
fver - numeric, file system capabilities version number
gid - numeric, group id
hostname - alphanumeric, the hostname that the user is connecting from
icmp_type - numeric, type of icmp message
id - numeric, during account changes, the user id of the account
igid - numeric, ipc object's group id
img-ctx - alphanumeric, the vm's disk image context string
ip - alphanumeric, network address of a printer
inode - numeric, inode number
inode_gid - numeric, group id of the inode's owner
inode_uid - numeric, user id of the inode's owner
item - numeric, which item is being recorded
items - numeric, the number of path records in the event
iuid - numeric, ipc object's user id
kernel - alphanumeric, kernel's version number
key - encoded, key assigned from triggered audit rule
kind - alphabet, server or client in crypto operation
ksize - numeric, key size for crypto operation
laddr - alphanumeric, local network address used in crypto session
lport - alphanumeric, local network port used in crypto session
list - numeric, the audit system's filter list number
mac - alphanumeric, crypto MAC algorithm selected
mode - numeric, mode flags on a file
model - alphanumeric, security model being used for virt
msg - alphanumeric, the payload of the audit record
nargs - numeric, the number of arguments to a socket call
name - encoded, file name in avcs
nametype - alphabet, kind of file operation being referenced
net - alphanumeric, network MAC address
new-disk - encoded, disk being added to vm
new-fs - encoded, file system being added to vm
new_gid - numeric, new group id being assigned
new-level - alphanumeric, new run level
new_pe - numeric, new process effective capability map
new_pi - numeric, new process inherited capability map
new_pp - numeric, new process permitted capability map
new-rng - encoded, device name of rng being added from a vm
obj - alphanumeric, lspp object context string
obj_gid - numeric, group id of object
obj_uid - numeric, user id of object
oflag - numeric, open syscall flags
ogid - numeric, file owner group id
old - numeric, old audit_enabled, audit_backlog, or audit_failure value
old-disk - encoded, disk being removed from vm
old_enforcing - numeric, old MAC enforcement status
old-fs - encode, file system being removed from vm
old-level - alphanumeric, old run level
old_pe - numeric, old process effective capability map
old_pi - numeric, old process inherited capability map
old_pp - numeric, old process permitted capability map
old_prom - numeric, network promiscuity flag
old-rng - encoded, device name of rng being removed from a vm
op - alphanumeric, the operation being performed that is audited
oauid - numeric, process login user id
ocomm - encoded, object's command line name
opid - numeric, object's process id
oses - numeric, object's session id
ouid - numeric, file owner user id
parent - numeric, the inode number of the parent file
path - encoded, file system path name
per - numeric, linux personality
perm - numeric, the file permission being used
perm_mask - numeric, file permission mask that triggered a watch event
pid - numeric, process id
printer - encoded, printer name
prom - numeric, network promiscuity flag
proctitle - encoded, process title and command line parameters
proto - numeric, network protocol
qbytes - numeric, ipc objects quantity of bytes
range - alphanumeric, user's SE Linux range
rdev - numeric, the device identifier (special files only)
reason - alphanumeric, text string denoting a reason for the action
res - alphanumeric, result of the audited operation(success/fail)
result - alphanumeric, result of the audited operation(success/fail)
role - alphanumeric, user's SE linux role
rport - numeric, remote port number
saddr - encoded, struct socket address structure
sauid - numeric, sending login user id
scontext - alphanumeric, the subject's context string
selected-context - alphanumeric, new MAC context assigned to session
seuser - alphanumeric, user's SE Linux user acct
ses - numeric, login session id
sgid - numeric, set group id
sig - numeric, signal number
sigev_signo - numeric, signal number
spid - numeric, sending process id
subj - alphanumeric, lspp subject's context string
success - alphanumeric, whether the syscall was successful or not
suid - numeric, sending user id
syscall - numeric, syscall number in effect when the event occurred
table - alphanumeric, netfilter table name
tclass - alphanumeric, target's object classification
tcontext - alphanumeric, the target's or object's context string
terminal - alphanumeric, terminal name the user is running programs on
tty - alphanumeric, tty udevice the user is running programs on
type - alphanumeric, the audit record's type
uid - numeric, user id
uri - alphanumeric, URI pointing to a printer
user - alphanumeric, account submitted for authentication
uuid - alphanumeric, a UUID
ver - numeric, audit daemon's version number
virt - alphanumeric, kind of virtualization being referenced
vm - encoded, virtual machine name
vm-ctx - alphanumeric, the vm's context string
watch - encoded, file name in a watch record

Maintenance
-----------
Over time compliance regulations change as do Common Criteria needs. Generally
once you write an event, you should never alter it. If you do, it's best to
send an email to the linux-audit mail list explaining what the change is prior
to implementing the change. This allows people that might have analysis
programs to know of the change or discuss options. Additionally, it may be
necessary to alter your event to change the formatting or field name or field
order over time. So, please get review to make sure everyone agrees and if
asked to make changes due to new requirements, please help out.

If you do make changes to your event, you should use the ausearch-test program
to make sure the new event is well formed. Passing the tests shows that the
event can still be searched, but you should also ask ausearch to interpret the
event to make sure any interpretation is what you expect. If not, then you have
problably used a pre-existing field name for a different purpose.

Logging Code Examples
---------------------
Kernel:

if (audit_enabled) {
struct audit_buffer *ab;
uid_t loginuid = from_kuid(&init_user_ns, audit_get_loginuid(current));
unsigned int sessionid = audit_get_sessionid(current);
char comm[sizeof(current->comm)];

ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_KERNEL_OTHER);
if (!ab)
return;
audit_log_format(ab, "auid=%u ses=%u" ,loginuid, sessionid);
audit_log_task_context(ab);
audit_log_format(ab, " comm=");
get_task_comm(comm, current);
audit_log_untrustedstring(ab, comm);
audit_log_end(ab);
}

User space:

char buf[4096], *acct;
int fd = audit_open();
acct = audit_encode_nv_string("acct", pamh->user, 0);
snprintf(buf, sizeof(buf), "op=change-password sauid=%d %s",
audit_getloginuid(), acct);
audit_log_user_message(fd, AUDIT_USER_CHAUTHTOK, "buf", NULL, NULL,
NULL, 0);
free(acct);
close(fd);

[-- Attachment #3: Type: text/plain, Size: 0 bytes --]