📜 ⬆️ ⬇️

Passwords for the lazy

Recently, one of the providers where I rent dedicated servers was hacked. The damage was fairly small, since backups are done daily. On the other hand, changing passwords for several dozen accounts on a sleepless night before the holidays is not a joyful activity either.

The idea of ​​automating the change of passwords sverbil brain for quite a long time, several Habratopikov pushed in the right direction. The idea was simple - to change passwords as often as possible (for example, every day), so that even if someone got the password from a correspondence two days ago, nothing could be done with it. Ideally, the system should generate and change the password immediately before the daily backup of each account.

It is easy to say - to automate the change of passwords on the Linux server - I have never seen this bash of yours (not counting the bootlog, of course), I do something completely different in this life. However, the method of breaking the problem into simple steps and Google helped solve the problem literally in one evening.

Step one - we get MD5 hash from some string, for example, from today's date:
')
echo -n $(date +%F) | md5sum

Step two - assign this pleasure to some variable, better 2 times at once, so that it will be longer (then I will show why):

a=$(echo -n $(date +%F) | md5sum) && a=${a:0:32}${a:0:32}

The third step - from the resulting string of 64 characters in length, choose, for example, 27 characters from the position number today (ie, if today is the third of August, then starting from the third position). Thus, on the 31st day of the month we are guaranteed to fit into a string of 64 characters (31 + 27 = 58). You can choose any other number, the main thing is to fit in 64 characters or to make the source string longer.

hs=${a:$(date +%d):27}

The next, fourth step is to get a list of all accounts on the server. I was satisfied with this option (if someone offers a more accurate one, I will be grateful):

cat /etc/passwd | grep "/home" | cut -d: -f1

The most difficult was the fifth step - searching the lines in the resulting list of users. After half an hour of experiments, I earned the following (intermediate) version, which showed me the name of the user and the resulting password stub:

lines=($(cat /etc/passwd | grep "/home" | cut -d: -f1))

for i in "${lines[@]}"
do
echo "$i" : $hs
done


It is clear that if you just leave this option, then knowing the algorithm itself to pick up the password is not a big deal. Therefore, I decided to complicate the situation a little and the sixth step for me looked like this:

salt="abracadabra"
lines=($(cat /etc/passwd | grep "/home" | cut -d: -f1))

for i in "${lines[@]}"
do
echo "$i" : $hs
s=$salt"$i"$hs
newhash=$(echo -n "$s" | md5sum)
done


In other words, we add the account name and “salt” to the hash collected from the current date, after which we again calculate the hash of the result. By adding the “salt” known only to us, we “break” the structure of the algorithm, and by adding the account name we also make the hash of the result unique for each of them. Since we are going to change passwords every day, we’ll let our paranoia go wild and we will not make all passwords the same :)

In the process of finding a convenient command to change the password for the user, I came across the mention of the fact that bash has all the moves recorded. And indeed, the .bash_history file in the most brazen way showed me pieces of my experiments. Therefore, I had to study the history command and the –c key as the seventh step.

The eighth step, which obviously looked like this:

cmd=`echo "$i":$newhash | chpasswd`
echo $cmd


The ninth and last step was to put it all together and add it to cron immediately before starting the daily backup. The script turned out like this:

#!/bin/bash
#
# Prep some salt
salt="abracadabra"

# Calculate hash from today's date and add it to itself
a=$(echo -n $(date +%F) | md5sum) && a=${a:0:32}${a:0:32}

# Strip 27 characters starting from the character number of today's day of month
hs=${a:$(date +%d):27}

# Grab users into array
lines=($(cat /etc/passwd | grep "/home" | cut -d: -f1))

# For each user create a new pass with salt + user name + hash
#
for i in "${lines[@]}"
do
s=$salt"$i"$hs
newhash=$(echo -n "$s" | md5sum)
newhash=${newhash:0:27}
# echo "$i" : $salt"$i"$hs : $newhash # print this out if you want to
cmd=`echo "$i":$newhash | chpasswd`
echo $cmd
done
history -c


Clearly visible flaws:
- strong algorithmization, i.e. you can't keep such a password in your head
- only small letters and numbers are used, i.e. dictionary for brute force is small
- accounts that do not need to change passwords can get into the distribution of passwords (I won’t figure out what they are at once, but for example on one of the servers I have a shell account to use PuTTy as a proxy - I wouldn’t want this account to change the password every hour) .

Advantages:
- the password can be changed as often as desired (if there is a desire - you can use the date / time instead of the date and change the password once a minute or even per second)
- frequent change and long length compensate for the simplicity of the dictionary (only small letters and numbers)
- knowing the algorithm and the "salt" password is easy to generate on any machine without fear for its safety - anyway, the next day / hour / minute :) the password will be different
- ease of automation, customizability (you can always tweak the algorithm for yourself) and as a result - significant time savings on changing passwords for a large number of accounts.

Questions:
- Is it possible to similarly generate more complex passwords using different registers and service characters?
- what are the other disadvantages of this implementation?
- what other advantages does this implementation have?
- can these disadvantages be compensated or get rid of them altogether (for example, in order to counteract changing passwords on some accounts, you can create a stop list and discard accounts from the general list that are in the stop list)?

UPD: The very first comments made it necessary to clarify. Clients occasionally log in to their account (for example, in cPanel) and it is for them that the login / password is more convenient, and not the certificate login. Shell for these accounts, as a rule, is disabled altogether (with very few exceptions).

Source: https://habr.com/ru/post/66029/


All Articles