Announcement

Collapse
No announcement yet.

Passwords entered in settingspage are stored in plain text

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Passwords entered in settingspage are stored in plain text

    When credentials are entered via the SettingsPage, they are stored in plain text in the ini file. If somebody gains access to the machine running HS4, it's just a matter of copying all the config files to steal all the passwords.

    The passwords should be stored encrypted, with a user defined key.

    MOVE TO BUGS PLZ

    #2
    How is the rest coping with this? Am i doing something wrong here ?

    Comment


      #3
      You can protect passwords by encrypting them, but how do you protect the decryption then? HS (or a plug-in) needs access to the password to be able to function, and (I assume) most people would want everything to start unattended. So the knowledge about how to decrypt needs to be present on the machine.

      If an unauthorized user gains access to your system (at the same or higher level as the user having the secrets you want to protect), the only advantage is that the encryption is a (small) hurdle to overcome.

      FileZilla refuses (refused?) to 'encrypt' passwords for this reason. They did not want to give their users a false sense of security by using an easy-to-reverse garbling.

      If you want to prevent a breach from spreading to other servers and services, you have a couple of choices (not exhaustive):
      • Inconvenience: Enter secrets or confirm access every time a third-party service needs to be accessed.
      • Way more complicated set-up of operating system, users, processes, (file) permissions, etc.
      I guess most people are not willing to put in this much effort for a home(/small to medium business) automation system. And for the second point above to work, the controller and plug-ins you use must be designed and written to support that high-security environment.

      I too wish it was a lot easier to separate processes (or even plug-ins within the same process), so a problem with 1 plug-in would not expose the whole system. Unfortunately, this is not easy to do. Windows has AppContainers and Linux has SELinux and AppArmor. Java has a security manager built in. Even if you build a very secure system, how can a user judge that the permissions requested by a plug-in are appropriate, and how fine-grained should the permissions be? Look at the permissions mess of Android, for example. Most Android users simply allow almost all apps access to all their data.

      So personally I want to have knowledge about how and where secrets are stored, so I can make sure that location is as secure as possible. I would take the risk that the secrets are exposed if the system was breached.

      Comment


        #4
        You could just specify a key to be used for encrypting and decrypting the string ? I've done this with my plugin in HS3. But HS4 makes it VERY simple to create basic config pages and filling/storing the data without any code. There should be something in place that decrypts the string (using a key specified by the plugin) and encrypts it back when it is saved to disk.

        IMHO it is not acceptable anymore to store passwords in plain text. So that's why I am wondering how other developers are dealing with this. You drop the serialization done by HS and implement it yourself ? Or do you store anything in clear text.

        Comment


          #5
          For reference, my code in HS3:

          Code:
          using System;
          using System.Collections.Generic;
          using System.IO;
          using System.Linq;
          using System.Security.Cryptography;
          using System.Text;
          using System.Threading.Tasks;
          
          namespace HSPI_SurveillanceStation
          {
              public static class StringEncryption
              {
                  public static string Encrypt(string inText, string key)
                  {
                      byte[] bytesBuff = Encoding.Unicode.GetBytes(inText);
                      using (Aes aes = Aes.Create())
                      {
                          Rfc2898DeriveBytes crypto = new Rfc2898DeriveBytes(key, new byte[] { <fill with data here> });
                          aes.Key = crypto.GetBytes(32);
                          aes.IV = crypto.GetBytes(16);
                          using (MemoryStream mStream = new MemoryStream())
                          {
                              using (CryptoStream cStream = new CryptoStream(mStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
                              {
                                  cStream.Write(bytesBuff, 0, bytesBuff.Length);
                                  cStream.Close();
                              }
                              inText = Convert.ToBase64String(mStream.ToArray());
                          }
                      }
                      return inText;
                  }
          
                  public static string Decrypt(string cryptTxt, string key)
                  {
                      cryptTxt = cryptTxt.Replace(" ", "+");
                      byte[] bytesBuff = Convert.FromBase64String(cryptTxt);
                      using (Aes aes = Aes.Create())
                      {
                          Rfc2898DeriveBytes crypto = new Rfc2898DeriveBytes(key, new byte[] { <fill with data here> });
                          aes.Key = crypto.GetBytes(32);
                          aes.IV = crypto.GetBytes(16);
                          using (MemoryStream mStream = new MemoryStream())
                          {
                              using (CryptoStream cStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Write))
                              {
                                  cStream.Write(bytesBuff, 0, bytesBuff.Length);
                                  cStream.Close();
                              }
                              cryptTxt = Encoding.Unicode.GetString(mStream.ToArray());
                          }
                      }
                      return cryptTxt;
                  }
              }
          }
          And when reading the config file:
          Code:
          m_config.Password = StringEncryption.Decrypt(m_config.Password, ENCRYPTION_KEY);

          Comment


            #6
            Originally posted by kriz83 View Post
            You could just specify a key to be used for encrypting and decrypting the string ? [...]
            I was trying to explain that this does not provide more security than plain text, just a hurdle. How can the key be more secure than the stored password (encrypted or not)?

            If someone has enough access to get the password data, they (most likely) have enough access for the key too. Encrypted password + key → password.

            Communicating to your users that passwords are stored encrypted, gives them a false sense of security. You should be clear and honest. For example: If an unauthorized user gains access to your system, you should consider all secrets used to access third-party services to be exposed. My plug-in garbles passwords to make it harder to retrieve the actual password, but it does not prevent an unauthorized user having access to all your data from obtaining the password.

            Comment


              #7
              Sure, but then the attacker would have to gain access to the config file AND the encryption key.
              This does not make it waterproof, I agree with that (I've also mentioned that in the doc of my plugin), but it's a hell of a lot better than just storing it in plain text.

              Comment


                #8
                kriz83

                You can catch changes made to the settings in the HSPI.OnSettingChange routine. Also it will pass though the HSPI.OnSettingsSave (might be even better). You have to override these routines.
                Would it be possible to use this routine to encrypt stuff? Have not tried a lot here, except catching them, but maybe you can change the value of the view with view.UpdateValue?

                You can then decrypt the item with "HSPI.OnSettingsLoad" and store it internally.

                Would this offer a way maybe?

                Wim

                -- Wim

                Plugins:RFXCOM, HSTouch Server, Squeezebox, BLGData, Restart, Jon00's Perfmon and Network monitor, WeatherXML, BLBackup, TenScripting, BC4, Pushover, PHLocation, JowiHue, Zwave, Sonos
                650 devices ---- 336 events ----- 40 scripts

                Comment


                  #9
                  Thx wim, will try it out this evening.

                  I would prefer a more standard (out-of-the-box) way though ;-)

                  Comment

                  Working...
                  X