From the project
Making TurnKey more turnkey - the end to default passwords
In our quest to make the upcoming TurnKey 11.0 release more "turnkey", I set out to extend the firstboot inithooks to include application specific configuration hooks such as setting of the admin password, email and domain to serve (where applicable).
I'm glad to announce that the quest is now over, and that puts the end to default passwords.

But what about hosting/cloud deployment where the user doesn't have boot interaction? Well, all the configurations can be pre-seeded. We'll be adding support for preseeding to the Hub soon after the 11.0 release. Until then, the instances will use default passwords, but they can be easily changed by executing the inithooks directly.
While on my quest, it was interesting to get a birds eye view of how the different applications store their passwords, so I thought I'd share:
Comparison table (22 applications)
| clear | crypt | md4 | md5 | sha1 | salt | |
| tomcat | x | |||||
| trac | x | |||||
| otrs | x | |||||
| twiki | x | |||||
| mldonkey | x | |||||
| joomla | x | |||||
| mantis | x | |||||
| wordpress | x | |||||
| dokuwiki | x | |||||
| phpbb | x | |||||
| extplorer | x | |||||
| gallery | x | x | ||||
| deki | x | x | ||||
| mediawiki | x | x | ||||
| moodle | x | x | ||||
| prestashop | x | x | ||||
| magento | x | x | ||||
| vtiger | x | x | ||||
| bugzilla | x | x | ||||
| roundup | x | |||||
| redmine | x | |||||
| django | x | x |
Foot notes
- clear: Passwords are stored in clear text.
- crypt: Passwords are hashed with crypt or htpasswd.
- md4/md5/sha1: Passwords are put through a cryptographic hash function, which is a deterministic one-way procedure that takes a block of data and returns a fixed-size bit string.
- salt: A salt (random bits) are added to the password before passing it through the hash function. Some of the applications use a randomly generated salt stored in a configuration file, others calculate it on the fly and add it the hash itself, while others use the user id as the salt. Using a salt is meant to add to the complexity and time it would take an attacker (who obtained the hashed passwords) to determine the original clear-text password.
Now for some code snippets
tomcat
doc = xml.dom.minidom.parse(TOMCAT_USERS).documentElement
users = doc.getElementsByTagName('user')
for user in users:
if not user.getAttribute('username') == 'admin':
continue
user.setAttribute('password', password)trac
system("htpasswd -cb %s admin %s" % (authfile, password))otrs
hashpass = crypt.crypt(password, 'ro') # 2 chars of username/email
twiki
output = getoutput("htpasswd -bn foo %s" % password)
hashpass = output.split(":")[1].strip()
mldonkey
MD4_HASH=$(echo -n $PASSWORD | openssl dgst -md4 | tr [a-z] [A-Z])
joomla
hashpass = hashlib.md5(password).hexdigest()
mantis
hashpass = hashlib.md5(password).hexdigest()
wordpress
hashpass = hashlib.md5(password).hexdigest()
dokuwiki
hashpass = hashlib.md5(password).hexdigest()
phpbb
hashpass = hashlib.md5(password).hexdigest()
extplorer
MD5_HASH=$(echo -n $PASSWORD | md5sum | cut -d " " -f 1)
hashpass = hashlib.md5(password).hexdigest()
gallery
salt = "".join(random.choice(string.letters) for line in range(4)) hashpass = salt + hashlib.md5(salt + password).hexdigest()
deki
hashpass = hashlib.md5(password).hexdigest()
hashpass = hashlib.md5("1-" + hashpass).hexdigest() # userid 1
mediawiki
hashpass = hashlib.md5(password).hexdigest()
hashpass = hashlib.md5("1-" + hashpass).hexdigest() # userid 1moodle
for line in file(conffile).readlines():
m = re.match("\$CFG->passwordsaltmain = '(.*)';", line)
if m:
salt = m.group(1)
hashpass = hashlib.md5(password + salt).hexdigest()
prestashop
for line in file(conffile).readlines():
m = re.match("define\('_COOKIE_KEY_', '(.*)'", line)
if m:
cookie_key = m.group(1)
hashpass = hashlib.md5(cookie_key + password).hexdigest()
magento
salt = "".join(random.choice(string.letters) for line in range(2)) hashpass = hashlib.md5(salt + password).hexdigest() + ":" + salt
vtiger
hashpass = hashlib.md5(password).hexdigest() $salt = substr($username, 0, 2); $salt = '$1$' . str_pad($salt, 9, '0'); $encrypted_password = crypt($password, $salt);
bugzilla
$salt = '';
for ( my $i=0 ; $i < 8 ; ++$i ) {
$salt .= $saltchars[rand(64)];
}
$cryptedpassword = crypt($password, $salt);
roundup
hashpass = "{SHA}" + hashlib.sha1(password).hexdigest()redmine
hashpass = hashlib.sha1(password).hexdigest()
django
salt = hashlib.sha1(str(random.random())).hexdigest()[:5] hash = hashlib.sha1(salt + password).hexdigest() hashpass = 'sha1$%s$%s' % (salt, hash)
Good idea regarding github, that will make it a lot easier to pull the code. It should also make your life simpler publishing updates, and tracking revisions (which I hope you're already doing).
I'll push out the feedback as soon as I can.