When we use SSLConnection, we have to use certificate.
I think if it's server certificate, The CN(CommonName) inside subject have to be Server Domain.
While, if it's user certificate, The CN will be identity infomation(ex.userId) of User.
My thinking is right ?
If it's right, I have another Question.
When a User connect website it requires UserCertificate, Browser will show certificate List on what basis?
In my thinking, browser check that Request Url and CN is same.Is it right?
If so, I think Browser cannot select UserCertificates from all UserCertificates.Please teach me this is right or not
Related
When I type a URL for example, www.google.com for the first time in my browser.
I am sure that something is sent out containing the URL. Then the returned HTML page is displayed on the screen.
How does my browser make sure that the server who responds to my request is the real Google's Server not someone else's server (Man-in-the-middle)?
I can see that an HTTPS connection is also established. I believe that this has something to do with the above question.
Can anyone anwser this question in detail with my www.google.com example?
I know what is public key and private key. I know that public key can be used to encrypt a message then its private key is used to decrypt. Private key can be used do digital signature and public key can be used to verify this signature.
But I don't know how they are applied in the www.google.com case.
As for using the public key to verify the signature, how do we do it? We use the public key to decrypt the message to see if we can get something that is previously defined?
Edited
Once the browser knows that it is a real google server that sends back the page, how can browser make sure that the page content itself is not modified by someone else? Is the first page sent back already encrypted?
Is symmetric encryption used for the following requests and responses?
Is the URL itself is encrypted?
https uses signed certificates to ensure the identity of the responding server.
The request is sent to the IP address your name resolution claims the name resolves to. That is not really reliable, since you yourself can easily alter that resolution.
The response from the server however contains a certificate that has been issued for the hostname (www.google.com here). This also does not yet provide the security you are looking for, but it brings us closer.
To verify if the certificate tells the truth your local browser tries to verify the certificate (its content). That is done by using a "certificate chain". A certificate can be signed with another certificate. If you trust that other certificate, then you can also trust those certificates that have been signed with the one you trust. That way a chain is created that reaches up to so called "root certificates". Such are certificates that are locally installed inside your system, so known and available to your browser, so they cannot be spoofed by an attacker.
Reality is a bit more complex, as always, but the above should give you an idea of how things work.
Note: you can also create a certificate yourself, you can even sign it yourself. This actually is helpful if you are just interested to establish an encrypted connection to your own https server, for example. But such self signed certificate does not prove the servers identity. That can only be done by using a certificate that has been signed the way described above.
Once the browser knows that it is a real google server that sends back
the page, how can browser make sure that the page content itself is
not modified by someone else?
The browser verifies that the certificate sent back in the SSL handshake is signed by a Certificate Authority (CA) that the browser trusts, and checks that certain fields are set to the correct value (e.g. Subject or Alternative Name is set to the displayed domain name and the valid from and to dates are current).
There can be multiple certificates in the chain if intermediary certificates are used, which is likely. As long as the second to last certificate in the chain is signed by a trusted root then everything is good.
Is the first page sent back already encrypted?
Yes, as soon as the SSL handshake is made, everything is encrypted. This includes any data in the initial request sent from the browser (e.g. cookies or query string).
Is symmetric encryption used for the following requests and responses?
Yes, although the keys are a function of random numbers generated by both client and server and a "pre master secret" which is sent from client to server encrypted by the certificate public key (or encrypted by one time generated keys in the case of Diffie-Hellman).
Is the URL itself is encrypted?
The domain name is sent in cleartext for the Server Name Indication extension, and also the DNS lookup and destination IP can also be known by an evesdropper on the connection.
The URL path and query string are encrypted though.
They use certificates to verify identities and signatures.
When the server responds to you, this contains a certificated that is being issued for that specific host. In your example this would be www.google.com
This provides some sort of trust because the root certificate is contained within your browser installment.
Speaking of a root certificate you start to build a chain of trust and one certificate is signed by another certificate until it reaches the root of this trusttree. These are installed locally on your browser and are therefore very hard to spoof for an attacker.
I'm setting up a server so that only mapped certificates can get to the webservice. It is set to require SSL/Client certificates, anonymous authentication, asp.net impersonation, forms authentication, and windows authentication are all disabled. One-to-one client certificate mapping is enabled, and certs are set up on the box with an appropriate user mapping. When I try to use the webservice, I get 401.2. If I enable anonymous authentication, it works, but I don't want any old cert to be able to access the website.
I have another machine that has anonymous authentication disabled in this configuration, and it works. I'm not sure what the difference is.
I ran into the same problem, but the solution above did not solve my problem. I was configuring IIS Certificate Authentication on a subdirectory of the website, not on the website itself.
So, this is wrong:
And this is correct:
Once I moved the configuration to the root of the website, everything worked perfectly.
I found the solution at http://blogs.msdn.com/b/saurabh_singh/archive/2009/06/13/avoid-this-confusion-around-client-certificate-mapping-in-iis-6-0-7-0.aspx.
Did you issue your client certs from a Certificate Server that the clients/server trust? If you look at the "Enhanced Key Usage" property on the certificates, is "Client Authentication" one of it's properties? In IIS, is the client certificate mapping role installed (see image 1)? did you enable "Client Certificate Mapping" and map the users to the certificate? You need to import all of the client certificates and map them to user accounts here. You can remove all of the other client authentication methods when you have configured that here.
The problem ended up being the software that was calling in, not in the configuration. I'm awarding natemrice the bounty since he put in a good effort to answer what ended up being a non-question.
edit: For more information, it actually ended up being a mismatch between the cert being sent (from the local box) and the cert that was put in the oneToOne mappings. The common name was the same, but the certs were different (likely the first one expired) so the cert simply wasn't authorized.
I'm making a server-client to use ssl for sign up and login process.
(and this is for iphone if it matters)
I just started looking at what ssl is and how to use it, and
saw there is a certificate in the process which can be bought or self-signed.
If I use self-signed certificate in web server, web browser would alert that cert is self-signed, that I understand.
But what would happen if I use self-signed certificate in regular application with tcp(not http), specifically iphone.
I just want to make the signup/login
info(their password) to be secure,
and hoping that using self-signed
certificate would be ok for this
purpose. But I also need to make
sure this won't cause "not trusted
certificate - alert" type of
interruption when used in application
other than a web browser.
Edit
I understand that "not trusted certificate alert" is saying client shouldn't trust this server.
But in my situation, client doesn't need to authenticate with the server.
The server just needs to get client's password in a secure way.
To answer your question: You can, but you shouldn't!
First, using SSL only for authentication isn't secure at all. The authentication process probably produces some kind of session (e.g. cookie) which is then transfered without encryption. Therefore, the session can be stolen (see Session hijacking).
Second, using a self-signed certificate allows man-in-the-middle attacks. So, someone can steal the user's password and he probably won't even notice it. The user doesn't know the difference between the alert that pops up when the client receives your self-signed certificat and the pop up that shows when the attackers self-signed certificate is used.
My advice: Don't use self-signed certificates. When an attack happens it's bad for you and your customers.
When you use an SSL connection to encrypt a login dialogue with a password the server sends the client a public key (in the form of a certificate), and the client generates a one-off session key, encrypts it using the server's public key, and sends it to the server. The server can then decrypt the session key because it has the private key.
The user then encrypts his password using the session key and sends that to the server, which can decrypt it because it knows the session key.
Now, without PKI if an attacker wanted to learn your password he could spoof the server. He'd send you his public key and you'd generate a session key, etc., in the usual way and send him your password which he would be able to decrypt because you'd be using his key without knowing whether you can trust it.
PKI protects you against this kind of attack by requiring that public keys are distributed as certificates. If you trust the CA that signed the certificate you can tell that the public key really does belong to the server and that it's safe to use it to encrypt your password. If you don't use a certificate -- or if you use an untrusted certificate -- you generally have no idea who you are sending your password to.
You don't give enough information about your own particular use case to say for certain whether you can use a self-signed certificate ... For example: It may be that you have one fixed certificate that is distributed in advance by some trusted channel and that you can check that the correct certificate is being used when you begin your SSL conversation. If that's the case then your client already knows that it has the correct public key and doesn't need to be able to check a signature. In general, though, you need a proper certificate signed by a trusted CA or else you have no security.
That's the entire point of trusted signing authorities - anything signed by someone else is supposed to give a security alert. So, no, there's no useful way to override this (unless you have control over the client computers - e.g. a self-signed certificate used for company-internal sites, when you can add your own CA into the clients' list), either for web browsers or anything else.
With a self-signed certificate, how can a user know whether the certificate is yours or an attacker's? He can't.
If you completely control both ends of the process (server and client), you can of course instruct the client to always trust "certificate from Eugene with a fingerprint of A01AABB546AC", for example, but then you need to build your own certificate infrastructure (expiration/revocation).
You will add no theoretical security by using a self-signed certificate, because of the possibility of man in the middle. The counterparts (your client and your server) in this communication will have no additional information about who is talking or listening, whereas the point of this kind of encryption is to make sure that there are only two participants in the communication and that the identity of at least one of them is known.
In your case, the password will not be transferred to you securely, because you don't know if it has passed through a third party on the way. Likewise, the user won't know who he sends the password to.
In practice, a man in the middle attack will be a bit of work to set up, and maybe that obstacle is some kind of security, but contrast that to the annoyance of forcing your users to accept a security warning with unclear consequences, and indeed the risk of "false sense of security".
There are companies that offer free certificates with the lowest form of validation (they will only check that you "own" the e-mail address hostmaster#domain). That way you won't have to do with the warning, either.
Unless there is a way for you to package your certificate or its fingerprint with the app, as Piskvor said.
Moved to answer - for this type of thing you should be fine. The only thing the users won't get is a way to confirm the trust level of the cert (like you could do with a signed cert in a browser for example) but as per your comment to #Piskvor that doesn't sound like an issue: you aren't using it for that.
Looking for some advice about the use of client certs to retro-fit access control to an existing app.
Our company has an existing intranet app (classic ASP/IIS) which we licence to others. Up till now it's been hosted within each organisation that used it and the security consisted of "if you're able to access the intranet you're able the access the application".
I'm now looking for a way to host this app externally so that other organisations who don't wish to host it themselves can use it (each new client would have their own installation).
All user in the new organisation would have a client cert so what I'd like to do is use the 'Require Client Certificate' stuff in IIS. It allows you to say "if Organisation=BigClientX then pretend they're local userY".
What I would prefer is something that says "if Organisation=BigClientX then let them access resources in virtualdirectoryZ otherwise ignore them".
I would be very happy to buy an addon (perhaps an ISAPI filter ?) which would do this for me if that was the best approach. Any advice / war stories would be welcomed.
You likely want to do this. client certs are really intended for a second factor of authentication, but not the primary source. To say it differently, you still need to configure your app for basic or forms authentication.
The technology behind public/private keys is rock solid. However, you need a very mature IT organization who is dealing with certificate lifecycle management. If you do not have this, you will get untold failure scenarios because the certificate was expired, wasn't copied to the new computer, etc.
This is especially true in your scenario where your application is internet facing (in thee 'hosted' scenario) - you have little control about the issuance of the certificates to your users.
I've done something similar...
Generate the certificates internally from your org's domain controller. Export them both as PFX format for distribution, and CER format for you to import in IIS.
Distribute the PFX format exports along with the CA certificate for your DC, so your customers machines will "trust" your CA.
Now in the app properties IIS, go to the Directory Security tab, and under "Secure Communications" click "Edit". In there, click "Accept client certificates", "Enable Client Certificate Mapping", then "Edit".
Under the 1-to-1 tab, click "Add" and import the CER file. Enter the account you'd like to map this certificate to.
As for the "let them access resources" I'd advise doing that by the user account they're mapped through - that is, you can provide access to resources based on that account either through NTFS permissions, or through code by identifying the security context of the logged-in user.
I'm going over some client code I've inherited for doing secure communication over HTTPS, and it seems that it's not checking the common name in the server certificate (eg. 'CN = "example.com"' against the actual URL that's being requested. This is probably deliberate, since our client app is required to talk to various environments, so after contacting an initial portal (eg. example.com/main) and the user choosing an environment the app gets redirected to a specific IP, so all future requests look something like "http://127.0.0.1/page".
However being an SSL newbie, I'm unsure of the implications of disabling this check. My first reaction would be that it'd be easier to perform some kind of man-in-the-middle attack, since someone else could just copy our certificate and pretend to be one of our servers. But if we were doing common name checking you'd be able to do the same thing with custom DNS settings anyway, so it doesn't seem to actually gain us anything. Are there other attacks that this leaves us open to which we wouldn't be otherwise?
Thanks
Someone else can't just copy your certificate and use it because they don't have your private key.
If you don't check that the certificate's CN doesn't match the domain name then they can simply create their own certificate (and have it signed by a trusted CA so it looks valid), use it in place of yours, and perform a man in the middle attack.
Also, you need to be checking that the certificate comes from a trusted CA. It's the CA's job to make sure that you can only get a certificate with the CN= if you actually control that domain.
If you skip either of these checks then you are at risk of a MITM attack.
See also this answer for a different approach that will work if you have sufficient control over the client.
If you control the client code, then you can restrict the trusted CAs to just your own. Then the domain check is less important - any of your servers can pretend to be another one.
If you don't control the client code, then a cert signed by a trusted CA can be substituted for yours.
$0.02: using CN for host names is deprecated, X.509 Subject Alternate Names should be used instead.
Verifying the certificate itself and that it can be chained to a CA certificate you already trust allows you to check that the certificate is genuine and valid.
Checking the host name in the certificate allows you to check you're talking with the server you intended to talk to, provided you've verified the certificate to be valid indeed.
(Checking that the remote party is indeed the one holding the private key for that certificate is done within the SSL/TLS handshake.)
If you want an analogy with passport/ID checking for people:
Verifying the certificate is like checking that a passport or a form of ID is genuine. You can decide which forms of ID you want to accept from a person (e.g. passport, driving licence, staff card, ...) and which issuer countries you trust to be able to verify their authenticity.
Checking that the remote party is the one holding the private key is similar to checking that the picture on the passport/ID matches the face of the person in front of you.
Checking the host name is like checking the passport belongs to the person whose name is the one you're looking for.
If you don't check the host name, anyone with a valid passport that you consider genuine could come to you and claim they're the one you're looking for (by name).
In very limited set of circumstances, where you only trust a specific CA or self-signed cert where you allow any potential certificate to impersonate any other in the entire set of certificates you trust, it can be acceptable to ignore this verification, but this is very rare, and not good practice.
Checking that the name in the passport matches the name of the person you're looking for would be considered common sense; do it for certificates too. Not doing so allows anyone who has a certificate that you trust as genuine to impersonate any other certificate you would trust, thereby potentially perform MITM attacks.
The HTTPS host name verification rules are defined in RFC 2818 Section 3.1 (also more recently in a "best practices" spec, RFC 6125, not much implemented yet).
In short, the host name should be in a Subject Alternative Name DNS entry (although you can fall back on the CN of the Subject DN where there's no SAN in the certificate). When you're using an IP address, the IP address must be in a SAN IP-address entry (although some browsers will let you get away with the IP address in the CN of the Subject DN).
To do the same thing with "custom DNS settings" the attacker should exploit a DNS server (yours or a client's) to point example.com to an IP he controls, as opposed to just copying the certificate. If possible I'd create all the specific apps as subdomains of example.com and use a wildcard certificate (*.example.com) to be able to validate the CN.
Hostname verification (verifying the CN part) guarantees that the other end of the connection (server) is having a SSL Certificate issues with the domain name you typed in the address bar. Typically an attacker will not be able to get such a certificate.
If you don't verify the hostname part, somebody (somebody sit at any of the routers or proxies the request passes though) could do a man in the middle attack. Or somebody could do exploit some DNS attacks.