We need to implement two-way SSL on Google App Engine, where we send out web service requests using JAX-WS to a server requring 2-way SSL authentication.
How can we set up 2-way SSL for our outgoing web service requests?
We know that javax.net.ssl* is forbidden in the App Engine environment.
Here's an example of our code:
#WebService(name="ListenerSoap", targetNamespace = "http://example.com/Listener.Wsdl")
#SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public interface ListenerSoap {
#WebMethod(operationName = "Ping", action="http://example.com/Listener.Wsdl#Ping")
public void ping();
}
#WebServiceClient(name="Listener", targetNamespace="http://example.com/Listener.Wsdl", wsdlLocation = "https://example.com/Listener.asmx?WSDL")
public class Listener extends Service
{
public ListenerSoap getListenerSoap() {
return super.getPort(new QName("http://example.com/Listener.Wsdl",
"ListenerSoap"), ListenerSoap.class);
}
}
And an example of above code in use:
ListenerSoap soap = new Listener().getListenerSoap();
soap.ping();
I figure we can store the keystores or any certs needed in the DataStore as binary objects (though how to upload them is still a lil' vague to me).
How can we go about setting the necessary values needed for this web service to authenticate using 2-way SSL?
Thanks for any help
Update:
Through research I've seen this is how it can be done on a traditional server (one with filesystem access):
ListenerSoap soap = new Listener().getListenerSoap();
((BindingProvider) soap).getRequestContext().put("javax.net.ssl.keyStore", "client_cert.p12"
However, in this approach, client_cert.p12 is expected to be on the filesystem.
Additionally, SSLSocketFactory, SSLContext, KeyManager, and KeyManagerFactory all aren't allowed on GAE.
Update:
As of GAE SDK version 1.7.7. this should now be possible:
Similarly, Java developers can now use the javax.net.ssl package to make outbound SSL connections.
GAE 1.7.7 SDK Release Notes
From my restricted knowledge about SSL authorization, it seems you may be missing something of vital importance here; the certificates. Two-way SSL requires the client and server certificates to be in your keystore, which can be either a self-signed certificate( a pkcs12 or pem file, which you can easily generate with a few commands through shell) or a proprietary certificate issued by an authorized company like Thawte or Verisign.
Although I am not sure if that is the problem you are facing, but its good to check it out.
(Also, I am a newbie so please don't downvote my answer, just trying to suggest possible options.)
ListenerSoap soap = new Listener().getListenerSoap();
Hope it improves
Thanks
I know you might not want to hear this, but using SSL is expensive and problematic for two way communication. Depending on how much control you have over the server/client ends, I prefer a simple bi-directional pipe like web sockets and a data packet protocol that can simply implement AES. It really depends on the problem you are trying to solve.
It sounds like there is confusion over simple connection over SSL (https://...) and what is known as "mutual authentication" or "public key infrastructure (PKI)". You can actually do both or one independent of another. With the latter (what I think the original question is referring to), when you make a request to the server, the server will respond to you asking for a certificate which you must present to authenticate yourself.
To answer the specific question above (loading a keystore from binary data), I don't think that is really possible, since it's the Java runtime that picks up on your keystore. The only think you could do is load the bits from your datastore and temporarily write it to disk. Optionally delete it when the application exists. This I have done before and works fairly well. If you do this, I'd recommend using a location likely to be writable (such as System.getProperty("java.io.tmpdir"));), then after writing the file to disk, set the JVM properties (e.g. System.getProperties().put( "javax.net.ssl.keyStore","...");)
You will need App Engine's Socket API for this. This API is in trusted tester mode, so it's not available for everyone.
You can ask for an access gere : https://docs.google.com/spreadsheet/viewform?formkey=dF9QR3pnQ2pNa0dqalViSTZoenVkcHc6MQ#gid=0
2-way SSL (from app hosted in GAE to outside world) is not supported as far as I know. I tried a sample app few months ago and was frustrated to find GAE does n't even support this basic feature.. and the documentations are n't clear either. You won't be able to present client cert when you contact a web-service.. there is no place to store it, the keystore cannot be accessed.
For what i know about two way SSL, you will have no link with Java EE code: two way SSL is a transport layer security: when your client application will try to create a secured HTTP connection (HTTPS) with the serve, the server will ask for a certificate and will approve or not this certificate. If the client certificate is approved, then a secured connection will be established on parties and they are allow to exchange some messages through this tunnel. But this process is done on the transport layer. Your code (on application layer) will never be informed of this process.
In order to established two way SSL, the setup is done on the application server setup for the SSL port.
Related
I have a server application and a client application created with java that will communicate with the server application. But, since i haven't put emphasis on security in the server side it is really easy to hack the server application if a hacker creates his own client to connect with my server. I want to make sure the client application that is communicating with my server is the authentic client that i created. I upload client to a specific host like www.abcd.com. Now, can i make sure when a client that connects to my server came from that host. I am knowledgeable about signing it with trusted signer but i am looking for a cheap option.
No, this isn't possible. If it were, DRM would work, but everyone knows it's hopelessly broken.
To be truly secure, the client has to be a machine with a "trusted platform module," TPM, that supports something called remote attestation. This allows the server to verify the client is authentic and unaltered. But I've never heard of a real world application of this, and though TPMs are common, I'm not sure if the remote attestation feature is.
I want to make sure the client application that is communicating with my server is the authentic client that i created.
You have two options. One is a password or shared secret, and the other is client certificates. All three are supported in SSL/TLS. Look for TLS-SRP (password based authenticated key exchange), TLS_PSK (preshared key based on a block cipher), and the traditional SSLTLS ciphers with client side certificates.
You can even set up the tunnel with Server Authentication only, and then perform the client authentication at the application level. This is what usually happens in web apps. But this has some non-trivial defects because it does not provide mutual authentication and lacks channel binding. You are better off with TLS-SRP, TLS-PSK, or client certificates.
EDIT: I focused on SSL/TLS because you cited a hostname, but you can do it at other layers, too. For example, you can use shared secrets and certificates at the VPN level. #erickson provides one method using TPMs that could be used at the application level.
Now, can i make sure when a client that connects to my server came from that host.... host like www.abcd.com
This will work if DNS is configured and trustworthy. That is, you will have to extract the host's name, perform a reverse lookup, and then authenticate the IP address. I believe this is called network based authentication.
If an attacker controls DNS or is on the same LAN segment as the server, then I believe network based authentication has some non-trivial security defects.
In any case, HSMs and TPMs are not the answer. To understand why, see Peter Gutmann's Engineering Security, and the section on Unattended Key Storage. From his book:
TPMs don’t work because all that they can do is store the fixed key
that’s required to decrypt the other keys (TPMs are just repurposed
smart cards and don’t have the horsepower to perform anything more
than lightweight crypto themselves so you can’t offload the overall
encryption processing to them), and since for unattended operation
they have to release their secrets without a PIN being entered they’re
just providing plaintext key storage with one level of indirection.
Say, I have a Java web app inside a war file that is hosted on cloudfoundry at the url mycoolapp.cfapps.io, which works perfectly. I now need to host it on a custom domain mycoolapp.com and I have purchased the domain.
What is process to host it on my own domain? Can I do it via Cloudfoundry?
My app needs ssl. Currently https://mycoolapp.cfapps.io works. But I need it to work on my custom domain. What will be involved in this? (I think I need to get a certificate for my domain, but what next?)
In the app some confidential information is embedded in urls (this cannot be changed), so I'd also need to ensure that the provider cannot know the urls accessed (apart from the base url). Can this be done? If not, what are the alternatives?
It could be done by creating a CNAME record for your app (see Azure example here). Unfortunately, it seems that Cloud Foudry (CF) does not support it yet. As I understand, it is caused by the fact that CF router determines the exact Virtual Machine (and, hence, IP) by parsing URL and determining the route according to the host name (mycoolapp in your case). Ideally there would be an interface in CF where you could register all CNAME aliases for your app (as implemented for Azure websites)
If CNAME record would be enabled, that it would also work for HTTPS, as it basically resolves IP address. And definitely there would be an interface for you to upload a certificate for your domain. This leads to problems mentioned below about SSL termination. But, again, as far as I know, it is not supported by CF yet.
That it a question to the internal structure of run.pivotal.io deployment of CF. Conceptually HTTPS will do the trick as it encrypts URL parameters. However I suppose that SSL terminates on the router (as certificate is issued for *.cfapps.io - single cert for all apps - you could check it in browser connection to your app by HTTPS). That likely means that internally CF has access to ALL data of your request, and leads to my question about SSL termination in CF, which currently has no answer. Hope CF will provide a way to terminate SSL on the final server processing the request.
UPDATE:
Cloud Foundry has proposed its own way to support custom domains - through using CloudFlare proxy. If the fact of using proxy that decrypts your data is Ok for you, it could be used.
I am writing a java app server that connects to another third party server over HTTPS. I would like to capture the traffic between these two servers (which is over HTTPS). The third party server's private key is not accessible to us. They have provided us pfx file which our server is using while making a connection to that thrird party server. Any tool I can use? I have seen several posts regarding this, but not sure which way works. Any help would be appreciated. Thanks.
The whole point of SSL is that you cannot do this... Check Diffie Hellman on why, even if you have the keys, you will not be able to decrypt traffic.
I would like to know if there is an easy (or hard) way to spy the secure sockets from a java applet ? (without having the source code)
The goal here is to know exactly what for informations send an (very good obfuscated) applet.
I thought i can simply compile myself a modified java version with a log function but the full source code from java is not available for security reasons...
Set up a proxy server with a security certificate that the applet accepts. Afterwards, you just have to configure your browser to use that proxy and the applet should use the same config.
See Does https prevent man in the middle attacks by proxy server? for how it works technically.
Some things you will need: A proxy than can act as a web server and which is probably reachable with the name of the real server from your browser. You will need to create a valid certificate for this combination which isn't trivial unless the applet is configured to accept certificates from untrusted sources (no CA authority will issue a certificate for, say, "google.com" so that you can feed that to your proxy).
Googling for "man in the middle attack ssl proxy" turns up many links that should be useful.
This article seems to describe an out-of-the-box solution: Understanding Man-In-The-Middle Attacks - Part 4: SSL Hijacking
It doesn't mention applets but Fiddler might fit the bill (from Capturing HTTPS traffic in the clear?)
Just set -Djavax.net.debug=all in the JVM properties. You will get all kinds of output from different layers of the network stack, including the pre-encrypted SSL traffic.
If you're talking about SSL, it wouldn't be secure if that was possible, and it is secure, so it isn't.
I have simple client-server communication thru WebServices.
Now, I'm using javax.ws.* and Endpoint class (is it a default implementation?) to create server side and Netbeans to create client side.
I have a basic knowledge about certificates etc.
I want clients to use (private?) certificate to sign (encrypt?) messages, so server knows (can identify) which particular client is calling.
So i have to generate private certificates for clients and public certificate for server?
Which APIs/frameworks (buzzwords like JAAS, ws-security, xwss, tls) should i use ?
Maybe just TLS could be enough for that ?
javax.ws.* - is it a reference implementation from Sun ?
I used SAAJ 1.3.4 and it works.
Now i have a question, how can i identify client (clients have unique private keys) can i extract some private key hash from SOAP envelope (to identify client) ?
You can try using Bouncycastle library, it's ligth weight and quite complete.
http://www.bouncycastle.org/java.html
Usually the client asks the server to identify itself and not the other way around. There is an option for a 2 way identification, I'm guessing you need to configure it.
I'd suggest using Axis2 for generating the client/service stub and Rampart for handling the security.
Rampart is an axis2 module that handles most of the security hustle for you.