1

I'm in a bit of a pickle.

I've got an IIS application which accesses an SQL database (on a different machine). This already means that:

a) the IIS application needs to have a connection string to the database containing the password
b) the IIS application needs to run using an AD identity which has access to the SQL database

Option b) seems to be more secure.

However, there's a secondary requirement:
The database mentioned earlier contains sensitive information which is AES encrypted. The IIS application has stores the AES key locally and also encrypts it using DPAPI (to avoid storing it in plain-text). DPAPI has a small issue however:

1) If I let the IIS application run using the ApplicationPoolIdentity role then DPAPI works fine
2) If I let the IIS application run as a specific AD user, then DPAPI fails to decrypt data after an IISRESET

As you can see, b) conflicts with 1), and a) conflicts with 2).

How should I tackle this problem?

Shaamaan
  • 380
  • 3
  • 12
  • Are you asking how the application should be coded for properly securing that data or how you should configure an existing app ? – Stephane Feb 18 '14 at 10:53
  • I'm not looking for coding solutions - I'm looking for a general description on how such a system should look like and what technologies I should use to make things secure. – Shaamaan Feb 18 '14 at 11:10
  • In 2), are you trying to decrypt data in DPAPI that was encrypted with a different user's credentials? – RJFalconer Feb 18 '14 at 12:25
  • Absolutely not @RJFalconer! I've found that, for some reason, an IIS application cannot decrypt data encrypted using DPAPI after an IISRESET when using an AD user as the applications identity - even if it was encrypted by said application. – Shaamaan Feb 18 '14 at 13:44

1 Answers1

1

DPAPI actually works through 2 pretty simple function calls: CryptProtectData and CryptUnprotectData.

To make a long story short, CryptProtectData has two mode of operation: User or system. If you use the user mode (default), then the data is encrypted using the current user logon data. It means that you can only sucessfully call CryptUnprotectData on the same data from the same user context as the one you called CryptProtectData from. (in "system" mode, any process running on that same machine can decrypt the data but not from another system: no too good when the data is in a database).

This means that, if you initially encrypted your data in the SQL server database using a specific AD user account, you're permanently limited to using this user to access it. (This might be considered a defect or a feature depending on the application).

What does it means to you? Well, unless you can change the way the application works or you're willing to reset encrypted data completely, you cannot change the identity used by the web application process.

The good news, however, is that this doesn't have to be insecure: if your web application is an ASP.NET app and uses connection strings stored in the web.config file in a standard way, you can protect them using the DAPI as well but this time with a delegate to the system. Microsoft has a pretty lengthy explanation on how to do that.

Finally, there is always the usual way to dead with that kind of issues: contact the application developers: they are the ones that can tell you exactly what is supported and how. If necessary, they are the ones that can also make the necessary changes to their system to reach the security goals that you have set.

Edit: There is an additional element that you must take into account in your case: when using DAPI, the master key used for encryption is stored in the user profile.

This means that, when you're using a virtual user account (as the ones created for you when running a web app under AppPoolidentity), DAPI actually will not be persisted or reloaded since there is no actual profile created and you will experience the issue you describe: IISreset causes the application to lose its master encryption key because it cannot persist it.

To solve that, you can switch to switch to the NetworkService identity for your web application pool. You will lose the segregation of user provided by the virtual account but, beyond that, it should work in the same way. Microsoft also suggests that you check the "LoadUserProfile" property of the web application pool but I'm dubious that changing it will solve your issue on its own: try it but my guess is that you'll have to use NetworkService as well.

Stephane
  • 18,557
  • 3
  • 61
  • 70
  • 1
    You missed a very importantpart of my question - data stored in SQL is encrypted using AES, and the AES key is encrypted locally using DPAPI to prevent storing it in plain-text by the IIS application. I've edited my question slightly - hopefully this will be more clear now. I am **NOT** trying to use DPAPI to decrypt data encrypted by another user. – Shaamaan Feb 18 '14 at 13:40
  • Right. It does not, however, fundamental change my answer: DAPI still limit the decryption to the same user that encrypted the data and if you change the identity of the web app, you're changing that user. – Stephane Feb 18 '14 at 13:55
  • But I've never changed the identity of the web app! As I wrote - if, from the very start, it's working as an AD user, then it won't be able to decrypt what it encrypted earlier after an IISRESET... – Shaamaan Feb 18 '14 at 23:16
  • 1
    Also, to note - the IIS application **first encrypts the AES key**. If it's running using an AD identity it won't be able to later decrypt it (after IISRESET). The only relevant part of your answer is the part about encrypting web.config files... – Shaamaan Feb 19 '14 at 11:16
  • You're right: there is something missing in my answer. I'm adding it – Stephane Feb 19 '14 at 13:26
  • Actually, you're wrong about the `AppPoolIdentity`. In this particular case DPAPI works fine (but, as noted in the question, this won't allow access to the SQL without providing credentials in the Web.config file). What only doesn't work is when AD user accounts are used for web application identities. You might be right about the cause - while AD users do have a user profile, it's... well... in AD, and chances are DPAPI can't access it locally. – Shaamaan Feb 19 '14 at 14:21
  • No, I checked it: the AppPoolIdentity does NOT create a profile (I verified this) while the AD user do create a local cache of the profile (even if it's just a copy of default one). Could you be using the system scope to encrypt your data instead of the user's ? – Stephane Feb 19 '14 at 15:57
  • And did you enable "LoadUserProfile" ? – Stephane Feb 19 '14 at 15:57
  • Yes, the LoadUserProfile option is turned on, and I was using the user scope. Hmm, then I still don't know why IIS works the way it does. Seriously, a simple web application which encrypts a string using DPAPI and saves it to a file will be able to decrypt said text file after an IISRESET so long as it is using the ApplicationPoolIdentity (I haven't tested this with other built-in identity types offered by the IIS), but won't work if configured with an AD user from the start. – Shaamaan Feb 20 '14 at 07:50
  • That makes no sense to me either. What's even stranger is that what you're reporting is exactly the opposite of what my own testing show me: ApplicationPoolIdentity has issues with DPAPI but a regular domain user doesn't (at least, as long as I can see from a ISAPI app point of view). Is there anything special going on on this machine ? A mandatory profile for domain users, for instance ? – Stephane Feb 24 '14 at 09:23