Merge branch 'magnuslarsen-grading_dev' into 3.1dev

This commit is contained in:
Dirk 2020-05-01 17:37:13 +02:00
commit f5a1884439
6 changed files with 624 additions and 55 deletions

View File

@ -13,7 +13,7 @@
* Several display/output fixes * Several display/output fixes
* Security fix: DNS input * Security fix: DNS input
* Don't use external pwd anymore * Don't use external pwd anymore
* Rating (pending) * Rating (SSL Labs, not complete)
### Features implemented / improvements in 3.0 ### Features implemented / improvements in 3.0

View File

@ -46,9 +46,9 @@ Full contribution, see git log.
- Client simulations - Client simulations
- CI integration, some test cases for it - CI integration, some test cases for it
* Steven Danneman * Steven Danneman
- Postgres and MySQL STARTTLS support - Postgres and MySQL STARTTLS support
- MongoDB support - MongoDB support
* Christian Dresen * Christian Dresen
- Dockerfile - Dockerfile
@ -78,6 +78,9 @@ Full contribution, see git log.
* Hubert Kario * Hubert Kario
- helped with avoiding accidental TCP fragmentation - helped with avoiding accidental TCP fragmentation
* Magnus Larsen
- SSL Labs Rating
* Jacco de Leeuw * Jacco de Leeuw
- skip checks which might trigger an IDS ($OFFENSIVE / --ids-friendly) - skip checks which might trigger an IDS ($OFFENSIVE / --ids-friendly)

View File

@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3 .\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3
. .
.TH "TESTSSL" "1" "January 2020" "" "" .TH "TESTSSL" "1" "May 2020" "" ""
. .
.SH "NAME" .SH "NAME"
\fBtestssl\fR \fBtestssl\fR
@ -43,10 +43,10 @@ Any OpenSSL or LibreSSL version is needed as a helper\. Unlike previous versions
1) SSL/TLS protocol check 1) SSL/TLS protocol check
. .
.P .P
2) standard cipher categories to give you upfront an idea for the ciphers supported 2) standard cipher categories
. .
.P .P
3) server's cipher preferences (server order) 3) server\'s cipher preferences (server order?)
. .
.P .P
4) forward secrecy: ciphers and elliptical curves 4) forward secrecy: ciphers and elliptical curves
@ -61,8 +61,14 @@ Any OpenSSL or LibreSSL version is needed as a helper\. Unlike previous versions
7) vulnerabilities 7) vulnerabilities
. .
.P .P
8) testing each of 370 preconfigured ciphers
.
.P
8) client simulation 8) client simulation
. .
.P
9) rating
.
.SH "OPTIONS AND PARAMETERS" .SH "OPTIONS AND PARAMETERS"
Options are either short or long options\. Any long or short option requiring a value can be called with or without an equal sign\. E\.g\. \fBtestssl\.sh \-t=smtp \-\-wide \-\-openssl=/usr/bin/openssl <URI>\fR (short options with equal sign) is equivalent to \fBtestssl\.sh \-\-starttls smtp \-\-wide \-\-openssl /usr/bin/openssl <URI>\fR (long option without equal sign)\. Some command line options can also be preset via ENV variables\. \fBWIDE=true OPENSSL=/usr/bin/openssl testssl\.sh \-\-starttls=smtp <URI>\fR would be the equivalent to the aforementioned examples\. Preference has the command line over any environment variables\. Options are either short or long options\. Any long or short option requiring a value can be called with or without an equal sign\. E\.g\. \fBtestssl\.sh \-t=smtp \-\-wide \-\-openssl=/usr/bin/openssl <URI>\fR (short options with equal sign) is equivalent to \fBtestssl\.sh \-\-starttls smtp \-\-wide \-\-openssl /usr/bin/openssl <URI>\fR (long option without equal sign)\. Some command line options can also be preset via ENV variables\. \fBWIDE=true OPENSSL=/usr/bin/openssl testssl\.sh \-\-starttls=smtp <URI>\fR would be the equivalent to the aforementioned examples\. Preference has the command line over any environment variables\.
. .
@ -235,8 +241,7 @@ session resumption capabilities,
Time skew relative to localhost (most server implementations return random values)\. Time skew relative to localhost (most server implementations return random values)\.
. .
.IP "\(bu" 4 .IP "\(bu" 4
Several certificate information .
.RS
.IP "\(bu" 4 .IP "\(bu" 4
signature algorithm, signature algorithm,
. .
@ -272,7 +277,7 @@ displaying DNS Certification Authority Authorization resource record
. .
.IP "\(bu" 4 .IP "\(bu" 4
Certificate Transparency info (if provided by server)\. Certificate Transparency info (if provided by server)\.
.RE .
.IP "" 0 .IP "" 0
. .
@ -406,7 +411,7 @@ Security headers (X\-Frame\-Options, X\-XSS\-Protection, Expect\-CT,\.\.\. , CSP
.IP "" 0 .IP "" 0
. .
.P .P
Please note that in testssl\.sh 3,0 you can still use \fBrfc\fR instead of \fBiana\fR and \fBno\-rfc\fR instead of \fBno\-iana\fR but it\'ll disappear after 3\.0\. Please note that in testssl\.sh 3\.0 you can still use \fBrfc\fR instead of \fBiana\fR and \fBno\-rfc\fR instead of \fBno\-iana\fR but it\'ll disappear after 3\.0\.
. .
.P .P
\fB\-\-show\-each\fR This is an option for all wide modes only: it displays all ciphers tested \-\- not only succeeded ones\. \fBSHOW_EACH_C\fR is your friend if you prefer to set this via the shell environment\. \fB\-\-show\-each\fR This is an option for all wide modes only: it displays all ciphers tested \-\- not only succeeded ones\. \fBSHOW_EACH_C\fR is your friend if you prefer to set this via the shell environment\.
@ -440,6 +445,9 @@ whole 9 yards
. .
.IP "" 0 .IP "" 0
. .
.P
\fB\-\-disable\-rating\fR disables rating\. Rating automatically gets disabled, to not give a wrong or misleading grade, when not all required functions are executed (e\.g when checking for a single vulnerabilities)\.
.
.SS "FILE OUTPUT OPTIONS" .SS "FILE OUTPUT OPTIONS"
\fB\-\-log, \-\-logging\fR Logs stdout also to \fB${NODE}\-p${port}${YYYYMMDD\-HHMM}\.log\fR in current working directory of the shell\. Depending on the color output option (see above) the output file will contain color and other markup escape codes, unless you specify \fB\-\-color 0\fR too\. \fBcat\fR and \-\- if properly configured \fBless\fR \-\- will show the output properly formatted on your terminal\. The output shows a banner with the almost the same information as on the screen\. In addition it shows the command line of the testssl\.sh instance\. Please note that the resulting log file is formatted according to the width of your screen while running testssl\.sh\. You can override the width with the environment variable TERM_WIDTH\. \fB\-\-log, \-\-logging\fR Logs stdout also to \fB${NODE}\-p${port}${YYYYMMDD\-HHMM}\.log\fR in current working directory of the shell\. Depending on the color output option (see above) the output file will contain color and other markup escape codes, unless you specify \fB\-\-color 0\fR too\. \fBcat\fR and \-\- if properly configured \fBless\fR \-\- will show the output properly formatted on your terminal\. The output shows a banner with the almost the same information as on the screen\. In addition it shows the command line of the testssl\.sh instance\. Please note that the resulting log file is formatted according to the width of your screen while running testssl\.sh\. You can override the width with the environment variable TERM_WIDTH\.
. .
@ -623,6 +631,30 @@ MAX_HEADER_FAIL: A number which tells testssl\.sh how often a HTTP GET request o
. .
.IP "" 0 .IP "" 0
. .
.SS "RATING"
This program has a near\-complete implementation of SSL Labs\'s \'SSL Server Rating Guide \fIhttps://github\.com/ssllabs/research/wiki/SSL\-Server\-Rating\-Guide\fR\'\.
.
.P
This is \fInot\fR a 100% reimplementation of the SSL Lab\'s SSL Server Test \fIhttps://www\.ssllabs\.com/ssltest/analyze\.html\fR, but an implementation of the above rating specification, slight discrepancies may occur\. Please note that for now we stick to the SSL Labs rating as good as possible\. We are not responsible for their rating\. Before filing issues please inspect their Rating Guide\.
.
.P
Disclaimer: Having a good grade is \fBNOT\fR necessarily equal to having good security! Don\'t start a competition for the best grade, at least not without monitoring the client handshakes and not without adding a portion of good sense to it\.
.
.P
As of writing, these checks are missing: * GOLDENDOODLE \- should be graded \fBF\fR if vulnerable * Insecure renegotiation \- should be graded \fBF\fR if vulnerable * Padding oracle in AES\-NI CBC MAC check (CVE\-2016\-2107) \- should be graded \fBF\fR if vulnerable * Sleeping POODLE \- should be graded \fBF\fR if vulnerable * Zero Length Padding Oracle (CVE\-2019\-1559) \- should be graded \fBF\fR if vulnerable * Zombie POODLE \- should be graded \fBF\fR if vulnerable * All remaining old Symantec PKI certificates are distrusted \- should be graded \fBT\fR * Symantec certificates issued before June 2016 are distrusted \- should be graded \fBT\fR * ! A reading of DH params \- should give correct points in \fBset_key_str_score()\fR * Anonymous key exchange \- should give \fB0\fR points in \fBset_key_str_score()\fR * Exportable key exchange \- should give \fB40\fR points in \fBset_key_str_score()\fR * Weak key (Debian OpenSSL Flaw) \- should give \fB0\fR points in \fBset_key_str_score()\fR
.
.P
To implement a new grading cap, simply call the \fBset_grade_cap()\fR function, with the grade and a reason: \fBbash set_grade_cap "D" "Vulnerable to documentation"\fR To implement a new grade warning, simply call the \fBset_grade_warning()\fR function, with a message: \fBbash set_grade_warning "Documentation is always right"\fR
.
.P
When implementing a new check (be it vulnerability or not) that sets grade caps, the \fBset_rating_state()\fR has to be updated (i\.e\. the \fB$do_mycheck\fR variable\-name has to be added to the loop, and \fB$nr_enabled\fR if\-statement has to be incremented)
.
.P
The \fBset_rating_state()\fR automatically disables ratinng, if all the required checks are \fInot\fR enabled\. This is to prevent giving out a misleading or wrong grade\.
.
.P
When a new revision of the rating specification comes around, the following has to be done: * New grade caps has to be either: 1\. Added to the script wherever relevant, or 2\. Added to the above list of missing checks (if \fIi\.\fR is not possible) * New grade warnings has to be added wherever relevant * The revision output in \fBrun_rating()\fR function has to updated
.
.SH "EXAMPLES" .SH "EXAMPLES"
. .
.nf .nf
@ -632,7 +664,7 @@ MAX_HEADER_FAIL: A number which tells testssl\.sh how often a HTTP GET request o
.fi .fi
. .
.P .P
does a default run on https://testssl\.sh (protocols, standard cipher lists, FS, server preferences, server defaults, vulnerabilities, testing all known 370 ciphers, client simulation\. does a default run on https://testssl\.sh (protocols, standard cipher lists, server\'s cipher preferences, forward secrecy, server defaults, vulnerabilities, client simulation, and rating\.
. .
.IP "" 4 .IP "" 4
. .

View File

@ -121,9 +121,9 @@ linked OpenSSL binaries for major operating systems are supplied in <code>./bin/
<p>1) SSL/TLS protocol check</p> <p>1) SSL/TLS protocol check</p>
<p>2) standard cipher categories to give you upfront an idea for the ciphers supported</p> <p>2) standard cipher categories</p>
<p>3) server's cipher preferences (server order)</p> <p>3) server's cipher preferences (server order?)</p>
<p>4) forward secrecy: ciphers and elliptical curves</p> <p>4) forward secrecy: ciphers and elliptical curves</p>
@ -135,6 +135,8 @@ linked OpenSSL binaries for major operating systems are supplied in <code>./bin/
<p>8) client simulation</p> <p>8) client simulation</p>
<p>9) rating</p>
<h2 id="OPTIONS-AND-PARAMETERS">OPTIONS AND PARAMETERS</h2> <h2 id="OPTIONS-AND-PARAMETERS">OPTIONS AND PARAMETERS</h2>
<p>Options are either short or long options. Any long or short option requiring a value can be called with or without an equal sign. E.g. <code>testssl.sh -t=smtp --wide --openssl=/usr/bin/openssl &lt;URI></code> (short options with equal sign) is equivalent to <code>testssl.sh --starttls smtp --wide --openssl /usr/bin/openssl &lt;URI></code> (long option without equal sign). Some command line options can also be preset via ENV variables. <code>WIDE=true OPENSSL=/usr/bin/openssl testssl.sh --starttls=smtp &lt;URI></code> would be the equivalent to the aforementioned examples. Preference has the command line over any environment variables.</p> <p>Options are either short or long options. Any long or short option requiring a value can be called with or without an equal sign. E.g. <code>testssl.sh -t=smtp --wide --openssl=/usr/bin/openssl &lt;URI></code> (short options with equal sign) is equivalent to <code>testssl.sh --starttls smtp --wide --openssl /usr/bin/openssl &lt;URI></code> (long option without equal sign). Some command line options can also be preset via ENV variables. <code>WIDE=true OPENSSL=/usr/bin/openssl testssl.sh --starttls=smtp &lt;URI></code> would be the equivalent to the aforementioned examples. Preference has the command line over any environment variables.</p>
@ -183,7 +185,7 @@ The same can be achieved by setting the environment variable <code>WARNINGS</cod
<p><code>--openssl-timeout &lt;seconds></code> This is especially useful for all connects using openssl and practically useful for mass testing. It avoids the openssl connect to hang for ~2 minutes. The expected parameter <code>seconds</code> instructs testssl.sh to wait before the openssl connect will be terminated. The option is only available if your OS has a timeout binary installed. As there are different implementations of <code>timeout</code>: It automatically calls the binary with the right parameters. OPENSSL_TIMEOUT is the equivalent environment variable.</p> <p><code>--openssl-timeout &lt;seconds></code> This is especially useful for all connects using openssl and practically useful for mass testing. It avoids the openssl connect to hang for ~2 minutes. The expected parameter <code>seconds</code> instructs testssl.sh to wait before the openssl connect will be terminated. The option is only available if your OS has a timeout binary installed. As there are different implementations of <code>timeout</code>: It automatically calls the binary with the right parameters. OPENSSL_TIMEOUT is the equivalent environment variable.</p>
<p><code>--basicauth &lt;user:pass></code> This can be set to provide HTTP basic auth credentials which are used during checks for security headers. BASICAUTH is the ENV variable you can use instead.</p> <p><code>--basicauth &lt;user:pass&gt;</code> This can be set to provide HTTP basic auth credentials which are used during checks for security headers. BASICAUTH is the ENV variable you can use instead.</p>
<h3 id="SPECIAL-INVOCATIONS">SPECIAL INVOCATIONS</h3> <h3 id="SPECIAL-INVOCATIONS">SPECIAL INVOCATIONS</h3>
@ -355,7 +357,7 @@ Also for multiple server certificates are being checked for as well as for the c
</ul> </ul>
<p>Please note that in testssl.sh 3,0 you can still use <code>rfc</code> instead of <code>iana</code> and <code>no-rfc</code> instead of <code>no-iana</code> but it'll disappear after 3.0.</p> <p>Please note that in testssl.sh 3.0 you can still use <code>rfc</code> instead of <code>iana</code> and <code>no-rfc</code> instead of <code>no-iana</code> but it'll disappear after 3.0.</p>
<p><code>--show-each</code> This is an option for all wide modes only: it displays all ciphers tested -- not only succeeded ones. <code>SHOW_EACH_C</code> is your friend if you prefer to set this via the shell environment.</p> <p><code>--show-each</code> This is an option for all wide modes only: it displays all ciphers tested -- not only succeeded ones. <code>SHOW_EACH_C</code> is your friend if you prefer to set this via the shell environment.</p>
@ -375,6 +377,9 @@ Also for multiple server certificates are being checked for as well as for the c
</ol> </ol>
<p><code>--disable-rating</code> disables rating.
Rating automatically gets disabled, to not give a wrong or misleading grade, when not all required functions are executed (e.g when checking for a single vulnerabilities).</p>
<h3 id="FILE-OUTPUT-OPTIONS">FILE OUTPUT OPTIONS</h3> <h3 id="FILE-OUTPUT-OPTIONS">FILE OUTPUT OPTIONS</h3>
<p><code>--log, --logging</code> Logs stdout also to <code>${NODE}-p${port}${YYYYMMDD-HHMM}.log</code> in current working directory of the shell. Depending on the color output option (see above) the output file will contain color and other markup escape codes, unless you specify <code>--color 0</code> too. <code>cat</code> and -- if properly configured <code>less</code> -- will show the output properly formatted on your terminal. The output shows a banner with the almost the same information as on the screen. In addition it shows the command line of the testssl.sh instance. Please note that the resulting log file is formatted according to the width of your screen while running testssl.sh. You can override the width with the environment variable TERM_WIDTH.</p> <p><code>--log, --logging</code> Logs stdout also to <code>${NODE}-p${port}${YYYYMMDD-HHMM}.log</code> in current working directory of the shell. Depending on the color output option (see above) the output file will contain color and other markup escape codes, unless you specify <code>--color 0</code> too. <code>cat</code> and -- if properly configured <code>less</code> -- will show the output properly formatted on your terminal. The output shows a banner with the almost the same information as on the screen. In addition it shows the command line of the testssl.sh instance. Please note that the resulting log file is formatted according to the width of your screen while running testssl.sh. You can override the width with the environment variable TERM_WIDTH.</p>
@ -473,12 +478,61 @@ Also for multiple server certificates are being checked for as well as for the c
</ul> </ul>
<h3 id="RATING">RATING</h3>
<p>This program has a near-complete implementation of SSL Labs's '<a href="https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide">SSL Server Rating Guide</a>'.</p>
<p>This is <em>not</em> a 100% reimplementation of the <a href="https://www.ssllabs.com/ssltest/analyze.html">SSL Lab's SSL Server Test</a>, but an implementation of the above rating specification, slight discrepancies may occur. Please note that for now we stick to the SSL Labs rating as good as possible. We are not responsible for their rating. Before filing issues please inspect their Rating Guide.</p>
<p>Disclaimer: Having a good grade is <strong>NOT</strong> necessarily equal to having good security! Don't start a competition for the best grade, at least not without monitoring the client handshakes and not without adding a portion of good sense to it.</p>
<p>As of writing, these checks are missing:
* GOLDENDOODLE - should be graded <strong>F</strong> if vulnerable
* Insecure renegotiation - should be graded <strong>F</strong> if vulnerable
* Padding oracle in AES-NI CBC MAC check (CVE-2016-2107) - should be graded <strong>F</strong> if vulnerable
* Sleeping POODLE - should be graded <strong>F</strong> if vulnerable
* Zero Length Padding Oracle (CVE-2019-1559) - should be graded <strong>F</strong> if vulnerable
* Zombie POODLE - should be graded <strong>F</strong> if vulnerable
* All remaining old Symantec PKI certificates are distrusted - should be graded <strong>T</strong>
* Symantec certificates issued before June 2016 are distrusted - should be graded <strong>T</strong>
* ! A reading of DH params - should give correct points in <code>set_key_str_score()</code>
* Anonymous key exchange - should give <strong>0</strong> points in <code>set_key_str_score()</code>
* Exportable key exchange - should give <strong>40</strong> points in <code>set_key_str_score()</code>
* Weak key (Debian OpenSSL Flaw) - should give <strong>0</strong> points in <code>set_key_str_score()</code></p>
<h4 id="Implementing-new-grades-caps-or-warnings">Implementing new grades caps or -warnings</h4>
<p>To implement a new grading cap, simply call the <code>set_grade_cap()</code> function, with the grade and a reason:
<code>bash
set_grade_cap "D" "Vulnerable to documentation"
</code>
To implement a new grade warning, simply call the <code>set_grade_warning()</code> function, with a message:
<code>bash
set_grade_warning "Documentation is always right"
</code></p>
<h4 id="Implementing-a-new-check-which-contains-grade-caps">Implementing a new check which contains grade caps</h4>
<p>When implementing a new check (be it vulnerability or not) that sets grade caps, the <code>set_rating_state()</code> has to be updated (i.e. the <code>$do_mycheck</code> variable-name has to be added to the loop, and <code>$nr_enabled</code> if-statement has to be incremented)</p>
<p>The <code>set_rating_state()</code> automatically disables ratinng, if all the required checks are <em>not</em> enabled.
This is to prevent giving out a misleading or wrong grade.</p>
<h4 id="Implementing-a-new-revision">Implementing a new revision</h4>
<p>When a new revision of the rating specification comes around, the following has to be done:
* New grade caps has to be either:
1. Added to the script wherever relevant, or
2. Added to the above list of missing checks (if <em>i.</em> is not possible)
* New grade warnings has to be added wherever relevant
* The revision output in <code>run_rating()</code> function has to updated</p>
<h2 id="EXAMPLES">EXAMPLES</h2> <h2 id="EXAMPLES">EXAMPLES</h2>
<pre><code> testssl.sh testssl.sh <pre><code> testssl.sh testssl.sh
</code></pre> </code></pre>
<p>does a default run on https://testssl.sh (protocols, standard cipher lists, FS, server preferences, server defaults, vulnerabilities, testing all known 370 ciphers, client simulation.</p> <p>does a default run on https://testssl.sh (protocols, standard cipher lists, server's cipher preferences, forward secrecy, server defaults, vulnerabilities, client simulation, and rating.</p>
<pre><code> testssl.sh testssl.net:443 <pre><code> testssl.sh testssl.net:443
</code></pre> </code></pre>
@ -604,7 +658,7 @@ where to get this program from.</p>
<ol class='man-decor man-foot man foot'> <ol class='man-decor man-foot man foot'>
<li class='tl'></li> <li class='tl'></li>
<li class='tc'>January 2020</li> <li class='tc'>May 2020</li>
<li class='tr'>testssl(1)</li> <li class='tr'>testssl(1)</li>
</ol> </ol>

View File

@ -40,7 +40,7 @@ linked OpenSSL binaries for major operating systems are supplied in `./bin/`.
1) SSL/TLS protocol check 1) SSL/TLS protocol check
2) standard cipher categories to give you upfront an idea for the ciphers supported 2) standard cipher categories
3) server's cipher preferences (server order?) 3) server's cipher preferences (server order?)
@ -52,8 +52,13 @@ linked OpenSSL binaries for major operating systems are supplied in `./bin/`.
7) vulnerabilities 7) vulnerabilities
8) testing each of 370 preconfigured ciphers
8) client simulation 8) client simulation
9) rating
## OPTIONS AND PARAMETERS ## OPTIONS AND PARAMETERS
@ -265,7 +270,7 @@ Also for multiple server certificates are being checked for as well as for the c
* `no-openssl`: don't display the OpenSSL cipher suite name, display IANA names only. * `no-openssl`: don't display the OpenSSL cipher suite name, display IANA names only.
* `no-iana`: don't display the IANA cipher suite name, display OpenSSL names only. * `no-iana`: don't display the IANA cipher suite name, display OpenSSL names only.
Please note that in testssl.sh 3,0 you can still use `rfc` instead of `iana` and `no-rfc` instead of `no-iana` but it'll disappear after 3.0. Please note that in testssl.sh 3.0 you can still use `rfc` instead of `iana` and `no-rfc` instead of `no-iana` but it'll disappear after 3.0.
`--show-each` This is an option for all wide modes only: it displays all ciphers tested -- not only succeeded ones. `SHOW_EACH_C` is your friend if you prefer to set this via the shell environment. `--show-each` This is an option for all wide modes only: it displays all ciphers tested -- not only succeeded ones. `SHOW_EACH_C` is your friend if you prefer to set this via the shell environment.
@ -284,6 +289,8 @@ Please note that in testssl.sh 3,0 you can still use `rfc` instead of `iana` and
5. display bytes received via sockets 5. display bytes received via sockets
6. whole 9 yards 6. whole 9 yards
`--disable-rating` disables rating.
Rating automatically gets disabled, to not give a wrong or misleading grade, when not all required functions are executed (e.g when checking for a single vulnerabilities).
### FILE OUTPUT OPTIONS ### FILE OUTPUT OPTIONS
@ -381,13 +388,55 @@ Except the environment variables mentioned above which can replace command line
* MAX_OSSL_FAIL: A number which tells testssl.sh how often an OpenSSL s_client connect may fail before the program gives up and terminates. The default is 2. You can increase it to a higher value if you frequently see a message like *Fatal error: repeated TCP connect problems, giving up*. * MAX_OSSL_FAIL: A number which tells testssl.sh how often an OpenSSL s_client connect may fail before the program gives up and terminates. The default is 2. You can increase it to a higher value if you frequently see a message like *Fatal error: repeated TCP connect problems, giving up*.
* MAX_HEADER_FAIL: A number which tells testssl.sh how often a HTTP GET request over OpenSSL may return an empty file before the program gives up and terminates. The default is 3. Also here you can incerase the threshold when you spot messages like *Fatal error: repeated HTTP header connect problems, doesn't make sense to continue*. * MAX_HEADER_FAIL: A number which tells testssl.sh how often a HTTP GET request over OpenSSL may return an empty file before the program gives up and terminates. The default is 3. Also here you can incerase the threshold when you spot messages like *Fatal error: repeated HTTP header connect problems, doesn't make sense to continue*.
### RATING
This program has a near-complete implementation of SSL Labs's '[SSL Server Rating Guide](https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide)'.
This is *not* a 100% reimplementation of the [SSL Lab's SSL Server Test](https://www.ssllabs.com/ssltest/analyze.html), but an implementation of the above rating specification, slight discrepancies may occur. Please note that for now we stick to the SSL Labs rating as good as possible. We are not responsible for their rating. Before filing issues please inspect their Rating Guide.
Disclaimer: Having a good grade is **NOT** necessarily equal to having good security! Don't start a competition for the best grade, at least not without monitoring the client handshakes and not without adding a portion of good sense to it.
As of writing, these checks are missing:
* GOLDENDOODLE - should be graded **F** if vulnerable
* Insecure renegotiation - should be graded **F** if vulnerable
* Padding oracle in AES-NI CBC MAC check (CVE-2016-2107) - should be graded **F** if vulnerable
* Sleeping POODLE - should be graded **F** if vulnerable
* Zero Length Padding Oracle (CVE-2019-1559) - should be graded **F** if vulnerable
* Zombie POODLE - should be graded **F** if vulnerable
* All remaining old Symantec PKI certificates are distrusted - should be graded **T**
* Symantec certificates issued before June 2016 are distrusted - should be graded **T**
* ! A reading of DH params - should give correct points in `set_key_str_score()`
* Anonymous key exchange - should give **0** points in `set_key_str_score()`
* Exportable key exchange - should give **40** points in `set_key_str_score()`
* Weak key (Debian OpenSSL Flaw) - should give **0** points in `set_key_str_score()`
#### Implementing new grades caps or -warnings
To implement a new grading cap, simply call the `set_grade_cap()` function, with the grade and a reason:
```bash
set_grade_cap "D" "Vulnerable to documentation"
```
To implement a new grade warning, simply call the `set_grade_warning()` function, with a message:
```bash
set_grade_warning "Documentation is always right"
```
#### Implementing a new check which contains grade caps
When implementing a new check (be it vulnerability or not) that sets grade caps, the `set_rating_state()` has to be updated (i.e. the `$do_mycheck` variable-name has to be added to the loop, and `$nr_enabled` if-statement has to be incremented)
The `set_rating_state()` automatically disables ratinng, if all the required checks are *not* enabled.
This is to prevent giving out a misleading or wrong grade.
#### Implementing a new revision
When a new revision of the rating specification comes around, the following has to be done:
* New grade caps has to be either:
1. Added to the script wherever relevant, or
2. Added to the above list of missing checks (if *i.* is not possible)
* New grade warnings has to be added wherever relevant
* The revision output in `run_rating()` function has to updated
## EXAMPLES ## EXAMPLES
testssl.sh testssl.sh testssl.sh testssl.sh
does a default run on https://testssl.sh (protocols, standard cipher lists, FS, server preferences, server defaults, vulnerabilities, testing all known 370 ciphers, client simulation. does a default run on https://testssl.sh (protocols, standard cipher lists, server's cipher preferences, forward secrecy, server defaults, vulnerabilities, client simulation, and rating.
testssl.sh testssl.net:443 testssl.sh testssl.net:443
@ -506,4 +555,3 @@ Probably. Current known ones and interface for filing new ones: https://testssl.
## SEE ALSO ## SEE ALSO
`ciphers`(1), `openssl`(1), `s_client`(1), `x509`(1), `verify`(1), `ocsp`(1), `crl`(1), `bash`(1) and the websites https://testssl.sh/ and https://github.com/drwetter/testssl.sh/ . `ciphers`(1), `openssl`(1), `s_client`(1), `x509`(1), `verify`(1), `ocsp`(1), `crl`(1), `bash`(1) and the websites https://testssl.sh/ and https://github.com/drwetter/testssl.sh/ .

View File

@ -140,6 +140,7 @@ declare CMDLINE
CMDLINE_PARSED="" # This makes sure we don't let early fatal() write into files when files aren't created yet CMDLINE_PARSED="" # This makes sure we don't let early fatal() write into files when files aren't created yet
declare -r -a CMDLINE_ARRAY=("$@") # When performing mass testing, the child processes need to be sent the declare -r -a CMDLINE_ARRAY=("$@") # When performing mass testing, the child processes need to be sent the
declare -a MASS_TESTING_CMDLINE # command line in the form of an array (see #702 and https://mywiki.wooledge.org/BashFAQ/050). declare -a MASS_TESTING_CMDLINE # command line in the form of an array (see #702 and https://mywiki.wooledge.org/BashFAQ/050).
declare -a SKIP_TESTS=() # This array hold the checks to be skipped
########### Defining (and presetting) variables which can be changed ########### Defining (and presetting) variables which can be changed
@ -374,6 +375,13 @@ SERVER_COUNTER=0 # Counter for multiple servers
TLS_LOW_BYTE="" # For "secret" development stuff, see -q below TLS_LOW_BYTE="" # For "secret" development stuff, see -q below
HEX_CIPHER="" # " HEX_CIPHER="" # "
GRADE_CAP="" # Keeps track of the current grading cap
GRADE_CAP_REASONS=() # Keeps track of all the reasons why grades are capped
GRADE_WARNINGS=() # Keeps track of all the grade warnings
KEY_EXCH_SCORE=0 # Keeps track of the score for category 2 "Key Exchange Strength"
CIPH_STR_BEST=0 # Keeps track of the best bit size for category 3 "Cipher Strength"
CIPH_STR_WORST=100000 # Keeps track of the worst bit size for category 3 "Cipher Strength"
# Intentionally set very high, so it can be set to 0, if necessary
########### Global variables for parallel mass testing ########### Global variables for parallel mass testing
# #
@ -984,10 +992,102 @@ f5_port_decode() {
echo $((16#${tmp:2:2}${tmp:0:2})) # reverse order and convert it from hex to dec echo $((16#${tmp:2:2}${tmp:0:2})) # reverse order and convert it from hex to dec
} }
###### START ServerHello/OpenSSL/F5 function definitions ###### ###### END universal helper function definitions ######
###### END helper function definitions ######
###### START scoring function definitions ######
# Sets the grade cap to ARG1
# arg1: A grade to set ("A", "B", "C", "D", "E", "F", "M", or "T")
# arg2: A reason why (e.g. "Vulnerable to CRIME")
set_grade_cap() {
"$do_rating" || return 0
GRADE_CAP_REASONS+=("Grade capped to $1. $2")
# Always set special attributes. These are hard caps, due to name mismatch or cert being invalid
if [[ "$1" == T || "$1" == M ]]; then
GRADE_CAP="$1"
# Only keep track of the lowest grade cap, since a higher grade cap wont do anything (F = lowest, A = highest)
elif [[ ! "$GRADE_CAP" > "$1" ]]; then
GRADE_CAP="$1"
fi
return 0
}
# Sets a grade warning, as specified by the grade specification
# arg1: A warning message
set_grade_warning() {
"$do_rating" || return 0
GRADE_WARNINGS+=("$1")
return 0
}
# Sets the score for Category 2 (Key Exchange Strength)
# arg1: Short key algorithm ("EC", "DH", "RSA", ...) # Can die, when we get DH_PARAMs
# arg2: key size (number of bits)
set_key_str_score() {
local type=$1
local size=$2
"$do_rating" || return 0
# TODO: We need to get the size of DH params (follows the same table as the "else" clause)
# For now, verifying the key size will do...
if [[ $type == EC || $type == DH ]]; then
if [[ $size -lt 110 ]]; then
let KEY_EXCH_SCORE=20
set_grade_cap "F" "Using an insecure key"
elif [[ $size -lt 123 ]]; then
let KEY_EXCH_SCORE=40
set_grade_cap "F" "Using an insecure key"
elif [[ $size -lt 163 ]]; then
let KEY_EXCH_SCORE=80
set_grade_cap "B" "Using a weak key"
elif [[ $size -lt 225 ]]; then
let KEY_EXCH_SCORE=90
elif [[ $size -ge 225 ]]; then
let KEY_EXCH_SCORE=100
else
let KEY_EXCH_SCORE=0
set_grade_cap "F" "Using an insecure key"
fi
else
if [[ $size -lt 512 ]]; then
let KEY_EXCH_SCORE=20
set_grade_cap "F" "Using an insecure key"
elif [[ $size -lt 1024 ]]; then
let KEY_EXCH_SCORE=40
set_grade_cap "F" "Using an insecure key"
elif [[ $size -lt 2048 ]]; then
let KEY_EXCH_SCORE=80
set_grade_cap "B" "Using a weak key"
elif [[ $size -lt 4096 ]]; then
let KEY_EXCH_SCORE=90
elif [[ $size -ge 4096 ]]; then
let KEY_EXCH_SCORE=100
else
let KEY_EXCH_SCORE=0
set_grade_cap "F" "Using an insecure key"
fi
fi
return 0
}
# Sets the best and worst bit size key, used to grade Category 3 (Cipher Strength)
# This function itself doesn't actually set a score; its just in the name to keep it logical (score == grading function)
# arg1: a bit size
set_ciph_str_score() {
local size=$1
"$do_rating" || return 0
[[ $size -gt $CIPH_STR_BEST ]] && let CIPH_STR_BEST=$size
[[ $size -lt $CIPH_STR_WORST ]] && let CIPH_STR_WORST=$size
return 0
}
###### END scoring function definitions ######
##################### START output file formatting functions ######################### ##################### START output file formatting functions #########################
#################### START JSON file functions #################### #################### START JSON file functions ####################
@ -1024,6 +1124,7 @@ fileout_json_section() {
9) echo -e ",\n \"vulnerabilities\" : [" ;; 9) echo -e ",\n \"vulnerabilities\" : [" ;;
10) echo -e ",\n \"cipherTests\" : [" ;; 10) echo -e ",\n \"cipherTests\" : [" ;;
11) echo -e ",\n \"browserSimulations\": [" ;; 11) echo -e ",\n \"browserSimulations\": [" ;;
12) echo -e ",\n \"rating\" : [" ;;
*) echo "invalid section" ;; *) echo "invalid section" ;;
esac esac
} }
@ -1758,12 +1859,14 @@ check_revocation_crl() {
out ", " out ", "
pr_svrty_critical "revoked" pr_svrty_critical "revoked"
fileout "$jsonID" "CRITICAL" "revoked" fileout "$jsonID" "CRITICAL" "revoked"
set_grade_cap "T" "Certificate revoked"
else else
retcode="$(verify_retcode_helper "$retcode")" retcode="$(verify_retcode_helper "$retcode")"
out " $retcode" out " $retcode"
retcode="${retcode#(}" retcode="${retcode#(}"
retcode="${retcode%)}" retcode="${retcode%)}"
fileout "$jsonID" "WARN" "$retcode" fileout "$jsonID" "WARN" "$retcode"
set_grade_cap "T" "Issues with certificate $retcode"
if [[ $DEBUG -ge 2 ]]; then if [[ $DEBUG -ge 2 ]]; then
outln outln
cat "${tmpfile%%.crl}.err" cat "${tmpfile%%.crl}.err"
@ -1825,6 +1928,7 @@ check_revocation_ocsp() {
out ", " out ", "
pr_svrty_critical "revoked" pr_svrty_critical "revoked"
fileout "$jsonID" "CRITICAL" "revoked" fileout "$jsonID" "CRITICAL" "revoked"
set_grade_cap "T" "Certificate revoked"
else else
out ", " out ", "
pr_warning "error querying OCSP responder" pr_warning "error querying OCSP responder"
@ -2444,15 +2548,18 @@ run_hsts() {
if [[ $hsts_age_days -eq -1 ]]; then if [[ $hsts_age_days -eq -1 ]]; then
pr_svrty_medium "misconfiguration: HSTS max-age (recommended > $HSTS_MIN seconds = $((HSTS_MIN/86400)) days ) is required but missing" pr_svrty_medium "misconfiguration: HSTS max-age (recommended > $HSTS_MIN seconds = $((HSTS_MIN/86400)) days ) is required but missing"
fileout "${jsonID}_time" "MEDIUM" "misconfiguration, parameter max-age (recommended > $HSTS_MIN seconds = $((HSTS_MIN/86400)) days) missing" fileout "${jsonID}_time" "MEDIUM" "misconfiguration, parameter max-age (recommended > $HSTS_MIN seconds = $((HSTS_MIN/86400)) days) missing"
set_grade_cap "A" "HSTS max-age is misconfigured"
elif [[ $hsts_age_sec -eq 0 ]]; then elif [[ $hsts_age_sec -eq 0 ]]; then
pr_svrty_low "HSTS max-age is set to 0. HSTS is disabled" pr_svrty_low "HSTS max-age is set to 0. HSTS is disabled"
fileout "${jsonID}_time" "LOW" "0. HSTS is disabled" fileout "${jsonID}_time" "LOW" "0. HSTS is disabled"
set_grade_cap "A" "HSTS is disabled"
elif [[ $hsts_age_sec -gt $HSTS_MIN ]]; then elif [[ $hsts_age_sec -gt $HSTS_MIN ]]; then
pr_svrty_good "$hsts_age_days days" ; out "=$hsts_age_sec s" pr_svrty_good "$hsts_age_days days" ; out "=$hsts_age_sec s"
fileout "${jsonID}_time" "OK" "$hsts_age_days days (=$hsts_age_sec seconds) > $HSTS_MIN seconds" fileout "${jsonID}_time" "OK" "$hsts_age_days days (=$hsts_age_sec seconds) > $HSTS_MIN seconds"
else else
pr_svrty_medium "$hsts_age_sec s = $hsts_age_days days is too short ( > $HSTS_MIN seconds recommended)" pr_svrty_medium "$hsts_age_sec s = $hsts_age_days days is too short ( > $HSTS_MIN seconds recommended)"
fileout "${jsonID}_time" "MEDIUM" "max-age too short. $hsts_age_days days (=$hsts_age_sec seconds) <= $HSTS_MIN seconds" fileout "${jsonID}_time" "MEDIUM" "max-age too short. $hsts_age_days days (=$hsts_age_sec seconds) <= $HSTS_MIN seconds"
set_grade_cap "A" "HSTS max-age is too short"
fi fi
if includeSubDomains "$TMPFILE"; then if includeSubDomains "$TMPFILE"; then
fileout "${jsonID}_subdomains" "OK" "includes subdomains" fileout "${jsonID}_subdomains" "OK" "includes subdomains"
@ -2470,6 +2577,7 @@ run_hsts() {
else else
pr_svrty_low "not offered" pr_svrty_low "not offered"
fileout "$jsonID" "LOW" "not offered" fileout "$jsonID" "LOW" "not offered"
set_grade_cap "A" "HSTS is not offered"
fi fi
outln outln
@ -2505,6 +2613,7 @@ run_hpkp() {
first_hpkp_header="$(grep -ai '^Public-Key-Pins:' $TMPFILE | head -1)" first_hpkp_header="$(grep -ai '^Public-Key-Pins:' $TMPFILE | head -1)"
# we only evaluate the keys here, unless they a not present # we only evaluate the keys here, unless they a not present
out "$spaces " out "$spaces "
set_grade_cap "A" "Problems with HTTP Public Key Pinning (HPKP)"
elif [[ $(grep -aci '^Public-Key-Pins-Report-Only:' $TMPFILE) -gt 1 ]]; then elif [[ $(grep -aci '^Public-Key-Pins-Report-Only:' $TMPFILE) -gt 1 ]]; then
outln "Multiple HPKP headers (Report-Only), taking first line" outln "Multiple HPKP headers (Report-Only), taking first line"
fileout "HPKP_notice" "INFO" "multiple Public-Key-Pins-Report-Only in header" fileout "HPKP_notice" "INFO" "multiple Public-Key-Pins-Report-Only in header"
@ -2531,6 +2640,7 @@ run_hpkp() {
if [[ $hpkp_nr_keys -eq 1 ]]; then if [[ $hpkp_nr_keys -eq 1 ]]; then
pr_svrty_high "Only one key pinned (NOT ok), means the site may become unavailable in the future, " pr_svrty_high "Only one key pinned (NOT ok), means the site may become unavailable in the future, "
fileout "HPKP_SPKIs" "HIGH" "Only one key pinned" fileout "HPKP_SPKIs" "HIGH" "Only one key pinned"
set_grade_cap "A" "Problems with HTTP Public Key Pinning (HPKP)"
else else
pr_svrty_good "$hpkp_nr_keys" pr_svrty_good "$hpkp_nr_keys"
out " keys, " out " keys, "
@ -2551,6 +2661,7 @@ run_hpkp() {
out "$hpkp_age_sec s = " out "$hpkp_age_sec s = "
pr_svrty_medium "$hpkp_age_days days (< $HPKP_MIN s = $((HPKP_MIN / 86400)) days is not good enough)" pr_svrty_medium "$hpkp_age_days days (< $HPKP_MIN s = $((HPKP_MIN / 86400)) days is not good enough)"
fileout "HPKP_age" "MEDIUM" "age is set to $hpkp_age_days days ($hpkp_age_sec sec) < $HPKP_MIN s = $((HPKP_MIN / 86400)) days is not good enough." fileout "HPKP_age" "MEDIUM" "age is set to $hpkp_age_days days ($hpkp_age_sec sec) < $HPKP_MIN s = $((HPKP_MIN / 86400)) days is not good enough."
set_grade_cap "A" "Problems with HTTP Public Key Pinning (HPKP)"
fi fi
if includeSubDomains "$TMPFILE"; then if includeSubDomains "$TMPFILE"; then
@ -2708,11 +2819,13 @@ run_hpkp() {
"$has_backup_spki" && out "$spaces" # we had a few lines with backup SPKIs already "$has_backup_spki" && out "$spaces" # we had a few lines with backup SPKIs already
prln_svrty_high " No matching key for SPKI found " prln_svrty_high " No matching key for SPKI found "
fileout "HPKP_SPKImatch" "HIGH" "None of the SPKI match your host certificate, intermediate CA or known root CAs. Bricked site?" fileout "HPKP_SPKImatch" "HIGH" "None of the SPKI match your host certificate, intermediate CA or known root CAs. Bricked site?"
set_grade_cap "A" "Problems with HTTP Public Key Pinning (HPKP)"
fi fi
if ! "$has_backup_spki"; then if ! "$has_backup_spki"; then
prln_svrty_high " No backup keys found. Loss/compromise of the currently pinned key(s) will lead to bricked site. " prln_svrty_high " No backup keys found. Loss/compromise of the currently pinned key(s) will lead to bricked site. "
fileout "HPKP_backup" "HIGH" "No backup keys found. Loss/compromise of the currently pinned key(s) will lead to bricked site." fileout "HPKP_backup" "HIGH" "No backup keys found. Loss/compromise of the currently pinned key(s) will lead to bricked site."
set_grade_cap "A" "Problems with HTTP Public Key Pinning (HPKP)"
fi fi
else else
outln "--" outln "--"
@ -3329,6 +3442,9 @@ neat_list(){
enc="${enc//POLY1305/}" # remove POLY1305 enc="${enc//POLY1305/}" # remove POLY1305
enc="${enc//\//}" # remove "/" enc="${enc//\//}" # remove "/"
# For rating set bit size
set_ciph_str_score $strength
[[ "$export" =~ export ]] && strength="$strength,exp" [[ "$export" =~ export ]] && strength="$strength,exp"
[[ "$DISPLAY_CIPHERNAMES" != openssl-only ]] && tls_cipher="$(show_rfc_style "$hexcode")" [[ "$DISPLAY_CIPHERNAMES" != openssl-only ]] && tls_cipher="$(show_rfc_style "$hexcode")"
@ -5034,6 +5150,7 @@ run_protocols() {
if [[ "$lines" -gt 1 ]]; then if [[ "$lines" -gt 1 ]]; then
nr_ciphers_detected=$((V2_HELLO_CIPHERSPEC_LENGTH / 3)) nr_ciphers_detected=$((V2_HELLO_CIPHERSPEC_LENGTH / 3))
add_proto_offered ssl2 yes add_proto_offered ssl2 yes
set_grade_cap "F" "SSLv2 is offered"
if [[ 0 -eq "$nr_ciphers_detected" ]]; then if [[ 0 -eq "$nr_ciphers_detected" ]]; then
prln_svrty_high "supported but couldn't detect a cipher and vulnerable to CVE-2015-3197 "; prln_svrty_high "supported but couldn't detect a cipher and vulnerable to CVE-2015-3197 ";
fileout "$jsonID" "HIGH" "offered, no cipher" "CVE-2015-3197" "CWE-310" fileout "$jsonID" "HIGH" "offered, no cipher" "CVE-2015-3197" "CWE-310"
@ -5055,6 +5172,7 @@ run_protocols() {
0) prln_svrty_critical "offered (NOT ok)" 0) prln_svrty_critical "offered (NOT ok)"
fileout "$jsonID" "CRITICAL" "offered" fileout "$jsonID" "CRITICAL" "offered"
add_proto_offered ssl2 yes add_proto_offered ssl2 yes
set_grade_cap "F" "SSLv2 is offered"
;; ;;
1) prln_svrty_best "not offered (OK)" 1) prln_svrty_best "not offered (OK)"
fileout "$jsonID" "OK" "not offered" fileout "$jsonID" "OK" "not offered"
@ -5063,6 +5181,8 @@ run_protocols() {
5) prln_svrty_high "CVE-2015-3197: $supported_no_ciph2"; 5) prln_svrty_high "CVE-2015-3197: $supported_no_ciph2";
fileout "$jsonID" "HIGH" "offered, no cipher" "CVE-2015-3197" "CWE-310" fileout "$jsonID" "HIGH" "offered, no cipher" "CVE-2015-3197" "CWE-310"
add_proto_offered ssl2 yes add_proto_offered ssl2 yes
add_tls_offered ssl2 yes
set_grade_cap "F" "SSLv2 is offered"
;; ;;
7) prln_local_problem "$OPENSSL doesn't support \"s_client -ssl2\"" 7) prln_local_problem "$OPENSSL doesn't support \"s_client -ssl2\""
fileout "$jsonID" "INFO" "not tested due to lack of local support" fileout "$jsonID" "INFO" "not tested due to lack of local support"
@ -5090,6 +5210,8 @@ run_protocols() {
latest_supported_string="SSLv3" latest_supported_string="SSLv3"
fi fi
add_proto_offered ssl3 yes add_proto_offered ssl3 yes
add_tls_offered ssl3 yes
set_grade_cap "B" "SSLv3 is offered"
;; ;;
1) prln_svrty_best "not offered (OK)" 1) prln_svrty_best "not offered (OK)"
fileout "$jsonID" "OK" "not offered" fileout "$jsonID" "OK" "not offered"
@ -5125,6 +5247,7 @@ run_protocols() {
5) pr_svrty_high "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl 5) pr_svrty_high "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl
fileout "$jsonID" "HIGH" "$supported_no_ciph1" fileout "$jsonID" "HIGH" "$supported_no_ciph1"
add_proto_offered ssl3 yes add_proto_offered ssl3 yes
set_grade_cap "B" "SSLv3 is offered"
;; ;;
7) if "$using_sockets" ; then 7) if "$using_sockets" ; then
# can only happen in debug mode # can only happen in debug mode
@ -5156,6 +5279,7 @@ run_protocols() {
latest_supported="0301" latest_supported="0301"
latest_supported_string="TLSv1.0" latest_supported_string="TLSv1.0"
add_proto_offered tls1 yes add_proto_offered tls1 yes
set_grade_cap "B" "TLS 1.0 offered"
;; # nothing wrong with it -- per se ;; # nothing wrong with it -- per se
1) out "not offered" 1) out "not offered"
add_proto_offered tls1 no add_proto_offered tls1 no
@ -5202,6 +5326,7 @@ run_protocols() {
5) outln "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl 5) outln "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl
fileout "$jsonID" "INFO" "$supported_no_ciph1" fileout "$jsonID" "INFO" "$supported_no_ciph1"
add_proto_offered tls1 yes add_proto_offered tls1 yes
set_grade_cap "B" "TLS 1.0 offered"
;; ;;
7) if "$using_sockets" ; then 7) if "$using_sockets" ; then
# can only happen in debug mode # can only happen in debug mode
@ -5234,6 +5359,7 @@ run_protocols() {
latest_supported="0302" latest_supported="0302"
latest_supported_string="TLSv1.1" latest_supported_string="TLSv1.1"
add_proto_offered tls1_1 yes add_proto_offered tls1_1 yes
set_grade_cap "B" "TLS 1.1 offered"
;; # nothing wrong with it ;; # nothing wrong with it
1) out "not offered" 1) out "not offered"
add_proto_offered tls1_1 no add_proto_offered tls1_1 no
@ -5283,6 +5409,7 @@ run_protocols() {
5) outln "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl 5) outln "$supported_no_ciph1" # protocol detected but no cipher --> comes from run_prototest_openssl
fileout "$jsonID" "INFO" "$supported_no_ciph1" fileout "$jsonID" "INFO" "$supported_no_ciph1"
add_proto_offered tls1_1 yes add_proto_offered tls1_1 yes
set_grade_cap "B" "TLS 1.1 offered"
;; ;;
7) if "$using_sockets" ; then 7) if "$using_sockets" ; then
# can only happen in debug mode # can only happen in debug mode
@ -5358,6 +5485,7 @@ run_protocols() {
fileout "$jsonID" "INFO" "not offered" fileout "$jsonID" "INFO" "not offered"
else else
fileout "$jsonID" "MEDIUM" "not offered" # TLS 1.3, no TLS 1.2 --> no GCM, penalty fileout "$jsonID" "MEDIUM" "not offered" # TLS 1.3, no TLS 1.2 --> no GCM, penalty
set_grade_cap "C" "TLS 1.2 or TLS 1.3 are not offered"
fi fi
else else
prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string" prln_svrty_critical " -- connection failed rather than downgrading to $latest_supported_string"
@ -5365,6 +5493,7 @@ run_protocols() {
fi fi
;; ;;
2) add_proto_offered tls1_2 no 2) add_proto_offered tls1_2 no
set_grade_cap "C" "TLS 1.2 is not offered"
pr_svrty_medium "not offered and downgraded to a weaker protocol" pr_svrty_medium "not offered and downgraded to a weaker protocol"
if [[ "$tls12_detected_version" == 0300 ]]; then if [[ "$tls12_detected_version" == 0300 ]]; then
detected_version_string="SSLv3" detected_version_string="SSLv3"
@ -5393,12 +5522,14 @@ run_protocols() {
3) out "not offered, " 3) out "not offered, "
fileout "$jsonID" "INFO" "not offered" fileout "$jsonID" "INFO" "not offered"
add_proto_offered tls1_2 no add_proto_offered tls1_2 no
set_grade_cap "C" "TLS 1.2 is not offered"
pr_warning "TLS downgraded to STARTTLS plaintext"; outln pr_warning "TLS downgraded to STARTTLS plaintext"; outln
fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext" fileout "$jsonID" "WARN" "TLS downgraded to STARTTLS plaintext"
;; ;;
4) out "likely "; pr_svrty_medium "not offered, " 4) out "likely "; pr_svrty_medium "not offered, "
fileout "$jsonID" "MEDIUM" "not offered" fileout "$jsonID" "MEDIUM" "not offered"
add_proto_offered tls1_2 no add_proto_offered tls1_2 no
set_grade_cap "C" "TLS 1.2 is not offered"
pr_warning "received 4xx/5xx after STARTTLS handshake"; outln "$debug_recomm" pr_warning "received 4xx/5xx after STARTTLS handshake"; outln "$debug_recomm"
fileout "$jsonID" "WARN" "received 4xx/5xx after STARTTLS handshake${debug_recomm}" fileout "$jsonID" "WARN" "received 4xx/5xx after STARTTLS handshake${debug_recomm}"
;; ;;
@ -5765,6 +5896,10 @@ sub_cipherlists() {
((ret++)) ((ret++))
;; ;;
esac esac
# Not a perfect place here. A new one should be picked in the future
[[ $sclient_success -eq 0 && "$1" =~ (^|:)EXPORT(:|$) ]] && set_grade_cap "F" "Export suite offered"
[[ $sclient_success -eq 0 && "$1" =~ AEAD ]] && set_grade_cap "B" "No AEAD ciphers offered"
fi fi
tmpfile_handle ${FUNCNAME[0]}.${5}.txt tmpfile_handle ${FUNCNAME[0]}.${5}.txt
[[ $DEBUG -ge 1 ]] && tm_out " -- $1" [[ $DEBUG -ge 1 ]] && tm_out " -- $1"
@ -6952,17 +7087,17 @@ verify_retcode_helper() {
case $retcode in case $retcode in
# codes from ./doc/apps/verify.pod | verify(1ssl) # codes from ./doc/apps/verify.pod | verify(1ssl)
44) tm_out "(different CRL scope)" ;; # X509_V_ERR_DIFFERENT_CRL_SCOPE 44) tm_out "(different CRL scope)" ;; # X509_V_ERR_DIFFERENT_CRL_SCOPE
26) tm_out "(unsupported certificate purpose)" ;; # X509_V_ERR_INVALID_PURPOSE 26) tm_out "(unsupported certificate purpose)" ;; # X509_V_ERR_INVALID_PURPOSE
24) tm_out "(certificate unreadable)" ;; # X509_V_ERR_INVALID_CA 24) tm_out "(certificate unreadable)" ;; # X509_V_ERR_INVALID_CA
23) tm_out "(certificate revoked)" ;; # X509_V_ERR_CERT_REVOKED 23) tm_out "(certificate revoked)" ;; # X509_V_ERR_CERT_REVOKED
21) tm_out "(chain incomplete, only 1 cert provided)" ;; # X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE 21) tm_out "(chain incomplete, only 1 cert provided)" ;; # X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
20) tm_out "(chain incomplete)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY 20) tm_out "(chain incomplete)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY
19) tm_out "(self signed CA in chain)" ;; # X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN 19) tm_out "(self signed CA in chain)" ;; # X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN
18) tm_out "(self signed)" ;; # X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT 18) tm_out "(self signed)" ;; # X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT
10) tm_out "(expired)" ;; # X509_V_ERR_CERT_HAS_EXPIRED 10) tm_out "(expired)" ;; # X509_V_ERR_CERT_HAS_EXPIRED
9) tm_out "(not yet valid)" ;; # X509_V_ERR_CERT_NOT_YET_VALID 9) tm_out "(not yet valid)" ;; # X509_V_ERR_CERT_NOT_YET_VALID
2) tm_out "(issuer cert missing)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT 2) tm_out "(issuer cert missing)" ;; # X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT
*) ret=1 ; tm_out " (unknown, pls report) $1" ;; *) ret=1 ; tm_out " (unknown, pls report) $1" ;;
esac esac
return $ret return $ret
@ -7058,6 +7193,7 @@ determine_trust() {
out "$code" out "$code"
fi fi
fileout "${jsonID}${json_postfix}" "CRITICAL" "failed $code. $addtl_warning" fileout "${jsonID}${json_postfix}" "CRITICAL" "failed $code. $addtl_warning"
set_grade_cap "T" "Issues with certificate $code"
else else
# is one ok and the others not ==> display the culprit store # is one ok and the others not ==> display the culprit store
if "$some_ok"; then if "$some_ok"; then
@ -7076,6 +7212,7 @@ determine_trust() {
out "$code" out "$code"
fi fi
notok_was="${certificate_file[i]} $code $notok_was" notok_was="${certificate_file[i]} $code $notok_was"
set_grade_cap "T" "Issues with certificate $code"
fi fi
done done
#pr_svrty_high "$notok_was " #pr_svrty_high "$notok_was "
@ -8193,6 +8330,7 @@ certificate_info() {
fi fi
outln outln
fileout "${jsonID}${json_postfix}" "MEDIUM" "SHA1 with RSA" fileout "${jsonID}${json_postfix}" "MEDIUM" "SHA1 with RSA"
set_grade_cap "T" "Uses SHA1 algorithm"
;; ;;
sha224WithRSAEncryption) sha224WithRSAEncryption)
outln "SHA224 with RSA" outln "SHA224 with RSA"
@ -8213,6 +8351,7 @@ certificate_info() {
ecdsa-with-SHA1) ecdsa-with-SHA1)
prln_svrty_medium "ECDSA with SHA1" prln_svrty_medium "ECDSA with SHA1"
fileout "${jsonID}${json_postfix}" "MEDIUM" "ECDSA with SHA1" fileout "${jsonID}${json_postfix}" "MEDIUM" "ECDSA with SHA1"
set_grade_cap "T" "Uses SHA1 algorithm"
;; ;;
ecdsa-with-SHA224) ecdsa-with-SHA224)
outln "ECDSA with SHA224" outln "ECDSA with SHA224"
@ -8233,6 +8372,7 @@ certificate_info() {
dsaWithSHA1) dsaWithSHA1)
prln_svrty_medium "DSA with SHA1" prln_svrty_medium "DSA with SHA1"
fileout "${jsonID}${json_postfix}" "MEDIUM" "DSA with SHA1" fileout "${jsonID}${json_postfix}" "MEDIUM" "DSA with SHA1"
set_grade_cap "T" "Uses SHA1 algorithm"
;; ;;
dsa_with_SHA224) dsa_with_SHA224)
outln "DSA with SHA224" outln "DSA with SHA224"
@ -8248,6 +8388,7 @@ certificate_info() {
sha1) sha1)
prln_svrty_medium "RSASSA-PSS with SHA1" prln_svrty_medium "RSASSA-PSS with SHA1"
fileout "${jsonID}${json_postfix}" "MEDIUM" "RSASSA-PSS with SHA1" fileout "${jsonID}${json_postfix}" "MEDIUM" "RSASSA-PSS with SHA1"
set_grade_cap "T" "Uses SHA1 algorithm"
;; ;;
sha224) sha224)
outln "RSASSA-PSS with SHA224" outln "RSASSA-PSS with SHA224"
@ -8274,6 +8415,7 @@ certificate_info() {
md2*) md2*)
prln_svrty_critical "MD2" prln_svrty_critical "MD2"
fileout "${jsonID}${json_postfix}" "CRITICAL" "MD2" fileout "${jsonID}${json_postfix}" "CRITICAL" "MD2"
set_grade_cap "F" "Supports a insecure signature (MD2)"
;; ;;
md4*) md4*)
prln_svrty_critical "MD4" prln_svrty_critical "MD4"
@ -8282,6 +8424,7 @@ certificate_info() {
md5*) md5*)
prln_svrty_critical "MD5" prln_svrty_critical "MD5"
fileout "${jsonID}${json_postfix}" "CRITICAL" "MD5" fileout "${jsonID}${json_postfix}" "CRITICAL" "MD5"
set_grade_cap "F" "Supports a insecure signature (MD5)"
;; ;;
*) *)
out "$cert_sig_algo (" out "$cert_sig_algo ("
@ -8336,6 +8479,8 @@ certificate_info() {
((ret++)) ((ret++))
fi fi
outln " bits" outln " bits"
set_key_str_score "$short_keyAlgo" "$cert_keysize" # TODO: should be $dh_param_size
elif [[ $cert_key_algo =~ RSA ]] || [[ $cert_key_algo =~ rsa ]] || [[ $cert_key_algo =~ dsa ]] || \ elif [[ $cert_key_algo =~ RSA ]] || [[ $cert_key_algo =~ rsa ]] || [[ $cert_key_algo =~ dsa ]] || \
[[ $cert_key_algo =~ dhKeyAgreement ]] || [[ $cert_key_algo == X9.42\ DH ]]; then [[ $cert_key_algo =~ dhKeyAgreement ]] || [[ $cert_key_algo == X9.42\ DH ]]; then
if [[ "$cert_keysize" -le 512 ]]; then if [[ "$cert_keysize" -le 512 ]]; then
@ -8362,6 +8507,8 @@ certificate_info() {
fileout "${jsonID}${json_postfix}" "WARN" "$cert_keysize bits (Odd)" fileout "${jsonID}${json_postfix}" "WARN" "$cert_keysize bits (Odd)"
((ret++)) ((ret++))
fi fi
set_key_str_score "$short_keyAlgo" "$cert_keysize"
else else
out "$cert_key_algo + $cert_keysize bits (" out "$cert_key_algo + $cert_keysize bits ("
pr_warning "FIXME: can't tell whether this is good or not" pr_warning "FIXME: can't tell whether this is good or not"
@ -8528,6 +8675,7 @@ certificate_info() {
if [[ "$issuer_O" == "issuer=" ]] || [[ "$issuer_O" == "issuer= " ]] || [[ "$issuer_CN" == "$cn" ]]; then if [[ "$issuer_O" == "issuer=" ]] || [[ "$issuer_O" == "issuer= " ]] || [[ "$issuer_CN" == "$cn" ]]; then
prln_svrty_critical "self-signed (NOT ok)" prln_svrty_critical "self-signed (NOT ok)"
fileout "${jsonID}${json_postfix}" "CRITICAL" "selfsigned" fileout "${jsonID}${json_postfix}" "CRITICAL" "selfsigned"
set_grade_cap "T" "Self-signed certificate"
else else
issuerfinding="$issuer_CN" issuerfinding="$issuer_CN"
pr_italic "$issuer_CN" pr_italic "$issuer_CN"
@ -8571,7 +8719,9 @@ certificate_info() {
has_dns_sans=$HAS_DNS_SANS has_dns_sans=$HAS_DNS_SANS
case $trust_sni in case $trust_sni in
0) trustfinding="certificate does not match supplied URI" ;; 0) trustfinding="certificate does not match supplied URI"
set_grade_cap "M" "Domain name mismatch"
;;
1) trustfinding="Ok via SAN" ;; 1) trustfinding="Ok via SAN" ;;
2) trustfinding="Ok via SAN wildcard" ;; 2) trustfinding="Ok via SAN wildcard" ;;
4) if "$has_dns_sans"; then 4) if "$has_dns_sans"; then
@ -8676,6 +8826,7 @@ certificate_info() {
# Shortcut for this special case here. # Shortcut for this special case here.
pr_italic "WoSign/StartCom"; out " are " ; prln_svrty_critical "not trusted anymore (NOT ok)" pr_italic "WoSign/StartCom"; out " are " ; prln_svrty_critical "not trusted anymore (NOT ok)"
fileout "${jsonID}${json_postfix}" "CRITICAL" "Issuer not trusted anymore (WoSign/StartCom)" fileout "${jsonID}${json_postfix}" "CRITICAL" "Issuer not trusted anymore (WoSign/StartCom)"
set_grade_cap "T" "Untrusted certificate chain"
else else
# Also handles fileout, keep error if happened # Also handles fileout, keep error if happened
determine_trust "$jsonID" "$json_postfix" || ((ret++)) determine_trust "$jsonID" "$json_postfix" || ((ret++))
@ -8768,6 +8919,7 @@ certificate_info() {
pr_svrty_critical "expired" pr_svrty_critical "expired"
expfinding="expired" expfinding="expired"
expok="CRITICAL" expok="CRITICAL"
set_grade_cap "T" "Certificate expired"
else else
secs2warn=$((24 * 60 * 60 * days2warn2)) # low threshold first secs2warn=$((24 * 60 * 60 * days2warn2)) # low threshold first
expire=$($OPENSSL x509 -in $HOSTCERT -checkend $secs2warn 2>>$ERRFILE) expire=$($OPENSSL x509 -in $HOSTCERT -checkend $secs2warn 2>>$ERRFILE)
@ -9562,8 +9714,9 @@ run_fs() {
if [[ $sclient_success -ne 0 ]]; then if [[ $sclient_success -ne 0 ]]; then
outln outln
prln_svrty_medium " No ciphers supporting Forward Secrecy offered" prln_svrty_medium " No ciphers supporting Forward Secrecy (FS) offered"
fileout "$jsonID" "MEDIUM" "No ciphers supporting (P)FS offered" fileout "$jsonID" "MEDIUM" "No ciphers supporting Forward Secrecy offered"
set_grade_cap "B" "Forward Secrecy (FS) is not supported"
else else
outln outln
fs_offered=true fs_offered=true
@ -14920,6 +15073,7 @@ run_heartbleed(){
else else
pr_svrty_critical "VULNERABLE (NOT ok)" pr_svrty_critical "VULNERABLE (NOT ok)"
fileout "$jsonID" "CRITICAL" "VULNERABLE $cve" "$cwe" "$hint" fileout "$jsonID" "CRITICAL" "VULNERABLE $cve" "$cwe" "$hint"
set_grade_cap "F" "Vulnerable to Heartbleed"
fi fi
else else
pr_svrty_best "not vulnerable (OK)" pr_svrty_best "not vulnerable (OK)"
@ -15078,6 +15232,7 @@ run_ccs_injection(){
# decryption failed received # decryption failed received
pr_svrty_critical "VULNERABLE (NOT ok)" pr_svrty_critical "VULNERABLE (NOT ok)"
fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe" "$hint" fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe" "$hint"
set_grade_cap "F" "Vulnerable to CCS injection"
elif [[ "$byte6" == "0A" ]] || [[ "$byte6" == "28" ]]; then elif [[ "$byte6" == "0A" ]] || [[ "$byte6" == "28" ]]; then
# Unexpected message / Handshake failure received # Unexpected message / Handshake failure received
pr_warning "likely " pr_warning "likely "
@ -15378,6 +15533,7 @@ run_ticketbleed() {
if [[ ${memory[1]} != ${memory[2]} ]] && [[ ${memory[2]} != ${memory[3]} ]]; then if [[ ${memory[1]} != ${memory[2]} ]] && [[ ${memory[2]} != ${memory[3]} ]]; then
pr_svrty_critical "VULNERABLE (NOT ok)" pr_svrty_critical "VULNERABLE (NOT ok)"
fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe" "$hint" fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe" "$hint"
set_grade_cap "F" "Vulnerable to Ticketbleed"
else else
pr_svrty_best "not vulnerable (OK)" pr_svrty_best "not vulnerable (OK)"
out ", session IDs were returned but potential memory fragments do not differ" out ", session IDs were returned but potential memory fragments do not differ"
@ -15435,6 +15591,7 @@ run_renego() {
case $sec_renego in case $sec_renego in
0) prln_svrty_critical "Not supported / VULNERABLE (NOT ok)" 0) prln_svrty_critical "Not supported / VULNERABLE (NOT ok)"
fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe" "$hint" fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe" "$hint"
set_grade_warning "Secure renegotiation is not supported"
;; ;;
1) prln_svrty_best "supported (OK)" 1) prln_svrty_best "supported (OK)"
fileout "$jsonID" "OK" "supported" "$cve" "$cwe" fileout "$jsonID" "OK" "supported" "$cve" "$cwe"
@ -15618,6 +15775,7 @@ run_crime() {
# not clear whether a protocol != HTTP offers the ability to repeatedly modify the input # not clear whether a protocol != HTTP offers the ability to repeatedly modify the input
# which is done e.g. via javascript in the context of HTTP # which is done e.g. via javascript in the context of HTTP
fi fi
set_grade_cap "C" "Vulnerable to CRIME"
fi fi
outln outln
@ -15750,6 +15908,7 @@ run_sweet32() {
local -i nr_sweet32_ciphers=0 nr_supported_ciphers=0 nr_ssl2_sweet32_ciphers=0 nr_ssl2_supported_ciphers=0 local -i nr_sweet32_ciphers=0 nr_supported_ciphers=0 nr_ssl2_sweet32_ciphers=0 nr_ssl2_supported_ciphers=0
local ssl2_sweet=false local ssl2_sweet=false
local using_sockets=true local using_sockets=true
local tls1_1_vulnerable=false
[[ $VULN_COUNT -le $VULN_THRESHLD ]] && outln && pr_headlineln " Testing for SWEET32 (Birthday Attacks on 64-bit Block Ciphers) " && outln [[ $VULN_COUNT -le $VULN_THRESHLD ]] && outln && pr_headlineln " Testing for SWEET32 (Birthday Attacks on 64-bit Block Ciphers) " && outln
pr_bold " SWEET32"; out " (${cve// /, }) " pr_bold " SWEET32"; out " (${cve// /, }) "
@ -15810,6 +15969,7 @@ run_sweet32() {
sclient_connect_successful $? $TMPFILE sclient_connect_successful $? $TMPFILE
sclient_success=$? sclient_success=$?
[[ $DEBUG -ge 2 ]] && grep -Eq "error|failure" $ERRFILE | grep -Eav "unable to get local|verify error" [[ $DEBUG -ge 2 ]] && grep -Eq "error|failure" $ERRFILE | grep -Eav "unable to get local|verify error"
[[ $proto == -tls1_1 && $sclient_success -eq 0 ]] && tls1_1_vulnerable=true
[[ $sclient_success -eq 0 ]] && break [[ $sclient_success -eq 0 ]] && break
done done
if "$HAS_SSL2"; then if "$HAS_SSL2"; then
@ -15829,9 +15989,11 @@ run_sweet32() {
if [[ $sclient_success -eq 0 ]] && "$ssl2_sweet" ; then if [[ $sclient_success -eq 0 ]] && "$ssl2_sweet" ; then
pr_svrty_low "VULNERABLE"; out ", uses 64 bit block ciphers for SSLv2 and above" pr_svrty_low "VULNERABLE"; out ", uses 64 bit block ciphers for SSLv2 and above"
fileout "SWEET32" "LOW" "uses 64 bit block ciphers for SSLv2 and above" "$cve" "$cwe" "$hint" fileout "SWEET32" "LOW" "uses 64 bit block ciphers for SSLv2 and above" "$cve" "$cwe" "$hint"
"$tls1_1_vulnerable" && set_grade_cap "C" "Uses 64 bit block ciphers with TLS 1.1 (vulnerable to SWEET32)"
elif [[ $sclient_success -eq 0 ]]; then elif [[ $sclient_success -eq 0 ]]; then
pr_svrty_low "VULNERABLE"; out ", uses 64 bit block ciphers" pr_svrty_low "VULNERABLE"; out ", uses 64 bit block ciphers"
fileout "SWEET32" "LOW" "uses 64 bit block ciphers" "$cve" "$cwe" "$hint" fileout "SWEET32" "LOW" "uses 64 bit block ciphers" "$cve" "$cwe" "$hint"
"$tls1_1_vulnerable" && set_grade_cap "C" "Uses 64 bit block ciphers with TLS 1.1 (vulnerable to SWEET32)"
elif "$ssl2_sweet"; then elif "$ssl2_sweet"; then
pr_svrty_low "VULNERABLE"; out ", uses 64 bit block ciphers wth SSLv2 only" pr_svrty_low "VULNERABLE"; out ", uses 64 bit block ciphers wth SSLv2 only"
fileout "SWEET32" "LOW" "uses 64 bit block ciphers with SSLv2 only" "$cve" "$cwe" "$hint" fileout "SWEET32" "LOW" "uses 64 bit block ciphers with SSLv2 only" "$cve" "$cwe" "$hint"
@ -15913,6 +16075,7 @@ run_ssl_poodle() {
POODLE=0 POODLE=0
pr_svrty_high "VULNERABLE (NOT ok)"; out ", uses SSLv3+CBC (check TLS_FALLBACK_SCSV mitigation below)" pr_svrty_high "VULNERABLE (NOT ok)"; out ", uses SSLv3+CBC (check TLS_FALLBACK_SCSV mitigation below)"
fileout "$jsonID" "HIGH" "VULNERABLE, uses SSLv3+CBC" "$cve" "$cwe" "$hint" fileout "$jsonID" "HIGH" "VULNERABLE, uses SSLv3+CBC" "$cve" "$cwe" "$hint"
set_grade_cap "C" "Vulnerable to POODLE"
else else
POODLE=1 POODLE=1
pr_svrty_best "not vulnerable (OK)"; pr_svrty_best "not vulnerable (OK)";
@ -15943,6 +16106,8 @@ run_tls_poodle() {
#FIXME #FIXME
prln_warning "#FIXME" prln_warning "#FIXME"
fileout "$jsonID" "WARN" "Not yet implemented #FIXME" "$cve" "$cwe" fileout "$jsonID" "WARN" "Not yet implemented #FIXME" "$cve" "$cwe"
# set_grade_cap "F" "Vulnerable to POODLE TLS"
return 0 return 0
} }
@ -16090,15 +16255,18 @@ run_tls_fallback_scsv() {
if [[ -z "$POODLE" ]]; then if [[ -z "$POODLE" ]]; then
pr_warning "Rerun including POODLE SSL check. " pr_warning "Rerun including POODLE SSL check. "
pr_svrty_medium "Downgrade attack prevention NOT supported" pr_svrty_medium "Downgrade attack prevention NOT supported"
fileout "$jsonID" "WARN" "NOT supported. Pls rerun wity POODLE SSL check" fileout "$jsonID" "WARN" "NOT supported. Pls rerun with POODLE SSL check"
ret=1 ret=1
elif [[ "$POODLE" -eq 0 ]]; then elif [[ "$POODLE" -eq 0 ]]; then
pr_svrty_high "Downgrade attack prevention NOT supported and vulnerable to POODLE SSL" pr_svrty_high "Downgrade attack prevention NOT supported and vulnerable to POODLE SSL"
fileout "$jsonID" "HIGH" "NOT supported and vulnerable to POODLE SSL" fileout "$jsonID" "HIGH" "NOT supported and vulnerable to POODLE SSL"
set_grade_cap "C" "Vulnerable to POODLE"
else else
pr_svrty_medium "Downgrade attack prevention NOT supported" pr_svrty_medium "Downgrade attack prevention NOT supported"
fileout "$jsonID" "MEDIUM" "NOT supported" fileout "$jsonID" "MEDIUM" "NOT supported"
fi fi
set_grade_cap "A" "Does not support TLS_FALLBACK_SCSV"
elif grep -qa "alert inappropriate fallback" "$TMPFILE"; then elif grep -qa "alert inappropriate fallback" "$TMPFILE"; then
pr_svrty_good "Downgrade attack prevention supported (OK)" pr_svrty_good "Downgrade attack prevention supported (OK)"
fileout "$jsonID" "OK" "supported" fileout "$jsonID" "OK" "supported"
@ -16441,6 +16609,7 @@ run_logjam() {
if "$vuln_exportdh_ciphers"; then if "$vuln_exportdh_ciphers"; then
pr_svrty_high "VULNERABLE (NOT ok):"; out " uses DH EXPORT ciphers" pr_svrty_high "VULNERABLE (NOT ok):"; out " uses DH EXPORT ciphers"
fileout "$jsonID" "HIGH" "VULNERABLE, uses DH EXPORT ciphers" "$cve" "$cwe" "$hint" fileout "$jsonID" "HIGH" "VULNERABLE, uses DH EXPORT ciphers" "$cve" "$cwe" "$hint"
set_grade_cap "B" "Uses weak DH key exchange parameters (vulnerable to LOGJAM)"
if [[ $subret -eq 3 ]]; then if [[ $subret -eq 3 ]]; then
out ", no DH key detected with <= TLS 1.2" out ", no DH key detected with <= TLS 1.2"
fileout "$jsonID2" "OK" "no DH key detected with <= TLS 1.2" fileout "$jsonID2" "OK" "no DH key detected with <= TLS 1.2"
@ -16456,6 +16625,7 @@ run_logjam() {
else else
if [[ $subret -eq 1 ]]; then if [[ $subret -eq 1 ]]; then
out_common_prime "$jsonID2" "$cve" "$cwe" out_common_prime "$jsonID2" "$cve" "$cwe"
set_grade_cap "A" "Uses known DH key exchange parameters"
if ! "$openssl_no_expdhciphers"; then if ! "$openssl_no_expdhciphers"; then
outln "," outln ","
out "${spaces}but no DH EXPORT ciphers${addtl_warning}" out "${spaces}but no DH EXPORT ciphers${addtl_warning}"
@ -16553,6 +16723,7 @@ run_drown() {
else else
prln_svrty_critical "VULNERABLE (NOT ok), SSLv2 offered with $nr_ciphers_detected ciphers"; prln_svrty_critical "VULNERABLE (NOT ok), SSLv2 offered with $nr_ciphers_detected ciphers";
fileout "$jsonID" "CRITICAL" "VULNERABLE, SSLv2 offered with $nr_ciphers_detected ciphers. Make sure you don't use this certificate elsewhere, see https://censys.io/ipv4?q=$cert_fingerprint_sha2" "$cve" "$cwe" "$hint" fileout "$jsonID" "CRITICAL" "VULNERABLE, SSLv2 offered with $nr_ciphers_detected ciphers. Make sure you don't use this certificate elsewhere, see https://censys.io/ipv4?q=$cert_fingerprint_sha2" "$cve" "$cwe" "$hint"
set_grade_cap "F" "Vulnerable to DROWN"
fi fi
outln "$spaces Make sure you don't use this certificate elsewhere, see:" outln "$spaces Make sure you don't use this certificate elsewhere, see:"
out "$spaces " out "$spaces "
@ -16866,6 +17037,7 @@ run_beast(){
pr_svrty_medium "VULNERABLE" pr_svrty_medium "VULNERABLE"
outln " -- and no higher protocols as mitigation supported" outln " -- and no higher protocols as mitigation supported"
fileout "$jsonID" "MEDIUM" "VULNERABLE -- and no higher protocols as mitigation supported" "$cve" "$cwe" "$hint" fileout "$jsonID" "MEDIUM" "VULNERABLE -- and no higher protocols as mitigation supported" "$cve" "$cwe" "$hint"
set_grade_cap "B" "Vulnerable to BEAST"
fi fi
fi fi
"$first" && ! "$vuln_beast" && prln_svrty_good "no CBC ciphers found for any protocol (OK)" "$first" && ! "$vuln_beast" && prln_svrty_good "no CBC ciphers found for any protocol (OK)"
@ -17113,6 +17285,11 @@ run_rc4() {
fi fi
"$WIDE" && "$SHOW_SIGALGO" && grep -q "\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-" $TMPFILE && \ "$WIDE" && "$SHOW_SIGALGO" && grep -q "\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-" $TMPFILE && \
sigalg[i]="$(read_sigalg_from_file "$TMPFILE")" sigalg[i]="$(read_sigalg_from_file "$TMPFILE")"
# If you use RC4 with newer protocols, you are punished harder
if [[ "$proto" == -tls1_1 ]]; then
set_grade_cap "C" "RC4 ciphers offered on TLS 1.1"
fi
done done
done done
@ -17193,6 +17370,7 @@ run_rc4() {
outln outln
"$WIDE" && out " " && prln_svrty_high "VULNERABLE (NOT ok)" "$WIDE" && out " " && prln_svrty_high "VULNERABLE (NOT ok)"
fileout "$jsonID" "HIGH" "VULNERABLE, Detected ciphers: $rc4_detected" "$cve" "$cwe" "$hint" fileout "$jsonID" "HIGH" "VULNERABLE, Detected ciphers: $rc4_detected" "$cve" "$cwe" "$hint"
set_grade_cap "B" "RC4 ciphers offered"
elif [[ $nr_ciphers -eq 0 ]]; then elif [[ $nr_ciphers -eq 0 ]]; then
prln_local_problem "No RC4 Ciphers configured in $OPENSSL" prln_local_problem "No RC4 Ciphers configured in $OPENSSL"
fileout "$jsonID" "WARN" "RC4 ciphers not supported by local OpenSSL ($OPENSSL)" fileout "$jsonID" "WARN" "RC4 ciphers not supported by local OpenSSL ($OPENSSL)"
@ -17837,6 +18015,7 @@ run_robot() {
prln_svrty_critical "VULNERABLE (NOT ok)" prln_svrty_critical "VULNERABLE (NOT ok)"
fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe" fileout "$jsonID" "CRITICAL" "VULNERABLE" "$cve" "$cwe"
fi fi
set_grade_cap "F" "Vulnerable to ROBOT"
else else
prln_svrty_best "not vulnerable (OK)" prln_svrty_best "not vulnerable (OK)"
fileout "$jsonID" "OK" "not vulnerable" "$cve" "$cwe" fileout "$jsonID" "OK" "not vulnerable" "$cve" "$cwe"
@ -18340,6 +18519,7 @@ output options (can also be preset via environment variables):
--color <0|1|2|3> 0: no escape or other codes, 1: b/w escape codes, 2: color (default), 3: extra color (color all ciphers) --color <0|1|2|3> 0: no escape or other codes, 1: b/w escape codes, 2: color (default), 3: extra color (color all ciphers)
--colorblind swap green and blue in the output --colorblind swap green and blue in the output
--debug <0-6> 1: screen output normal but keeps debug output in /tmp/. 2-6: see "grep -A 5 '^DEBUG=' testssl.sh" --debug <0-6> 1: screen output normal but keeps debug output in /tmp/. 2-6: see "grep -A 5 '^DEBUG=' testssl.sh"
--disable-rating Explicitly disables the rating output
file output options (can also be preset via environment variables) file output options (can also be preset via environment variables)
--log, --logging logs stdout to '\${NODE}-p\${port}\${YYYYMMDD-HHMM}.log' in current working directory (cwd) --log, --logging logs stdout to '\${NODE}-p\${port}\${YYYYMMDD-HHMM}.log' in current working directory (cwd)
@ -20315,6 +20495,224 @@ run_mass_testing_parallel() {
return $? return $?
} }
run_rating() {
local final_score pre_cap_grade final_grade
local c1_score c2_score c3_score c1_wscore c2_wscore c3_wscore
local c1_worst c1_best
local c3_worst c3_best c3_worst_cb c3_best_cb
local old_ifs=$IFS sorted_reasons sorted_warnings reason_nr=0 warning_nr=0
outln "\n";
pr_headlineln " Rating (experimental) "
outln
if [[ -n "$STARTTLS_PROTOCOL" ]]; then
pr_bold " Grade "; pr_svrty_critical "T"
outln " - STARTTLS encryption is opportunistic"
outln " (Further details would lead to a false sense of security)"
fileout "grade" "CRITICAL" "T"
fileout "grade_cap_reasons" "INFO" "No more details shown as it would lead to a false sense of security"
return 0
fi
# Sort the reasons. This is just nicer to read in genereal
IFS=$'\n' sorted_reasons=($(sort -ru <<<"${GRADE_CAP_REASONS[*]}"))
IFS=$'\n' sorted_warnings=($(sort -u <<<"${GRADE_WARNINGS[*]}"))
IFS=$old_ifs
pr_bold " Rating specs"; out " (not complete) "; outln "SSL Labs's 'SSL Server Rating Guide' (version 2009q from 2020-01-30)"
pr_bold " Specification documentation "; pr_url "https://github.com/ssllabs/research/wiki/SSL-Server-Rating-Guide"
outln
fileout "rating_spec" "INFO" "SSL Labs's 'SSL Server Rating Guide' (version 2009q from 2020-01-30)"
# No point in calculating a score, if a cap of "F", "T", or "M" has been set
if [[ $GRADE_CAP == F || $GRADE_CAP == T || $GRADE_CAP == M ]]; then
pr_bold " Protocol Support"; out " (weighted) "; outln "0 (0)"
pr_bold " Key Exchange"; out " (weighted) "; outln "0 (0)"
pr_bold " Cipher Strength"; out " (weighted) "; outln "0 (0)"
pr_bold " Final Score "; outln "0"
pr_bold " Overall Grade "; prln_svrty_critical "$GRADE_CAP"
fileout "grade" "CRITICAL" "$GRADE_CAP"
else
## Category 1
# get best score, by searching for the best protocol, until a hit occurs
if [[ $(has_server_protocol "tls1_3") -eq 0 || $(has_server_protocol "tls1_2") -eq 0 ]]; then
c1_best=100
elif [[ $(has_server_protocol "tls1_1") -eq 0 ]]; then
c1_best=95
elif [[ $(has_server_protocol "tls1") -eq 0 ]]; then
c1_best=90
elif [[ $(has_server_protocol "ssl3") -eq 0 ]]; then
c1_best=80
# If the best protocol offered is SSLv3, cap to F. It is easier done here
set_grade_cap "F" "SSLv3 is the best protocol offered"
else # SSLv2 gives 0 points
c1_best=0
fi
# get worst score, by searching for the worst protcol, until a hit occurs
if [[ $(has_server_protocol "ssl2") -eq 0 ]]; then
c1_worst=0
elif [[ $(has_server_protocol "ssl3") -eq 0 ]]; then
c1_worst=80
elif [[ $(has_server_protocol "tls1") -eq 0 ]]; then
c1_worst=90
elif [[ $(has_server_protocol "tls1_1") -eq 0 ]]; then
c1_worst=95
else # TLS1.2 and TLS1.3 both give 100 points
c1_worst=100
fi
let c1_score="($c1_best+$c1_worst)/2" # Gets the category score
let c1_wscore=$c1_score*30/100 # Gets the weighted score for category (30%)
pr_bold " Protocol Support "; out "(weighted) "; outln "$c1_score ($c1_wscore)"
## Category 2
let c2_score=$KEY_EXCH_SCORE
let c2_wscore=$c2_score*30/100
pr_bold " Key Exchange "; out " (weighted) "; outln "$c2_score ($c2_wscore)"
## Category 3
# Get the cipher bits sizes for the best cipher, and the worst cipher
c3_best_cb=$CIPH_STR_BEST
c3_worst_cb=$CIPH_STR_WORST
# Determine score for the best key
if [[ $c3_best_cb -ge 256 ]]; then
c3_best=100
elif [[ $c3_best_cb -ge 128 ]]; then
c3_best=80
elif [[ $c3_best_cb -ge 0 ]]; then
c3_best=20
else
c3_best=0
fi
# Determine the score for the worst key
if [[ $c3_worst_cb -gt 0 && $c3_worst_cb -lt 128 ]]; then
c3_worst=20
elif [[ $c3_worst_cb -lt 256 ]]; then
c3_worst=80
elif [[ $c3_worst_cb -ge 256 ]]; then
c3_worst=100
else
c3_worst=0
fi
let c3_score="($c3_best+$c3_worst)/2" # Gets the category score
let c3_wscore=$c3_score*40/100 # Gets the weighted score for category (40%)
pr_bold " Cipher Strength "; out " (weighted) "; outln "$c3_score ($c3_wscore)"
## Calculate final score and grade
let final_score=$c1_wscore+$c2_wscore+$c3_wscore
pr_bold " Final Score "; outln $final_score
# get score, and somehow do something about the GRADE_CAP
if [[ $final_score -ge 80 ]]; then
pre_cap_grade="A"
elif [[ $final_score -ge 65 ]]; then
pre_cap_grade="B"
elif [[ $final_score -ge 50 ]]; then
pre_cap_grade="C"
elif [[ $final_score -ge 35 ]]; then
pre_cap_grade="D"
elif [[ $final_score -ge 20 ]]; then
pre_cap_grade="E"
elif [[ $final_score -lt 20 ]]; then
pre_cap_grade="F"
fi
# If the calculated grade is bigger than the grade cap, then set grade as the cap
if [[ -n "$GRADE_CAP" && ! $pre_cap_grade > $GRADE_CAP ]]; then
final_grade=$GRADE_CAP
# For "exceptional" config, an "A+" is awarded, or "A-" for slightly less "exceptional"
elif [[ -z "$GRADE_CAP" && $pre_cap_grade == A ]]; then
if [[ ${#sorted_warnings[@]} -eq 0 ]]; then
final_grade="A+"
else
final_grade="A-"
fi
else
final_grade=$pre_cap_grade
fi
pr_bold " Overall Grade "
case "$final_grade" in
A*) prln_svrty_best $final_grade
fileout "grade" "OK" "$final_grade"
;;
B) prln_svrty_medium $final_grade
fileout "grade" "MEDIUM" "$final_grade"
;;
C) prln_svrty_medium $final_grade
fileout "grade" "MEDIUM" "$final_grade"
;;
D) prln_svrty_high $final_grade
fileout "grade" "HIGH" "$final_grade"
;;
E) prln_svrty_high $final_grade
fileout "grade" "HIGH" "$final_grade"
;;
F) prln_svrty_critical $final_grade
fileout "grade" "CRITICAL" "$final_grade"
;;
esac
fi
# Pretty print - again, it's just nicer to read
for reason in "${sorted_reasons[@]}"; do
if [[ $reason_nr -eq 0 ]]; then
pr_bold " Grade cap reasons "; outln "$reason"
else
outln " $reason"
fi
let reason_nr++
fileout "grade_cap_reason_${reason_nr}" "INFO" "$reason"
done
for warning in "${sorted_warnings[@]}"; do
if [[ $warning_nr -eq 0 ]]; then
pr_bold " Grade warning "; prln_svrty_medium "$warning"
else
prln_svrty_medium " $warning"
fi
let warning_nr++
fileout "grade_cap_warning_${warning_nr}" "INFO" "$warning"
done
return 0
}
# Checks whether rating can be done or not.
# Rating needs a mix of certificate and vulnerabilities checks, in order to give out proper grades.
# This function disables rating, if not all required checks are enabled
# Returns "0" if rating is enabled, and "1" if rating is disabled
set_rating_state() {
local gbl
local nr_enabled=0
# All of these should be enabled
for gbl in do_protocols do_cipherlists do_fs do_server_defaults do_header \
do_heartbleed do_ccs_injection do_ticketbleed do_robot do_renego \
do_crime do_ssl_poodle do_tls_fallback_scsv do_drown do_beast \
do_rc4 do_logjam; do
"${!gbl}" && let nr_enabled++
done
# ... atleast one of these has to be set
[[ "$do_allciphers" || "$do_cipher_per_proto" ]] && let nr_enabled++
# ... else we can't do rating
if [[ $nr_enabled -lt 18 ]]; then
do_rating=false
return 1
fi
return 0
}
# This initializes boolean global do_* variables. They keep track of what to do # This initializes boolean global do_* variables. They keep track of what to do
@ -20358,6 +20756,7 @@ initialize_globals() {
do_client_simulation=false do_client_simulation=false
do_display_only=false do_display_only=false
do_starttls=false do_starttls=false
do_rating=false
} }
@ -20393,6 +20792,7 @@ set_scanning_defaults() {
else else
VULN_COUNT=12 VULN_COUNT=12
fi fi
do_rating=true
} }
# returns number of $do variables set = number of run_funcs() to perform # returns number of $do variables set = number of run_funcs() to perform
@ -20403,8 +20803,8 @@ count_do_variables() {
for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \ for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \
do_freak do_logjam do_drown do_header do_heartbleed do_mx_all_ips do_fs do_protocols do_rc4 do_grease do_robot do_renego \ do_freak do_logjam do_drown do_header do_heartbleed do_mx_all_ips do_fs do_protocols do_rc4 do_grease do_robot do_renego \
do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv \ do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv \
do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only; do do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do
[[ "${!gbl}" == true ]] && let true_nr++ "${!gbl}" && let true_nr++
done done
return $true_nr return $true_nr
} }
@ -20416,13 +20816,31 @@ debug_globals() {
for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \ for gbl in do_allciphers do_vulnerabilities do_beast do_lucky13 do_breach do_ccs_injection do_ticketbleed do_cipher_per_proto do_crime \
do_freak do_logjam do_drown do_header do_heartbleed do_mx_all_ips do_fs do_protocols do_rc4 do_grease do_robot do_renego \ do_freak do_logjam do_drown do_header do_heartbleed do_mx_all_ips do_fs do_protocols do_rc4 do_grease do_robot do_renego \
do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv \ do_cipherlists do_server_defaults do_server_preference do_ssl_poodle do_tls_fallback_scsv \
do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only; do do_sweet32 do_client_simulation do_cipher_match do_tls_sockets do_mass_testing do_display_only do_rating; do
printf "%-22s = %s\n" $gbl "${!gbl}" printf "%-22s = %s\n" $gbl "${!gbl}"
done done
# ${!var} is an indirect expansion, see https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html
# Example: https://stackoverflow.com/questions/8515411/what-is-indirect-expansion-what-does-var-mean#8515492
printf "%-22s : %s\n" URI: "$URI" printf "%-22s : %s\n" URI: "$URI"
} }
# This is determining the tests which should be skipped by --no-* or --disable-* a a cmdline arg.
# It achieves that by setting the do_<variables> according to the global array $SKIP_TESTS
#
set_skip_tests() {
local t
for t in ${SKIP_TESTS[@]} ; do
t="do_${t}"
# declare won't do it here --> local scope
eval "$t"=false
debugme printf '%s\n' "set $t: ${!t}"
done
}
# arg1: either switch+value (=) or switch # arg1: either switch+value (=) or switch
# arg2: value (if no = provided) # arg2: value (if no = provided)
parse_opt_equal_sign() { parse_opt_equal_sign() {
@ -20494,7 +20912,7 @@ parse_cmd_line() {
;; ;;
esac esac
# initializing # set all do_* globals to false
initialize_globals initialize_globals
while [[ $# -gt 0 ]]; do while [[ $# -gt 0 ]]; do
@ -20680,6 +21098,11 @@ parse_cmd_line() {
-g|--grease) -g|--grease)
do_grease=true do_grease=true
;; ;;
--disable-rating|--no-rating)
SKIP_TESTS+=("rating")
# TODO: a generic thing would be --disable-* / --no-* ,
# catch $1 and add it to the array ( #1502 )
;;
-9|--full) -9|--full)
set_scanning_defaults set_scanning_defaults
do_allciphers=false do_allciphers=false
@ -20690,18 +21113,18 @@ parse_cmd_line() {
ADDTL_CA_FILES="$(parse_opt_equal_sign "$1" "$2")" ADDTL_CA_FILES="$(parse_opt_equal_sign "$1" "$2")"
[[ $? -eq 0 ]] && shift [[ $? -eq 0 ]] && shift
;; ;;
--devel) ### this development feature will soon disappear --devel) echo -e "\nthis is a development feature and may disappear at any time"
# arg1: SSL/TLS protocol (SSLv2=22) # arg1: SSL/TLS protocol (SSLv2=22)
# arg2: list of cipher suites / hostname/ip # arg2: list of cipher suites / hostname/ip
# arg3: hostname/ip # arg3: hostname/ip
HEX_CIPHER="$TLS12_CIPHER" # DEBUG=3 ./testssl.sh --devel 04 "13,02, 13,01" google.com --> TLS 1.3
# DEBUG=3 ./testssl.sh --devel 04 "13,02, 13,01" google.com --> TLS 1.3 # DEBUG=3 ./testssl.sh --devel 03 "cc, 13, c0, 13" google.de --> TLS 1.2, old CHACHA/POLY
# DEBUG=3 ./testssl.sh --devel 03 "cc, 13, c0, 13" google.de --> TLS 1.2, old CHACHA/POLY # DEBUG=3 ./testssl.sh --devel 03 "cc,a8, cc,a9, cc,aa, cc,ab, cc,ac" blog.cloudflare.com --> new CHACHA/POLY
# DEBUG=3 ./testssl.sh --devel 03 "cc,a8, cc,a9, cc,aa, cc,ab, cc,ac" blog.cloudflare.com --> new CHACHA/POLY # DEBUG=3 ./testssl.sh --devel 01 yandex.ru --> TLS 1.0
# DEBUG=3 ./testssl.sh --devel 01 yandex.ru --> TLS 1.0
# DEBUG=3 ./testssl.sh --devel 00 <host which supports SSLv3> # DEBUG=3 ./testssl.sh --devel 00 <host which supports SSLv3>
# DEBUG=3 ./testssl.sh --devel 22 <host which still supports SSLv2> # DEBUG=3 ./testssl.sh --devel 22 <host which still supports SSLv2>
TLS_LOW_BYTE="$2"; HEX_CIPHER="$TLS12_CIPHER"
TLS_LOW_BYTE="$2"
if [[ $# -eq 4 ]]; then # protocol AND ciphers specified if [[ $# -eq 4 ]]; then # protocol AND ciphers specified
HEX_CIPHER="$3" HEX_CIPHER="$3"
shift shift
@ -20963,9 +21386,9 @@ parse_cmd_line() {
SSL_NATIVE=true SSL_NATIVE=true
;; ;;
--basicauth|--basicauth=*) --basicauth|--basicauth=*)
BASICAUTH="$(parse_opt_equal_sign "$1" "$2")" BASICAUTH="$(parse_opt_equal_sign "$1" "$2")"
[[ $? -eq 0 ]] && shift [[ $? -eq 0 ]] && shift
;; ;;
(--) shift (--) shift
break break
;; ;;
@ -20999,10 +21422,15 @@ parse_cmd_line() {
grep -q "BEGIN CERTIFICATE" "$fname" || fatal "\"$fname\" is not CA file in PEM format" $ERR_RESOURCE grep -q "BEGIN CERTIFICATE" "$fname" || fatal "\"$fname\" is not CA file in PEM format" $ERR_RESOURCE
done done
[[ "$DEBUG" -ge 5 ]] && debug_globals
count_do_variables count_do_variables
[[ $? -eq 0 ]] && set_scanning_defaults [[ $? -eq 0 ]] && set_scanning_defaults
set_skip_tests
[[ "$DEBUG" -ge 5 ]] && debug_globals
# Unless explicit disabled, check if rating can be enabled
# Should be called after set_scanning_defaults
! "$do_rating" && set_rating_state
CMDLINE_PARSED=true CMDLINE_PARSED=true
} }
@ -21171,6 +21599,10 @@ lets_roll() {
fileout_section_header $section_number true && ((section_number++)) fileout_section_header $section_number true && ((section_number++))
"$do_client_simulation" && { run_client_simulation; ret=$(($? + ret)); stopwatch run_client_simulation; } "$do_client_simulation" && { run_client_simulation; ret=$(($? + ret)); stopwatch run_client_simulation; }
fileout_section_header $section_number true && ((section_number++))
"$do_rating" && { run_rating; ret=$(($? + ret)); stopwatch run_rating; }
fi fi
fileout_section_footer true fileout_section_footer true
fi fi