While preparing slides and demos for the upcoming BSides Warsaw conference, I spent some time digging through the code of the old ASP.NET Crypto stack. In case you do not remember, six years ago researchers reported multiple cryptographic design flaws in ASP.NET. One of the critical issues was that ASP.NET did not authenticate ciphertexts. Thus they were vulnerable to the padding oracle attack. Microsoft learned its lesson and rewrote the crypto stack in ASP.NET 4.5. If you want to find out more, have a look at those three excellent articles by Levi Broderick: Part 1, Part 2, Part 3. As I plan to demo the padding oracle attack during my presentation I wanted to restore the old behavior using the latest version of the ASP.NET framework. In this post, I am presenting how I achieved that. But to watch the live demo, I invite you to come to my presentation at 10:00, Saturday, October 14th :).
Always Encrypted is a feature of the SQL Server 2016/Azure SQL which allows you to take full control over the encryption process of the sensitive data stored in your SQL databases. Thanks to this mechanism the encryption key is stored only on the client side and is never revealed to the SQL Server. In consequence, data traveling from the server to the client is also encrypted (although I would not rely too much on this fact and always use encrypted connections to the SQL Server). That is a very different approach to Transparent Data Encryption or Cell-level Encryption, in which it is the server role to encrypt/decrypt data received/sent to the client. Server-side encryption is completely transparent to the client and does not impact the way the client builds SQL queries. In Always Encrypted model, any query against an encrypted column will perform comparisons on byte arrays of cipher text. As you can imagine this raises some challenges when building a data model. In this post, I am going to cover some details of how the Always Encrypted feature is implemented and, hopefully, help you use it effectively.
Each build and release definition in TFS has a set of custom variables assigned to it. Those variables are later used as parameters to PowerShell/batch scripts, configuration file transformations, or other tasks being part of the build/release pipeline. Accessing them from a task resembles accessing process environment variables. Because of TFS detailed logging, it is quite common that values saved in variables end up in the build log in a plain text form. That is one of the reasons why Microsoft implemented secret variables.
The screenshot below presents a TFS build configuration panel, with a sample secret variable amiprotected set (notice the highlighted padlock icon on the right side of the text box):
Once the secret variable is saved, it is no longer possible to read its value from the web panel (when you click on the padlock, the text box will be cleared).
And this is how the output log looks like if we pass the secret variable to a PowerShell script and print it:
Let’s now have a look where and how the secret variables are stored.
TestLib, Version=188.8.131.52, Culture=neutral, PublicKeyToken=769a8f10a7f072b4
If the above line means anything to you, you are probably a .NET developer. You also probably know that the hex string at the end represents a public key token, which is a sign that the assembly has a strong name signature. But do you know how this token is calculated? Or do you know the structure of the strong name signature? In this post, I will go into details how strong naming works and what are its shortcomings. We will also have a look at certificate-based signatures and, in the end, we will examine the assembly verification process.
The title mentions ASP.NET 4.5.x, but the encryption algorithm is exactly the same in ASP.NET 4.6.x. It won’t work however in earlier versions of ASP.NET.
Some time ago I published a post entitled “Decrypting ASP.NET identity cookies”. In that post we wrote a Python script to decrypt ASP.NET Identity cookies. You could have also learnt how the derived keys, used to encrypt those cookies, are calculated. If you are interested in details, please have a look at that article. But to summarize, the following steps are performed by ASP.NET:
- Extract the encryption and the validation key from the web.config file
- Calculate the derived keys using the SP800-108 specification, with the context and the label taken from an adequate Purpose class instance
- Validate and decrypt the cipher
The above procedure applies not only to the cookies decryption, but also to many other cryptographic operations, such as ViewState encryption, Forms Authentication, Anti-Forgery tokens creation etc. However, there is still a missing gap in the presented flow. What if the encryption and the validation keys are not explicitly set in the web.config file? Today, we will answer this question.