.NET/C# reading certificate from store cause AccessViolationException - c#

I've getting very strange code exception, which is should work but not work.
I have following code:
X509Certificate certificate;
X509CertificateStore store = X509CertificateStore.LocalMachineStore(X509CertificateStore.MyStore);
store.OpenRead();
var certs = new X509CertificateCollection();
Microsoft.Web.Services2.Security.X509.X509CertificateCollection findCertificateBySubjectName = store.FindCertificateBySubjectName("localhost");
foreach (X509Certificate tempCertificate in store.Certificates)
{
if (String.CompareOrdinal(tempCertificate.Subject, "") == 0)
{
certs.Add(tempCertificate);
}
}
Current code runs inside w3wp process under admin rights. But I get exception which you can see on screenshot. I tried many things, give all access to all certificates, change users, reimport certificate.
I will be appreciate for any help or assistance.

Related

SignerInfo.CheckSignature throws out exception "Parameter is incorrect"

There is a method (simplified here) that verifies the digital signature. When I try to check a signed file, I get an error "Parameter is incorrect" in the method SignerInfo.CheckSignature. No matter what parameters I pass. This is happening on the production server and I cannot reproduce the same error on myself - everything works fine. The signature and certificate chain are valid. The code and certificate collection are the same for development and production servers.
public string Check(byte[] fileBytes)
{
X509Store store = new X509Store(StoreName.Root, StoreLocation.LocalMachine);
store.Open(OpenFlags.MaxAllowed);
X509Certificate2Collection collection = new X509Certificate2Collection(store.Certificates);
store.Close();
byte[] encodedSignedCms = fileBytes;
SignedCms signedCms = new SignedCms();
signedCms.Decode(encodedSignedCms);
if (signedCms.SignerInfos.Count == 0)
return ("not found");
SignerInfoEnumerator enumerator = signedCms.SignerInfos.GetEnumerator();
while (enumerator.MoveNext())
{
SignerInfo current = enumerator.Current;
try
{
//any of these methods will return the same error
current.CheckSignature(true);
current.CheckSignature(collection, true);
current.CheckSignature(collection, false);
}
catch (CryptographicException e)
{
//parameter is incorrect
return ("error");
}
}
return ("success");
}
Error:
MESSAGE: parameter is incorrect
INNEREXCEPTION: null
STACKTRACE: in System.Security.Cryptography.Pkcs.SignerInfo.Verify(X509Certificate2Collection extraStore, X509Certificate2 certificate, Boolean verifySignatureOnly) in System.Security.Cryptography.Pkcs.SignerInfo.CheckSignature(X509Certificate2Collection extraStore, Boolean verifySignatureOnly) in ProjectName.Controllers.SignatureController.Check(Byte[] fileBytes).
TARGETSITE: Void Verify(System.Security.Cryptography.X509Certificates.X509Certificate2Collection, System.Security.Cryptography.X509Certificates.X509Certificate2, Boolean)
Technical info:
ASP.NET MVC
Production: Windows Server 2016. Net Framework 4.8. IIS 10.
Development: Windows 7 Pro or Windows Server 2016. Net Framework 4.8. Visual Studio 2015
What can I fix or check? Thanks in advance.
I noticed that the chain was not displayed when opening any certificate. And the error "A system-level error occurred while verifying trust" was displayed. I found a recommendation to reinstall the crypto provider. In my case, it is Crypto Pro CSP. After that, the chain of certificates lined up correctly, and the code worked fine. Most likely this happened after the Windows update.

Private Key Permissions Breaking on Program Exit

I have a small application as a 'certificate manager' to a larger program, so that users won't have to manually install and configure certificates.
It's fairly simple - it has some certificates as Embedded Resources, which it loads into the appropriate stores, then sets appropriately configured permissions.
This appears to work correctly while the program is running. Using MMC, I can see that the certificate is installed. If I Manage Private Keys, it has a new permission added correctly. However, as soon as I close the certificate manager, the permissions break. The certificate is still installed, but hitting Manage Private Keys pops up an error similar to "Key does not exist."
Additionally, if the program is run a second time, the permissions will 'stick' correctly after the program exits.
Here's code which the program uses to verify that the permissions were added. This method returns 'true' every time, even when the permissions break afterwards.
private bool GetSecurityStatus(X509Certificate2 cert, X509Store store)
{
store.Open(OpenFlags.ReadOnly);
//add Authenticated Users to private cert
RSACryptoServiceProvider privKeyRSA = cert.PrivateKey as RSACryptoServiceProvider;
string keyFilePath = FindKeyLocation(privKeyRSA.CspKeyContainerInfo.UniqueKeyContainerName);
FileInfo privateKeyFileInfo = new FileInfo(keyFilePath + "\\" + privKeyRSA.CspKeyContainerInfo.UniqueKeyContainerName);
FileSecurity privateKeyFileSecurity = privateKeyFileInfo.GetAccessControl();
AuthorizationRuleCollection rules = privateKeyFileSecurity.GetAccessRules(true, true, typeof(NTAccount));
foreach (FileSystemAccessRule fsar in rules)
{
if(fsar.IdentityReference.Value.Contains("Authenticated Users") && fsar.AccessControlType == AccessControlType.Allow && fsar.FileSystemRights == FileSystemRights.FullControl){
store.Close();return true;
}
}
//Close Private Cert store
store.Close();
return false;
}
The FindKeyLocation returns the appdata\Microsoft\Crypto\RSA\ path of the private key.
I'm thinking it has to do somehow with the exiting of the program altering the private key file itself, but I'm unsure why it would then work the second time.
I believe I've found a solution to my issue, based on the respones here:
Import certificate with private key programmatically
and from MSDN here
https://support.microsoft.com/en-us/help/950090/installing-a-pfx-file-using-x509certificate-from-a-standard-.net-application
I had to pass two flags within the certificate's parameters, instead of just MachineKey
X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet

Loading X509Certificate results in exception CryptographicException "Cannot find the original signer"

I am trying to instantiate an X509Certificate object, but I keep running into the same CryptographicException, with the error message:
"Cannot find the original signer".
I have tried several ways of loading the certificate:
// some different things that I have tried
var cert = X509Certificate.CreateFromCertFile(certFileName);
var cert2 = new X509Certificate(byteArray);
var cert3 = new X509Certificate(byteArray, secretString);
var cert4 = X509Certificate.CreateFromSignedFile(certFileName);
I have tried both loading from a file and from a byte array. Each time I get the same error. What could be causing this?
I figured out the problem. I was attempting to load just the certificate file, which did not include the private key. To fix the problem, I had to install the private key on the machine on which the certificate was purchased, and then export it as a .pfx file and move it to where I actually wanted to use it. I'm sure was a newbie mistake. Hopefully, my silly issue will help other newbies in the future.
var collection = new X509Certificate2Collection();
collection.Import(byteArray);
return collection;
via https://stackoverflow.com/a/44073265, by https://stackoverflow.com/users/6535399, who writes crypto for msft - e.g. https://github.com/dotnet/corefx/pull/25920

C# Registry SetValue throws UnauthorizedAccessException

Before you try to answer this with, "Do a quick Google search." I'd like to point out that I have already. Here is the situation, I have the following method that attempts to modify a registry key value. The problem I'm getting is that when executed, it throws an UnauthorizedAccessException even though I've opened the key as writeable. I'm running Visual Studio as administrator and even tried to make a small .exe with a manifest file forcing it to run as admin that will execute the code with no luck. The key already exists, it doesn't try to go into the CreateKey method. Here is the block of code.
Path = "S-1-5-21-1644491937-1078145449-682003330-5490\Software\Microsoft\Windows\CurrentVersion\Policies\System"
Key = "DisableTaskMgr"
NewValue = 1
public OperationResult ModifyKey()
{
OperationResult result = new OperationResult();
if (!Path.IsNullOrEmptyTrim())
{
if (!Key.IsNullOrEmptyTrim())
{
try
{
var key = Microsoft.Win32.Registry.Users.OpenSubKey(Path, true);
if (key != null)
{
key.SetValue(Key, NewValue);
key.Close();
}
else
{
result = CreateKey();
}
}
catch (Exception ex)
{
result.SetFail("Error accessing registry", ex);
}
}
else
{
result.SetFail("Registry key was null");
}
}
else
{
result.SetFail("Registry path was null");
}
return result;
}
Do I have to manually walk down the registry tree setting each OpenSubKey call to writeable? I tried this as well, still threw the same error...
in the var for your key
var key = Microsoft.Win32.Registry.Users.OpenSubKey(Path, true);
change to
var key = Microsoft.Win32.Registry.Users.OpenSubKey(Path, RegistryKeyPermissionCheck.ReadWriteSubTree);
Have you tried setting the accessrule and permissions?
string user = Environment.UserDomainName + "\\" + Environment.UserName;
RegistryAccessRule rule = new RegistryAccessRule(user,
RegistryRights.FullControl,
AccessControlType.Allow);
RegistrySecurity security = new RegistrySecurity();
security.AddAccessRule(rule);
var key = Microsoft.Win32.Registry.Users.OpenSubKey(subKeyPath, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.FullControl);
key.SetAccessControl(security);
One possible issue that I see with your code is that the Path variable is being set to a string that doesn't escape the \ characters. How about something like:
Path = #"S-1-5-21-1644491937-1078145449-682003330-5490\Software\Microsoft\Windows\CurrentVersion\Policies\System";
As a last ditch effort to figure out what was going on, I created a simple service to test this code that will run as the local system account. It's the highest privileges I could think of to try and run the code with. Running the code with these permissions worked.
Special thanks go out to 0_____0 and Charleh for pointing out the anti-virus as well. I checked the logs and it turns out it was trying to quarantine my changes. I guess even it won't stop the System user from making these changes though.
Special thanks go out to Sorceri as well for helping me research this so much.
In conclusion, if you're having intermittent, extremely odd behavior, check your virus scanner and permissions.
I ran into the same problem recently. So I tried a few things and instead of calling key.SetValue(Key, NewValue) simply calling create function solved my problem. That is;
Microsoft.Win32.RegistryKey key1 = Microsoft.Win32.Registry.Users.CreateSubKey(Path);
key1.SetValue(Key, NewValue);
CreateSubKey call doesn't delete the current entry but provided with the ability to write without exception. I hope that helps.
Only set grants to dword. You must to open Registry and at the last folder path, rigth click over it and set Grants, and select All Aplications and check Total Control. I hope to help you.
just Registry.SetValue(sub_key, key, value);
Example:
Registry.SetValue(
#"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run",
"MyApp",
Application.ExecutablePath);

Using WMI to uninstall programs

I want to uninstall a program using WMI, but I get this error : "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))". Installing it worked without any problems, using the same ConnectionOptions.
Is there any possibility that the Administrator user has rigths to install software, but not to uninstall? If so, how can I edit them?
Main()
{
ConnectionOptions oConn = new ConnectionOptions();
oConn.Impersonation = ImpersonationLevel.Impersonate;
oConn.EnablePrivileges = true;
oConn.Username = "Administrator";
oConn.Password = "password";
System.Management.ManagementScope oMs =
new System.Management.ManagementScope("\\\\192.168.14.128\\root\\cimv2", oConn);
Uninstall(oMs, "\\\\192.168.14.128\\root\\cimv2:Win32_Product.IdentifyingNumber= \"{926C96FB-9D0A-4504-8000-C6D3A4A3118E}\",Name=\"Java DB 10.4.2.1\",Version=\"10.4.2.1\"");
}
static void Uninstall(ManagementScope oMs, string path)
{
if (!oMs.IsConnected) oMs.Connect();
ManagementObject product = new ManagementObject(path);
if ((product != null) && (product.Path.ClassName ==
"Win32_Product"))
{
object result = product.InvokeMethod("Uninstall", null); //here is where I get the error
Console.WriteLine("The Uninstall method result is {0}",
result.ToString());
}
}
Thank You!
Are you doing this on an XP machine? I just Google-d your error number and got a couple links to this: http://www.0x80070005.net/. There's a lot of information about the problem, and here's a copy and paste:
The error 0x80070005 often occurs when
a scheduled task in Task Scheduler in
Windows becomes corrupt, you need to
install a security update which will
receive an error message. The error
message usually shows “Access denied”.
Here it needs a vulnerability task
scheduler which will allow code
execution. These are security updates
which were issued in the earlier
bulletin. This needs a Microsoft
knowledge base. So it is clear that
this error is about the security issue
and it finds error in the access.
Also, we're using WiX for our installer solution. Not sure if it' something you can use, but I figured I would just throw it out there.

Categories