Today’s post is going to examine an ethical grey area that I currently find to be very relevant. Is it ever okay to ignore responsible disclosure standards for security related issues? Spoiler alert: I’m going to argue that there are cases in which ignoring these standards is not only permissible but the only real ethical course of action.
Okay so lets start with some sample code. The below code represents a simple .NET Core C# program that encrypts a piece of plaintext.
using System;
using System.Linq;
using System.IO;
using System.Text;
using System.Security.Cryptography;
namespace Playground
{
class Program
{
private const string ENCRYPTION_KEY = "SuperSecretKey678$210!Hahahaha";
public static void Main(string[] args)
{
if (args.Length > 0)
{
var plainText = string.Join(" ", args);
Console.WriteLine($"Plain Text is {plainText}");
var encrypted = Encrypt(plainText);
Console.WriteLine($"Encrypted Version is {encrypted}");
}
}
private static string Encrypt(string plainText)
{
using (var aes = GetAes())
{
using (var encryptor = aes.CreateEncryptor(aes.Key, aes.IV))
{
using (MemoryStream encryptedData = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(encryptedData, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
using (var combiner = new MemoryStream())
{
var encryptedBytes = encryptedData.ToArray();
combiner.Write(aes.IV, 0, aes.IV.Length);
combiner.Write(encryptedBytes, 0, encryptedBytes.Length);
return Convert.ToBase64String(combiner.ToArray());
}
}
}
}
}
}
private static Aes GetAes(byte[] iv = null)
{
using (var sha = SHA256.Create())
{
var aes = Aes.Create();
aes.KeySize = 256;
aes.Key = sha.ComputeHash(Encoding.UTF8.GetBytes(ENCRYPTION_KEY));
aes.IV = iv ?? aes.IV;
return aes;
}
}
}
}
Pretty basic, right? Now this program contains a rather large security flaw. Namely the fact that it uses a hard coded encryption key in the form of the ENCRYPTION_KEY constant near the top. But hey so what? When I distribute the program the code will be obfuscated by the compilation process, right? Well yeah, but not really. Even if it was, this encryption implementation is unforgivable as it effectively ensures that the only thing standing between your users and a breach is the contents of the ENCRYPTION_KEY string constant. If I compiled this C# code I would get back a DLL file. That DLL file can be dissected using fun little tools like ILSpy or Reflector which effectively decompile compiled .NET binaries back into useful source code. So that effectively means that anybody with a copy of the DLL file can obtain the keys to the entire kingdom. It is stunningly easy for any competent C# developer to write a decryption routine after having seen the code above.
So while this example may seem contrived, I can assure you that I’ve seen this kind of thing more than a few times over my last 20 years in the business despite the fact that everything ever written on the subject of implementing encryption in code (regardless of language and platform) will decry this approach. Okay so what if you find out that some piece of software has employed this technique, is it okay to irresponsibly disclose the security vulnerability due to the nature of the bug? No, I don’t believe so. But as I’ve already indicated, I believe there are other circumstances that can arise which force issue. For starters, what if the data being encrypted is something sensitive like say a credit card number? Or a users password? Or some key piece of info used to implement an authentication system? To be honest even in the face of those extenuating circumstances, I still stand by responsible disclosure though I would find it difficult. So what then? Is it ever acceptable to eschew the standards of conduct?
Absolutely yes. Where I personally draw the line is in situations in which the piece of software has clearly been relying upon the flawed implementation for an extended period of time. This becomes even more pertinent in situations in which the piece of software and its creator advertises or implies that security is one of their core competencies. In cases such as those, I believe the bug represents an egregious violation of an implied agreement between the creator of the software and the users of the software. To put it bluntly: the reality in this situation is that if the bug is this easy to find, other less than savory individuals are likely already aware of it and actively exploiting it.
That being the case, time is of the essence. The interests of the users must be placed above that of the creator. While responsible disclosure typically serves the needs of both by at least attempting to protect users while giving the creator time to react, in cases such as these, protecting the users isn’t actually possible. Once the users interests have already been so deeply compromised, only the desires of the creator remain. Given the severity inherent in the oversight and how little the creator seems to care, the creator likely deserves no real consideration.
Is this policy harsh? Absolutely. But it needs to be. The world of software ought to be harsh lest we fall into the trap of simply devouring whatever garbage a particular creator or creators sees fit to offer us. In the situation I described above, I prefer to err on the side of the greater good. The greater good in this case is to let the users as well as the creator know about the issue simultaneously so that users have an opportunity to mitigate their level of exposure and risk. Anything less than that gives the already irresponsible creator an opportunity to punt on taking responsibility at the expense of their users - yet again.