[ https://issues.apache.org/jira/browse/VCL-560?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Aaron Coburn updated VCL-560: ----------------------------- Attachment: vmprofile.alter.sql web.patch managementnode.patch > cleartext password stored in VMProfile table > -------------------------------------------- > > Key: VCL-560 > URL: https://issues.apache.org/jira/browse/VCL-560 > Project: VCL > Issue Type: Bug > Components: database, vcld (backend), web gui (frontend) > Affects Versions: 2.2.1 > Reporter: Aaron Coburn > Labels: security > Attachments: managementnode.patch, vmprofile.alter.sql, web.patch > > > To provide some background, we are setting up a VCL system for several > institutions, using multiple, physically distributed management nodes (each > located at different institutions). Each management node will control its own > VMware infrastructure of one or more hosts while all accessing the central > vcl database. > As you know, each VMhost draws its configuration information from the > `vmprofile` table, including information for accessing that VMhost > infrastructure. For vSphere-based systems, the management node extracts login > credentials from the `username` and `password` fields. The other API modules > do not require the password field. The problem, however, is that the > passwords are stored in cleartext. > Yes, cleartext. > This means that if the VCL is using the vSphere API, anyone from institution > X who has access to the VCL database could easily access the login > credentials for the VM Host(s) at institution Y. The other issue is that > these passwords are being transferred in cleartext between database and > management nodes, so anyone listening in on the wire could also, potentially, > gain access to the VMware infrastructure. Furthermore, while the passwords > are masked in the web UI behind 'password' fields, the ajax call that > populates those fields can easily be inspected in order to get the actual > text. I can see how this isn't such an issue if a VCL system is running > within a single institution inside a single network, but in our case, that is > not the situation. > A compounding issue is that the web UI allows admins to enter the passwords > for VMhost profiles, which means that there would need to be a mechanism for > making sure that the password for the VMprofile at institution X isn't > encrypted using the same key as the password for the corresponding profile at > institution Y. > To solve this, I have written some code that performs asymmetric key > encryption so that the passwords are stored in a more secure format. Attached > are the relevant patch files. > Effectively, what I have done is add three fields to the `vmprofile` table: > rsa_pub: a string containing a public key > rsa_key: the location of the corresponding private key (i.e. > "/etc/vcl/vmhost01.key") > encrypted_passwd: the RSA-encrypted password. (There isn't a strong reason to > have this be a separate field from the existing password field, but > separating the two made it easier to test.) > Next, I added additional input fields in the VMProfile UI for accepting > rsa_pub and rsa_key. I have also updated the javascript code to support this. > If an RSA public key is supplied, the vm.php file will encrypt the incoming > password using the openssl_* functions that come with most distributions of > PHP. The encrypted password is stored in the `encrypted_passwd` field and the > `password` field is set to NULL. This causes the web UI not to show the > masked passwords, which is a behavior that I preferred to have, though others > may prefer something different. The encryption function was put in utils.php > and called encryptDataAsymmetric($data, $public_key) -- it more or less > follows the style of the existing encryptData($data) function. > Finally, vcld needs to be able to decrypt the data, so I added some code to > VCL::utils. First, I expanded the vmhost/vmprofile SQL statement to include > the new rsa_key and encrypted_passwd fields. Then, vcld will check whether a > key exists in the location specified, and if so, it will use that key to > decrypt the password. The decrypted password is then put into the data > structure in the expected location: vmprofile.password > The perl code relies on one additional library: Crypt::OpenSSL::RSA, which > has its own set of dependencies, but these are all available on the EPEL > repository or CPAN. I would add that the Crypt::OpenSSL::RSA library is quite > mature and well maintained. > I wrote this code so that it is entirely optional to encrypt passwords. If an > RSA public key is not attached, then no encryption is performed: the password > is stored, as before, in cleartext in vmprofile.password. If the private > keyfile does not exist on a management node, then no decryption is performed, > and the existing value of vmprofile.password is used. I should also add that > the encrypted passwords are stored in hexadecimal format, since that is > easier to deal with when it comes to storing them in a database. > In order to use this code, one will need to generate RSA keys ahead of time > like so: > $ openssl genrsa -out vmhost.key 1024 > $ openssl rsa -in vmhost.key -pubout > vmhost.key.pub > (One can generate a larger key, if desired, by specifying a larger bit size > in the first command.) > It is a good idea to control access to the private key: > $ chown root.root vmhost.key > $ chmod 600 vmhost.key > An admin will also need the contents of the public key to enter into the web > UI: > $ cat vmhost.key.pub -- This message is automatically generated by JIRA. If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa For more information on JIRA, see: http://www.atlassian.com/software/jira