aws root pinning error CURLE_SSL_PINNEDPUBKEYNOTMATCH - c++

I am using libcurl and shifting cert pinning to AWS root as per this document https://www.amazontrust.com/repository/
I used the SHA-256 Hash of Subject Public Key Information data from that website, formed a string:
static string PUBLIC_KEY = "sha256//fbe3018031f9586bcbf41727e417b7d1c45c2f47f93be372a17b96b50757d5a2;sha256//7f4296fc5b6a4e3b35d3c369623e364ab1af381d8fa7121533c9d6c633ea2461;sha256//36abc32656acfc645c61b71613c4bf21c787f5cabbee48348d58597803d7abc9;sha256//f7ecded5c66047d28ed6466b543c40e0743abe81d109254dcf845d4c2c7853c5;sha256//2b071c59a0a0ae76b0eadb2bad23bad4580b69c3601b630c2eaf0613afa83f92";
and set the string to curl
curl_easy_setopt(handle, CURLOPT_PINNEDPUBLICKEY, PUBLIC_KEY.c_str());
The curl error I get is CURLE_SSL_PINNEDPUBKEYNOTMATCH
Google does not have any insight into why, as far as I searched. If anyone has any input on how to fix this and still pin to the root, it would be super useful. Thanks.

Found the reason. Root pinning is not supported yet.
13.11 Support intermediate & root pinning for PINNEDPUBLICKEY
CURLOPT_PINNEDPUBLICKEY does not consider the hashes of intermediate & root certificates when comparing the pinned keys. Therefore it is not compatible with "HTTP Public Key Pinning" as there also intermediate and root certificates can be pinned. This is very useful as it prevents webadmins from "locking themself out of their servers".
Adding this feature would make curls pinning 100% compatible to HPKP and allow more flexible pinning.
https://curl.haxx.se/docs/todo.html

Related

Look up leaf certificate from issuer’s thumbprint?

I have a leaf certificate installed on my machine, which was issued by a Certificate Authority (CA); this CA is not present on the system.
If I am given the thumbprint (i.e. the SHA-1 hash) of the CA, can I look up and thereby retrieve the installed leaf signers issued by this CA? If I am able to, then what are the required Windows function calls for accomplishing this?
I have been examining a leaf certificate and I only see the standard string representation name of the CA and not a thumbprint. This string name is not unique, hence why I am utilizing the thumbprint (SHA-1’s poor security here is not a problem as it is only used for looking up a proper signer). Microsoft has the CertGetIssuerCertificateFromStore function, but this requires having the CA in memory.
No, it is not possible to look up an issued leaf signer using only the issuer's CA's thumbprint. You first have to install the CA on the machine and then use the entirety of the CA to find its issued leaf signers. The CA's thumbprint is not stored in the leaf signers it issues from what it appears.
All in all, the first operation that needs to be done is installing the CA on the machine you want to find its issued leaf signers on.

TLS Upgradation

public bool CheckValidationResult(ServicePoint sp,
System.Security.Cryptography.X509Certificates.X509Certificate cert, WebRequest req, int problem)
{
return true;
}
Here , I am in the position to access the web service using Tls 1.2 alone from the web service.
So , after adding the below lines before the return true in the method. ,
Then ,I can be able to access the service and also able to get the response.
Is it the correct way to handle these or any other way is there ? ? ?
Please help anyone who has experience on this .
Thanks in Advance.
//Here given protocol version with or operator accepting tls 1.1 ,1.2 and 1.0 along with ssl3
sp.Expect100Continue = true;
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls | SecurityProtocolType.Tls12;
No, that is not the correct way! Although I am aware that 100's of developers do this (return true for certificate validation), however their communication is no longer secure and is now subject to middleman and replay attacks, which are the most-common SSL attacks known to man.
The truth is you need provide a "comprehensive implementation" for certificate validation, which is based-on several RFCs (search for: X.509 Certificate validation). At a minimum you need to check the certificates validity (dates), validate subject signature hash using CA's public key and validate CA's CRL revocations (ensure server certficate has not been revoked). However ...
To keep things simple, without degrading TLS's integrity, you could simply check the "problem" (int problem), then return true or false, based on the value of problem. The OS should set the problem value, based-on internal OS security policy. Personally, I still would prefer "comprehensive implementation", because OS security policy can be weak, inundated or corrupt (hacked). Let me know if you need more details on "comprehensive implementation"

Boost, asio, https, and host/certificate verifcation

I'm looking at Boost's SSL Client. There's a reference to OpenSSL in the comments (sorry, no line numbers):
// The verify callback can be used to check whether the certificate that is
// being presented is valid for the peer. For example, RFC 2818 describes
// the steps involved in doing this for HTTPS. Consult the OpenSSL
// documentation for more details. Note that the callback is called once
// for each certificate in the certificate chain, starting from the root
// certificate authority.
Proper OpenSSL use and verification can be tricky. From experience, I know I have to perform the following to use the library correctly:
Disable SSLv2, SSLv3, and Compression on the Context object
Provide the proper root certificate for chain building and checking
Call SSL_get_peer_certificate and verify the certificate is non-NULL
Call SSL_get_verify_result and verify the result is X509_V_OK
Perform name matching (CN or SAN must match requested host)
OpenSSL 1.1.0 will provide name checking, but its only in HEAD at this point in time. From the OpenSSL Change Log:
Integrate hostname, email address and IP address checking with certificate
verification. New verify options supporting checking in opensl utility.
And:
New functions to check a hostname email or IP address against a
certificate. Add options x509 utility to print results of checks against
a certificate.
I don't see where Boost is performing any of the configurations or checks in the client code.
What precisely is Boost configuring, and what is it checking or verifying in its asio library component when using SSL?
Short answer: The Boost callback function, from the link you cited, doesn't verify anything. It returns whatever preliminary verification result was supplied to it by OpenSSL (via bool preverified). If there is any fine grained verification required (like the CN match, etc.), it has to be done explicitly by the callback.
Long answer: By the time the OpenSSL (or the Boost wrapper for OpenSSL) calls the verification function, in this case, bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx), a set of preliminary (or mandatory) verification is already done by OpenSSL. This is explained in the documentation.
The certificate chain is checked starting with the deepest nesting level (the root CA certificate) and worked upward to the peer's certificate. At each level signatures and issuer attributes are checked. Whenever a verification error is found, the error number is stored in x509_ctx and verify_callback is called with preverify_ok=0. By applying X509_CTX_store_* functions verify_callback can locate the certificate in question and perform additional steps (see EXAMPLES). If no error is found for a certificate, verify_callback is called with preverify_ok=1 before advancing to the next level.
The documentation also cites an example of how a more fine-grained verification callback could be written. You can draw inspiration from that depending on what your needs are.
EDIT: To be sure that Boost's internal callback function doesn't do anything special other than calling the application callback function, I took a look at engine.ipp, the C++ module that invokes OpenSSL's SSL_set_verify to set up callback functions. Take a look at how verify_callback_function is implemented. It simply invokes the application callback.

SSLSniff error: "SSL Accept Failed"

I'm trying to use SSLSniff's tool, and I have some technical issues... I've been looking for any similar problems, but the only results are from Twitter feeds, with no public useful answer. So, here it is:
(My version of SSLSniff is 0.8) I'm launching sslsniff with args:
sslsniff -a -c cert_and_key.pem -s 12345 -w out.log
where: cert_and_key.pem file is my authority's certificate concatenate with my unencrypted private key (in PEM format of course), and 12345 is the port where I redirect traffic with my iptables rule.
So sslsniff is correctly running:
INFO sslsniff : Certificate ready: [...]
[And anytime I connect with a client, there are these 2 following lines:]
DEBUG sslsniff : SSL Accept Failed!
DEBUG sslsniff : Got exception: Error with SSL connection.
On my client' side, I've register my AC as a trusted CA (with FF). Then when I connect through SSL I'm having the error:
Secure Connection Failed.
Error code: ssl_error_bad_cert_domain
What is super strange (moreover the fact that the certificate is not automatically accepted since it should be signed by my trusted CA) is that I cannot accept the forged certificate by clicking on "Add exception..." : I am always returning to the error page asking me to add an(other) exception...
Moreover, when I try to connect to for example: https://www.google.com, SSLSniff's log is completed with a new line :
DEBUG sslsniff : Encoded Length: 7064 too big for session cache, skipping...
Does anyone know what I'm doing wrong?
-- Edit to summer up the different answers --
The problem is that SSLSniff is not taking care of alternive names when it forges certificates. Apparently, Firefox refuses any certificate as soon as the Common Name doesn't match exactly the domain name.
For example, for Google.com : CN = www.google.com and there is no alternative name. So when you connect to https://www.google.com, it's working fine.
But for Google.fr : CN = *.google.fr, with these alternative names: *.google.fr and google.fr. So when you connect to https://www.google.fr, FF is looking for alternative names and, since it obviously doesn't find any, refuses the malformed certificate.
... So a solution would be to patch/commit... I don't know if Moxie Marlinspike has intentionally forgot this functionnality because it was too complicated, or if he was just not aware of this issue. Anyway, I'll try to have a look at the code.
The session encoded length error message: When caching the SSL session fails, it means that SSL session resumption on subsequent connections will fail, resulting in degraded performance, because a full SSL handshake needs to be done on every request. However, despite using the CPU more heavily, sslsniff will still work fine. The caching fails because the serialized representation of the OpenSSL session object (SSL_SESSION) was larger than the maximum size supported by sslsniff's session cache.
As for your real problem, note that sslsniff does not support X.509v3 subjectAltNames, so if you are connecting to a site whose hostname does not match the subject common name of the certificate, but instead matches only a subjectAltName, then sslsniff will generate a forged certificate without subjectAltNames, which will cause a hostname verification mismatch on the connecting client.
If your problem happens only for some specific sites, let us know the site so we can examine the server certificate using e.g. openssl s_client -connect host:port -showcerts and openssl x509 -in servercert.pem -text. If it happens for all sites, then the above is not the explanation.
Try a straight MITM with a cert you fully control , and make sure you don't have some OCSP/Perspectives/Convergance stuff meddling with things. Other than that, maybe add the cert to the OS trusted roots. I think FF on windows uses the windows cert store (start->run->certmgr.msc). It may also be worth trying with something like Burp to see if the error is localized to SSLSniff or all MITM attempts.

How to add software update subscription

We want to add auto-update or update notification to our products (C++).
Update should be subscription-based:
user buys subscription for 1 year of updates
when subscription expires, no more updates are available.
Can someone suggest software or provider for implementing such a service?
I found a few examples of auto-update but they all are unlimited in time.
This service must be limited on per-user basis and allow extensions.
What you would need, in terms of ingredients, would be:
a method to download the updates - I would suggest HTTP(S) for that
a method to encode the license, including what kind of updates you're entitled to and how long you're entitled to it. Ideally, this would be opaque to the user but easily verifiable on both ends (so an erroneous entry can be notified to the user without having to contact the server)
an easy way to know whether updates are available, and perhaps when to check again
What I would suggest would be to define a simple XML over HTTP service using an embeddable HTTP client, such as (shameless plug) Arachnida, with a simple API - something like:
class UpdateAgent
{
/* boilerplate */
public :
/* set the key to use. Throws an InvalidKey exception if not valid
* validity is checked locally - no HTTP queries are used.
* Key may have been invalidated on the server without notification
* at this point */
void setKey(const std::string &key);
// Get the key currently set
std::string getKey() const;
/* using a synchronous HTTPS query, check with the server if updates are
* available for the current key. Throws on error: one of the QueryError
* subclasses if there has been a query error, or InvalidKey is the
* key is either not set or is not valid (i.e. invalidated server-side) */
bool isUpdateAvailable() const;
/* etc. */
};
They key itself would, as seen above, be a string that, through its encoding, would contain some kind of information as to its validity - e.g. some kind of CRC to know whether the entered string is valid. The rest of the key - including its expiration date - could be managed server-side, although expiration information could also be encoded in the key itself (but that would mean changing the key if the user extends the license).
As for the server-side, when presented with a key and a request for an update, the server would
check the validity of the key
check whether any updates are available for the software the key is for (information that may or may not be part of the key itself, depending on whether you want to manage it in a database or want it to be part of the license key)
copy or hardlink the file into a place it can be downloaded, with a unique and hard-to-guess name
provide the URL for download to the client - e.g. in an XML stream returned for the HTTP request
start a time-out to remove the file after it hasn't been downloaded for N seconds/minutes/hours
remove the file once it has been downloaded by the client
If a download fails, it can be restarted or asked for again. If you want to charge for individual downloads, you'd need the client to confirm a successful download - or report an error on failure - so you don't count individual downloads twice.
Of course, all this is off the top of my head - there might be some details I haven't thought of here. Each of the ingredients are pretty easy to come by. An open source version of Arachnida is available on SourceForge and I have some code to encode license keys if you need it (used it for another of my products), but I'm sure that you can write that if you don't want to use mine.
A few things you might want to think of are secure authentication of your clients - so they don't share license keys - securing your HTTP connection so you don't end up publishing your updates to the world, etc. Neither the server nor the client need be very complicated to implement, as most of the building blocks already exist.
HTH
rlc