I'm using clojure-http to make the following POST:
(clojure-http.resourcefully/post "https://android.apis.google.com/c2dm/send"
{"Authorization" (str "GoogleLogin auth=" auth-token)}
{"registration_id" registration-id
"data.msg" "blah"
"collapse_key" "blah"})
And getting this exception:
java.security.cert.CertificateException: No subject alternative DNS name matching android.apis.google.com found.
[Thrown class javax.net.ssl.SSLHandshakeException]
For some weird reason, about 10% of the time I don't get the exception and the request goes through.
I believe it's an issue with Java's host name checking on SSL connections*, so my question is, how do I disable that from Clojure? (or is that a bad idea security-wise?)
Thanks,
Wei
*deduced from this post and others like it: http://www.jroller.com/hasant/entry/no_subject_alternative_names_matching
Its not a problem with your code, its a problem with android's website.
Open this link in a modern browser- https://android.apis.google.com/. You will see that the SSL certificate belongs to *.google.com, but you are visiting a domain under *.apis.google.com. You should probably search on Android forums for a solution to this problem.
Its a bad idea to disable host name checking, you are opening up yourself to man-in-the-middle attacks. If you don't really care about security, you might as well use http, its easier than disabling host name checks.
Related
My Java server is using a rest service to retrieve information. Every several months I get an exception from java:
javax.net.ssl.SSLHandshakeException: No subject alternative DNS name
matching found.
This exception happens for few seconds and goes away until next time. From reading in the internet, I saw it's a problem of the remote server and its certificate. I talked to the support of the service but they say they updated the certificate on January and nothing was done regarding the certificate.
What/where else can I check or tell them to check in order to avoid this error?
Thanks
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpget = new HttpGet(url);
System.out.println(httpclient.execute(httpget));
I am using this programming snippet and using this with couple of urls. "https://abc.def.com/file.txt" and "https://ab_c.def.com/file.txt" (actual names i used exist - this is just an example). When i run the code with -Djavax.net.debug=ssl:handshake:data options set, I see _server_name_ extension is added only in case of abc.def.com and not in case of ab_c.def.com.
I am aware that java.net.URL package doesn't allow '_' in hostname. Is this a similar issue? Is there any workaround to get the SSL handshake include the hostname with '_'?
The answer is no. This wont work in java using the standard JDK libraries with HTTPS.
There virtually no "normal" Java way to work around this problem.
Other ideas:
ask the service owner to provide a domain name without the _.
dont use SSL/HTTPS. Most Java HTTP clients that are not doing strict checks will work with a hostname with an underscore in it. This is not a great solution if you are on the open internet
do use HTTPS but go direct to the IP address and disable HTTPS hostname validation. This is also a bad idea if you are on the open internet
introduce a MITM or forward proxy that can provide a HTTP endpoint to your service, but will do HTTPS over the untrusted parts of the network, (SSL onloading?)
just shell out to curl and read the resulting string, as described here on Baeldung. Be very careful here, as it's very easy to unwittingly open yourself up security issues like remote code execution
use jni to get to a network library that will allow the underscore - libcurl is an obvious candidate, but this will be significantly more work than the System.execute method, also possibly unsafe for other reasons (memory management, instability of badly written jni interop, not great for maintainability)
You could possibly try to fork the related URI / URL parsing classes in java.net to remove the check for the underscore. The problem with this is it's a massive hack, possibly of unbounded difficulty, could easily break all manner of things unintentionally and you might need to build your own version of the JDK as I have some recollection of java.net code being special for some reason in that you couldn't just chuck a patched class in ext/lib dir of the JVM (but I could be mixing that up with something else).
I will provide a hotfix.
In your /etc/hosts file, include a new entry without the underscore to the IP.
For example,
abc.com xx.xx.xx.xx
Then, use abc.com in your program.
I am getting a warning :
not secured for Chrome but in IE it is working fine
site url :-https://10.71.8.165:8443/NextGene/
Detailed warning:
Your connection is not private
Attackers might be trying to steal your information from 10.71.8.165 (for example, passwords, messages, or credit cards). Learn more
NET::ERR_CERT_COMMON_NAME_INVALID
Help improve Safe Browsing by sending some system information and page content to Google. Privacy policy
This server could not prove that it is 10.71.8.165; its security certificate does not specify Subject Alternative Names. This may be caused by a misconfiguration or an attacker intercepting your connection.
Proceed to 10.71.8.165 (unsafe)
I have tried to give SAN same as of ip 10.71.8.165, but still facing same issue.
please, suggest any solution
If the IP address has a DNS entry that matches the certificate's subject and, more importantly, is in the certificate's list of Subject Alternative Names (SANs), use that. If your organization does not have a DNS entry for the IP address, add a DNS entry that maps to that IP address and is contained in the certificate's list of SANs.
Thank you
Yes it is working for chrome browser but still my site is not working for mozilla.
mozilla version is :70.0
error:-Warning: Potential Security Risk Ahead
Someone could be trying to impersonate the site and you should not continue.
Websites prove their identity via certificates. Firefox does not trust iims.jci.com:8443 because its certificate issuer is unknown, the certificate is self-signed, or the server is not sending the correct intermediate certificates.
Error code: SEC_ERROR_UNKNOWN_ISSUER
So I have this situation: I try to download an image from somedomain.com using HTTPS. The domain is probably misconfigured, but unfortunately I can't change that. What exactly is happening:
When I browse to https://somedomain.com/animage.jpg I get a valid certificate issued for somedomain.com, which is perfect. But when I call the same site using it's IP address, say https://123.123.123.123 - I get a (also valid) certificate for *.hostingcompany.com - the certificate of the hosting company.
Now, I try to download the contents of the file using Java's HttpsUrlConnection, nothing special:
var urlConnection = new URL(imageUrl).openConnection();
((HttpURLConnection) urlConnection).getResponseCode();
(I want to first check the response code, but it's not important here.)
This code runs inside a Spring Boot App and is run on request. It works fine for the first request since booting the app. Each subsequent request fails with java.security.cert.CertificateException: No subject alternative DNS name matching somedomain.com found. It's because on each subsequent request the SSL Handshake is sent to the IP, not hostname, and get's the hosting company's certificate.
I was trying to find different settings for the SSL classes, but to no avail. I know there is a workaround where I could supply my own HostnameVerifier which could just return true, but that won't be secure, so I don't want to do that.
Did anyone encounter such problem? Maybe I'm searching in the wrong places? Maybe it's something with DNSes? I will appreciate any help.
Turns out it is a bug in Java 11.01. It is fixed since 11.02. After switching to 11.03. the behaviour I described above is gone. Each request gets a proper certificate.
Here are the details of the bug: https://bugs.openjdk.java.net/browse/JDK-8211806
I am using SSLContext so set up Jersey client, and need to disable the common name check in order to avoid unnecessary issues. However, I can find no documentation as to how we can do it correctly. So is the common name check disabled by default in SSLContext (assuming using TLS) or do we need to explicitly disable it? If so, how? Thanks.
This does not answer your question, but it tells you that what you are doing is a bad idea and probably caused by a misunderstanding of how verification works.
...need to disable the common name check in order to avoid unnecessary issues
I don't know what the "unnecessary issues" are which you are trying to avoid, but not verifying the hostname is more or less that same as disabling all validation and thus make it possible to incorporate the server and/or to do man-in-the-middle attacks.
If you don't verify the hostname but still validate the certificate trust chain the attacker can now simply use a certificate signed by a trusted CA for the attackers own site, e.g. attacker.example.com. CA's will issue such certificate since the attacker can prove ownership of its own site.
Using its own certificate the attacker can now incorporate all the other sites, since the trust chain is valid even if the hostname is not. This is the same as if you would accept any kind of identification issued by a state, without even looking if the picture in the I.D. matches the person showing the I.D.
If I'm understanding you correctly, I think you can accomplish what you are trying to do by implementing a HostnameVerifier, and just returning true in the verify method. You can set up the verifier on the ClientBuilder. For example
Client client = ClientBuilder.newBuilder()
.sslContext(sslContext)
.hostnameVerifier(hostnameVerifier)
.build();