try {
String urlImage="https://maps.googleapis.com/maps/api/staticmap?center=0,0&zoom=1&size=100x100&key=AIzaSyD_GK1iiZD2kV5J_v6";
System.out.println(urlImage);
bitmap1 = BitmapFactory.decodeStream((InputStream) new URL(urlImage).getContent());
} catch (Exception e) {
e.printStackTrace();
}
when i call this url i get
javax.net.ssl.sslhandshakeexception:Handshake failed
exception how can i solve it
Based from this related SO post, you need to obtain the public certificate from the server you're trying to connect to. Try contacting the server admin and asking for it, using openssl to download it, or, since this appears to be an HTTP server, connecting to it with any browser, viewing the page's security info, and saving a copy of the certificate. As stated also in this documentation, this can happen for several reasons, including:
The CA that issued the server certificate was unknown
The server certificate wasn't signed by a CA, but was self signed
The server configuration is missing an intermediate CA
You can check the documentation which discussed how to address these problems while keeping your connection to the server secure.
Related
I'm new to reverse engineering, I've never developed an android application before and I'm trying to extract from an android application the certificate it's using to authenticate to the server.
One of the answers to this post mentions that extracting a private key from an apk file is indeed a possible thing.
This post says that unlesss we have the original keystore file of the application we won't be able to extract the private key. Is it possible to get the original keystore file? Most of the posts seem to agree on the fact that this is impossible!
I've decompiled the application I'm interested in, and I retrieved the CERT.RSA from it, but I don't know if this can help me extract the certificate and the private key from the application. What can we do with the CERT.RSA file anyways?
I know that an android application is accessible to anyone from the google play store, so if what I'm trying to do is possible anyone could extract the certificate and private key and hack any application, but I just want to know if there were some specific tips/hacks, a good tutorial or just an indication of where to start off?
Here is the pcap I get when I send a request to the server that the app communicates with:
10.0.0.1 is the client IP address and 192.168.10.211 is the server's IP address, and we can see that the client is sending 2 certificates to the server during the handshake session, so where do these certificates come from? are they hardcoded in the application?
UPDATE
As you can see on the pcap file, the client does send a certificate to the server during the handshake session, so I spent the last few days trying to retrieve it and use it to forward a request to my server.
I've finally managed to retrieve the certificate, the problem is I don't know how can I use it to get the job done.
Here is exactly what I did:
This is the java code that logs the certificate and the password that the client uses during the handshake protocol:
public static native byte[] getCplusPKCS12Cert();
public static native byte[] getCplusPKCS12Pass();
static {
System.loadLibrary("cplusnative");
}
public static SSLSocketFactory a() {
SSLSocketFactory sSLSocketFactory = null;
SSLContext instance = SSLContext.getInstance("TLS");
byte[] cplusPKCS12Cert = getCplusPKCS12Cert();
String s = Base64.getEncoder().encodeToString(cplusPKCS12Cert);
Log.d('certificate',s);
byte[] cplusPKCS12Pass = getCplusPKCS12Pass();
Log.d('password',cplusPKCS12Pass);
return sSLSocketFactory;
}
This allows me to get the certificate which is a PKCS12 certificate that's secured with a password which is logged to the terminal too when I launch:$ adb logcat
This is what I get:
certificate:
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
wCFEL+hYAgIIAA==
password: S0xXYUY4QWtSdW9mYW5VAA==
I put the certificate in a .p12 file, but I can't open it.
To overcome this issue I print the certificate to android storage: storage/emulated/0/output.p12 which created a file containing hexadecimal data. When I use this file to forward a request to my server using python:
$ python3
> from requests_pkcs12 import get
> r = get(url, pkcs12_filename='theOutput.p12', pkcs12_password='S0xXYUY4QWtSdW9mYW5VAA==')
I get the following error:
Error: [('asn1 encoding routines', 'ASN1_get_object', 'header too long')]
I feel that I have all the pieces of the puzzle and I only need to put them together, so my question is: How can I use the resources (certificate/password) I have retrieved to forward requests to the server?
Thank you.
I would like to ask the following. We have a mobile app both for Android & iOS that exchanges data with a .NET server.
For Android the ksoap2 library is used, while for iOS the Alamofire with AEXML libraries are used.
We would like to enable encryption for the communication between the server and the apps, specifically Message Security with Mutual Certificates (https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/message-security-with-mutual-certificates)
I am not able to find any information how either the Android or the iOS client could encrypt/decrypt the requests/responses.
Can you please provide any relative information?
Thanks in advance!
For the iOS Part.
By default, Alamofire will evaluate the certificate chain provided by the server using Apple's built in validation provided by the Security framework.
While this guarantees the certificate chain is valid, it does not prevent man-in-the-middle (MITM) attacks or other potential vulnerabilities.
In order to mitigate MITM attacks, applications dealing with sensitive customer data or financial information should use certificate or public key pinning provided by the ServerTrustPolicy.
ServerTrustPolicy
The ServerTrustPolicy enumeration evaluates the server trust generally provided by an URLAuthenticationChallenge when connecting to a server over a secure HTTPS connection.
let serverTrustPolicy = ServerTrustPolicy.pinCertificates(
certificates: ServerTrustPolicy.certificates(),
validateCertificateChain: true,
validateHost: true
)
There are many different cases of server trust evaluation giving you complete control over the validation process:
performDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to validate the host provided by the challenge.
pinCertificates: Uses the pinned certificates to validate the server trust. The server trust is considered valid if one of the pinned certificates match one of the server certificates.
pinPublicKeys: Uses the pinned public keys to validate the server trust.
The server trust is considered valid if one of the pinned public keys match one of the server certificate public keys.
disableEvaluation: Disables all evaluation which in turn will always consider any server trust as valid.
customEvaluation: Uses the associated closure to evaluate the validity of the server trust thus giving you complete control over the validation process. Use with caution.
AlamoFire documentation
For Android part, i am not experienced with but i came across someone asking about the same thing and got an answer with
what you need to do is only to install your certificate into the webserver and call the webservice URL like https://my.webservice.url/ instead of http://my.webservice.url/.
If your certificate is a self-signed certificate, means you did not
bought it from a certificate authority, you will need to set the
SSLSocketFactory. You can check the project wiki on how to do that:
http://code.google.com/p/ksoap2-android/wiki/CodingTipsAndTricks#How_to_set_the_SSLSocketFactory_on_a_https_connection__in_order
Check Here.
This might be Helpful too
UPDATE: i've found this framework SOAPEEngine
this one.
Supports Basic, Digest and NTLM Authentication, WS-Security, Client side Certificate and custom security header.
you check its example for more clarifications too.
Message encryption with WCF is done through the WS-Security protocol, by setting the security attribute mode to Message. As you have undoubtedly realized by now, WS-Security is not exactly popular on the Android and iOS platforms, mostly due to it having been superseded by other technologies (like HTTPS,) so your choices in terms of existing libraries are not abundant. The fact that not even Microsoft-owned Xamarin supports it says a lot.
First, a word on WS-Security, This protocol provides three main means of enhancing message security:
Authentication through security tokens
Signing SOAP messages
Encryption of SOAP messages
So a conforming implementation should really provide all three of these functions, but we are mostly interested in encryption here, as from the question and comments it seems like you have the authentication part working.
Therefore, assuming we are looking for a mobile platform library providing minimal WCF compatibility with WS-Security signing and encryption:
Android
On Android, the closes to your needs is WSS-Client for Android. This project:
... implements the OASIS Web Service Security (WSS) standard for
Android platforms and makes XML Encryption and XML Signature available
for tablets and smartphones.
Note that this is GPL-licensed software. The readme says to contact the author for commercial license details. However, it seems to do what you're looking for. Once you have negotiated the key exchange with the server, to encrypt a previously constructed SOAP message using the SOAPUtil class you would do something like:
SOAPMessage message = SOAPUtil.createSOAPMessage();
//... Populate the message (possibly with another library)
SecCrypto serverCrypto = new SecCrypto(serverCertificate, null);
SecCrypto clientCrypto = new SecCrypto(clientPublicKey, clientPrivateKey);
SOAPMessage securedMessage = SOAPUtil.secureSOAPMessage(message, new HashMap<String,String>(SecConstants.REQ_ENCRYPT_SIGN, "yes"), clientCrypto, serverCrypto);
//...
SOAPMessage returnedSecuredMessage = SOAPUtil.sendSOAPMessage(context, securedMessage, endpoint, cryptoParams);
SOAPMessage returnedMessage = SOAPUtil.validateSOAPMessage(returnedSecuredMessage, new HashMap<String,String>(SecConstants.RES_DECRYPT_VERIFY, "yes", decCrypto);
Nevertheless, be prepared to do quite a bit of configuration work and debugging to make it match your server's needs.
If you are looking for a more current and actively developed product, Quasar Development offers a WS-Security implementation for Android.
iOS
Things look a lot more bleak on the iOS side. There are a few libraries claiming varying degrees of support for WSS, but none of them seem to match your needs:
At first SOAPEngine looks the most promising, as it claims
support for WS-Security. However, in a footnote it says that it has a
limitation that it only supports the WCF basicHttpBinding. This
would actually be OK if true. The binding used in the sample code you
linked to in the question is wsHttpBinding however it's important
to note that both wsHttpBinding and basicHttpBinding have support
for encryption though WS-Security. The difference is that
wsHttpBinding supports WS-Security by default (whereas it needs to
be enabled with basicHttpBinding) and it also supports
WS-ReliableMessaging and some other features you may or may not
care about. But the basicHttpBinding is the one intended for
compatibility with other technologies. So in order to have
WS-Security encryption on your WCF server and maximize compatibility
with other technologies at the same time, it would be OK to use
basicHttpBinding and enable WS-Security signing and encryption by
setting the mode security attribute to Message. With the
Message attribute, from the docs:
Security is provided using SOAP message security. By default, the body
is encrypted and signed. For this binding, the system requires that
the server certificate be provided to the client out of band. The only
valid ClientCredentialType for this binding is Certificate.
But this is of no use as SOAPEngine does not have any support for
encrypting messages (or at least I could not find any support for it
in the API). The only WS-Security function it supports is
authentication. So the claim that it supports WS-Security seems
misleading as the support is quite limited.
ServiceNow offers very limited support for WS-Security. It only
supports verifying server signatures. No encryption or signing on the
client side.
Chilkat has some rudimentary XML support and there is sample
code for WS-Security authentication. I didn't see any support or
sample code for WS-Security encryption.
Therefore for iOS, to the best of my knowledge, your two options are:
Pick one of the existing libraries that best matches your other needs
and reach out to the developer and see if you can get them to add the
WS-Security features you need.
Implement the bare minimum features
you need yourself. The spec is actually not that complicated and
there is sample code out there (for non-mobile platforms) that you
can use as guide, like WSS4J for example.
In Android:
I use kasoap2 to call the web services, but before the call, to enable mutual authentication with client certificate you need to initialize a SSLContext with the client authentication keys (KeyManager).
To do that you have to load your certificate and the corresponding password in a KeyStore object, my certificate is a *.pfx file. I cerate a "PKCS12" KeyStore instance. Then you need a KeyManagerFactory object to obtain the KeyManager array. I use a "PKIX" KeyManagerFactory instance. The KeyManager array is needed to init the SSLContext.
Here is an example:
public void enableMutualAuthentication(String filename, String password) {
try {
// InputStream to read the certificate file
FileInputStream cert = new FileInputStream(filename);
char[] pass = password.toCharArray();
KeyStore keystore = KeyStore.getInstance("PKCS12");
keystore.load(cert ,pass);
cert.close();
KeyManagerFactory keymanagerfactory = javax.net.ssl.KeyManagerFactory.getInstance("PKIX");
keymanagerfactory.init(keystore, pass);
KeyManager[] keymanagers = keymanagerfactory.getKeyManagers();
// This is not for the mutual authentication.
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
} };
// Install the mutual authentication manager
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(keymanagers, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
}
}
Check those links, was what help me most.
https://chariotsolutions.com/blog/post/https-with-client-certificates-on/
http://callistaenterprise.se/blogg/teknik/2011/11/24/android-tlsssl-mutual-authentication/
I'm writing a small SSL proxy server and keep getting ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:661) from an android app client but not a browser. I did set ssl.CERT_NONE. Here is my test code:
SSLcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
SSLcontext.load_cert_chain('server.crt', 'server.key')
SSLcontext.verify_mode = ssl.CERT_NONE
SSLcontext.check_hostname = False
s = socket.socket()
s.bind(('127.0.0.1', 443))
s.listen(5)
c = s.accept()[0]
c = SSLcontext.wrap_socket(c, server_side = True)
print c.recv(1024)
Is this because of certificate pinning on the android app or I'm doing something wrong ?
I did set ssl.CERT_NONE
This does not affect how the client verifies the server certificate at all. The server can not instruct the client to not verify the certificate and it would be a serious security issue if the server could do this.
SSLV3_ALERT_CERTIFICATE_UNKNOWN ... from an android app client but not a browser.
It is unknown what kind of certificate you use here. If this is a self-signed one you have probably added it once as trusted to the browser or added an explicit exception - but you did not do this for the Android app. If this is a certificate issued by a public CA then you are probably missing the chain certificates. Desktop browsers often work around this server side problem while most other clients don't.
I have this scenario where my App needs to make requests towards a secure server (NON http(s), actually it is about SIP protocol but the question should apply to any non http(s) protocol), and I need be able to tell if the server is considered trusted, based on the System Default Trusted certificates installed in my Android device's keystore.
The problem is that after checking all the APIs Android provides for certificates (like KeyStore, KeyChain, etc) I haven't been able to find a solution.
Seems that each app, even though it can gain access to the System Default keystore of the device, it can only access it's own resources, not global, even when we are talking about TrustedCertificateEntry-type entries.
Is there anything I'm missing here?
Seems like a pretty valid use case for non-https authentication
Best regards,
Antonis
Finally, managed to find a way to do this, so let me share in case this can be useful to others. Turns out Android gives access to system wide trusted certificates. The detail here (and the reason it didn't work for me previously) was the keystore 'type' identifier that I used:
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
Which I believe was trying to find actual keys, which off course shouldn't be shared. So after some digging I found that there's a separate type, AndroidCAStore, which did the trick for me. So here's a working code excerpt, that just prints out certificates:
try {
KeyStore ks = KeyStore.getInstance("AndroidCAStore");
ks.load(null);
try {
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
Certificate cert = ks.getCertificate(aliases.nextElement());
Log.e(TAG, "Certificate: " + cert.toString());
}
}
catch(Exception e) {
e.printStackTrace();
}
}
catch (IOException|NoSuchAlgorithmException|KeyStoreException|CertificateException e) {
e.printStackTrace();
}
I'm trying to make a connection to an LDAP server in my Android app, and am using the UnboundID SDK. Recently, a change was made from unsecured to secured LDAP, and I have to change the app accordingly. I have been given the SSL certificates file to validate against. I've already used the file to make a keystore as described here. I've got this keystore file in the assets folder of my app, and am pulling from that. The code below does not currently work, and throws the exception:
LDAPException(resultCode=01 (connect error), errorMessage=('An error occurred while attempting to connect to server place.myserver.com:636: javax.net.ssl.SSLHandShakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found
// code from above link
AssetManager assetManager = getApplicationContext().getAssets();
InputStream keyStoreInputStream = assetManager.open("yourapp.store");
KeyStore trustStore = KeyStore.getInstance("BKS");
trustStore.load(keyStoreInputStream, "myPassword".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance("X509");
tmf.init(trustStore);
// my code
SSLUtil sslUtil = new SSLUtil(tmf.getTrustManagers());
LDAPConnection connection = new LDAPConnection(sslUtil.createSSLSocketFactory());
connection.connect("place.myserver.com", 636);
However, the code segment:
SSLUtil sslUtil = new SSLUtil(new TrustAllTrustManager());
LDAPConnection connection = new LDAPConnection(sslUtil.createSSLSocketFactory());
connection.connect("place.myserver.com", 636);
does work (although I was informed by the higher-ups that this would be insecure).
I'm not quite sure as to what exactly I'm doing wrong here, so any help would be appreciated. Also, if there is a better way of accomplishing this than what I'm attempting to do above, feel free to let me know :) I would like to stick with the UnboundID library though, since the rest of the code is already written using that as well, and everything works if I use the TrustAllTrustManager.
It's true that the trust all trust manager isn't secure. It's convenient for testing purposes, but it will allow a bad guy to set up his own server with a certificate he generates for himself and use it to impersonate the real server, or to operate as a man in the middle, intercepting and potentially alerting any communication between the client and the real server. With a more strict trust manager in place, the client should reject the bogus certificate that the fake server will present.
Unfortunately, though, it looks like the trust manager you're trying to use in this case doesn't like the certificate that your server is presenting to it. Because the trust all trust manager allows you to establish the connection, that means that your server does have a certificate and is capable of performing SSL communication, but there's something about that certificate that your trust manager doesn't like. It's almost certainly not an issue with the LDAP SDK, since the same problem should arise with any other LDAP API if you're using the same trust store.
If you look at the result, it has a message of "Trust anchor for certification path not found". This implies that neither the certificate the server is using nor those of any of its issuers was found in the trust store. You'll need to import the server certificate (or the certificate of one of its issuers) into the trust store that you're using. It sounds like you've tried to do that, but since it's not working then something must not be quite right with the way it was done. I'd recommend working wit the directory server administrator to ensure that you're trying to import the right certificate based on the server configuration.