Bugs in your script
If you think this script runs great, you haven't tested it enough.
There is a classic vulnerability in your script: insecure temporary file. You attempted to protect from it, but in an overly complicated way, and you shot yourself in the foot.
random=$(tr -dc [:digit:] </dev/urandom | head -c2)
random
is set to two random digits. There's a 1% chance that this returns 01
, which causes random2
to be set to a string of length 1. If you run this script every 10 minutes, this happens about once or twice a day. (Actually that's an underestimate: the vulnerability remains practically exploitable if for 02
(~4k files) and perhaps 03
(~240k files).) A local user can create all the files /tmp/.0
, /tmp/.1
, etc. When the 1% chance hits, your script writes to a file owned by that user then reads back from it. The user can modify the file in the meantime to put their preferred root password. This is a race condition, so an exploit might not be 100% reliable, but it should only take a few days of waiting before it succeeds.
Another vulnerability that doesn't require a race condition on top of the random chance is that the local user could create a symbolic link, allowing them to truncate a file of their choice (your call to shred
truncates the file contents, then removes the link).
There's also a 3% chance that random2
will be an empty string: when random
is 00. In that case, your script runs
chmod 0400 /tmp`. That's going to cause a lot of disruption.
Lessons learned
Well, lessons to learn, at any rate.
- Catch errors. Your script assumes that everything happens correctly and keeps going forward even if it's just banged its head against a wall. Use
set -e
to abort the script if an error occurs. (It doesn't always suffice in complex scripts, but here it would have been enough.)
- Use standard tools in preference to home-built solutions. To create a temporary file, use
mktemp
.
- Understand why you're doing things. Creating a file in
/tmp
with a random name protects against insecure temporary files. But making the length of the name random makes no sense. It's a security parameter. Make it constant, or make it vary based on the configuration or the environment if it's a compromise between security and usability or performance; in this case, you could make it large enough at no performance penalty.
- The best way to protect data is not to expose it. Using a temporary file is not useful here: you could have piped the data to
chpasswd
. If you pipe the data, it's never in a disk file in the first place, so you don't need to worry about creating the temporary file securely and you don't need to worry about wiping it afterwards.
No security gain
Including the current date in a password is pointless. The point of passwords is to be secret. Everybody knows the date.
Changing a password doesn't make it any harder to crack. The attacker's goal is to find the current password, whichever it is. That the password changed in the past and will change in the future doesn't matter.
If somebody cracks your password at a given time and it no longer works later, they'll see the date and figure out pretty quickly what they need to change.
Instead of adding a public element to your password, make it longer, with a secret, randomly generated element. That'll make it harder to memorize, but you only need to memorize it once, and you don't need to change it. Password changes don't improve security for a shell account, where once the attacker has had access, they can plant a backdoor that doesn't depend on the password. XKCD #936: Short complex password, or long dictionary passphrase? describes a good method to generate a strong yet memorable password.
More lessons
You shouldn't design a security system until you get better at doing security assessments.
- Trying to improve security by adding a public value to a password.
- That file name length issue.
- Calling the script
screenshot.jpg
may look cute, but it actually has zero security advantage, and the only person it could harm is you, if you accidentally delete that old useless screenshot.