I am using HMACSHA256 for message authentication in a web-farm environment.
Within the web-farm each machine has the same machine key, so the ViewState will work across machines, however, I need to do HMAC message authentication which will work across machines, so I figured that since all machines use the same machine key, there should be a way to derive a key from that to use as the HMAC key.
I notice that as of .NET 4.0 there is the MachineKey class, however, I am stuck with using .NET 3.5, and this is unavailable to me.
Is there a way to get some sort key that is the same on all machines without generating my own, for use in an ASP.NET 3.5 environment?
Edit
I don't actually need the machine key itself, just the validation key that is derived from the machine key (or equivalent).
You can read the machine key from the web.config. This link shows how to do so: http://aspnetresources.com/blog/how_to_read_auto_generated_machinekey
Keep in mind, that the author of the article reads the generated machine key - so you have to do some changes in the code.
I just read the article a little bit more and saw, that it uses reflection, which isn't neccessary, if you store the machine key inside the web.config.
Essentially it breaks down to this line:
MachineKeySection section = (MachineKeySection)
ConfigurationManager.GetSection ("system.web/machineKey");
Related
I am trying to use a stored procedure that has encrypted data, I have written the same program in Python with success. However when I use c# connecting to same db, it throws this error. Cannot find the symmetric key 'keyFieldProtection', because it does not exist or you do not have permission.'
You need to grant permissions to the keys. If you are unable to grant permissions, need to switch mode to windows authentication.
Else if you are opening master key, then refer to the following:
https://learn.microsoft.com/en-us/sql/t-sql/statements/open-master-key-transact-sql?redirectedfrom=MSDN&view=sql-server-2017
As per above;
“If the database master key was encrypted with the service master key, it will be automatically opened when it is needed for decryption or encryption. In this case, it is not necessary to use the OPEN MASTER KEY statement.”
Its hard to tell without looking at your code
I'm having an issue with a COM based client-server setup. The COM server is written in C# (.NET 4.0) and runs as a (registered) local server.
Depending on which application connects to the server, other clients will receive a Server execution failed (Exception from HRESULT: 0x80080005 (CO_E_SERVER_EXEC_FAILURE)
The underlying issue is explained here (in the section COM is integrity aware). The way I understand it, it is being caused by the fact that an elevated application creates the server with a higher integrity level. When another non-elevated application then connects, it is not allowed to connect to the same instance. The same happens when a non-elevated application creates the process, followed an elevated application connecting.
I've tried to implement the solution described on the page: modifying the registry to set a security descriptor that should allow all clients to connect. There is a code sample in C++, but this does effectively the same thing in .NET:
// Security Descriptor with NO_EXECUTE_UP
var sd = new RawSecurityDescriptor("O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)");
byte[] securityDescriptor = new Byte[sd.BinaryLength];
sd.GetBinaryForm(securityDescriptor, 0);
RegistryKey key = Registry.ClassesRoot.OpenSubKey("AppID\\{APP-ID-GUID}", true);
if (key == null)
{
key = Registry.ClassesRoot.CreateSubKey("AppID\\{APP-ID-GUID}");
}
using (key)
{
key.SetValue("LaunchPermission", securityDescriptor, RegistryValueKind.Binary);
}
However, this does not have the desired effect. When the second client tries to create an instance of the object in question, Windows tries to launch a separate instance of my COM Server, but the server prevents two instances from running as the same user. Given the permissions I've set, I would not expect a second instance to launch in the first place.
Since one of the client applications is running in Medium IL and the other in High IL, I also experimented with variants on the mandatory label, like:
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;ME)
O:BAG:BAD:(A;;0xb;;;WD)S:(ML;;NX;;;LW)(ML;;NX;;;ME)(ML;;NX;;;HI)
I've also tried setting the ROTFlags registry key to 0x1 (ROTFLAGS_ALLOWANYCLIENT) as suggested on the page, still no change in behavior.
I've established that the LaunchPermission registry value is being used in some way. I cannot discover where it's being read using Process Monitor, but when I use the dcomcnfg.exe tool to set the same key, I can force the server to fail loading by denying launch permissions.
I would like to point out that my server process does not need elevation. How do I make both elevated and non-elevated processes capable of connecting to a single server instance?
According to Windows Vista Security Model Analysis you will need to use shared objects such as a named pipe to go between the different IL. Also, the shared object should have an IL equivalent to your lowest IL being used.
you have to Set Debug option to Any cpu in VS.
I wrote an C# WPF application that signs a license xml file using the standard .Net SignedXml class. I am able to extract the public and private key as xml strings. I can safely tuck away my private key locally for the signing application, but what about the public key needed in the remote sign check application (library)? Options considered:
KeyContainer: no good, because signing and checking happens in 2 separate environments
Hardcoded: hardcode the public key as xml string in my checking library. I know the public key is not secret, but how can I prevent hackers from replacing the key with their own? I can sign the library, but then they could tamper with the application using the library....
Put the public key in a standard digital certificate that you distribute with your app. The integrity of the certificate will then be guaranteed by Windows, and you can tell if it's been changed.
Of course both the hardware and Windows itself is under the control of any potential attacker, so you can't really prevent a compromise of a specific machine.
Here's an example from a program that I used to distribute. When the program was activated from a licence perspective, it sent a hardware hash to a web service. This returned a self-signed certificate containing the hardware hash, which my program then checked whenever it was started. If the certificate had been changed in any way, the program would stop.
I put the public key in a directory outside of the inetpub directory, and if you move the private key off of the computer, then the worst someone could do is to replace the public key and it no longer can decrypt, but you could be informed when it can't decrypt to know something happened.
But, if someone was able to change your file you will have bigger problems that just having this one file changed.
UPDATE:
Oops, I missed that this is a WPF program. Unfortunately the best you can do is to have the private key separate from the public key, so, you can decrypt, but if the hacker changes the public key the application won't function properly.
That is one of the advantages of using the public/private key, to verify that only you can do the encryption.
The other option is to fetch the public key from a webserver, but then you have the same problem in that it is possible for someone to trick the application to go to the wrong server, so it isn't full-proof, and it will require that the user had an Internet connection, and for you to uniquely identify them.
I have a bit of code that needs to run with elevated privileges (more that I want the rest of my code running at).
I have my code that sets up the Impersonation working, but it requires a username, domain and password. As my code is in C#.net I know that the password can be found by anyone determined enough.
Is there a way to encrypt the password in my code? Or otherwise secure this password and still be able to pass it in?
Here is the code I am calling:
using (new Impersonator("UserNameGoesHere", "DomainNameGoesGere", "Password Goes Here"))
{
uint output;
NetUserAdd(AUTHENTICATION_SERVER, 1, ref userinfo, out output);
return output;
}
I would love an example that shows how to fix this to not show my password in plain text.
I am using Visual Studio 2008, .NET 3.5 SP1, and running on Windows Server 2003.
Vaccano,
I would recommend investigating the data protection API (DPAPI) for what you're attempting to achieve. It is considered part of the solution in many best practice approaches to reversibly storing passwords needed by applications.
A good article discussing the DPAPI (and other techniques + concerns) can be found here:
http://msdn.microsoft.com/en-us/magazine/cc164054.aspx
With C# 2.0, P/Invoking isn't even required; managed wrappers exist:
http://blogs.freshlogicstudios.com/Posts/View.aspx?Id=41ca5a99-ddc0-4d0a-9919-2ce10bf50c7e
I hope this helps!
You have multiple options here.
You can hash the password the very first time and store the hash to a file. Now the next time, you want to execute the code with elevated privileges, you need to accept/retype the password and re-compute the hash and match it with the stored hash. Only if it matches will you execute your code in elevation modes. You could hash using SHA. Please look at System.Crytography namespace for examples on hashing.
Second option is to encrypt the password using algorithms like AES. However you will need to have a key to do this and you will have to worry about securing this key.
Third option is to use DPAPI and encrypt the password but not worry about securing the keys - much easier option than 2.
I would recommend 1 if you do not mind re-entering the password every time the application starts. If that is not a possibility, I would suggest going with 3 and use DPAPI.
Here are some links to get you started.
1.http://www.obviex.com/samples/dpapi.aspx
2. http://www.obviex.com/samples/Encryption.aspx
You can use safe-config nuget package. Internally it uses data protection api to encrypt and decrypt data.
//Save some configuration data at folder data\temp\
var configManager = new ConfigManager()
.WithOptions(DataProtectionScope.CurrentUser)
.Set("password", "my-massword")
.AtFolder(#"data\temp\")
.Save();
...
//Load configuration data
var loadedValue = new ConfigManager()
.AtFolder(#"data\temp\")
.Load()
.Get<string>("password");
I recently encountered an odd problem with RSACryptoServiceProvider.VerifyHash.
I have a web application using it for decryption. When users running the web service were doing so over our VPN it became very very slow. When they had no connection or a internet connection they were fine.
After much digging I found that every time RSACryptoServiceProvider.VerifyHash is called it makes an LDAP request to check MyMachineName\ASPNET.
This doesn't happen with our WebDev (cassini based) servers as they run as the current user, and it is only really slow over the VPN, but it shouldn't happen at all.
This seems wrong for a couple of reasons:
Why is it checking the domain controller for a local machine user?
Why does it care? The encryption/decryption works regardless.
Does anyone know why this occurs or how best to work around it?
From this KB it looks like a 'wrinkle' in the code that needs sorting:
http://support.microsoft.com/kb/948080
Thanks (+1 & ans)
Tested and works.
From the KB article:
The SignData or VerifyData methods
always perform an OID lookup query
which is sent to the domain
controller, even when the application
is running in a local user account.
This may cause slowness while signing
or verifying data. Logon failure
audit events occur on the DC because
the client machine's local user
account is not recognized by the
domain. Therefore, the OID lookup
fails.
This is exactly what we were seeing.
We changed this line:
rsa.VerifyHash( hashedData, CryptoConfig.MapNameToOID( "SHA1" ), signature );
To this:
rsa.VerifyHash( hashedData, null, signature );
And that fixed it.