Rest API encryption with SSL - api

I'm in the process of designing a REST Api and we're trying to decided how to do encryption. We are currently using https for all request/responses however various logs (dns, browser, ...) will log the plain text url. This raises an issue when we're sending sensitive data in the url, such as "www.mysite.com/user/credit-card-number/". Is there a way to leverage the SSL/TLS public/private keys to encrypt path parameters? For example, "www.mysite.com/user/credit-card-number/" turns into "www.mysite.com/encryptedstring".

I would highly recommend that you not put sensitive data in the URL. If you need something identifying, you could at least use a randomly generated String/UUID/token/whatever that maps to whatever it is that is being identified.
Handling manual encryption/decryption would depend on what language/framework you are using. For example, if you were using Java, then do some google searches on JSSE, which is Java's framework for SSL/TLS.
If you're looking for something to automajically do the encryption/decryption for you, I would think that would also depend on the framework you are using.

If I understand correctly, you are asking if urls are encrypted over an SSL/TLS channel. The answer is yes as this SO question points out. Over TLS, everything is encrypted between the client and server except the IP address and port of the targeted server. (This includes the http headers as well.)
EDIT:
After reading again, I see that you are interested in stopping the the URL being logged. I'm pretty sure the only way to do this is to change the url on the server. Not much help, but my suggestion is don't put the cc number in the url or use some kind of derived key instead.

Related

SSL Certificate Authentication

We have a HTTP endpoint where a form request is posted containing transaction data from a 3rd party https website.
We are investigating ways that our HTTP endpoint can contain code to check that the host that posted the request is the 3rd party website and no-one else (i.e. a hacker).
Is there any way our HTTP endpoint can authenticate with the website where the posted form request originated? Maybe by SSL Certificate Authentication?
Many thanks in advance.
To guarantee that the server on the other side is who they say they are the safest way is to have them use an SSL Certificate. If the they also need to trust who you are then each side should have their own SSL Certificate.
The IP Range solution provided in the comment could be a possible hack but it's quite brittle and it couldn't be applied in a very serious environment.
The Shared Key solution will work and it's reliable but you have to change keys from time to time depending on the volume of traffic between the two servers.
Hope this helps.
It might be better to use message-level security instead of transport-level security (SSL/TLS).
The third party website would sign the message using its certificate (or to be precise, using the private key matching its certificate), and your website would verify this signature.
This could allow for that message to be relayed by the user's browser, without needing a direct connection between the two servers.
This sort of mechanism already exists in the Identity Management world, for example with SAML and Shibboleth. (You can still have direct connections between the servers to get additional information too.)

WCF Service with Message Level Encryption over HTTPS

I have seen one or two questions about this but no definite answers. I have a customer requirement to implement a WCF-based client/server solution using Message Encryption AND HTTPS. I understand that WCF doesn't support this as standard, and the options are HTTP with Message Encryption, HTTPS without Message Encryption, or HTTPS with Message Credentials.
None of these will satisfy the customer requirement. I have control over both the service and the desktop-based clients. The service is hosted at my location and the clients access it over the internet.
I have dug around for days (and nights :( ) trying out custom bindings and so on, but whenever I try to combine message encryption with Https, I come up against this error:
"The binding contains both a SymmetricSecurityBindingElement and a secure transport binding element. Policy export for such a binding is not supported."
I would prefer to user username/password for authentication but I am prepared to use client certificates if this makes it possible. So far I haven't found any combination which is acceptable to WCF.
Is there any way to achieve this or am I just wasting my time? I would value a quick answer because my customer's deadline is drawing very near!
Thanks!
According to this, the special both mode for security (meaning both message and transport) is only supported in the NetMsmqBinding binding, which I'm guessing, is not an option for you. Does your client happen to be the NSA? (Just wondering why anyone would need their communication encrypted twice).
OK I've found a solution ...
Using IMessageInspector I intercepted the incoming and outgoing messages so that they can be encrypted and decrypted. Encryption uses a symmetric technique - best because asymmetric only allows encryption of short strings and is very slow.
The downside is that both ends need to have the private key of the certificate - so the cert needs to be installed on both client and server machines (or the key could be placed in config). This works for me though because the number of users is limited and all are under the control of the IT dept.
If I had more time I would have looked at setting up a second SSL connection with a different cert, purely to handle the certificate negotiation and avoid placing the cert on the client machine. Using SslStream was a possibility but I wasn't sure whether I could access key information to use for my own encryption, or whether this is held privately within SslStream class.
For now I'm just pleased to have it working before my deadline (only just though :) ) ...

Non-SSL site making API call to SSL site

I apologize, I know this is a very short question but Google doesn't seem to help (I guess I'm not searching for the correct phrase or set of keywords).
If I have a site not protected by SSL and it makes an api call to an https site, is that information secure or do I need to have SSL as well?
I want to make sure I keep my users' data secure.
Only data in the API call (request) needs to be protected. Data returned by the API (response) to my (non-SSL) site isn't meaningful or sensitive.
Thanks in advance.
The call to the SSL site will be protected, but if it's multihop (client to non SSL to SSL site) and the data on first hop is plain text.
However as #VictorRonin says, security is a much bigger concern than just SSL.
The call is protected. Your website talking to another website (protected by SLL) will send and get information inside of protected channel.
However, it's hard to say whether your users data is secure. Security requires a lot more than just usage of SSL.
I also got the same problems.
I'm using 16 bits micro connect to net by Wifi's AT command .
after connected in transparent mode. normally I can send some simple text (HTTP ) to request content from every web page.(if those webpages not need SSL).
this makes programing fun and easy.
But these few years. life got stuck almost webpage use SSL. mean programming need more complex step to reach content.
but the most serious things is that the CA (cert auth) cannot use forever it has expired time !!!
This mean hardware device have to modified CA data frequently . so it's not practical for small iot firm .
However I found a way even it's not the best by using thingspeak.com (ThingHTTP)
with ThingHTTP you can request without SSL to any website which need SSL
I hope in the future there are more iot cloud or even some webpage turn to use old method (HTTP) in case of that data no need secure.
In my opinion user can encode/decode the data by themself instead of secure everything in webpage.
Thnks

How to send new passwords securely across to the server

My client-side code calls the REST WCF service for changing passwords. I defined changePassword with "UriTemplate" set to "?user={userName}&oldPwd={oldHashPwd}&newPwd={newEncryptPwd}"
My question is: how to encrypt the new password on the client side so that we can successfully decrypt it on the server side ? Please be specific. Thanks.
Use HTTPS. If the whole communication is encrypted, you won't even need to encrypt/decrypt the password individually.
Beyond HTTPS, you could use a secure, salted password hash on the client side. That would mean even interception of the URL would be safe - having the hash would allow efficient "proof of ownership", but not discovery of the password.
Yinfang. You don't need to be worry to encrypt your password from client side that would only be decrypted on the server side. Now a days, there are so many channels through which you can protect you personal data like your passwords. One way is to check that whether yo use "HTTPS" for your browsing because it will provide you secure channel to send you information from one place to another.
On the other hand you can get VPN connection. Through which all of your information gets encrypted and provided secure channel to pass your personal sensitive data from client side to server. There are so many providers of VPN connection are available in the market like PureVPN, Hidemyass,switchvpn etc etc. If you want all of your information encrypted ans secure you can use these useful information.
Hope this could help. I use to encrypt data using Rijndael
Sample code here:
Cryptography
You can create logic on backend side and be used by the client side for encrypting and decrypting data.
You have 2 options to go with either "https" or "VPN/Proxy". Going through 'https' won't hazel much while encrypting anything on the web. I will give you smooth path to surf the web and do whatever you want. But the point is that if you are looking to get something more than just encryption then you should try VPN/Proxy. If you can google around then you will find that proxy is not that much safer. However, going through VPN is completely opposite to proxy. VPN is one of the best and most reliable feature that a user can have for their web. VPN absolutely anonymize one's identity and allow the local ISP to surf (encrypt/decrypt) user data with out any threats from hackers.

Are HTTPS URLs encrypted?

Are all URLs encrypted when using TLS/SSL (HTTPS) encryption? I would like to know because I want all URL data to be hidden when using TLS/SSL (HTTPS).
If TLS/SSL gives you total URL encryption then I don't have to worry about hiding confidential information from URLs.
Yes, the SSL connection is between the TCP layer and the HTTP layer. The client and server first establish a secure encrypted TCP connection (via the SSL/TLS protocol) and then the client will send the HTTP request (GET, POST, DELETE...) over that encrypted TCP connection.
Note however (as also noted in the comments) that the domain name part of the URL is sent in clear text during the first part of the TLS negotiation. So, the domain name of the server can be sniffed. But not the rest of the URL.
Since nobody provided a wire capture, here's one.
Server Name (the domain part of the URL) is presented in the ClientHello packet, in plain text.
The following shows a browser request to:
https://i.stack.imgur.com/path/?some=parameters&go=here
See this answer for more on TLS version fields (there are 3 of them - not versions, fields that each contain a version number!)
From https://www.ietf.org/rfc/rfc3546.txt:
3.1. Server Name Indication
[TLS] does not provide a mechanism for a client to tell a server
the name of the server it is contacting. It may be desirable for
clients to provide this information to facilitate secure
connections to servers that host multiple 'virtual' servers at a
single underlying network address.
In order to provide the server name, clients MAY include an
extension of type "server_name" in the (extended) client hello.
In short:
FQDN (the domain part of the URL) MAY be transmitted in clear inside the ClientHello packet if SNI extension is used
The rest of the URL (/path/?some=parameters&go=here) has no business being inside ClientHello since the request URL is a HTTP thing (OSI Layer 7), therefore it will never show up in a TLS handshake (Layer 4 or 5). That will come later on in a GET /path/?some=parameters&go=here HTTP/1.1 HTTP request, AFTER the secure TLS channel is established.
EXECUTIVE SUMMARY
Domain name MAY be transmitted in clear (if SNI extension is used in the TLS handshake) but URL (path and parameters) is always encrypted.
MARCH 2019 UPDATE
Thank you carlin.scott for bringing this one up.
The payload in the SNI extension can now be encrypted via this draft RFC proposal. This capability only exists in TLS 1.3 (as an option and it's up to both ends to implement it) and there is no backwards compatibility with TLS 1.2 and below.
CloudFlare is doing it and you can read more about the internals here —
If the chicken must come before the egg, where do you put the chicken?
In practice this means that instead of transmitting the FQDN in plain text (like the Wireshark capture shows), it is now encrypted.
NOTE: This addresses the privacy aspect more than the security one since a reverse DNS lookup MAY reveal the intended destination host anyway.
SEPTEMBER 2020 UPDATE
There's now a draft RFC for encrypting the entire Client Hello message, not just the SNI part:
https://datatracker.ietf.org/doc/draft-ietf-tls-esni/?include_text=1
At the time of writing this browser support is VERY limited.
As the other answers have already pointed out, https "URLs" are indeed encrypted. However, your DNS request/response when resolving the domain name is probably not, and of course, if you were using a browser, your URLs might be recorded too.
I agree with the previous answers:
To be explicit:
With TLS, the first part of the URL (https://www.example.com/) is still visible as it builds the connection. The second part (/herearemygetparameters/1/2/3/4) is protected by TLS.
However there are a number of reasons why you should not put parameters in the GET request.
First, as already mentioned by others:
- leakage through browser address bar
- leakage through history
In addition to that you have leakage of URL through the http referer: user sees site A on TLS, then clicks a link to site B. If both sites are on TLS, the request to site B will contain the full URL from site A in the referer parameter of the request. And admin from site B can retrieve it from the log files of server B.)
Entire request and response is encrypted, including URL.
Note that when you use a HTTP Proxy, it knows the address (domain) of the target server, but doesn't know the requested path on this server (i.e. request and response are always encrypted).
Yes and no.
The server address portion is NOT encrypted since it is used to set up the connection.
This may change in future with encrypted SNI and DNS but as of 2018 both technologies are not commonly in use.
The path, query string etc. are encrypted.
Note for GET requests the user will still be able to cut and paste the URL out of the location bar, and you will probably not want to put confidential information in there that can be seen by anyone looking at the screen.
An addition to the helpful answer from Marc Novakowski - the URL is stored in the logs on the server (e.g., in /etc/httpd/logs/ssl_access_log), so if you don't want the server to maintain the information over the longer term, don't put it in the URL.
It is now 2019 and the TLS v1.3 has been released. According to Cloudflare, the server name indication (SNI aka the hostname) can be encrypted thanks to TLS v1.3. So, I told myself great! Let's see how it looks within the TCP packets of cloudflare.com
So, I caught a "client hello" handshake packet from a response of the cloudflare server using Google Chrome as browser & wireshark as packet sniffer. I still can read the hostname in plain text within the Client hello packet as you can see below. It is not encrypted.
So, beware of what you can read because this is still not an anonymous connection. A middleware application between the client and the server could log every domain that are requested by a client.
So, it looks like the encryption of the SNI requires additional implementations to work along with TLSv1.3
UPDATE June 2020:
It looks like the Encrypted SNI is initiated by the browser. Cloudflare has a page for you to check if your browser supports Encrypted SNI:
https://www.cloudflare.com/ssl/encrypted-sni/
At this point, I think Google chrome does not support it. You can activate Encrypted SNI in Firefox manually. When I tried it for some reason, it didn't work instantly. I restarted Firefox twice before it worked:
Type: about:config in the URL field.
Check if network.security.esni.enabled is true.
Clear your cache / restart
Go to the website, I mentioned before.
As you can see VPN services are still useful today for people who want to ensure that a coffee shop owner does not log the list of websites that people visit.
A third-party that is monitoring traffic may also be able to determine the page visited by examining your traffic an comparing it with the traffic another user has when visiting the site. For example if there were 2 pages only on a site, one much larger than the other, then comparison of the size of the data transfer would tell which page you visited. There are ways this could be hidden from the third-party but they're not normal server or browser behaviour. See for example this paper from SciRate, https://scirate.com/arxiv/1403.0297.
In general other answers are correct, practically though this paper shows that pages visited (ie URL) can be determined quite effectively.
You can not always count on privacy of the full URL either. For instance, as is sometimes the case on enterprise networks, supplied devices like your company PC are configured with an extra "trusted" root certificate so that your browser can quietly trust a proxy (man-in-the-middle) inspection of https traffic. This means that the full URL is exposed for inspection. This is usually saved to a log.
Furthermore, your passwords are also exposed and probably logged and this is another reason to use one time passwords or to change your passwords frequently.
Finally, the request and response content is also exposed if not otherwise encrypted.
One example of the inspection setup is described by Checkpoint here. An old style "internet café" using supplied PC's may also be set up this way.
Linking to my answer on a duplicate question. Not only is the URL available in the browsers history, the server side logs but it's also sent as the HTTP Referer header which if you use third party content, exposes the URL to sources outside your control.
Althought there are some good answers already here, most of them are focusing in browser navigation. I'm writing this in 2018 and probably someone wants to know about the security of mobile apps.
For mobile apps, if you control both ends of the application (server and app), as long as you use HTTPS you're secure. iOS or Android will verify the certificate and mitigate possible MiM attacks (that would be the only weak point in all this). You can send sensitive data through HTTPS connections that it will be encrypted during transport. Just your app and the server will know any parameters sent through https.
The only "maybe" here would be if client or server are infected with malicious software that can see the data before it is wrapped in https. But if someone is infected with this kind of software, they will have access to the data, no matter what you use to transport it.
While you already have very good answers, I really like the explanation on this website: https://https.cio.gov/faq/#what-information-does-https-protect
in short: using HTTPS hides:
HTTP method
query params
POST body (if present)
Request headers (cookies included)
Status code
Additionally, if you're building a ReSTful API, browser leakage and http referer issues are mostly mitigated as the client may not be a browser and you may not have people clicking links.
If this is the case I'd recommend oAuth2 login to obtain a bearer token. In which case the only sensitive data would be the initial credentials...which should probably be in a post request anyway