HTTPS authentication and session hijack - security

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.

Related

PKI: web server certificate

I'm learning the process of authentication in PKi environement.
Imagine I have two web servers (example IIS) that are configured with same TLS certificate to bind websites.
Now, if I remove and add a new certificate on one of two servers. It's still have the same common name but generated with a different private key.
I wonder if having two certificate with the same common name (subject) with two different private keys will be a problem?
What information is used by the client to choose a specific public key to encrypt information?
I hope that my question is clear. Let me know if you need more information.
Many thanks for your help.
No matter how many certificates you installed to Windows certificate stores, IIS only uses the mappings in Windows HTTP API to determine the actual server certificate to use for a specific site,
https://docs.jexusmanager.com/tutorials/https-binding.html#background
If you are familiar with SSL/TLS handshake process, you can easily see in that way the browser always knows which public key to use.
Will it be a problem? The answer is maybe.
Assuming a modern browser, then the PKI works broadly like this:
the browser first uses DNS to resolve the FQDN into an address;
then the browser sends a TLS client hello to it, which contains an
SNI matching the FQDN;
the server receives the TLS client hello, checks whether the FQDN matches ones it owns, then responds with a TLS server hello containing the X.509 certificate;
the browser receives the TLS server hello, then checks that the certificate is valid;
that the SubjectAltName (SAN) field contains the FQDN (SAN has replaced
CN); and
that the certificate is signed by a CA that it trusts.
At this point the browser doesn't actually care whether you have multiple servers with multiple different certificates (which can be normal during a patch where they are being revoked and replaced).
The maybe comes afterwards, because there are a collection of HTTP extensions that can cause the browser to reject the certificate if it does not comply with what it is expecting, such as Expect-CT and HSTS.

Secure frontend connecting to backend with self signed certificates

Our frontend at domain.com uses an API located at api.domain.com.
For domain.com, we use SSL by LetsEncrypt. For the backend, however, it is much simpler to use self signed certificates.
Will users be presented with Red Warning Banner if they go to domain.com, which connects to https://api.domain.com with self signed certificates? Is this okay practice? Furthermore, can we replace https://api.domain.com with external IP instead?
That's not a good idea in general. The purpose of a certificate is to allow a client to verify that it is actually talking to the right server, and not for example to a man-in-the-middle attacker. The way it does that (somewhat simplified) is the certificate includes the public key of the server, and the domain name ("common name") of the server the client intended to communicate with. The certificate is then signed by another certificate of about the same type and contents and so on, until the chain reaches a certificate that does not need to be signed by another, because it is already trusted by the client (it is in the trusted roots list of your OS for example).
A self-signed certificate doesn't have this chain of signatures, it is called self-signed, because the certificate used to sign it is itself. There is no way for a client to verify the certificate (unless it explicitly has it listed as trusted of course). This means an attacker can spoof (impersonate) your API by self-signing a different certificate for the same domain name, but with a different keypair. This might allow stealing credentials or serving fake data. Note that the attacker might also relay the information entered by the user (all the requests made) to the real API, so responses (also received by the attacker first, but relayed to the victim) can easily look very real without much background information.
This could (in theory) be solved by certificate pinning, but in case of a Javascript client that's going to be difficult (if at all possible). HPKP would seem like a solution, but HPKP won't work with a self-signed (not verifiable) certificate. I'm not sure if Javascript has an appropriate level of access to the server certificate to implement pinning.
Even if you did implement pinning, a self-signed certificate also cannot be revoked. Think about what would happen if you discovered a compromise of the TLS key used for https in your api domain. You would have no way to revoke the key, so clients would still accept a MitM attacker serving the compromised key.
There goes a lot of effort, and you could implement something that is not standard, hard to get right and error-prone.
Or you could just use a free letsencrypt certificate for api.domain.com as well, for which all the necessary infrastructure and setup is already done on the main domain. :)

It is possible to copy the server certificate to attackers server to misuse it?

I aks myself if it is possible to copy the server certificate to another server to misuse it. Example: An attacker visits https website X and copies the X.509 certificate. He placed the stolen X.509 certificate on his own server and would like being trustworthy.
Of course, the attacker does not have the private key, but the private key is only required to decrypt the encrypted message from the client. In terms of authentification there is no reason to be doubtfully. Or?
The server responses with the X.509 certificate. The client receives the certificate and validates successfully using the stored root certificates. Why should the server not be authentificated? Only when the client sends an encrypted message using the public key the server is not able to decrypt the message - because he does not own the private key.
It is right so far?
Only when the client sends an encrypted message using the public key the server is not able to decrypt the message - because he does not own the private key.
The server also needs the private key to sign messages being sent to the client.
The SSL/TLS handshake protocol itself effectively involves such an authenticated message being sent to the client. If the private key is unavailable then this step will fail before any 'real' payload message gets sent.
Why should the server not be authentificated?
The certificate is tied to a domain name.
The web browser will download the certificate and validate it. One of the steps in the validation is to compare the domain the certificate is for to the domain that the browser actually downloaded it from. If there is a mismatch (and there will be, since the attacker is on their own domain, not the original site's domain) then the browser will present the user with a certificate error and ask them to make the call about whether or not to accept it.
You're probably used to seeing this in action on bad web server configurations. Ever seen an error saying, "This certificate was intended for www.example.com" when you were trying to visit "example.com"?
Of course, the attacker does not have the private key, but the private key is only required to decrypt the encrypted message from the client.
Public/private key pairs have other uses than that. In this case, the private key signs the certificate and the public key verifies it. There is no encryption involved. (What you described is more like a normal encryption scheme, like RSA.)
No, the certificate is a pubic element and it is just a way to bind a public key to a name (here, a DNS name). During the authentication process (in the TLS protocol) the server sends its certificate along with signs some data with the associated private key. In order to verify that the server is the legitimate owner of the certificate, the client have to verify the validity of this signature with the sent certificate. A rogue server can try to use the certificate but without the private key it cannot prove it is the real holder.

TLS man in the middle security certificates

First of all, I apologize for sending yet another question about this seeing as there are so many related posts. After reading through them and related sites I'm still not clear on a few points.
Browser connects to server through secure socket
Server responds with its public key with its certificate. This is the step I have the most trouble with. In this message from server to client, can the certificate be easily separated from the server's public key? If it's a root certificate (one which is already included in the browser) then a man-in-the-middle can't fake it, but what if it's not? Can't whatever this online mechanism the client uses to verify the certificate be hijacked? Furthermore, if the client's computer is compromised, the root CA's can be compromised, right? Any steps that avoid this? One last thing: It is said that a certificate is insecure until signed. I can't figure out what this means, especially since a certificate can sign itself. I think it's supposed to mean that someone is assuring the authenticity of the message, so a certificate signing itself sounds insecure ("Are you a REAL certificate?"..."ummm, sure, sure I am"). If the mechanism for authenticating a certificate is the internet, I'm wondering how is that secure. Is signing a certificate the same as thing (literally) as saying the client verifies the certificate?
Session key is encrypted with public key and sent to server. This session key is a symmetric key that both server and client will use for remainder of encrypted communication.
I must say, most information online is so vague. So many holes in explanations and hand-waving going on. My guess is that very few people know the actual mechanisms very well?
You've left out several steps. One of them is that the server sends a digital signature over the entire handshake so far, signed with its private key. Only the server can do that, with its own certificate. Nobody else's. The client verifies the digital signature using the public key in the certificate that was sent. That proves that the server owns the certificate. It also proves that the server is the same entity that sent all the other handshake messages.
BTW your step 3 is imaginary. The session key is never sent at all. It is computed independently at both ends.
EDIT Comments on your answer:
Server (from JoesGoods) gets a certificate from the CA via?
Usually via an Internet browser.
Can this be hijacked?
No more than any other secure SSL session can be.
The certificate is "signed"
Correct.
which means a bit of it is encrypted using the CA's private key.
No. You made that up.
Specifically the bit that has the web server's info (JoesGoods' server info)
No. You made that up.
The entire certificate is signed, and that does not mean 'encrypted', with the CA's private key.
Bob's browser connects to server through a secure socket and sends a "hello" packet.
The socket isn't secure at this point. It's just plaintext.
The server sends its public key and certificate to Bob.
No. The server sends its certificate. The public key is already inside the certificate.
the browser checks that the webserver (JoesGoods) matches what's in the signed portion of the certificate
The entire certificate is signed. The client checks that the server it is connecting to matches the subjectDN of the certificate.
The webserver's public key is also signed with the CA's private key
Because it's in the certificate. Otherwise there is no other way this can be accomplished. That's why it isn't sent separately, and it's also why the entire certificate is signed, not just the bits you like.
The browser sends a client key exchange packet to the webserver (JoesGoods) using the webserver's public key included in step (2).
This part is cipher suite-dependent. What you have described applies to RSA cipher suites. Diffie-Hellman is a different story, and there is room for expansion to include others.
This client key is used to generate symmetric keys to conduct the remainder of the exchange. This client key is called a "premaster secret" and is a random key. Since the symmetric keys are created using this key, I wonder why not just send the symmetric key itself since the connection is encrypted and validated at this point.
Because it wouldn't be nearly as secure.
You also have some of these steps out of order.
I really don't see the point of enumerating all these steps informally when they are already completely specified in RFC 2246. There's enough misinformation about TLS floating around the Internet already, such as this piece of unmaintained drivel.

Can I use a self-signed SSL certificate for commercial purposes?

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.

Resources