So, I've been trying to figure out the following problem for the past few weeks, and at this point I'm almost exhausting my options because how contradictory the situation seems.
I have an application which is developed to work under SharePoint but it's basically ASP.NET code. I have an encrypted connection string which I decrypt it in memory and store it in a configuration object to access the database. My configuration object is static (accesible through a Service Locator pattern), which I later use to seed a LINQ-to-SQL data context.
My internal key for decryption is stored, privately in a class as private static readonly string myPassword = "MyPassword"; (just an example, the actual password is more complex and valid). There's no single statement, anywhere, referencing that field, except one on a static method using it as a parameter for another decryption method (instance method), which instantiates a new DESCryptoServiceProvider with it.
And still, I get the following exception from time to time in my production server logs:
Exception type: CryptographicException
Exception message: Specified key is a known weak key for 'DES' and cannot be used.
As such, the connection string decryption fails and, of course, the database is not accessed anymore. Poof, application down.
How is this even possible?
Disclaimer: This is an old application I am maintaining. The description I provide here is to help troubleshoot, but I cannot change the way it works internally. Some will agree that this is not the best approach but the application has been running without a problem for more than 2 years and suddenly these exceptions are taking it down.
Update: I've been requested to clarify with a stack trace of the exception, but I cannot provide one full stack trace for NDA reasons. What I can tell is the following:
The object throwing the exception is the System.Security.DESCryptoServiceProvider.CreateDecryptor(Byte[] rgbKey, Byte[] rgbIV) method
The original key (the one we actually use) does validate and does not generate an exception. Still, we get this exception from time to time (not always), without knowing which is the current value which does not validate
The instance of the DESCryptoServiceProvider is stored statically, privately, in a helper class
This is all triggered by System.Web.HttpApplication.InitModulesCommon(), to initialize the application internal parts
Also, here is an obscured stack trace:
at System.Security.Cryptography.DESCryptoServiceProvider.CreateDecryptor(Byte[] rgbKey, Byte[] rgbIV)
at SymmetricEncryption.Decrypt(String contents, String key)
// our helper, just a wrapper, based from this class: http://www.codeproject.com/Articles/1967/Encryption-Decryption-with-NET
at EncryptedConnectionStringHelper.DecryptUserAndPass(String connectionString)\
// our container for parsing the connection string and decrypting the user and password, not the full connstring is encrypted
at OurModule.Init(OurConfigurationSection config)
at OurModule.Boot(OurConfigurationSection config)
at OurModule.Boot()
at OurModule.Init(HttpApplication context)
at System.Web.HttpApplication.InitModulesCommon()
at System.Web.HttpApplication.InitInternal(HttpContext context, HttpApplicationState state, MethodInfo[] handlers)
at System.Web.HttpApplicationFactory.GetNormalApplicationInstance(HttpContext context)
at System.Web.HttpApplicationFactory.GetApplicationInstance(HttpContext context)
at System.Web.HttpRuntime.ProcessRequestInternal(HttpWorkerRequest wr)
Our application registers this module in the following way:
public class OurModule : IHttpModule
{
public static bool initialized = false;
public void Init(HttpApplication context)
{
if (!initialized) {
subscribe(context);
OurModule.Boot();
initialized = true;
}
}
Have a look at your wrapper SymmetricEncryption.Decrypt. My guess would be that the issue is in there. How it creates the Key from your password. Does it use PasswordDeriveBytes or some other half baked solution?
Failing that maybe you could try get a better key than "MyPassword".
Failing that maybe you could use web.config encryption. Scott Gu wrote about it here.
It doesn't sound like anything's mutating the object. It sounds like "something" (if you'd posted the stack trace it would be clearer) is validating the DES key... and complaining that it's a known weak key.
Ideally, you should change your password to be more secure, of course - but if you can't, you should look at exactly where that exception's coming from, and see if there are settings somewhere controlling how and when it's validated.
If you're not already logging the full stack trace (instead of just the exception message) that's the first thing you should do.
Related
Is there any way to track if end-point is available for Tcp Sink logging ?
For example locally on my machine I do not have FileBeat setup, while its working on Staging machine.
The way I initialize Logger
private readonly ILogger _tcpLogger;
public TcpClient(IOptions<ElasticSearchConfig> tcpClientConfig)
{
var ip = IPAddress.Parse(tcpClientConfig.Value.TcpClientConfig.IpAddress);
_tcpLogger = new LoggerConfiguration()
.WriteTo.TCPSink(ip, tcpClientConfig.Value.TcpClientConfig.Port, new TcpOutputFormatter())
.CreateLogger();
}
and simple method just to submit log
public void SubmitLog(string json)
{
_tcpLogger.Information(json);
}
And in my case when its submitting json string locally, it just goes nowhere and I would like to get an exeption/message back.
ideally on json submit, but during initialization is Ok.
Writing to a Serilog logger is meant to be a safe operation and never throw exceptions, and that's by design. Thus any exceptions that happen when sending those messages would only appear in the SelfLog - if you enable it.
e.g.
// Write Serilog errors to the Console
Serilog.Debugging.SelfLog.Enable(msg => Console.WriteLine(msg));
The example above is, of course, just to illustrate the SelfLog feature... You'll choose where/how to display or store these error messages.
Now, if the operation you're logging is important enough that you'd want to guarantee it succeeds (or throws exception if it doesn't) then you should use Audit Logging, i.e. Use .AuditTo.TCPSink(...) instead of .WriteTo.TCPSink(...)
I've got an ASP.NET that relies on some code that uses static constructors. The code in these type initializers sometimes fails. Let's say, for sake of argument, that the code is:
public static readonly string Thing = SomeSpecialCallThatRarelyFails();
Perhaps that's vile, but it cannot be changed. And this kinda code is in every controller, so ASP.NET can't create the controller and just sits there broken until someone comes along to restart it.
I understand this is the way it should be, because the problem may very well be non-transient and auto-restarting would create a loop. Or perhaps only one controller fails, so the app is still sort of alive. So I get the default behaviour to just keep returning the error. But in this particular case, let's pretend the best thing is to notice this failure and restart.
How can I automate the detection of this scenario and trigger a restart or recycle of the IIS app pool/AppDomain?
I've noticed that if I cause an exception on Application_Start, then the app will auto-restart. So one way is for me to iterate over all my types and try accessing them. If they have .cctor failures, then I'll crash Application_Start and ASP.NET will restart. But that's pretty hacky, plus it won't help if the actual request code references another type that I don't know about which throws on .cctor.
Is there a better way? Should I write a Web API filter and look for TypeInitializerException or something?
Just a thought. Is the 'rare failure' deterministic? Could it be solved by adding retry logic?
public static readonly string Thing = RetrySpecialCall();
private static string RetrySpecialCall()
{
while (true)
{
try
{
return SomeSpecialCallThatRarelyFails();
}
catch (Exception) {}
}
}
So here's a way to handle it in Web API 1:
In Application_Start, iterate over your controller types, calling System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor to force all your known type constructors to run. If it Application_Start fails, ASP.NET seems to restart.
Add an exception filter that looks for TypeInitializationExceptions. Then call HttpRuntime.UnloadAppDomain().
The two parts are needed as a controller failing to construct will not hit the exception filters.
With Web API 2 it seems like you could do it in one go by implementing System.Web.Http.ExceptionHandling.IExceptionLogger and registering it as a global service. Same logic: check for TypeInitializationException and UnloadAppDomain if so.
I am administrator of a small practice project web application, AngularJS front-end pulling its back-end data from a C#/.NET WebAPI, and I'm handling security using the SimpleMembershipProvider.
I suspect that the way I implemented said security is not the best (I'm told ASP.NET Identity is now the way to go?) but that's another question altogether.
The issue that I'm very bewilderingly running into is that I get occasional reports that on a given page load to display a particular user's data, it returns somebody else's. Reloading the page fixes the issue (evidently) and I haven't been able to duplicate the scenario myself, or figure out anything particularly consistent in the users to which this happens.
None of the information being displayed is at all sensitive in nature (the app's just a friendly front end for an already public third-party API) so I'm not in panic mode about this, but I am both concerned and confused and want it fixed.
Here is what one of my API controller endpoints looks like:
[Authorize]
public class UserController : ApiController
{
private static int _userId;
private readonly IUserProfileRepository _userProfileRepository;
public UserController()
{
_userProfileRepository = new UserProfileRepository(new DatabaseContext());
_userId = WebSecurity.GetUserId(User.Identity.Name);
}
public UserProfileDto Get()
{
return _userProfileRepository.GetUserProfileById(_userId).ToDto();
}
}
Any feedback on where I might be going wrong here or what might be causing the intermittant inconsistency would be very much appreciated. (Laughter also acceptable if the way I handled this is just really bad. :P )
Static class fields are shared by all instances/threads of the same AppDomain (in your case - process). Different http requests are processed by threads running in parallel. Any two threads running [almost] at the same time may (will) change the value of _userId. You are assigning _userId in the constructor of your controller, and a new instance of this controller is created for each http request that is to be responded to by UserController. Therefore, this assignment will happen multiple times.
You will have hard time replicating this problem, since you are a single user testing the code, hence there are no overlapping request threads.
Remove static specifier from the _userId field declaration of the controller class.
Note: make sure that DatabaseContext is disposed of. One place that can be used for this is the overriden Controller.Dispose.
Change the Get to retrieve the user id rather than from a static variable:
public UserProfileDto Get()
{
return _userProfileRepository.GetUserProfileById(WebSecurity.GetUserId(User.Identity.Name)).ToDto();
}
Hello fellow seasoned developers!
I was wondering if it were possible to override the .Net Request.QueryString object somehow? It would be really nice if this could be done without having to create my own HTTP module as well.
I have been tasked with RSA(1024) encrypting all the querystrings in my application. However, the application is already built and there's a LOT of places where querystrings are being set so ideally i would like to make a global change that would decrypt the query and place it in the normal Request.QueryString so as to not have to change my code everywhere, and maybe pass it along to other devs within my team and they also don't have to change their code.
Now, I already built the encryption object and use the SessionID for salts to make the keys unique per session. I have also tried intercepting the HTTP request in Global.asax so as to rewrite the request path with the decrypted query, however, that was a bust as any postbacks being performed on those pages put the decrypted querystring back into the POST, which i obviously don't want.
So now i'm at a stage where i would like instead of re-writing the path, to intercept or override the Request.QueryString object on a global level and use my decryption methods there whenever a call to this[key] is placed, and thus again, not having to stop using Request.QueryString. However, after hours of searching on the web, i could not find a single example on how to do this...
If anyone could help me out with this i would be most grateful!
I think the easiest way to accomplish this is to use an Extension Method. Perhaps something like this:
class Program
{
static void Main()
{
var decryptedValue = HttpContext.Current.Request.DecryptQueryStringParam("myParam");
}
}
public static class HttpRequestExtensions
{
public static string DecryptQueryStringParam(this HttpRequest extendee, string name)
{
// do stuff to decrypt
return DecryptMethodStub(extendee.QueryString[name]);
}
private string DecryptMethodStub(string queryString)
{
return "something decrypted the string";
}
}
Please note that the Program class above is for illustrative purposes only... in reality you would call Request.{ExtensionMethod} within the body of a asp.net web forms page or an MVC controller which already provide direct access to the HttpRequest object through the Request property.
here is some information about extensions:
http://msdn.microsoft.com/en-us/library/bb383977.aspx
Within a web site I'm using the PrincipalPermission attribute to restrict access to certain methods.
Here's a canoncial example:
class Program
{
static void Main(string[] args)
{
Foo();
}
[System.Security.Permissions.PrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Role = "Winners")]
static void Foo()
{ }
}
If the principal isn't in the role specified then the .net infrastructure throws a System.Security.SecurityException with the generic message "Request for principal permission failed".
If the permission check fails I'd like to log what role the PrincipalPermission required. This will be really useful for our support staff who can then either assign the role to the user and/or monitor the logs to see if anything suspicious is happening. Clearly for security purposes the end user will still see a generic unauthorised message. I've trawled through the SecurityException itself but it doesn't have the "Role" anywhere in it.
Is there anyway to get this information?
If your code is fully trusted, you can extract the required information by parsing the XML representation of the SecurityException's FirstPermissionThatFailed property. However, for your second purpose of detecting "suspicious" activity, it might be preferable to simply log the return value of the SecurityException's ToString() method. This will include both the details of the denied PrincipalPermission and the stack trace where the exception occurred. The context given by the stack trace is likely to be very useful, assuming that the support staff in question understand how to relate it to your application structure.