When using signtool.exe to perform authenticode signing of executables, we want to use timestamping to ensure that the executable will still be valid in the future. It seems that the timestamping server protocol only supports http:// and not https:// out of the box. This seems like a security vulnerability on Microsoft's part.
Does anyone know how to perform signtool.exe timestamping via SSL? In other words, to use a time server https://timestamp.digicert.com instead of http://timestamp.digicert.com
Related
I have a Windows image that uses the PowerShell execution policy AllSigned
I also have a PowerShell script that is signed by a signing certificate issued by an internal CA
The certificate of the issuing CA is installed/trusted on the target machine
When I sign the PowerShell script, I am including the full certificate chain (IncludeChain = 'All')
The certificate chain looks like this:
|- Issuing CA Certificate
|- Signing Certificate
The PowerShell script is signed by the Signing Certificate, but we are not installing that certificate on our target machine. We are only installing the Issuing CA Certificate into the Trusted Publishers and other certificate stores.
This method works when we sign our custom application binaries using the Signing Certificate (we use Windows Defender Application Control to ensure that any applications running on our target are signed by trusted publishers) but it does not work when running PowerShell scripts.
According to this MSDN community post, PowerShell uses Known Publisher rules, which state that the Signing Certificate itself has to be in the Trusted Publishers certificate store.
This is not ideal, as the signing certificate we use to sign the PowerShell scripts is not something we want to ship out, nor will it be valid anymore by the time our product ships.
I understand that if I use a timestamp server when signing the PowerShell scripts, that the signature will still be considered valid if the signature was generated within the validity window of the signing certificate, but this is not our preferred solution.
Ideally I would like to know if it is possible, and how, to have PowerShell use the Issuing CA Certificate to validate the signed PowerShell scripts. (i.e. Known Issuer rules)
In the case that it's not possible, I would like to know why Microsoft departed from the practice of allowing you to validate signatures without explicitly trusting the signing certificate (i.e. using the issuing certificate to validate it).
Any help would be greatly appreciated.
There is a difference between deployment and the running of PowerShell scripts.
The confusion is that Windows Defender Application Control can use code signing 2 different ways, for 2 different reasons, and PowerShell has only ever supported one. Windows Defender Application Control can use code signing:
With a trusted Issuing CA Certificate to authenticate applications. This is the situation when your company wants to share many internal applications among all employees easily. It is also used for "trusted" Microsoft Store applications.
Because "normal" people don't blindly trust all applications and generic certificate authorities, you can instead deploy based off of trusting just the Signing Certificate for verification. (see Catalog Files). This is so that you could deploy applications with certificates that may not have an accessible CA. e.g. if you singed the application with an internal CA and you sell it to another company, or if you are using a self signed certificate.
Windows Defender Application Control primary purpose is for Application deployment/control, and a byproduct is that it can do PowerShell scripts as well. Most "normal" applications can run with "invalid" or "broken" certificates with incomplete certificate chains. The certificate was only used to control the distribution of the code and validation that the application was not tampered with/changed, and has nothing to do with the active "running" of the code.
PowerShell, on the other hand, when running with AllSigned, always validates the entire chain before running. It doesn't care about the distribution, it cares about what it runs. That means that the entire certificate chain needs to be present and trusted on the running machine. Yes, that means that if you sign with an internal CA, you need the Issuing CA Certificate, and the Signing Certificate distributed and trusted by the running party.
This leads you to 3 options:
Self signed certificate - This is ok for personal/development projects, and marginally better than distributing unsigned code.
Internal CA certificate - This is ok for internal projects. In this case, yes, you would have to share the entire certificate chain if you wanted to distribute.
Global/Public CA Certificate - This is the recommended method if you are distributing publicly/commercially. The Public CA's are trusted, and code signing certificates can be bought from places like DigiCert and can last 3 years. I know, for me, I would feel much more comfortable running code signed by a DigiCert over having to mess with internal or self signed certificates.
That doesn't make sense.
If the internal root CA certificate is in your trusted root CA store and the intermediate in your trusted intermediate store. Then a PS script is signed by a certificate with a trusted chain back to the trusted root, it should trust the signing of the certificate.
There should be no difference between an internal trusted CA and a public trusted CA.
If anything a code signing certificate issued by an internal CA is more trustworthy than a public signed one. Internal processes and controls mean only actual trusted internal publsihers can get one, unlike a public code signing cert bought for a small amount.
How do browsers like Chrome check SSL Certificate?
IS there any online databases or websites that they use?
What steps are taken by browsers to validate a SSL certificate?
Am I able to do it manually without using browser?
How do browsers like Chrome check SSL Certificate?
The certificate and chain is send by the server during the SSL handshake. The browser will create the trust chain based on the certificate issuer, provided chain certificates and the local root certificates. It will check expiration and purpose of the certificate and also check the subject alternative names (and maybe subject too) to make sure that the certificate is actually issued for the domain in the URL. It might also do some checks for certificate revocation.
For details see SSL Certificate framework 101: How does the browser actually verify the validity of a given server certificate? and How Do Browsers Handle Revoked SSL/TLS Certificates?.
I there any online database or websites that they use?
Not really. The necessary trust store is local. They might check revocation though against some online resource. See Is Certificate validation done completely local?.
Am I able to do it manually without using browser?
Sure, what the browser does could in theory be replicated manually. You can for example access the site and get the leaf and intermediate certificates with openssl s_client -showcerts .... You can then use openssl verify to verify the certificate chain, see also Verify a certificate chain using openssl verify. Then you need to look at the leaf certificate with openssl x509 -text ... to check purpose, expiration and the subject. Revocation is tricky but could be done with the help of openssl crl and openssl ocsp, although this does not really reflect what browsers do.
The official algorithm for validating any SSL/TLS certificate is defined by PKIX as modified by OCSP. For TLS nowadays the OCSP token is often transported by 'stapling' in the TLS handshake instead of by a separate connection, which requires several other RFCs, but that only affects transport, not the actual validation by the relier. For HTTPS specifically, the client must also check server identity aka 'hostname' as defined by rfc2818.
In practice, browsers may vary some. Chrome mostly uses a google-determined scheme to 'push' revocation data they select, but this has changed from time to time. Firefox, last I heard, used their own 'one-CRL' scheme. Also, although the standard and traditional practice was to check hostname against SAN if present and otherwise fall back to Subject.CN, Chrome since a few years ago requires SAN and never uses CN; you can find dozens of Qs on several stacks about "my selfsigned or otherwise DIY cert not from a real CA stopped working on Chrome".
If by 'do it manually' you really mean manually, that will be a lot of work. If you mean with tools other than a browser offline, somewhat easier; OpenSSL (if installed) can do most of this, although you need more options than shown in Steffen's link to get it right.
If you mean with tools other than a browser online, absolutely. The WWW has become extremely popular in recent decades, and there are zillions of programs and libraries for accessing it, nearly all of them including HTTPS (although two decades ago that was less common), which includes validating the certificate -- at least by default; many have options to disable, bypass, or override validation. There are standalone tools like curl and wget -- or openssl s_client can do the SSL/TLS and certificate part without doing HTTP on top. There are innumerable libraries and middlewares like ssl in python (or requests using it), tls in nodejs, (older) HttpsURLConnection and (newer) java.net.http in Java as well as third-parties like Apache HttpComponents; I'm sure there are counterparts for perl and dotnet although I'm not familiar with them. As well as powershell, which is fuzzy on the program/library distinction.
I am writing a test and windows seems to be prompting me for what certificate to use when using x509 client certificates.
I would like to have it automatically select one without user interaction (user interaction is bad when writing tests).
The problem is there seems to be no documentation on how this works in MSDN, could someone at least point me towards an answer?
You can have the server request a client certificate signed by a specific CA.
If only one certificate installed locally is issued by that CA then this should surpass the prompt.
We sign our executables on the build server. Suddenly the build server failed to build giving the error:
SingTool Error: The sepcified timestamp server either could not be reached or returned an invalid response.
After changing the timestamp server to http://sha256timestamp.ws.symantec.com/sha256/timestamp, singing did work again.
Are there any issues with our old url? Why is it not available anymore?
Could we have some (security) issues with the old signed files or the new url?
I know this is a little bit broad I just don't want to miss anything...
I asked Symantec about that, so they sent me this link: https://knowledge.symantec.com/support/partner/index?page=content&id=NEWS10071&viewlocale=en_US
By April 18, 2017, Symantec will decommission the "Legacy"
timestamping service.
(Legacy) RFC 3161 SHA128 Timestamp Service:
https://timestamp.geotrust.com/tsa
To support business continuity for our customers, we have provided the
following replacement services.
(New) RFC 3161 Service SHA256:
http://sha256timestamp.ws.symantec.com/sha256/timestamp
Important: Customers must leverage SHA256 Timestamping service going
forward, and should not use a SHA1 service unless there is a legacy
platform constraint which doesn't allow use of SHA2 service (in this
case you can use this new URL: RFC 3161 Service SHA128:
http://sha1timestamp.ws.symantec.com/sha1/timestamp).
Background and Key Industry Mandates affecting the Timestamping
services
To comply with Minimum Requirements for Code Signing (CSMRs) published
by CA Security Council and Microsoft Trusted Root Program Requirements
(section 3.14), Symantec has set up the "new" RFC 3161 (SHA1 and SHA2)
service as per specifications and requirements laid out by section
16.1 which requires FIPS 140-2 Level 3 key protection. In the near future, Oracle will be taking steps to remove SHA1 support for both
Java signing and timestamping. This will not impact Java applications
that were previously signed or timestamped with SHA1 as these will
continue to function properly. However, Java applications signed or
timestamped with SHA1 after Oracle's announced date may not be
trusted.
Working link for timestamp from another provider:
http://tsa.starfieldtech.com
You can also try:
http://timestamp.globalsign.com/scripts/timstamp.dll
http://timestamp.comodoca.com/rfc3161
You can choose KeyStore Explorer (sign tool with good GUI). It has default and not be working link http://timestamp.geotrust.com/tsa
If so, do not forget to change the unworking link in the option TSA URL (Add timestamp) with other working options.
For example, this option (link) worked for me fine:
http://tsa.starfieldtech.com
I experienced the same TSA issue starting on 2017-04-21. Switching from https://timestamp.geotrust.com/tsa to http://sha256timestamp.ws.symantec.com/sha256/timestamp fixed our problem as well, so thanks for the pointer. The specific error I received using the old URL was that jarsigner returned"java.net.socketException: software caused connection abort: recv failed."
The Verisign knowledge base article AR185, updated 2017-03-16, recommends the jarsigner arguments "-tsa http://sha256timestamp.ws.symantec.com/sha256/timestamp" where it used to recommend https://timestamp.geotrust.com/tsa . This documentation change suggests to me that the disabling of the URL may be intentional, but I don't know whether that has any implications for the level of trust of JARs signed using the old timestamp server.
Hy!
I want sign a windows .exe binary with signtool from the Microsoft Platform SDK (7.1) and add a timestamp to the signature. I have two problems with that.
The (RFC compliant) timestamp server I want to use only allows encrypted https connections, but the /tr option of signtool returns an error, if the URL is not prefixed by http://
I need to authenticate to the timestamp server prior to using it, either by TLS-Client-Authentication (using the signature certificate) or by classic HTTPS username/password login. But I can't find a way to set any of these with signtool.
Is there a way to accomplish this?