Hello, the attached patches propose a way to audit administrative commands. Summary ------- A per-process "audit TTY input" attribute is added. The attribute is inherited across fork (). A new PAM module is used to turn the attribute on or off on login. Data read from TTYs by processes with the attribute is sent to the audit subsystem by the kernel. Optionally, user-space applications can send advisory audit events describing the "meaning" of the TTY input. Fundamental limitations ----------------------- Only TTY input is logged, so an administrator may execute unknown code by downloading shell scripts over the network. The act of downloading the shell script would be audited, however. For GUI or a complex TUI applications (e.g. emacs or mc), auditing the TTY input probably does not save enough information to reproduce the sequence of executed commands. If necessary, these applications may be extended to send advisory audit events. (Any approach to administrative action auditing would have to extend these applications). Why auditing needs to be done by the kernel ------------------------------------------- If system call auditing is not an option, there are simply too many applications that can be used to perform non-trivial administrative tasks that would have to be extended. All shells, most programming language interpreters, awk, m4, ... . In the worst case, the user might be using a proprietary shell. The system should also be able to handle at least the trivial workarounds like (cat | sh). So, if we can't audit the program actions (system calls), and we can't in general modify the programs themselves, the only remaining option is to audit the inputs to the programs - TTY input. This could be done in user-space by running all administrative sessions in a pseudo-TTY and auditing the data sent to the pseudo-TTY. Unfortunately that's not transparent enough, and changes behavior (after logging on to a text console, /dev/stdin is not a VT and can't be used to send VT ioctls - for a simple example, see /etc/profile.d/lang.sh on Fedora/RHEL). Auditing processes, not TTYs ---------------------------- If actions of ordinary users are not audited, after (su -) there are both administrative and non-administrative processes with the TTY open. The answer to the question "should this particular byte of input to the TTY be audited" depends on whether the byte is processed by an "administrative process", not on whether the TTY is /dev/tty1 or a PTY representing a ssh connection, or on whether an administrative process has ever been executed on the TTY since last hangup. Audit event generation based on a process-inherited flag has one additional advantage: If root within a (su -) session runs (su - unprivileged user), root's actions as the unprivileged user are audited. A potential problem with is approach is unwanted auditing of TTY input to system daemons run (or restarted) by an administrator; if the administrator restarts an *getty daemon, all inputs to the daemon would be audited. As a special hack, opening a TTY in a process that has no TTY currently open automatically disables the "audit TTY input" flag. Closing the current TTY and opening another one does not really make any sense in a regular application, but daemons which close all file descriptors on startup would be handled by the hack. If the hack doesn't handle a specific daemon automatically, the daemon could either be modified to disable auditing, or its startup scripts could explicitly close TTYs to activate the hack. Semantics of the logged data ---------------------------- The data is not logged byte by byte; a per-process buffer of data to be audited is kept, collecting the characters as they are read by the application. The contents of the buffer are audited if: - the buffer is full - ICANON is enabled and an EOL or EOF character is "delivered" to the application ("delivering EOF" doesn't actually provide any bytes) - ICANON is enabled or disabled - auditing TTY input is disabled for the process - the process exits - the process sends an advisory TTY input audit event. Thus, for applications using ICANON, input is audited line by line. For applications not using ICANON (e.g. uses readline), it is audited in blocks of N_TTY_BUF bytes. If the application is not using ICANON, it may send advisory messages; in that case, each "command" is audited using both the kernel's audit events containing the exact tty input (e.g. C-r up RET) and the advisory message (e.g. "yum upgrade"), and the raw input is always audited before the advisory messages. As a special case, input read when the TTY is using ICANON without ECHO is _not_ audited, to avoid storing passwords in the audit log. On the other hand, non-ICANON input is always audited (e.g. vim/emacs/mc input) in full. Note that passwords may still be audited if they are echoed, e.g. when sending CREATE USER commands to a SQL server. Attached code ------------- - a kernel patch, against a current-ish Linux tree. - a patch against audit-1.5.3 to recognize the new netlink message types - a PAM module which allows enabling/disabling TTY auditing on login - a patch against readline-5.2 to generate advisory audit events on returned strings. The exact same patch can be used for the readline copy included in bash-3.2. Unresolved questions: --------------------- The advisory audit events may be emitted by any process for which TTY input is audited, no additional privileges are necessary. Is it necessary to separately limit the rate of the generated events, or is the current kernel rate limit sufficient? Reading and modifying the "audit TTY input" attribute using a the audit netlink socket works, but it feels unnatural. Should it be done differently (e.g. /proc, prctl ())? Is it enough to allow an administrative process to read/modify its own "audit TTY input" attribute, or is it necessary to access the attribute of other processes? I'll be grateful for any comments. Mirek