The database connection string in the configuration file is encrypted. Do you think I can't dig it out?

1: Background

1. Tell a story

A bug was found on the app.com cabinet a few days before debugging The database connection string in config is encrypted. To switch the database during debugging, I need to decrypt the ciphertext on a special gadget. After changing the database name on the connection string, I have to encrypt and paste it to app In config, I'm bored to death. The contents are as follows:

  <appSettings>
    <!-- Database connection string -->
    <add key="OLEDBConnStr" value="XfES27am6Muw48iB1GlMVqvUbq7/Pp9n4XbZJsDu19YDr/Zdb3m7KT6haD7f9HLj/ZEvIiZbmSU4O5L9g03Y5IUB6KLCZI7s3nDLwTIC+bXLf5quu/r8ZAI+rgNnsNZdwoDfquRLQy5Cf2X8/MFDOcMNaZYMpTYeHsZoEERU/TP9t3n5QllJTihrmDFbiGHLqe1kfN3uB3g1kgs0oobIEfNPr09kQ/pFgzZi/kZCrK10PLZZ0pFj1YU5ReFqBsdBlecV3D2Zl3lx1Ibls24t7w==" />
  </appSettings>

After fixing the bug, I thought this thing could be prevented. Who? I think it's just a gentleman to prevent such trouble. For a knowledgeable person like me, adding or not encrypting is equal to not encrypting, so I'll take you out of the database... 😄😄😄

2: Use ILSpy to take off the library

1. Decompile code from DAL/Repository layer

To get the database connection string in plaintext, you can deduce it from the code. For example, you can find the connection string field ConnectionString from DAL or Repository. My terminal program is written in wpf and adopts the classic three-tier architecture, so it can be easily found under bin, as shown in the following figure:

Next, decompile the dll with ILSPy.

As can be seen from the above figure, the plaintext of the connection string is stored in: oledbhelper In connectionstring, then you can see that a Decrypt method is defined in the program to Decrypt the connection string. Ha ha, with this algorithm, can we get rid of the library??? The following code is shown:

    class Program
    {
        static void Main(string[] args)
        {
            var str = "XfES27am6Muw48iB1GlMVqvUbq7/Pp9n4XbZJsDu19YDr/Zdb3m7KT6haD7f9HLj/ZEvIiZbmSU4O5L9g03Y5IUB6KLCZI7s3nDLwTIC+bXLf5quu/r8ZAI+rgNnsNZdwoDfquRLQy5Cf2X8/MFDOcMNaZYMpTYeHsZoEERU/TP9t3n5QllJTihrmDFbiGHLqe1kfN3uB3g1kgs0oobIEfNPr09kQ/pFgzZi/kZCrK10PLZZ0pFj1YU5ReFqBsdBlecV3D2Zl3lx1Ibls24t7w==";
            
            Console.WriteLine(Decrypt(str));
        }

        public static string Decrypt(string str)
        {
            if (!string.IsNullOrEmpty(str))
            {
                DESCryptoServiceProvider descsp = new DESCryptoServiceProvider();
                byte[] key = Encoding.Unicode.GetBytes("Oyea");
                byte[] data = Convert.FromBase64String(str);
                MemoryStream MStream = new MemoryStream();
                CryptoStream CStream = new CryptoStream(MStream, descsp.CreateDecryptor(key, key), CryptoStreamMode.Write);
                CStream.Write(data, 0, data.Length);
                CStream.FlushFinalBlock();
                return Encoding.Unicode.GetString(MStream.ToArray());
            }
            return "";
        }
    }

However, fortunately, the database is also deployed independently on the customer's side. There is no external network, otherwise it will play a big game... Next, let's see how to prevent it.

2. Shelling / confusion / dongle

Now both commercial and free versions on the market provide C# code encryption and confusion, but I haven't used it. I think it's only a matter of time to add some obstacles to the readability after decompilating the code. After all, SqlConnection and SqlCommand FCL classes can't be confused. I can easily find plaintext ConnectionString from these classes, So I think this road is impassable.

3. Put the decryption algorithm on the server side

Since the decryption algorithm is buried in the client, you can dig it out. Can't you just put it on the server? When the program starts, call webapi to decrypt, so you have no choice??? Ha ha, you can use your brain to think about whether this method is feasible or not? It is true that the decryption algorithm has been removed, and it is meaningless to dig with ILSpy, but there is an important breakthrough here. No matter what form of decryption is used, the final connection string plaintext is stored in oledbhelper Connectionstring is a static variable, right! The next question is whether there is a way to dig out this static variable in the process? You're right. Grab the dump file of the program and dig it with windbg.

3: Use windbg to remove the library

1. Ideas

To dig out oledbhelper Connectionstring, in fact, is also very simple. In the fourth chapter of CLR via C# the interpretation of object types and type objects has such a picture, which is very classic.

As can be seen from the above figure, the static fields are in the Manager type object and the instance fields are in the Manager object. Compared with this figure, I only need to find the OleDbHelper type object through windbg, that is, the so-called EEClass.

2. windbg mining practice

  • use! name2ee found Decrypt method descriptor (MethodDesc)
0:000>  !name2ee xxx.Utilities.dll xxx.Utilities.Database.OleDbHelper.Decrypt
Module:      08ed7cdc
Assembly:    xxx.Utilities.dll
Token:       060002aa
MethodDesc:  08ed83b0
Name:        xxx.Utilities.Database.OleDbHelper.Decrypt(System.String)
JITTED Code Address: 048b6af0

The above MethodDesc: 08ed83b0 is the address of the method descriptor.

  • use! dumpmd exports the details of the method descriptor and finds the EEClass address of the OleDbHelper type object
0:000> !dumpmd 08ed83b0
Method Name:  xxx.Utilities.Database.OleDbHelper.Decrypt(System.String)
Class:        08ecab30
MethodTable:  08ed8468
mdToken:      060002aa
Module:       08ed7cdc
IsJitted:     yes
CodeAddr:     048b6af0
Transparency: Critical

The above class: 08ecab30 is the memory address of the OleDbHelper type object on the heap.

  • use! dumpclass exports Class: 08ecab30 to find the static field of OleDbHelper class
0:000> !dumpclass 08ecab30
Class Name:      xxx.Utilities.Database.OleDbHelper
mdToken:         02000033
File:            D:\code\A18001\Source\Main\TunnelClient\bin\Debug\xxx.Utilities.dll
Parent Class:    795115b0
Module:          08ed7cdc
Method Table:    08ed8468
Vtable Slots:    4
Total Method Slots:  6
Class Attributes:    100081  Abstract, 
Transparency:        Critical
NumInstanceFields:   0
NumStaticFields:     2
      MT    Field   Offset                 Type VT     Attr    Value Name
799bfd60  4000152       74        System.String  0   static 04c28270 ConnectionString
799bfd60  4000153       78        System.String  0   static 04c299e8 SecurityConnectionString

From the above exported information, you can see that there are two static fields in the OleDbHelper class: ConnectionString and SecurityConnectionString.

  • use! do prints out two static fields

See, the two purple boxes in the figure above are plaintext ConnectionString. Ha, how about it? 🐂 no 🐂.

4: Summary

When you realize the above two ways to remove the database, you should be able to think that in fact, it is a mistake for you to connect the database in the program. The operating system can pirate for you, not to mention your little software? Personally, I think the way to completely eliminate it should be to destroy the local SQL server and make all data acquisition provided by the remote webapi. Of course, this is divorced from business chat technology! 😄😄😄

Tags: C#

Posted by kumschick on Mon, 23 May 2022 08:13:28 +0300