Send email when user changes password - linux

I have a remote server to which I login using ssh. Is there a way to be notified through email (using a bash script) when someone changes the user password using passwd including the new password?
I am guessing it has to do with /etc/pam/passwd, but not entirely sure what the trigger and flags should be.
This would be useful if for example I give my access to a "friend" and they decide to lock me out of my account. Of course I could create a new account for them etc, but this is more of a "it should be possible" task rather than a practical one.

First, a Dope Slap
There's a rule that this question reminds me of... What is it? Oh yeah...
NEVER SHARE YOUR PASSWORDS WITH ANYONE!
Which also goes well with the rule.
NEVER SEND SOMETHING SECRET THROUGH EMAIL!
Sorry for the shouting. There's a rule in security that the likelihood a secret will get out is the square of the number of people who know it. My corollary is:
if ( people_who_know_secret > 1 ) {
It ain't a secret any more
}
In Unix, even the system administrator, the all powerful root, doesn't know your password.
Even worse, you want to email your password. Email is far from secure. It's normally just plain text sent over the Aether where anyone who's a wee bit curious can peek at it.
Method One: Allowing Users to use SSH without Knowing Your Password
Since you're using SSH, you should know that SSH has an alternate mechanism for verifying a user called Private/Public keys. It varies from system to system, but what you do is create a public/private key pair. You share your public key with the system you want to log into, but keep your private key private.
Once the remote machine has your public key, you can log into that system via ssh without knowing the password of that system.
The exact mechanism varies from machine to machine and it doesn't help that there are two different ssh protocols, so getting it to work will vary from system to system. On Linux and Macs, you generate your public/private key pair through the ssh-keygen command.
By default, ssh-keygen will produce a file called $HOME/.ssh/id_rsa.pub and $HOME/.ssh/id_rsa. The first one is your public key. You run ssh-keygen on both your machine and the machine you want to log into.
On the machine you're logging into, create a file called $HOME/.ssh/authorized_keys, and copy and paste your public key into this file. Have your friend also send you his public key, and paste that into the file too. Each public key will take up one line in the file.
If everything works, both you and your friend can use ssh to log into that remote machine without being asked for a password. This is very secure since your public key has to match your corresponding private key. If it doesn't you can't log in. That means even if other popel find your public key, they won't be able to log into that remote system.
Both you and your friend can log into that system without worrying about sharing a password.
Method Two: A Better Solution: Using SUDO
The other way to do this is to use sudo to allow your friend to act as you in certain respects. Sudo has a few advantages over actually sharing the account:
All use of SUDO is logged, so you have traceability. If something goes wrong, you know who to blame.
You can limit what people can do as SUDO. For example, your friend has to run a particular command as you, and nothing else. In this case, you can specify in the /etc/sudoers file that your friend can only run that one particular command. You can even specify if your friend can simply run the command, or require your friend to enter their password in order to run that command.
On Ubuntu Linux and on Macintoshes, the root password is locked, so you cannot log in as root. If you need to do something as root, you set yourself up as an administrator (I believe by putting yourself in the wheel group) and then using sudo to run required administrator functions.
The big disadvantage of Sudo is that it's more complex to setup and requires administrator access on the machine.
Try setting up public/private keys using SSH. It might take some tweaking to get it to work, but once it works, it's beautiful. Even better, you can run remote commands and use sep to copy files from one machine to the other -- all without the password prompt. This means that you can write shell scripts to do your work for you.
By the way, a sneaky trick is to set your remote shell to /bin/false. That way, you can't log into that system -- even using ssh, but you can run remote commands using ssh and use sep to copy files back and forth between systems.

Personal passwords are only supposed to be known by the user themselves. Not even the root user is supposed to know them, which is why they are stored encrypted. Of course, the root user has sufficient access to decrypt them, but the principle is the same.
If you are giving your "friend" access, them assign them proper privileges! Do not make them a root user, and you shouldn't be a root user either. Then you're "friend" won't have access to change your password, let along muck about in areas they aren't supposed to be in.
If you absolutely must monitor the passwd and shadow files, install iwatch. Then set it to watch the /etc/passwd and /etc/shadow files. If they change, it runs a script that decrypts the file and emails someone. If you keep a copy to diff against, you'll even know who changed. You should probably also gpg the email, so that it does not go over the internet in plain text, since it has everyone's password in it. Please note that any other users on the system will be upset by the dystopian world they find themselves in.
Just because root is the law of the land does not mean we want to be living in 1984.

Try some kind of:
alias passwd='passwd && echo 'Alert! Alert! Alert!' | mail -s 'pass change' alert#example.com'
Should be enough for you:)
Another possible solutions for those, who think, that alias is too mainstream)) :
1) You could make a cron job, that will be checking your /etc/shadow file every, for example, minute, and when the file changes, it will send you an alert-email. The easiest way here, I think, will be making md5 checksum
2) You can move /usr/bin/passwd to /usr/bin/passwd.sys and make a script with /usr/bin/passwd.sys && echo 'Alert! Alert! Alert!' | mail -s 'pass change' on it's place. And yes, this way is also could be discovered be the user and scrubed round:)

Related

External script for account using pam_exec for openssh

I have a PHP application, with Usernames and Public SSH Keys in it. I would like to use these accounts as the user back end of openssh.
I think I need to use pam_exec and a PHP/Bash script. I've written a php script that I can execute at CLI (The shebang sets an env of php executable). If I need to wrap this in a bash script instead to access environment variables I can do that. The script currently takes a username as its first and only parameter like so:
/opt/scripts/my-auth-script.php user_to_look_for
The script will exit zero on success (the user exists) or exit 1 if not. It currently echoes OK or Failed also but I can easily turn that off.
So, my question is, how do I have pam_exec call my script to look for user accounts, before looking on the actual host system for user accounts?
I've got it working. The way to do this is to set the AuthorizedKeysCommand and AuthorisedKeyUser settings of openssh in sshd_config. There is a caveat, the reason that github and others provide ssh as a service through a single login user shared among customers is that the user being called must be resolvable by the system being logged into, so they muxt exist locally, or the user db must be connected to a remote source like LDAP, which would also then have to be integrated into the application.
The way to get around this though, is that the AuthorizedKeyCommand can take parameters, %u for username, and also in this case %k for key or %f for sha256 fingerprint of the key. Then, that script can ignore the generic username it was given, and then just check the database for a match for the key or fingerprint. If we find it, we have the user for that key and successful authentication. If not we dont.

Perform multiple command on 1000 remote servers?

I have the scenario to perform multiple linux commands on 1000 servers(linux) for the auditing purpose.What i feel is ssh & copying key to the remote hosts are bit tough to do on all the 1000-1500 server. Is there is any possibility to achieve that.
In fact i heard some where about rcmd command utility.But i'm not able to find the exact work done.
Regards,
Sarvan
Maybe you can give a try for "sshrun" script. It takes a list of servers in a text file and run the commands from another text file. I have used that script for a similar maintenance purpose for a bunch of servers. It is able to use commands needing "sudo" at the destination.
http://www.homelinuxpc.com/download/sshrun_user_guide.pdf
http://www.homelinuxpc.com/download/sshrun.tar.gz
You may need also "autopass" if you need to type password for each server:
http://www.homelinuxpc.com/download/autopass_user_guide.pdf
http://www.homelinuxpc.com/download/autopass.tar.gz
That "autopass" is a combined bash/expect script. It asks password once and whenever remote server is asking password it will respond with that password. "autopass" can be used to run that "sshrun" to avoid typing password manually for example 1000 times.

What is the best way to implement public key authentication in my automated root password change script?

Here are some details about my setup...
Current environment:
40+ *nix systems managed by 6 admins
Highly secure, closed network (no internet access)
Regularly audited (all account passwords must be changed every 90 days)
Current procedures:
Each administrator has a personal account with sudo access. These admin accounts are managed via Active Directory so password changes are not an issue
Root account is also active for specific circumstances (i.e. admin account is locked out)
When it comes time to change the root passwords, an admin will do so by SSHing into each system (40+)
I want to write a script to make the root password changing process more efficient and everything I've read indicates that the most secure way to go about it is by using public key authentication. So my question is: If I log in as root to SYSTEM_1 and set up the public/private key pairs between that system and SYSTEM_2, SYSTEM_3, etc, does that mean I will only be able to run the script from SYSTEM_1? Is this even a good idea security wise? Are there any other ways to script this that I am missing?
You can use RSA Authentication and expect script
Let's say you are executing expect script on system 1, create public-private key pair and store public key on all the other systems you have to login (system 2.....n)
Now you wont need a password when you ssh into those system.
Now you can use expect script to change password for either root or any other user.
NOTE : usually expect interpreter is at /usr/bin/expect
you can find this my doing "whereis expect"
I hope it helps.
Try to use this algorithm and post your results.

How to give password in shell script?

In a shell script file I am using some commands like scp and make install which ask for my password.
I run a shell script to compile a big project, and after some time it asks for my password for using scp. I need to wait for that process and give the password after that.
I just want to do it all by shell script without interaction, so how can I avoid being prompted for the password here?
Short answer: DON'T
Use public key authentication for SCP and sudo with NOPASSWD directive for make install
If you can't use ssh trust and must enter the password later on in your script, use read -s -p "Password:" USER_PASSWORD to silently read in the password. You can then export USER_PASSWORD to an expect script, avoiding it being displayed in ps:
#!/usr/bin/expect -f
spawn scp some.file USER#otherhost:~
expect "assword:"
send -- "$env(USER_PASSWORD)\r"
expect eof
I think it's a better idea to generate an authentication key, and use this key based authentication instead of writing plain text passwords into your scripts.
No, you won't find any method to use SSH config files or a command line option to have a password hard coded and I'm sure this is by design.
If you environment makes this difficult, perhaps it would be helpful to know that the script can specify an identity file using the -i argument so you don't have to have a whole home directory setup or anything like that. There are other options that help use the key authentication that ssh really encourages over password authentication.
If you are using this across several users who you don't want to be bothered to create keys and copy them to the server, you could script that also. It wouldn't be hard to check for an existing key and do a quick test to see if you can make a connection with it. If you can't without a password, then you'd ssh-copy-id to the server asking for the ssh password that one time and at the beginning of the script so very little lag would occur between starting and running the script and it would be only once. You could even setup a separate key for each user for just the script in their own ~/.script/key/ directory so that you would discourage users access to the SSH server.
If you want to really restrict what can be done on the remote server by that user, you could use rssh as the shell on the remote account which will limit the user access to transferring files.
A good way we did this in the past to provide passwords to needed scripts when using key based authentication was impossible or needed to use passwords for apps, services, mysql, whatever...we stored passwords in an encrypted file and then decrypted this file at runtime to provide the password to the scripts.
The password decryption script, let's call it, yourcreds.rb, was restricted to root use only of course and the unencrypted passwords wern't stored anywhere. So for example you could run:
root#host:~# yourcreds.rb | grep mysql | awk {'print $3'}
Which without awk would for example output the stored line:
service | user | password | description | etc...
mysql mysqluser password ....
With yourcreds.rb (or whatever) you can output just the password and easily incorporate this method into scripts / cron jobs in larger or more complex environments.
Also if I remember correctly we didn't have to use grep / awk or anything. We just programmed in opts parse stuff like: yourcreds.rb list mysql or yourcreds.rb -l, etc.
We used blowfish and yamls to store the encrypted passwords. I'm sure you can be creative. Just make sure it's bullet proof to anyone but root.

Obscuring network proxy password in plain text files on Linux/UNIX-likes

Typically in a large network a computer needs to operate behind an authenticated proxy - any connections to the outside world require a username/password which is often the password a user uses to log into email, workstation etc.
This means having to put the network password in the apt.conf file as well as typically the http_proxy, ftp_proxy and https_proxy environment variables defined in ~/.profile
I realise that with apt.conf that you could set chmod 600 (which it isn't by default on Ubuntu/Debian!) but on our system there are people who need root priveleges .
I also realise that it is technically impossible to secure a password from someone who has root access, however I was wondering if there was a way of obscuring the password to prevent accidental discovery. Windows operates with users as admins yet somehow stores network passwords (probably stored deep in the registry obscured in some way) so that in typical use you won't stumble across it in plain text
I only ask since the other day, I entirely by accident discovered somebody elses password in this way when comparing configuration files across systems.
#monjardin - Public key authentication is not an alternative on this network I'm afraid. Plus I doubt it is supported amongst the majority of commandline tools.
#Neall - I don't mind the other users having web access, they can use my credentials to access the web, I just don't want them to happen across my password in plain text.
With the following approach you never have to save your proxy password in plain text. You just have to type in a password interactively as soon as you need http/https/ftp access:
Use openssl to encrypt your plain text proxy password into a file, with e.g. AES256 encryption:
openssl enc -aes-256-cbc -in pw.txt -out pw.bin
Use a (different) password for protecting the encoded file
Remove plain text pw.txt
Create an alias in e.g. ~/.alias to set your http_proxy/https_proxy/ftp_proxy environment variables (set appropriate values for $USER/proxy/$PORT)
alias myproxy='PW=`openssl aes-256-cbc -d -in pw.bin`; PROXY="http://$USER:$PW#proxy:$PORT"; export http_proxy=$PROXY; export https_proxy=$PROXY; export ftp_proxy=$PROXY'
you should source this file into your normal shell environment (on some systems this is done automatically)
type 'myproxy' and enter your openssl password you used for encrypting the file
done.
Note: the password is available (and readable) inside the users environment for the duration of the shell session. If you want to clean it from the environment after usage you can use another alias:
alias clearproxy='export http_proxy=; export https_proxy=; export
ftp_proxy='
I did a modified solution:
edit /etc/bash.bashrc and add following lines:
alias myproxy='read -p "Username: " USER;read -s -p "Password: " PW
PROXY="$USER:$PW#proxy.com:80";
export http_proxy=http://$PROXY;export Proxy=$http_proxy;export https_proxy=https://$PROXY;export ftp_proxy=ftp://$PROXY'
From next logon enter myproxy and input your user/password combination! Now work with sudo -E
-E, --preserve-env
Indicates to the security policy that the user wishes to reserve their
existing environment variables.
e.g. sudo -E apt-get update
Remark: proxy settings only valid during shell session
There are lots of ways to obscure a password: you could store the credentials in rot13 format, or BASE64, or use the same password-scrambling algorithm that CVS uses. The real trick though is making your applications aware of the scrambling algorithm.
For the environment variables in ~/.profile you could store them encoded and then decode them before setting the variables, e.g.:
encodedcreds="sbbone:cnffjbeq"
creds=`echo "$encodedcreds" | tr n-za-mN-ZA-M a-zA-Z`
That will set creds to foobar:password, which you can then embed in http_proxy etc.
I assume you know this, but it bears repeating: this doesn't add any security. It just protects against inadvertently seeing another user's password.
Prefer applications that integrate with Gnome Keyring. Another possibility is to use an SSH tunnel to an external machine and run apps through that. Take a look at the -D option for creating a local SOCKS proxy interface, rather than single-serving -L forwards.
Unless the specific tools you are using allow an obfuscated format, or you can create some sort of workflow to go from obfuscated to plain on demand, you are probably out of luck.
One thing I've seen in cases like this is creating per-server, per-user, or per-server/per-user dedicated credentials that only have access to the proxy from a specific IP. It doesn't solve your core obfuscation problem but it mitigates the effects of someone seeing the password because it's worth so little.
Regarding the latter option, we came up with a "reverse crypt" password encoding at work that we use for stuff like this. It's only obfuscation because all the data needed to decode the pw is stored in the encoded string, but it prevents people from accidentally seeing passwords in plain text. So you might, for instance, store one of the above passwords in this format, and then write a wrapper for apt that builds apt.conf dynamically, calls the real apt, and at exit deletes apt.conf. You still end up with the pw in plaintext for a little while, but it minimizes the window.
Is public key authentication a valid alternative for you?
As long as all three of these things are true, you're out of luck:
Server needs web access
Users need absolute control over server (root)
You don't want users to have server's web access
If you can't remove #2 or #3, your only choice is to remove #1. Set up an internal server that hosts all the software updates. Keep that one locked down from your other users and don't allow other servers to have web access.
Anything else you try to do is just fooling yourself.
we solved this problem by not asking for proxy passwords on rpm, apt or other similar updates (virus databases, windows stuff etc)
That's a small whitelist of known repositories to add to the proxy.
I suppose you could create a local proxy, point these tools through that, and then have the local proxy interactively ask the user for the external proxy password which it would then apply. It could optionally remember this for a few minutes in obfuscated internal storage.
An obvious attack vector would be for a privileged user to modify this local proxy to do something else with the entered password (as they could with anything else such as an email client that requests it or the windowing system itself), but at least you'd be safe from inadvertent viewing.

Resources