KeePass save my credentials after sync via trigger

Help
Dvvarf
2014-04-30
2014-05-16
  • Dvvarf

    Dvvarf - 2014-04-30

    Hi everyone,
    I was always interested in syncing my database with some kind of remote location, but was afraid that it will compromise the security by saving login/password security in XML configuration file. But recently I learned about trigger - the way of syncing your database and not saving your credentials... or so I thought. For a few times I wondered, why the hell my local file was switched with remote one and today I checked my XML in %APPDATA%\KeePass\KeePass.config.xml and discovered that my login/password was indeed saved in that file. Sure, the password is obfuscated, but it's easily reversible.

    I found out that in function IOFromParameters (line 316, EcasDefaultActionProvider.cs) the credentials are saved if the password is supplied along with the login. I think that this behavior is wrong. Credentials should not be saved when user doesn't explicitly wants to save it, nor login only, nor the whole login/password pair. Also, as far as I know, these functions are used only in triggers, so the credentials are always supplied through parameters and there is no need to save them.

    tl;dr: KeePass will save your credentials to the local XML file even if you sync (or open) databases using triggers. Be advised.

    Should I fill the ticket about this?

    By the way, all of this is about the latest 2.26 version (but this behavior carries on from 2.13).

     
  • wellread1

    wellread1 - 2014-04-30

    Store your remote login credentials in your database and pass them to the trigger by using Field References in the IO Connection - username & password parameters. The field references will be saved in the trigger instead of the actual remote login credentials. When the trigger executes, the username and password will be sent.

     
  • Dominik Reichl

    Dominik Reichl - 2014-05-01

    This behavior is correct and not a security problem.

    In detail, the IOFromParameters method that you mentioned does the following: it builds an object describing the connection (including path, user name and password); if the trigger parameters specify a user name, the object is marked with the 'Remember user name only' flag; if the trigger parameters specify a password, the object is marked with the 'Remember user name and password' flag. When the synchronization completes, the connection details are put into the list of most recently used (MRU) files.

    So, if your trigger parameters contain the connection credentials, these credentials are also remembered by the MRU list after a synchronization. This is not a security problem: triggers are also stored in the configuration file unencryptedly (because triggers are application-wide and independent of databases; we don't have any key for encrypting the configuration), i.e. the credentials already were available to attackers before the synchronization. Of course, if the trigger parameters do not contain the connection credentials, KeePass asks for them when required and only saves them if the user explicitly chooses one of the 'Remember user name only' or 'Remember user name and password' options in the connection dialog.

    Like wellread1 wrote already, if you wish to avoid this issue you can use field references, which makes KeePass retrieve the connection credentials from an open database.

    Best regards,
    Dominik

     
  • Dvvarf

    Dvvarf - 2014-05-01

    I use field references in my trigger. Here is my trigger on pastebin. The credentials passed to this function are saved anyway, it doesn't matter if you store them in trigger unencrypted or use field references.

    The field references are resolved before this function is called, not after. And then it saves them.

    How it works: I pass the credentials to this function while the database is opened and function gets my user name and password. Function gets password (already unencrypted and ready for use) and saves it in MRU. MRU is being saved in XML - and password is saved with it.

     
    Last edit: Dvvarf 2014-05-01
  • wellread1

    wellread1 - 2014-05-04

    Dominik,

    I tested for the behavior that Dvvarf reports. It appears that the obfuscated password needed to access the URL (my tests used an ftp site) are stored obfuscated in the MRU list even if the password was passed as a field reference. The trigger behaves as if the user has selected "Remember user name and password".

    I have attached the relevant excepts of the keepass.config.xml from several tests below. In each case I cleared the Recently Used List and exited KeePass prior to re-starting KeePass for the test. The keepass.config.xml excerpts were obtained after completing each test and exiting KeePass. The actual test FTP credentials are shown in the examples below.

    Test 2 below exhibits the behavior of concern.

    1. Sync trigger contained FTP credentials in the clear. A local test.kdbx was opened and synced with its counterpart on an ftp site. The MRU contains the obfuscated password. This behavior is of no concern because the ftp password is present in the clear in the trigger.

      <MostRecentlyUsed>
          <MaxItemCount>12</MaxItemCount>
          <Items>
              <ConnectionInfo>
                  <Path>ftp://192.168.1.100/keepass/test.kdbx</Path>
                  <UserName>user</UserName>
                  <Password>U1BRVldU</Password>
                  <CredProtMode>Obf</CredProtMode>
                  <CredSaveMode>SaveCred</CredSaveMode>
              </ConnectionInfo>
              <ConnectionInfo>
                  <Path>..\..\Users\username\Documents\KeePass\test.kdbx</Path>
                  <CredProtMode>Obf</CredProtMode>
                  <CredSaveMode>NoSave</CredSaveMode>
              </ConnectionInfo>
          </Items>
      </MostRecentlyUsed>
      .
      .
      <TriggerSystem>
          <Triggers>
              <Trigger>
                  <Guid>laD9O7i1YUycUr4KRppOeA==</Guid>
                  <Name>ftp test</Name>
                  <Events>
                      <Event>
                          <TypeGuid>R0dZkpenQ6K5aB8fwvebkg==</TypeGuid>
                          <Parameters>
                              <Parameter>btn_ftp</Parameter>
                          </Parameters>
                      </Event>
                  </Events>
                  <Conditions />
                  <Actions>
                      <Action>
                          <TypeGuid>Iq135Bd4Tu2ZtFcdArOtTQ==</TypeGuid>
                          <Parameters>
                              <Parameter>ftp://192.168.1.100/keepass/test.kdbx</Parameter>
                              <Parameter>user</Parameter>
                              <Parameter>123456</Parameter>
                          </Parameters>
                      </Action>
                  </Actions>
              </Trigger>
      
    2. Sync trigger contained FTP credentials passed as field references. A local test.kdbx was opened and synced with its counterpart on an ftp site. The MRU contains the obfuscated password. The same obfuscated ftp password is present in the MRU as in 1. above even though it was passed as a field reference in the trigger.

      <MostRecentlyUsed>
          <MaxItemCount>12</MaxItemCount>
          <Items>
              <ConnectionInfo>
                  <Path>ftp://192.168.1.100/keepass/test.kdbx</Path>
                  <UserName>user</UserName>
                  <Password>U1BRVldU</Password>
                  <CredProtMode>Obf</CredProtMode>
                  <CredSaveMode>SaveCred</CredSaveMode>
              </ConnectionInfo>
              <ConnectionInfo>
                  <Path>..\..\Users\username\Documents\KeePass\test.kdbx</Path>
                  <CredProtMode>Obf</CredProtMode>
                  <CredSaveMode>NoSave</CredSaveMode>
              </ConnectionInfo>
          </Items>
      </MostRecentlyUsed>
      .
      .
      <TriggerSystem>
          <Triggers>
              <Trigger>
                  <Guid>laD9O7i1YUycUr4KRppOeA==</Guid>
                  <Name>ftp test</Name>
                  <Events>
                      <Event>
                          <TypeGuid>R0dZkpenQ6K5aB8fwvebkg==</TypeGuid>
                          <Parameters>
                              <Parameter>btn_ftp</Parameter>
                          </Parameters>
                      </Event>
                  </Events>
                  <Conditions />
                  <Actions>
                      <Action>
                          <TypeGuid>Iq135Bd4Tu2ZtFcdArOtTQ==</TypeGuid>
                          <Parameters>
                              <Parameter>ftp://192.168.1.100/keepass/test.kdbx</Parameter>
                              <Parameter>{REF:U@I:11D097939E90CB4DBF206A8EC0405714}</Parameter>
                              <Parameter>{REF:P@I:11D097939E90CB4DBF206A8EC0405714}</Parameter>
                          </Parameters>
                      </Action>
                  </Actions>
              </Trigger>
      
    3. The test.kdbx on the ftp site was opened directly using "Remember user name and password". The same obfuscated ftp password is present in the MRU as in 1 and 2. This expected behavior is of no concern because the user directed that KeePass save the password.

      <MostRecentlyUsed>
          <MaxItemCount>12</MaxItemCount>
          <Items>
              <ConnectionInfo>
                  <Path>ftp://192.168.1.100/keepass/test.kdbx</Path>
                  <UserName>user</UserName>
                  <Password>U1BRVldU</Password>
                  <CredProtMode>Obf</CredProtMode>
                  <CredSaveMode>SaveCred</CredSaveMode>
              </ConnectionInfo>
          </Items>
      </MostRecentlyUsed>
      
     
  • Dominik Reichl

    Dominik Reichl - 2014-05-04

    I see, thanks.

    It's rather difficult to define a consistent, reasonable behavior here; depending on the situation, different behaviors may make sense. I've now implemented a behavior that should hopefully make most people happy (basically the user name from the trigger now acts as a filter for the MRU items with the same path, a matching MRU item defines the default settings, and the password from the trigger overrides any others; one consequence is that the credentials coming from a trigger are remembered if and only if the MRU list already contains an item with one of the 'Remember ...' options activated).

    Here's the latest development snapshot for testing:
    http://keepass.info/filepool/KeePass_140504.zip

    Thanks and best regards,
    Dominik

     
  • wellread1

    wellread1 - 2014-05-05

    I believe the snapshot addresses the security concern that Dvvark raised.

    However in this snapshot, the trigger action "Synchronize active database with a file/URL" presents the 'Open from URL' dialog even when the user has provided complete path, username, and password information. It would be preferable if the 'Open from URL' dialog were suppressed in this specific case.


    I believe the principal obstacle to achieving consistent behavior is that KeePass is not capturing all the information needed to determine the appropriate behavior.

    Background: There are 8 possible combinations of path, username and password. The user necessarily creates one of these combinations in the trigger. Since the MRU list does not contain additional information that could guide ftp/webdav login, it is unnecessary to refer to it when the trigger executes. However, an MRU entry could be created if one doesn't exist. The appropriate Remember setting in all cases is "Do not remember username and password" because all the information the user intended to store is already contained in the trigger.

    The specific situation where KeePass can not determine correct behavior without additional user input is for an anonymous login. Several combinations of trigger parameters are potentially anonymous, all others are either complete and can bypass the 'Open from URL' dialog, or are incomplete and require the 'Open from URL' dialog:

    Potential anonymous login cases:

    1. The path and username are provided but not the password.
    2. Two combinations are probably user error and should trigger the 'Open from URL' dialog unless there exist ftp/webdav servers that allow login without a username:
      • The path is provided but neither username or password are provided.
      • The path and password are provided but no username is provided.

    I believe the solution to situation 1 and 2 is to add a flag to the trigger that identifies it as an "Anonymous login". KeePass could use the flag to restrict user input, or it could be settable only when it detects that the appropriate conditions are met (e.g. conditions 1 & possibly 2), or the flag could always be user settable provided that KeePass fails gracefully when the user makes a mistake. The information currently collected in the trigger when combined with the "Anonymous login" flag, provide KeePass with the information necessary to determine whether the login information is complete so that an accurate determination of whether the 'Open from URL' dialog should be displayed becomes possible.

    This flag setting need not be saved in the MRU list, but it could be saved if there is an advantage to using the flag in the 'File>Open>Open URL...' and 'File>Synchronize>Synchronize with URL...' options.

    Obviously the current program organization may not be amenable to incorporating the additional flag, in that case the snapshot addresses the security concern, convenience is secondary.

     
    Last edit: wellread1 2014-05-05
  • Dominik Reichl

    Dominik Reichl - 2014-05-06

    Thanks for the hint with the dialog; I've added this now.

    The defaults for the connection info (and especially the 'Remember ...' mode) must be retrieved from the MRU. If we would not do this and always use 'Do not remember user name and password' for connection infos originating from a trigger, existing MRU items could lose data (an item with 'Remember ...' would be overwritten by one with 'Do not remember ...').

    Here's the latest development snapshot for testing:
    http://keepass.info/filepool/KeePass_140506.zip

    Best regards,
    Dominik

     
  • wellread1

    wellread1 - 2014-05-06

    I knew I went on on a limb, but I am glad you found something useful in my comments :-).

    The current snapshot works well.

     
  • Dvvarf

    Dvvarf - 2014-05-16

    Just had the chance to test out the latest development snapshot and it works great.
    Thanks to wellread1 for clearing up the problem and suggesting potential fixes for it. And I'd like to thank Dominik not only for following up on this problem and implementing the fix so fast, but for all of his hard work on KeePass. =)

     

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks