मुझे एक अवैध SSL प्रमाणपत्र के साथ वेब सर्वर पर होस्ट की गई HTTP सेवा को कॉल करना होगा। देव में, मैं कीटोल के साथ प्रमाण पत्र आयात कर रहा हूं लेकिन प्रमाण पत्र प्रत्येक क्लाइंट इंस्टॉल पर अलग होगा, इसलिए मैं इसे केवल बंडल नहीं कर सकता।जावा में SSL सत्यापन को अनदेखा करना
प्रस्तावना: I DO पता है कि एसएसएल सत्यापन छोड़ना वास्तव में बदसूरत है। इस विशिष्ट मामले में, मुझे एसएसएल की आवश्यकता नहीं होगी और सिस्टम में अन्य सभी संचार सरल HTTP से अधिक हैं। इसलिए मुझे वास्तव में एमआईटीएम हमलों या इस तरह की परवाह नहीं है। एक हमलावर को एसएसएल तोड़ने के लिए जाने की आवश्यकता नहीं होगी क्योंकि डेटा के लिए कोई एसएसएल नहीं है। यह एक विरासत प्रणाली के लिए समर्थन है जिस पर मेरा कोई नियंत्रण नहीं है।
मैं HttpURLConnection
का उपयोग SSLSocketFactory
के साथ कर रहा हूं जिसमें NaiveTrustManager
और NaiveHostnameVerifier
है। यह कुछ स्वयं-हस्ताक्षरित सर्वरों पर काम करता है जो मैंने कोशिश की लेकिन ग्राहक की साइट पर नहीं। त्रुटि मैं हो रही है:
javax.net.ssl.SSLKeyException: [Security:090477]Certificate chain received from xxxxxxxxxx was not trusted causing SSL handshake failure.
at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireException(Unknown Source)
at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireAlertSent(Unknown Source)
at com.certicom.tls.record.handshake.HandshakeHandler.fireAlert(Unknown Source)
at com.certicom.tls.record.handshake.HandshakeHandler.fireAlert(Unknown Source)
at com.certicom.tls.record.handshake.ClientStateReceivedServerHello.handle(Unknown Source)
at com.certicom.tls.record.handshake.HandshakeHandler.handleHandshakeMessage(Unknown Source)
at com.certicom.tls.record.handshake.HandshakeHandler.handleHandshakeMessages(Unknown Source)
at com.certicom.tls.record.MessageInterpreter.interpretContent(Unknown Source)
at com.certicom.tls.record.MessageInterpreter.decryptMessage(Unknown Source)
at com.certicom.tls.record.ReadHandler.processRecord(Unknown Source)
at com.certicom.tls.record.ReadHandler.readRecord(Unknown Source)
at com.certicom.tls.record.ReadHandler.readUntilHandshakeComplete(Unknown Source)
at com.certicom.tls.interfaceimpl.TLSConnectionImpl.completeHandshake(Unknown Source)
at com.certicom.tls.record.WriteHandler.write(Unknown Source)
at com.certicom.io.OutputSSLIOStreamWrapper.write(Unknown Source)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:123)
at java.io.FilterOutputStream.flush(FilterOutputStream.java:123)
at weblogic.net.http.HttpURLConnection.writeRequests(HttpURLConnection.java:154)
at weblogic.net.http.HttpURLConnection.getInputStream(HttpURLConnection.java:358)
at weblogic.net.http.SOAPHttpsURLConnection.getInputStream(SOAPHttpsURLConnection.java:37)
at weblogic.net.http.HttpURLConnection.getResponseCode(HttpURLConnection.java:947)
at (my own code)
मेरे SimpleSocketFactory
लगता है:
public static final SSLSocketFactory getSocketFactory()
{
if (sslSocketFactory == null) {
try {
// get ssl context
SSLContext sc = SSLContext.getInstance("SSL");
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[]{
new NaiveTrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
log.debug("getAcceptedIssuers");
return new java.security.cert.X509Certificate[0];
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
log.debug("checkClientTrusted");
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
log.debug("checkServerTrusted");
}
}
};
sc.init(null, trustAllCerts, new java.security.SecureRandom());
// EDIT: fixed the following line that was redeclaring SSLSocketFactory sslSocketFactory, returning null every time. Same result though.
sslSocketFactory = sc.getSocketFactory();
HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
// EDIT: The following line has no effect
//HttpsURLConnection.setDefaultHostnameVerifier(new NaiveHostNameVerifier());
} catch (KeyManagementException e) {
log.error ("No SSL algorithm support: " + e.getMessage(), e);
} catch (NoSuchAlgorithmException e) {
log.error ("Exception when setting up the Naive key management.", e);
}
}
return sslSocketFactory;
}
NaiveHostnameVerifier
वैध मेजबान को सीमित करने के लिए एक रास्ता है, लेकिन यह अशक्त बचा है, तो मूल रूप से कुछ भी स्वीकार करने:
public class NaiveHostnameVerifier implements HostnameVerifier {
String[] patterns;
public NaiveHostnameVerifier() {
this.patterns=null;
}
public NaiveHostnameVerifier (String[] patterns) {
this.patterns = patterns;
}
public boolean verify(String urlHostName,SSLSession session) {
if (patterns==null || patterns.length==0) {
return true;
} else {
for (String pattern : patterns) {
if (urlHostName.matches(pattern)) {
return true;
}
}
return false;
}
}
}
उपयोग इस तरह है:
try {
conn = (HttpURLConnection)url.openConnection();
if (conn instanceof HttpsURLConnection) {
((HttpsURLConnection)conn).setSSLSocketFactory(SimpleSSLSocketFactory.getSocketFactory());
// EDIT: added this line, the HV has to be set on connection, not on the factory.
((HttpsURLConnection)conn).setHostnameVerifier(new NaiveHostnameVerifier());
}
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-type","application/x-www-form-urlencoded");
conn.connect();
StringBuffer sbContent = new StringBuffer();
// (snip)
DataOutputStream stream = new DataOutputStream(conn.getOutputStream());
stream.writeBytes(sbContent.toString());
stream.flush();
stream.close();
} catch (ClassCastException e) {
log.error("The URL does not seem to point to a HTTP connection");
return null;
} catch (IOException e) {
log.error("Error accessing the requested URL", e);
return null;
}
जब मैं त्रुटि संदेश पर खोज कर रहा हूं, तो अधिकांश लोग केवल अपने स्टोर में प्रमाण पत्र आयात करते हैं लेकिन फिर से, मैं वास्तव में ऐसा नहीं कर सकता क्योंकि मुझे नहीं पता कि यह कौन सा प्रमाण पत्र होगा। मेरा एकमात्र विकल्प अगर यह काम नहीं करता है तो ऐसा टूल बनाना है जो प्रमाण पत्र डाउनलोड कर सके और क्रिप्टिक कमांड लाइनों को आसानी से जोड़ सके, लेकिन मैं अपने जावा कोड को अमान्य प्रमाणपत्र को अनदेखा कर दूंगा।
कोई विचार?
क्या आपको पता है कि प्रमाणपत्र (और होस्ट नाम) सत्यापन को अनदेखा करने से संभावित एमआईटीएम हमलों के कनेक्शन खुलते हैं? अगर आपको प्रमाणपत्र त्रुटियों को अनदेखा करना है तो आपकी (प्रशासनिक) सुरक्षा प्रक्रियाओं में कोई दोष दिखता है। इसके अतिरिक्त, आपको Certicom TLS विकल्पों को देखना चाहिए, क्योंकि आप स्पष्ट रूप से डिफ़ॉल्ट JSSE प्रदाता का उपयोग नहीं कर रहे हैं। – Bruno
मैं एमआईटीएम हमलों के बारे में अच्छी तरह से जानता हूं। वास्तव में, अगर कोई उस नेटवर्क पर एमआईटीएम हमला करने में सक्षम है, तो संचार से हस्तक्षेप करने की तुलना में हमारे पास बहुत बड़ी समस्याएं हैं। सबसे पहले, मैं सॉफ़्टवेयर में एक कदम पर विचार कर रहा था जहां हम प्रमाण पत्र पुनर्प्राप्त करते हैं और यदि उपयोगकर्ता द्वारा सत्यापित किया जाता है, तो इसे और उपयोग के लिए स्टोर करें। हालांकि, छोटी समस्या की तुलना में यह एक बड़ी चुनौती है जिसे मैं संबोधित करने की कोशिश कर रहा हूं। मुझे Certicom TLS विकल्पों पर एक नज़र डालेंगे। –
वेबलॉगिक ने एसएसएल के साथ भयानक, भयानक चीजें की हैं, और मैं आपको इससे निपटने की कोशिश करने के लिए करुणा करता हूं। वे जावा मानकों का पालन नहीं करते हैं, उनके पास सब कुछ खराब करने का अपना खराब और टूटा तरीका है। – erickson