Find out which user accessed a particular file on what time in UNIX - linux

can someone suggest me any command that i can use to see which user accessed a particular file on what time in UNIX. I know history command lists the commands fired previously, but it doesn't include "who" fired it and on what time.

Use Linux auditd for a particular file
http://www.cyberciti.biz/tips/linux-audit-files-to-see-who-made-changes-to-a-file.html
Example
Let say I have a file (let it be $HOME/an_important_file.txt) and I want to watch all accesses to it. First set up audit rule for it:
$ sudo auditctl -w $PWD/an_important_file.txt -p warx -k watch_an_important_file
And checked the audit log:
$ sudo ausearch -k watch_an_important_file
----
time->Thu May 12 10:54:16 2016
type=CONFIG_CHANGE msg=audit(1463039656.913:278): auid=500 ses=1 subj=unconfined_u:unconfined_r:auditctl_t:s0-s0:c0.c1023 op="add rule" key="watch_an_important_file" list=4 res=1
Then I modified the file with touch ($ touch $HOME/an_important_file.txt). I am checking again the audit log:
$ sudo ausearch -k watch_an_important_file
----
time->Thu May 12 10:54:16 2016
type=CONFIG_CHANGE msg=audit(1463039656.913:278): auid=500 ses=1 subj=unconfined_u:unconfined_r:auditctl_t:s0-s0:c0.c1023 op="add rule" key="watch_an_important_file" list=4 res=1
----
time->Thu May 12 10:56:42 2016
type=PATH msg=audit(1463039802.788:291): item=1 name=(null) inode=535849 dev=fd:02 mode=0100664 ouid=500 ogid=500 rdev=00:00 obj=unconfined_u:object_r:user_home_t:s0 nametype=NORMAL
type=PATH msg=audit(1463039802.788:291): item=0 name="/home/Sergey.Kurenkov/" inode=524289 dev=fd:02 mode=040700 ouid=500 ogid=500 rdev=00:00 obj=unconfined_u:object_r:user_home_dir_t:s0 nametype=PARENT
type=CWD msg=audit(1463039802.788:291): cwd="/usr"
type=SYSCALL msg=audit(1463039802.788:291): arch=c000003e syscall=2 success=yes exit=3 a0=7fff6d986060 a1=941 a2=1b6 a3=3149b8f14c items=2 ppid=4852 pid=10022 auid=500 uid=500 gid=500 euid=500 suid=500 fsuid=500 egid=500 sgid=500 fsgid=500 tty=pts1 ses=1 comm="touch" exe="/bin/touch" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key="watch_an_important_file"

You can use stat to find out when a file was last accessed. This is only possible if your file system stores the atime of inodes. But this does not tell you who accessed the file.
You can use lsof to list processes which currently use a file. But you might not see processes of other users if your user has insufficient privileges (you can see all processes if you are root).
Normally the output of history is generated from a history file of the executing user. So you can assume that the commands printed by history where all executed by the same user. In some shells you can set an option in order to store the time of execution together with the command. Then you can also get this time with history. This might depend on the shell you are using.
You can read the man pages of stat, lsof, bash or zsh (or maybe ksh?) to learn more about this.

You can add these following lines in ~/.bashrc so that now history command
logs the commands in the [<user> 2016-05-11 14:04:33] <command> format. The below commands apply to all open interactive terminals.
export HISTFILESIZE=100000000
export HISTSIZE=100000000
# First two are optional, they need to be changed only if the default 500
# lines history logging needs to be changed
export HISTTIMEFORMAT="[$USER %F %T] "
HISTCONTROL=ignoredups:erasedups
shopt -s histappend
PROMPT_COMMAND="history -n; history -w; history -c; history -r; $PROMPT_COMMAND"
Original answer with modification done to store the $USER

Related

Monitoring the System Log File via Bash Script

I am currently using the following to read the system log:
journalctl -u <service name> | tail -n1
However I have a need to monitor the system log live, as changes come in (in a bash script), instead of just looping through the log file.
What is the best way to do this? I did some research to where the journalctl command is reading from, and it seems that the system logs are unreadable (or at least when I attempted with cat.
Any suggestions would be much appreciated!
journalctl tool has a -f flag which enables printing the contents of log file as soon as it is changed. Use it like this:
$ journalctl -u <service name> -f

Logging ssh sessions using tee and parsing file for user commands

I need to log ssh session of every user from the client side. I'm using the tee to do this
ssh abc#example.com | tee $(whoami).$(date).log
However, I only want to log user commands within the ssh session and skip the output of the command. For eg: If a user tailed a large file, I don't want to log the entire file.
I tried to grep for the command prompt and redirect the output to another file.
ssh abc#example.com | tee >(cat logfile) | grep "CMD_PROMPT_PATTTERN" >> $(whoami).$(date).log
But this does not work if the user changes the command prompt.
I wanted to know if there was a way to grep for linux commands from a text file.
Some related context:
I have read other posts which suggest adding a wrapper around ssh to do the logging.
But in this case, users can ssh to another host(say example2.com) from example.com and we need to log commands executed here as well from the starting host. I have also tried keystroke loggers but there is no way to distinguish commands executed by different users.
I'd appreciate any other suggestions to implement logging.
Why not tail -f user's .bash_history ? (or what shell they use), but 1st you will need to set "online" writing to it export PROMPT_COMMAND='history -a'

Linux cron job fails to execute part of script which works in shell

I'm having a problem with a script that writes to a log file during a backup procedure. Tested perfectly when called from the root shell, but fails when run from the cron demon.
Backup is done over a series of partitions and the on-site admin will rotate the drives in the top dock weekly. In order to know where the most recent backup is located I've included the following lines
sudo hdparm -I /dev/sdb | grep 'Model Number'
sudo hdparm -I /dev/sdb | grep 'Serial Number'
I've tried this with a >> /batch/backup.log and without.
When the bash script is run from the command line, it works beautifully. But when the crontab calls the script the output from these lines is blank.
crontab entry: 00 00 * * * /batch/backup.bat >> /batch/backup.log
I have no idea why other than the possibility that cron can't handle the pipe or the grep or something.
I have isolated the lines in a test.bat but they remain blank.
The backup script uses the hdparm to spin down the drive at the end, but now I wonder if that's not working properly either if cron can't handle hdparm.
That is probably because hdparm is not in the PATH when the script is executed through cron. Although less likely, same might apply to grep as well.
Try replacing hdparm with /full/path/to/hdparm in your script.
You need to either put this in the root crontab, or you need to store your password in plain text and pipe it into the sudo command. That second option is obviously NOT RECOMMENDED. See https://askubuntu.com/questions/173924/how-to-run-a-cron-job-using-the-sudo-command
As #Paul hinted, it is also possible to create a directive in /etc/sudoers to override the need for a password for a specific user / host / command combination. See https://askubuntu.com/a/159009
Copying just a little bit from that answer:
If your user is called user and your host is called host you could add these lines to /etc/sudoers:
user host = (root) NOPASSWD: /sbin/shutdown
user host = (root) NOPASSWD: /sbin/reboot
This will allow the user user to run the desired commands on host without entering a password. All other sudoed commands will still require a password.
Edit the crontab entry as below
00 00 * * * /batch/backup.bat 1> /batch/backup.op 2> /batch/backup.err
Standard output will be redirected to /batch/backup.op
Standard error will be redirected to /batch/backup.err
Check the errors in /batch/backup.err and fix

Detect use of su command in bash

I would like to know if there is anyway to send a mail as soon as someone tries su -, su or su root. I know the mail command and I am trying to write a script but I am very confused as to
where to write it - whether in .bashrc of root or in /etc/process
how to invoke the mail on the use of su
I've tried the usual Google search etc. but got links on usage of su, disabling it, securing ssh etc - none of which answered this question.
Thanks in advance
I guess that your underlying requirement is that you have a bunch of people you have given root privilege to but you don't completely trust them so you want to keep an eye on them. Your solution to this is to get yourself sent mail whenever they become root.
The problem with this solution is that the root user has unlimited privilege and so there's nothing to stop them from counteracting this mechanism. They could for instance, edit the /etc/login.defs file in one session, do the good thing that you want them to do and then later su to root and do the bad thing that you fear and at the end of that session they edit the /etc/login.defs file back to it's original state and you're none the wiser. Alternatively they could just make a copy of /usr/bin/bash and make the copy a suid file that will give them privilege whenever they run it.
You might be able to close any of the vulnerabilities I've just suggested but there will be many, many more. So you either trust them or else don't use su at all and give them sudo permission to run just those commands that they need to do the thing you want them to do.
There's a log file called /var/log/secure which receives an entry any time su is executed. It gets entries under other conditions as well. It's described in the Linux Administrator's Security Guide.
If user "fred" executes su -, an entry will appear which looks something like this:
Jul 27 08:57:41 MyPC su: pam_unix(su-l:session): session opened for user root by fred(uid=500)
A similar entry would appear with su or su root.
So you could set up a script which monitors /var/log/secure as follows:
#!/bin/sh
while inotifywait -e modify /var/log/secure; do
if tail -n1 /var/log/secure | grep " su: "; then
tail -n1 /var/log/secure | grep " su: " | mail -s "su occurred" you#email.com
fi
done
Note that you need to have the inotify-tool package installed to use inotifywait.
If this script is running in the background, it should send an email to you#email.com any time an su entry occurs.
Now where to run the script. One approach would be to put this into an executable script file (say, watchsu) and call it from your rc.local file:
nohup /path/to/watchsu 2>&1 &
I'm sure there are other ideas for where to start it. I'm not familiar with CentOS.
According to the man page for su, in /etc/login.defs you can set either SULOG_FILE file or SYSLOG_SU_ENABLE yes to log all su activity. Then you just need something like inotifywait to watch the log file for su events.

Suppress log entry for single sudo commands

For server monitoring, we execute couple of commands with password-less sudo every minute. This fills the server logs.
sudo: zabbix : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/foo/bar
Can I prevent these entries? The options NOLOG_INPUT and NOLOG_OUTPUT don't look like what I want.
I don't want to omit sudo's logging completely, only for the one user and the one (or more) command.
Is there a way to achieve this?
You can disable the logging on a user basis using the Defaults: directive
example (disabled logging for user bla)
Defaults:bla !syslog
or using a Cmnd_Alias to disable it per command(s)
Cmnd_Alias SCRIPT = /usr/local/bin/myscript
Defaults!SCRIPT !syslog
# multiple commands need a comma between them
Cmnd_Alias MORE = /bin/ls, /bin/cat
Defaults!MORE !syslog
Tested on Debian 6.0.6 with sudo version 1.7.4p4 (so rather old ;) )

Resources