Home » c# » c# – How to obfuscate locally stored user/password to be sent onward to 3rd party app?-Exceptionshub

c# – How to obfuscate locally stored user/password to be sent onward to 3rd party app?-Exceptionshub

Posted by: admin February 24, 2020 Leave a comment

Questions:

Scenario:

  • User A logs into Windows (8 upwards, Server 2008R2 upwards).
  • The user accesses a 3rd party service through software with username and passwort.
  • I need to provide a “Keep logged in”-experience, hence I need a symetrically obfuscated PW stored password locally (user specific – inside %localappdata%/software/….)

Problem:

So far my predecessor used Symetric Rijndael with Cipher Block Chaining and hardcoded digest to obfuscate the password. Any user & any maschine wich got the %localappdata% file copied over could authenticate successfully with User A‘s stored creds. I don’t like.

Constraints for obfuscation:

  • I want to tie the password obfuscation somehow to the logged in windows user/maschine
  • changing f.e. the windows users password should not invalidate the obfuscated password
  • moving the file over to a different maschine with a (cloned) User A should invalidate the deobfuscation
  • moving the file from User A to User B should invalidate the deobfuscation

Jon Galloway’s blog which is from 2008 but made me look into DPAPI: as I understand it, System.Security.Cryptography.ProtectedData with DataProtectionScope.CurrentUser should disable other Users to deobfustcate the password.

Question:

What do I provide as entropy value to disable access for a cloned User A on a different maschine or should I go another route altogether?


Some code to test the ProtectedData stuff from MSDN with a string passphrase:

// modified from https://docs.microsoft.com/de-de/dotnet/api/system.security.cryptography.protecteddata
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

public class DataProtectionSample
{
  static string GetHexString (byte [] data)
    => string.Join (" ", data.Select (d => d.ToString ("x2")));

  static string GetUnicodeString (byte [] data)
    => Encoding.Unicode.GetString (data);

  static byte [] GetBytesFromUnicode (string data)
    => Encoding.Unicode.GetBytes (data);

  public static void Main ()
  {
    // Create byte array for additional entropy when using Protect method.
    byte [] entropy = { 9, 8, 7, 6, 5 };
    byte [] secret = GetBytesFromUnicode ("Cräzy obfuscated paß phrâse");

    //Encrypt the data.
    byte [] encryptedSecret = Protect( secret , entropy );

    Console.WriteLine ("The encrypted byte array is:");
    Console.WriteLine (GetHexString (encryptedSecret));

    // Decrypt the data and store in a byte array.
    byte [] originalData = Unprotect( encryptedSecret, entropy );
    Console.WriteLine ("{0}The original data is:", Environment.NewLine);
    Console.WriteLine (GetUnicodeString (originalData));

    Console.ReadLine ();
  }

  static byte [] Protect (byte [] data, byte [] entropy)
  {
    try
    {
      return ProtectedData.Protect (data, entropy, DataProtectionScope.CurrentUser);
    }
    catch (CryptographicException e)
    {
      Console.WriteLine (e.ToString ());
      return null;
    }
  }

  static byte [] Unprotect (byte [] data, byte [] entropy)
  {
    try
    {
      return ProtectedData.Unprotect (data, entropy, DataProtectionScope.CurrentUser);
    }
    catch (CryptographicException e)
    {
      Console.WriteLine (e.ToString());
      return null;
    }
  }
}

I am aware that impersonating User A will make the obfuscation void – hence obfuscation not encryption. What I am after, is a kindof tougher version of “can’t read plaintext pw from file” with a second factor of “need to be logged in with same windows user” and “on the same maschine”.

I also looked into How should I ethically approach user password storage for later plaintext retrieval? wich does not quite help as it’s answers mostly assume some kind of web scenario with password reset mechanism which I do not have.

Disclaimer: My passwords are random generated Keypass stored values. I do not use “Keep logged in” features. Storing passwords in plaintext is evil, storing passwords symetrically encrypted can be broken and has to be avoided. Still need to provide above feature …

https://www.harmj0y.net/blog/redteaming/operational-guidance-for-offensive-user-dpapi-abuse/ suggests that DPAPI has several exploitable “flaws” as soon as you are able to impersonate the user in any way or form.

How to&Answers: