How to detect fake trusted personal/root SSL certificates of target domain - c#

Someone can add a fake SSL cert. into trusted certificates collection. How can I detect these fakes? How can I verify a cert is official, is there any list to compare?
I've added a screenshot of a legal & a fake one (created by Fiddler):
ADDITION:
To ensure your sensitive SSL communication is secure, you have to use certificates of common trusted authorities. If someone installed Fiddler -or a malicious software installed its own cert.- then I need to cancel any communication attempts and alert in my app at client's pc.
ADDITION 2
I only care about communication between end user's pc & Google Docs. We know Google Docs web site's public certificate is given by "Google Internet Authority". I think I have to compare it & installed certificate for Google Docs on user's pc.
Last word:
I need to simply compare the certificate in use for target site vs the target site's original SSL certificate just before any SSL comunication.
More info: This link

There is no single "official list". You must compare your list to someone else's list.
Windows has its own list which is used by Internet Explorer.
Firefox maintains a separate list of its own.
I don't know about Chrome, Safari or Opera.
But the long and short is you need to compare your list to other lists which you know are correct, for example from a colleague's computer.

You can't. If user added it, that means she trusts it. And also, a certificate can be valid without being part of the "official" lists.

Each application maintains (or relies on other applications) the list of trusted root certificate authorities. Windows has its own list, OpenSSL has its own list, all major browsers have their own lists (Chrome uses or can use Windows one, if memory serves).
If you create a Windows application, your best bet is to rely on system list, as it is updated on a regular basis (if you carry your own list, you have to maintain it as well).
One thing to pay attention to is that the certificate issued by trusted authority doesn't mean trusted certificate. Some certificates are issued by hacking (this happened at least with two intermediate CAs during last years), private keys for others are leaked, and this causes the need to revoke such certificates. Revocation status can be checked by inspecting CRLs (revocation lists published by CAs) or using OCSP (online certificate status protocol).
You need to use them no matter where you get the list of trusted CAs.

Related

Adding a <publisher> to an Excel add-in project

I recently had to take over an Excel plugin project and one of the issue I'm getting is that a customer can't use the plugin because their Trust center only allows COM add-ins signed by Trusted publishers. (And they are not able to disable it)
I'm quite new and don't really understand this signing issue so I self-signed the code.
But the add-in has its publisher set to None. Here's how it's showing.
I believe that's not what I need to do, right? As a self signing will not be trusted by the customer Trust Center.
I saw this post but I was quite unsure about what was going on.
Does that mean there is no possible workaround or am I getting this wrong?
One thing I was wondering but I needed some help over is that if the add-in needs to be signed by a Trusted publisher.. Would that do the trick if the client is generating .pfx and I use it to sign the add-in?
AFAIK, there are no "tricks" you can do from the DEV side. This is a security feature. You need to sign your add-in with a valid certificate to get rid of "unknown publisher". You can do that by selecting that certificate on "Sign" tab in Project settings in Visual Studio.
If you are a public company/developer and don't really have any assumptions about your users, then you can obtain the code signing certificate from one of the public code signing certificate providers. The main ones are listed here: https://learn.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate
It is not free, and you'll need to prove your identity to the certificate issuing authority (like, provide them your passport/company registration details/etc).
If you are developing an add-in for a specific organization and you can negotiate with it's admins, or your users have admin rights on their computers and are allowed to mess with security, then you can create a self-signed certificate, sign your code with it (select it on "Signature" tab), and then ask your users (or user's admin) to add this self-signed certificate to "trusted root" for their organization/on their PC.
Please note that self-signed certificate usually work only on the PC where the certificate was created, and used for testing or development purposes. In your case, this means that your self-signed certificate is considered valid on your PC, but not on the customer's PC. If you want a certificate created by you on your PC to also work on customer's PC, then you'll have to ask the customer to add your certificate as "trusted root", i.e. to treat your signature the same way as one of those "worldwide trusted certification authorities" from the list above.
The normal practice is to buy a certificate from the certification authorities though.

Open X509 Certificates Selection Using USB Token in C# Hosted on IIS

I am working on a requirement which required Digital Signature on PDF files in ASP.Net C# and developed one application who gets the client certificate using USB token on my local machine. But, When hosting this application on IIS server getting error 'Current Session is not Interactive'.
Anyone have any idea, how can we get X509Certificates from client machine in ASP.Net C# and this application hosted on IIS server not console application.
My code for reference:
private void getSign()
{
X509Store store = new X509Store(StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
X509Certificate2 cert = null;
//manually chose the certificate in the store
X509Certificate2Collection sel = X509Certificate2UI.SelectFromCollection(store.Certificates, null, null, X509SelectionFlag.SingleSelection);
if (sel.Count > 0)
cert = sel[0];
else
{
//MessageBox.Show("Certificate not found");
return;
}
SignWithThisCert(cert);
}
Disclaimer: although, it is not a straight answer to your question, but may contain directions for you to get the right way depending on a business requirements. There are two major issues in your question. One of them I tried to discuss in comments, but may need to explain.
Let's try to analyze your initial post:
Task: let users to upload a PDF to web application and make it signed.
Requirements: the PDF must be signed by using a certificate stored on a client's USB token.
Your proposed solution: get client certificate (from the client) and perform signing on a server side.
Let's formalize terms and operations used in your scenario.
Signing: document signing is used to guarantee document integrity and ensure that the document was not tampered in any way after it was signed. Digital signaure provides information about the entity who performed signing. This adds non-repudiation feature. Once signed, signer cannot deny the signing fact and proves that the information in the document was correct at the signing time. Asymmetric signing requires private key. Associated public key can be used to verify and validate the signature.
Private key: is a part of a key pair which belongs to particular client. No one else should know private key.
Security boundaries: client (web browser or other web client) and web server run in different security boundaries and have different trust levels. They are under different administrative controls. As the result, web server has very limited access to client machine/data and vice versa: web client has very limited access to server machine/data.
Your proposed design assumes that client picks the document and upload it to a server. Then client picks a signing certificate (particularly, private key) and upload it to a server for signing operation.
Issue #1: once private key leaves client and is copied to your web application you are breaking security boundary. As the result, the key is no longer private, because web application possesses a knowledge of private key and it is stored (even if temporarily) in server memory. Or, in simple word, the key is leaked and compromised.
Client is no longer responsible for his key and operations made by the key. Client may deny anything that was made by using its private key. And deny signatures made by your web application.
Issue #2: your proposed design assumes that PDF is copied to a server as is. And only then it is signed. However, once the document (or its exact binary copy, to be more precise) touches the network, client is no longer responsible for document accuracy. Because the document may be transformed during transit or some code that touches the document between client and document signing code.
Once document leaves client machine, client is no longer responsible for document integrity, because the document is passed through various pieces of code that compose the document to a suitable for transmission format (encapsulation, for example). As the result, document sent by client and recieved by document signing code on a server side may not be the same. Document integrity is not guaranteed. Although, you can apply TLS to protect the document during transmit, there still are places where the document can be anonymously tampered and no one will notice that.
Again, due to the fact that client cannot guarantee that web application received the same document he sent, client can deny the document you are trying to sign and deny the signature. Thus, making signature useless, because it proves nothing.
Issue #3: (not really an issue, but worth explanation) provided piece of code doesn't perform intended task (even though, it looks working in dev environment). Your goal is to invoke certificate selection dialog on client to select proper certificate.
During testing, you are running all the code locally. In debugger, the web application runs under currently logged user (which is interactive session) and is able to show the certificate selection dialog. However, you can't easily identify in which context (client or server) it is executed, because both, client and server run on the same machine and under the same security context. In fact, it is called under server context.
When you deploy the application to web server, you see the difference. Web application runs under some application pool context (user account) and this session is not interactive. As the result, X509Certificate2UI class cannot show the dialog, because no one will see it and no one can press buttons on it. This behavior is consistent regardless if the client and server run on the same or different machines, because IIS (or other web server) immediately separate concerns and security boundaries, while debugger does not. And client and server will definitely run under different security contexts. Even if you force to use the same context, IIS will make a secondary non-interactive user session to run the web application.
In order to show certificate selection dialog on client, you have to have a deep interaction with client, for example, via Silverlight (not sure if X509Certificate2UI is available in Silverlight) or some ActiveX control. You have to run some code on client side to accomplish that.
All stated above shows potential issues in your initial design, they simply break basic security rules. Technologies and tools are designed to follow these rules, not break them. By pursuing your initial design you will be forced to constantly fight with technologies to break them and making your application very insecure and vulnerable.
Preferred solution: we identified common risks in your design: key leak and document integrity between client and signing code on a server. To easily mitigate all this, you should do the only thing: perform document signing on client side. by doing this, signing private key will never leak from client and document integirty will be guaranteed over the course of signing and receipt by web application.
Now, we can talk about certificate properties. Your requirement is to use the certificate which is stored on a USB token. I don't know what kind of token you mean here. Is is a standard USB mass storage with PFX on it, or it is cryptographic device (smart card with USB interface, which is usually referred to USB token. For example, Aladdin (SafeNet) eToken devices).
If it is USB mass storage device, then it can't be a part of requirement, because generic USB drive does not offer anything helpful to identify the source of the certificate. Any certificate can be easily copied to USB drive and any certificate can be copied from USB drive.
If it is USB smart card, then there is a way to identify whether the certificate came from this device, or other source. Smart cards have one unique property: private key never leaves the card. All operations are performed on a card (this is the reason why they are slow comparing to certificates stored on PC).
This is usually accomplished by adding extra information to signing certificate during certificate issuance. For example, by adding Certificate Policies certificate extension. This will require that CA operator/manager ensures that certificates with specified certificate policies is deployed to smart cards only.
If these processes are established, you can use the code on server side that accepts signed PDF document and examines signing certificate contents. For example, you read certificate policies and expect to see particular entry there. If it is presented, then you can safely make assumptions that the document was signed by using the certificate stored on a smart card, because the key cannot be copied to anywhere from card device. If the certificate does not contain specific entry in certificate policies, then you can reject the documment acceptance and ask client to use proper certificate.

Read certificates from a PKI card

How can I read certificates from a PKI card?
I tried finding answer on the Internet but I didn't get any good results.
Any ideas how to get the certs from a PKI card?
I need to sign some forms with a certificate key. All this will happen in a web app.
Later...
I didn't tried much because I don't have a point to start. I've just learned that all of the certs are read by Windows when you insert the card. This way I think I can get them using X509Store. I'll try it and I'll be back but still I'm in the need of some help.
As soon as you plugin in your SmartCard the certificates are copied to your local, personal certificate store. You can use "certmgr.msc" (run -> enter) to have a look at these certs.
You can access the certificates, as well as the associated private keys, with the X509Store. But of course you can only do it locally on your machine due to security reasons. Imagine every website would have access to your private keys...
How to Sign and Verify the signature with .NET and a certificate (C#)
If you are using CAPICOM, you will still need to execute code on the local machine (JavaScript).
You find the following statement here :
[CAPICOM is a 32-bit only component that is available for use in the following operating systems: Windows Server 2008, Windows Vista, Windows XP. Instead, use the .NET Framework to implement security features. For more information, see the alternatives listed below.]
Important None of the alternatives to CAPICOM offer a solution for scripts; therefore, you must write your own ActiveX control. For more information, see ActiveX Controls.
Which indicates that the .Net classes are not a "full" replacement to CAPICOM. So you can't use the "X509" classes in JavaScript.
If you want to use a client side private certificate to sign some data (assume a hash), you need to run code on the client. Here are some ideas what you could do:
Write an ActiveX control
Write browser Plugin(s)
Write an application which can be called by using a custom URI schema (can't post another Link, google it and you will find it).
Of course you need to retrieve the data on the server side and for the last solution you may need a kind of a webservice.
Conclusion
Don't be confused about private and public keys from a certificate.
There are scenarios where you send a certificate to the server for e.g. authentication.
But then its your public key. You should never send your private key around (of course technically its possible).

How to find out a possible man-in-the-middle the Google way?

I am wondering how is Google able to show messages like Cannot connect to the real mail.google.com or similar? Are the IP addresses of Google servers simply hard-coded within Chrome or is it possible to do a similar thing? This could help making sure clients are not visiting phishing or scams websites.
This errors only shows when trying to access Google related websites, nothing else.
Here is a sample of what Google Chrome shows when trying to connect to Gmail without providing the proxy credentials.
PS: I usually use C# & ASP.NET. I am open to suggestions.
EDIT :
Following the answer from SilverlightFox, is there any way to "request" the pinning of my website certificate? And/Or how to add it to the "STS preloaded list"?
As #Ted Bigham mentioned in comments, this will be achieved via Certificate pinning:-
One way to detect and block many kinds of MITM attacks is "certificate pinning", sometimes called "SSL pinning". A client that does certificate pinning adds an extra step to the normal TLS protocol or SSL protocol: After obtaining the server's certificate in the standard way, the client checks the server's certificate against trusted validation data. Typically the trusted validation data is bundled with the app, in the form of a trusted copy of that certificate, or a trusted hash or fingerprint of that certificate or the certificate's public key. For example, Chromium and Google Chrome include validation data for the *.google.com certificate that detected fraudulent certificates in 2011. In other systems the client hopes that the first time it obtains a server's certificate it is trustworthy and stores it; during later sessions with that server, the client checks the server's certificate against the stored certificate to guard against later MITM attacks.
From What is certificate pinning?:-
some newer browsers (Chrome, for example) will do a variation of cerficiate pinning using the HSTS mechanism. They preload a specific set of public key hashes into this the HSTS configuration, which limits the valid certificates to only those which indicate the specified public key.
HTTP Strict Transport Security (HSTS) is a technology that is implemented via a HTTP response header (sent via HTTPS only) that tells a browser to "remember" that a website is to only be accessed via HTTPS for a period of time. If HSTS is set on www.example.com and the user visits http://www.example.com before max-age has expired, the browser will request https://www.example.com instead and no request will be sent via plain HTTP. HSTS requires that the user has already visited the site in order to have received the header, however a workaround has been implemented by Google in their Chrome browser code:
Google Chrome and Mozilla Firefox address this limitation by implementing a "STS preloaded list", which is a list that contains known sites supporting HSTS. This list is distributed with the browser so that it uses HTTPS for the initial request to the listed sites as well.
Update following question edit
Following the answer from SilverlightFox, is there any way to "request" the pinning of my website certificate? And/Or how to add it to the "STS preloaded list"?
According to this blog post you should contact the browser developers to be included in the HSTS list and have your public key (or CA's) pinned in the browser:
is this domain HSTS-preloaded in Chrome? For now it is hardcoded in the binary and will hopefully grow. You can contact Chromium to have your site included in that list.
and
So right now, the only solution to pin public keys of CAs signing your website certificates would be to contact Chromium team to be included in the code.
The only way to fight the man-in-the-middle is to have some pre-shared knowledge. In this case those are hardcoded certificates of a couple of root authorities that your browser trusts. These root certificates are used by their authority to sign certificates of other authorities which in turn become trustworthy too. A chain of trust is built until you hit the certificate of mail.google.com.
When you go to mail.google.com you are automatically redirected to the HTTPS (note the S!) version of the site. HTTPS means certificates. Your browser downloads the certificate of that site and inspects if the signing chain is rooted by some of the authorities your browser trusts. If not: Big fat warning! Possibly man-in-the-middle spoof going on!
Another thing that might happen is that the redirect from HTTP to HTTPS fails because some firewall between you and Google blocks HTTPS. That might be the warning you are getting.

How to create my own certificate authority for IIS?

I am tired of buying SSL Certificates for my clients. We spend thousand dollars per month on average. Can someone please show me how to start my own certificate authority (Not the the self-sign certificate)? This SSL is for IIS.
It seemed like IIS can issue self-sign and OpenSSL can do the same thing and I do not want it unless it can provide a full SSL like Verisign and other big companies.
If you want to roll your own certificate authority (suppose for closed in-company infrastructure), you start by (surprise, surprise) creating a self-signed certificate, which will act as a root CA certificate. Then you generate the first child certificate - intermediate CA certificate. Now put the private key of the root certificate to the safe place - most likely you will not need it for years. Intermediate CA certificate is used to issue end-user (or other sub-CA) certificates.
If you want your certificates to be recognized by standard browsers and other client software, you need to find a way to get your public root certificate to the list of trusted roots in the OS itself and in those browsers and clients, if they have their own certificate storages. This is a complicated procedure, different for each OS and each browser. It involves repeating audits, compliance to tough procedures etc.
Again, if you create certificates for internal company use only, you can make software installer (or just write a custom script or application) that will add your certificate to the trusted root list on each user's computer. This can be done in code almost without problems, but the user will have to (a) run that script or program, and (b) confirm addition of the certificate. For some browsers or other client applications the procedure can be more complicated.
The procedure of creating a CA is quite a complex topic. I suggest that you read some books on PKI before you proceed. Here are the great books I'd recommend:
Rsa Security's Official Guide to Cryptography
PKI: Implementing & Managing E-Security
Creating your own certificate authority is not an issue. Your issue is creating a certificate authority that other people will trust!
There is absolutely no point you creating your own unless all your users are prepared to accept certificates signed by you, and this is a pretty unlikely scenario unless you have a small number of users that are prepared to trust your root CA.
Getting them to trust you involves them all installing your root CA as a trusted CA on their web browsers which is hardly good security practice.
Unless you work in a controlled environment, and all your users are internal, or you have a very suggestible group of users who will do whatever you say - I would recommend you forget this idea.

Categories