wso2 - how to get TLS certificate details in sequence - wso2

In my integration scenario I need to veryfy some data of TLS certificate.
Is there a way to get details of TLS certificate (eg. subject name) in sequence?

No, you can do that in wso2. In any of wso2 scopes (Axis2/Axis2-Client/Transport/Operation/Synapse), you don't have access / information to used TLS certificate in request.
Some workaround, could be use reverse proxy, for example HAProxy to add information in request header, like described here: SSL Client Certificate Information in HTTP Headers and read in sequence from header. In nginix I belive that is also possible.
Last way, I think, is to modify source code, or implement own TransportReceiver for https requests.

Related

Hostname/IP does not match certificate's altnames

I'm working on a REST API that itself makes requests to another REST API -- basically, it provides a more convenient interface and also some extra functionality. Let's call my REST API X and the REST API to which my API calls Y.
Whenever I make requests to the endpoints of Y on my machine with cURL, REST Client, etc; all requests are successful. Like I mentioned, my API X is acting as a wrapper to Y, so when I upload my API to aws Lambda and create the respective endpoints in API Gateway, when I make a request to one of the endpoints I get this message:
Hostname/IP does not match certificate's altnames: Host:
X.execute-api.us-west-2.amazonaws.com. is not in the cert's altnames:
DNS:somehostname.com
So far, I have uploaded two lambdas with their respective endpoints, and the problem above only seems to be happening for one of the endpoints (the request to the other endpoint happens without problem).
I would like to know why this is happening and if this is a problem on my side? Meaning, is there something I am forgetting or something I can do -- except bypassing some security mechanism -- to fix this on my side? Whenever I make requests to the original API Y on my machine I'm not getting any errors so I'm a bit puzzled by this.
I think you're missing how SSL certificates work. Depending on how the certificate is setup for "API Y" you can't just connect to a different server and have it work. While you are conceptually a proxy to the real back end from the client perspective, you're a totally different host and the SSL certificate is for "API Y" only.
This is the same reason that you can't decide that you want to have an API named trustme.google.com - you don't have control over the google.com domain (presumably).
If there is a way to change the hostname that your client connections are using (to something like proxy.yourdomain.tld) then you can setup an SSL certificate for that domain and things should work. However, at that point you may run into CORS issues - post again if you have that issue.
AWS documents how to setup your own SSL certificate for API gateway. It's pretty easy though if you have an existing certificate you may need to use the AWS certificate manager to get a (free) certificate for your API.
Update 03/10/2022: Before your proxy hands off the request to the real backend service, make sure to set Host header to the hostname of the real service, see here.
I also developed a HTTP client -> APIG endpoint -> Lambda -> Host application, where the Lambda acts as a proxy between the client and the 3rd party Host. My Lambda is written in Node.js. I was getting this same exact error when the Lambda tried to invoke the 3rd party Host,
{
"statusCode": 500,
"body": "Hostname/IP does not match certificate's altnames: Host: zyxfghsk.execute-api.us-east-1.amazonaws.com. is not in the cert's altnames: DNS:*.somehost.com, DNS:somehost.com"
}
My setup uses Lambda Proxy integration with APIG, and I pass the set of HTTP headers from the client as-is to the 3rd party Host. I noticed the headers contained header Host: zyxfghsk.execute-api.us-east-1.amazonaws.com, which I think comes from the client. So in the Lambda code, right before passing the request to the 3rd party Host, I just simply delete the Host header from the request, and the problem went away. Another approach I was trying earlier, which also works, but not as ideal is that I was setting NODE_TLS_REJECT_UNAUTHORIZED=0 in the Node.js environment, which effectively disables SSL certificate validation by Node.js.
I believe, though not 100% certain, that in my case at least the error was getting thrown by Node.js certificate validation.
Update 03/10/2022: Before your proxy hands off the request to the real backend service, make sure to set Host header to the hostname of the real service, see here.

How to verify certificate with ocsp using openssl

I have a problem.
I am using openssl for validate my cert - x509_verify_cert(). But this function doesn't use ocsp. So it can be a problem if there is no crl.
In openssl errors i found this define - x509_err_ocsp_verify_needed, but i don't understand how it uses.
It seems that may be exists some kind of callback for my connecting to ocsp server function or something like that.
Also i found it which i can use, as i understand, for my own validate function, but i want only ocsp check.
So my question is: is it possible ask openssl use ocsp for validation and how?
It is possible :
openssl ocsp -issuer certchain.pem -cert cert.pem -text -url <the ocsp responder URL>
Some links to articles with more details:
https://raymii.org/s/articles/OpenSSL_Manually_Verify_a_certificate_against_an_OCSP.html
https://akshayranganath.github.io/OCSP-Validation-With-Openssl/
OpenSSL API does not provide a single API to do OCSP validation. The OpenSSL API provides the primitives so that you can implement your own validation. There are details you need to fill to the implementation which may depend on your situation you are trying to solve.
I would suggest that you get to know the openssl ocsp command as a basis of your understanding. Reading the links from Sanjeev's answer gives you examples of using this command as well.
To implement OCSP validation you will need to:
Extract server and issuer certificates from somewhere (SSL connection most likely)
Extract the OCSP server list from the server certificate
Generate a OCSP request using the server and issuer certificates
Send the request to the OCSP server and get a response back
Optionally validate the response
Extract the certificate status
Optionally you can also cache the result with the response update date range so that you can shortcut the above procedure if you see the certificate again.
You can also group a bunch of server certificates to the same OCSP server into a single request as well.
Of note is that the OCSP server link may not be HTTP and you may need to support whatever link type the certificate may have. For example in windows AD enterprise setups, the server OCSP may only have LDAP OCSP server links.
You may also like to see my answer to a question where I go into code examples of OCSP request and response handling.
UPDATE:
If you want to check the whole chain, you will have to do the above one certificate at a time (although the certificates operations can be overlapped). As far as I know, there is no way to check a whole chain at once. Also, you may find that a lot of intermediate certificates don't provide OCSP links anyway so there is no way to check. If you need to do this then it would be a good idea to cache the results as you will come across the same intermediate certificates all the time. In fact you could schedule to do this ahead of time for "known" intermediate certificates that you come across all this time.
You also keep pointing to "x509_verify_cert" check I quote:
Applications rarely call this function directly but it is used by
OpenSSL internally for certificate validation, in both the S/MIME and
SSL/TLS code.
So you shouldn't be calling this yourself anyway.
It seems that may be exists some kind of callback for my connecting to ocsp server function or something like that.
X509_STORE_CTX_set_verify_cb - used to set a callback to do your own custom verification - used a lot in server SSL setups
X509_STORE_CTX_set_ex_data - used to add custom argument values used by the callback
X509_VERIFY_PARAM_set_flags - used to setup flags (e.g. X509_V_FLAG_CRL_CHECK or X509_V_FLAG_CRL_CHECK_ALL)
In openssl errors i found this define - x509_err_ocsp_verify_needed
X509_V_ERR_OCSP_VERIFY_NEEDED is defined and never used in the openssl codebase. It is meant to returned from a verify callback function that the user provides (i.e. X509_STORE_CTX_set_verify_cb) to indicate that verification should fail with that error. What you do with that information is up to you. If you supply a callback and return that error from a openssl SSL connection that the SSL connection will terminate.
Also of note, if you do add a custom verification callback that does do full OCSP checking, it will slow down the SSL connection setup a lot. This is why most browsers don't do this by default as it slows down the user experience to much.

How do http-websites prevent MITM attack for token based authentication?

I am new to web services and read about token based authentication which can be used with web services from What is token based authentication?. I searched on internet but its quite confusing how http based websites manage to do token based authentication without any security vulnerability.
What point I have?
I can sit in between server and client and store the token somehow by sniffing the traffic and make misuse of it before it expires. Am I wrong here?
EDIT
As mentioned on https://security.stackexchange.com/questions/46348/token-based-authentication-under-http.
"Facebook uses an OAuth token passed as a cookie or HTTP header and
protected by HTTPS."
How can I implement this as in that case the website will be http-based and only http-headers will be using https. Please correct me if I am wrong.
Your edit suggest a misunderstanding of what HTTPS does.
Normatively speaking, HTTP (meaning, the "language" that is spoken on the network, defined by https://www.ietf.org/rfc/rfc2616.txt) is a text based, "application level protocol", used over TCP sockets (TCP being the "transport level" layer).
In that sense, HTTP and HTTPS are the same "language", nothing differs in them. HTTP and HTTPS are both text based request/response protocols, each consisting of headers and an body, with requests specifying a verb such as GET, POST, PUT, ... No difference whatsoever.
What is different in HTTP vs. HTTPS, is that underneath this HTTP "language" (application level protocol), HTTPS uses TCP sockets that are encrypted using a SSL or TLS layer that provides encryption.
As the SSL/TLS layer happens under the HTTP layer, there can be no difference between what happens to the headers of a request and what happens to the body.
Back to your question :
How can I implement this as in that case the website will be http-based and only http-headers will be using https. Please correct me if I am wrong.
You can't have only the headers, and not the body using HTTPS in a single request/response cycle. It's all or nothing.
The conclusion is, as per the article you link to : token based authentication can only be secure if the token is always secured. Which, if you are always using HTTPS (in all request/response), is guaranteed (both the headers and the body are protected). If even one single request or response is not sent over HTTPS, then you have a flaw.

How to use HTTPS for webservice and android app?

Im working on some JSON-based web service that is supposed to work with Android application.
I would like to encrypt data transport between client (android) and server (virtual server in datacenter).
I don't have to make sure that my server is my server, just data encryption.
I have no idea how to use HTTPS.
Do I just put my PHP files in private_html and use https://example.com url?
To use HTTPS, you don't have to do anything in the coding of your web service - it's all in your hosting. Here the are steps you can follow. The specific instructions differ in your hosting (IIS, Apache, AWS/Azure, etc), but you can google specifics on how to accomplish any of these steps for whatever host and application framework you decide.
Buy an SSL certificate (there are many different vendors, but expect between $75-$200 for the certificate) based on the vendor, reputation, and level of security you need.
Generate a certificate signing request (CSR) from the server you'll be hosting.
Upload the CSR to the SSL vendor who will validate and provide the certificate for your use.
Import the SSL certificate into your application server, and configure the site to use the certificate. For instance, if you're hosting Microsoft IIS, you'd import the SSL certificate and then add HTTPS bindings on 443 to the specific website hosting your web service.
Another point of security. Since you are deploying SSL, you don't have to do any application level encryption (assuming you are not putting sensitive information in query strings - use POST if you think you need to). You probably would want to implement some security to restrict access to your web service so only your app can access it. Best practice is some level of OAuth, but at a minimum some type of pre-shared key in the header of the request is a lot better than nothing.
Here are some additional sites for more information:
https://www.digicert.com/ssl-certificate-installation.htm
https://support.godaddy.com/help/category/742/ssl-certificates-installing-ssl-certificates?prog_id=GoDaddy
If you don't want to pay for a certificate, you can use certificate signet by your own CA and add the root certificates into your application using HTTPClient and keystores
Here there's some guides
http://datacenteroverlords.com/2012/03/01/creating-your-own-ssl-certificate-authority/
http://developer.android.com/reference/org/apache/http/client/HttpClient.html
KeyStore, HttpClient, and HTTPS: Can someone explain this code to me?
http://blog.antoine.li/2010/10/22/android-trusting-ssl-certificates/
You can limit users to use JUST and only HTTPS in apache, IIS or whatever do you use. If your client connects to your server, his communications will be likely to encrypted, because he is already using HTTPS. And for responsing in HTTPS you virtually cannot send HTTPS responses, as far as I know, unless that other side isn't also a website (for example, if you have your website, you could send such a response e.g. to Google). You should be okay to send data like http status codes (OK, NotModified, PageNotFound, ...), or if you want something more, or if it is a requirement, then there you still have JSON and you could encode it as well, with some encoding algorithms, or use binary JSON format.
Check if your hosting company provides a free public shared https address. Most of them do.
If you want to understand how to do it right, follow this thread
Warning: Don't stick with the solution below for production.
If you plan o use an https endpoint without a certificate you have to make sure to disable peer verification, check this answer

Boost ASIO with OpenSSL Can't Read HTTP Headers

I'm attempting to write a simple HTTP/HTTPS proxy using Boost ASIO. HTTP is working fine, but I'm having some issues with HTTPS. For the record this is a local proxy. Anyway so here is an example of how a transaction works with my setup.
Browser asks for Google.com
I lie to the browser and tell it to go to 127.0.0.1:443
Browser socket connects to my local server on 443I attempt to read the headers so I can do a real host lookup and open a second upstream socket so I can simply forward out the requests.
This is where things fail immediately. When I try to print out the headers of the incoming socket, it appears that they are already encrypted by the browser making the request. I thought at first that perhaps the jumbled console output was just that the headers were compressed, but after some thorough testing this is not the case.
So I'm wondering if anyone can point me in the right direction, perhaps to some reading material where I can better understand what is happening here. Why are the headers immediately encrypted before the connection to the "server" (my proxy) even completes and has a chance to communicate with the client? Is it a temp key? Do I need to ignore the initial headers and send some command back telling the client what temporary key to use or not to compress/encrypt at all? Thanks so much in advance for any help, I've been stuck on this for a while.
HTTPS passes all HTTP traffic, headers and all, over a secure SSL connection. This is by design to prevent exactly what you're trying to do which is essentially a man-in-the-middle attack. In order to succeed, you'll have to come up with a way to defeat SSL security.
One way to do this is to provide an SSL certificate that the browser will accept. There are a couple common reasons the browser complains about a certificate: (1) the certificate is not signed by an authority that the browser trusts and (2) the certificate common name (CN) does not match the URL host.
As long as you control the browser environment then (1) is easily fixed by creating your own certificate authority (CA) and installing its certificate as trusted in your operating system and/or browser. Then in your proxy you supply a certificate signed by your CA. You're basically telling the browser that it's okay to trust certificates that your proxy provides.
(2) will be more difficult because you have to supply the certificate with the correct CN before you can read the HTTP headers to determine the host the browser was trying to reach. Furthermore, unless you already know the hosts that might be requested you will have to generate (and sign) a matching certificate dynamically. Perhaps you could use a pool of IP addresses for your proxy and coordinate with your spoofing DNS service so that you know which certificate should be presented on which connection.
Generally HTTPS proxies are not a good idea. I would discourage it because you'll really be working against the grain of browser security.
I liked this book as a SSL/TLS reference. You can use a tool like OpenSSL to create and sign your own certificates.