Passwords for the Lazy

    Recently, one of the providers where I rent dedicated servers has been hacked. The damage was quite small, since backups are done daily. On the other hand, changing passwords for several dozens of accounts on a sleepless night before vacation is also not a joyful activity.

    The idea of ​​automating a password change drove the brain for a long time, several habratopics 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 a password from a correspondence two days ago, nothing could be done with him. Ideally, the system should generate and change a password immediately before the daily backup of each account.

    It’s easy to say - to automate the change of passwords on a Linux server - I haven’t seen this bash in your eyes (apart from bashorgh, of course), I’m doing completely different things in this life. However, the technique of dividing the task into the simplest steps and Google helped solve the problem in just one evening.

    Step one - 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, it’s better to do it 2 times at once to make it longer (then I'll show you why):

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

    Step three - from the resulting string of 64 characters, for example, select 27 characters from the position number today (i.e. 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 that it will fit in 64 characters or make the original 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 fifth step turned out to be the most difficult - iterating over the lines in the resulting list of users. After half an hour of experiments, the following (intermediate) option worked for me, which displayed the user name and the resulting blank for the password:

    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 a password is not a big deal. Therefore, I decided to complicate the situation a bit and the sixth step looked like this: In other words, we add the account name and “salt” to the hash collected from the current date, and then again calculate the hash from the result. By adding the “salt” known only to us, we “break” the structure of the algorithm, and adding the account name as well, we make the result hash unique for each of them. Since we are going to change passwords every day, we will let our paranoia go around and we will not make all passwords the same :)

    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 the process of finding a convenient password change command for the user, I came across a mention that bash has all the moves recorded. Indeed, the .bash_history file in the most insolent way showed me pieces of my experiments. Therefore, I had to study the history command and the -c switch as a seventh step.

    The eighth step, which, obviously, looked like this: The ninth, and the last step was to put it all together and add it to cron immediately before starting the daily backup. The script turned out to be something like this: Obviously visible shortcomings: - strong algorithmization, i.e. you can’t keep such a password in your head - only small letters and numbers are used, i.e. search dictionary is small

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




    #!/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





    - under the distribution of passwords, accounts may fall into which you do not need to change passwords (I won’t immediately think which ones, but for example on one of the servers I have a shell account for using PuTTy as a proxy - I would not want this account to change password every hour) .

    Advantages:
    - the password can be changed as often as desired (if you wish - you can use the date / time instead of the date and change the password once a minute or even per second)
    - frequent changes and a large length compensate for the simplicity of the dictionary (only small letters and numbers)
    - knowing the algorithm and the "salt" password can be easily generated 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 generate more complex passwords in this way, using different registers and service characters?
    - What other disadvantages does this implementation have?
    - What other advantages does this implementation have?
    - is it possible to compensate for these disadvantages or get rid of them altogether (for example, to neutralize password changes on some accounts, you can create a stop list and drop out the accounts that are in the stop list from the general list)?

    UPD: The very first comments made it necessary to clarify. Clients occasionally log into their account themselves (for example, in cPanel) and it is they who are more comfortable with a login / password rather than a login with a certificate. Shell for these accounts is usually disabled altogether (with very few exceptions).

    Also popular now: