Closed CrackerHax closed 7 years ago
Without having tested it yet with the link you provided:
You can define ciphers using the ssl_cipher_list
configuration option. You should set ssl_protocol_version
to 4 as well.
I'm going to run the test myself later, but I don't know if it works with self signed certificates.
Use ssl_cipher_list
= DES-CBC3-SHA:AES128-SHA:AES128-GCM-SHA256
(see cipher strings) and ssl_protocol_version
= 3
. Then you don't get any of the errors above. I still get some errors for using a too weak and self signed x509 certificate (the one in the resources folder) which does not match the hostname (my test system has no public domain name with an official certificate), so I get grade F for this test system anyway. But I think you do not have these problems with your certificate/hostname, so please just try the cipher configuration and tell me if it works.
I think some of the issues might also depend on the OpenSSL version you are using.
Yeah I don't know... I tried adding these options but nothing changes at all.
` const char *options[] = { "request_timeout_ms","30000","websocket_timeout_ms", "30000","enable_directory_listing","no","document_root", DOCUMENT_ROOT, "listening_por\ ts", PORT,"ssl_certificate","./ssl_cert.pem", "ssl_cipher_list","DES-CBC3-SHA:AES128-SHA:AES128-GCM-SHA256", "ssl_protocol_version", "2", 0};
CivetServer server(options);`
I used ssl_protocol_version 3 instead of 2, but maybe this does not matter for this test.
I had to get stronger certificates than the test certificates in the repository, but they are still self signed, so the test will not fully pass:
Untrusted Reasons: [The certificate is self-signed] [The certificate doesn't match hostname]
Also The RSA certificate provided has been signed using sha1WithRSAEncryption algorithm which is weak.
, and I don't know how to change this at the command line.
The RSA certificate provided is missing OCSP URI and crlDistributionPoints extension, making impossible to verify if it has been revoked.
So I'm not sure if I can succeed this test with the way I currently get my test certificates.
I tried both 2 and 3, it made no difference at all. the tests came out the same. In fact nothing I did made any difference at all, with or without ssl options.
I am using a Comodo certificate and it tests fine on my other ports, It's civetweb configuration that is the problem.
https://www.htbridge.com/ssl/?id=96d5027d156b485a7a14704972f9ac08f568c558d34c72a0de5f2c9b07e1528c are the results from the civetweb test
and https://www.htbridge.com/ssl/?id=fb341c807bcae277569252a5a97a3f5927283f277944f066513d070e458fac92 are the results from my normal port 443 https tests.
These links do not work for me:
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator at webmaster@localhost to inform them of the time this error occurred, and the actions you performed just before this error.
More information about this error may be available in the server error log.
Their site must be down. I am getting the same thing now.
I hope I did not kill it by testing some curious certificate configuration. I made it with OpenSSL 1.0.2h for Win32 using this sequence:
del server.*
c:\OpenSSL-Win32\bin\openssl.exe genrsa -des3 -out server.key 4096
c:\OpenSSL-Win32\bin\openssl.exe req -sha256 -new -key server.key -out server.csr -utf8
copy server.key server.key.orig
c:\OpenSSL-Win32\bin\openssl.exe rsa -in server.key.orig -out server.key
c:\OpenSSL-Win32\bin\openssl.exe x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
copy server.crt server.pem
type server.key >> server.pem
Haha.
Could you repeat the test with the following changes:
Add these defines:
#define SSL_OP_SINGLE_DH_USE (0x00100000L)
+ #define SSL_OP_CIPHER_SERVER_PREFERENCE (0x00400000L)
and
SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE);
+ SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_CIPHER_SERVER_PREFERENCE);
SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
I found the SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is not what you need regarding renegotiation. It seems one is supposed to count the renegotiation manually using a callback, and turn it off by setting a flag once a negotiation completed: http://www-01.ibm.com/support/docview.wss?uid=swg1PJ37087
ssl_info_callback(const SSL *ssl, int what, int ret) {
if (what & SSL_CB_HANDSHAKE_START) {
count negotiations and stop if it's too much
}
if (what & SSL_CB_HANDSHAKE_DONE) {
ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
}
}
The test is up again and I get a B+ rating for my server configuration with a self signed certificate. Remaining complaints are:
init_ssl
callback.There are a few small steps from the B+ to an A rating, but in the moment they all need to be done with callbacks, not with config entries. I will have a look if some of them could be made accessible with a configuration value.
I would consider adding some config values as an enhancement now. For the moment they have to be fixed using callbacks.
Do you agree?
Yeah that sounds good. Maybe the default values should be what you are using now for the B+ rating?
I still got a c with your changes... maybe I am doing something wrong. Do I need to add anything in my own code? Server options or anything?
I am not sure why but it still seems as if none of my options or changes affect SSL in any way at all (except specifying the path of the pem file). Could this be because I am using WITH_CPP=1 as a compile option?
I do not use C++ in CivetWeb, I just keep the current C++ wrapper, but all features are implemented in C. I did not test it, but I can not imagine this has anything to do with WITH_CPP=1
Try ssl_protocol_version 3 - not 2 - this will disable SSL3 and prevent POODLE. The cipher list in your test has some bad ciphers, try my minimal set of 3 ciphers and then add more, one by one, and check the rating. Add the SSL_OP_CIPHER_SERVER_PREFERENCE above (in https://github.com/civetweb/civetweb/pull/227, we discussed it is not really a security improvement, since a client can still force a bad cipher, but this choice seems to improve the test rating).
If you still get a C rating, maybe try a self signed certificate (even if you finally need an official one), to check if the certificate is limiting the ratio. My steps to create the certificate: see above. Use openssl_1.02h.
You don't seem to understand what I am telling you....
Changing the options has ZERO effect. I still get exactly the same report no matter what I change. I tried all the ssl protocol versions, I tried all your recommended changes. I just now tried changing the number of cyphers and still no change at all.
No effect? If you change ssl_protocol_version to 0 ? It should change the "List of all SSL/TLS protocols supported by the server". In the beginning, it was a little confusing for me that the site does not refresh the results if I enter the server address once more and/or click refresh in the browser. The site only refreshes the result, if the blue "Refresh results" button in the OPTIONS box is pressed. I do observe an effect or the server config on the result of this test.
Meanwhile I managed to get an A- result:
Create a (self signed) cert:
del server.*
c:\OpenSSL-Win32\bin\openssl.exe genrsa -des3 -out server.key 4096
c:\OpenSSL-Win32\bin\openssl.exe req -sha256 -new -key server.key -out server.csr -utf8
copy server.key server.key.orig
c:\OpenSSL-Win32\bin\openssl.exe rsa -in server.key.orig -out server.key
echo [ v3_ca ] > server.ext.txt
echo [ req ] >> server.ext.txt
echo req_extensions = my_extensions >> server.ext.txt
echo [ my_extensions ] >> server.ext.txt
echo extendedKeyUsage=serverAuth >> server.ext.txt
c:\OpenSSL-Win32\bin\openssl.exe x509 -req -days 365 -extensions v3_ca -extfile server.ext.txt -in server.csr -signkey server.key -out server.crt
copy server.crt server.pem
type server.key >> server.pem
and this config
authentication_domain 1.2.3.4 <<--- ip or common name from the certificate
access_log_file d:\log\access.log
error_log_file d:\log\error.log
enable_keep_alive yes
listening_ports 80,[::]:8080,8080,443s
document_root r:\
ssl_certificate d:\cert\server.pem
ssl_ca_file D:\civetweb\civetweb\resources\cert\client.pem
ssl_default_verify_paths no
ssl_cipher_list DES-CBC3-SHA:AES128-SHA:AES128-GCM-SHA256
ssl_protocol_version 3
lua_preload_file d:\lualib\preload.lua
and the SSL_OP_CIPHER_SERVER_PREFERENCE above
AHH that was my problem... I wasn't hitting full refresh.
I got an A that time but my provider is still saying there is a problem connecting for webhook callbacks... "An error occurred while validating SSL connectivity. Please make sure the URL you supplied is using TLSv1 or above, and its SSL certificate is installed properly."
That sure doesn't tell me much.
They did tell me my port 443 was ok (which is not civetweb) so here are the differences in the reports.
Civetweb: SERVER DOES NOT PREFER PFS ENABLED CIPHER SUITES The server does not prefer cipher suites providing strong Perfect Forward Secrecy (PFS). We advise to configure your server to prefer cipher suites with ECDHE or DHE key exchange.
SERVER SUPPORTS CLIENT-INITIATED SECURE RENEGOTIATION The server supports client-initiated secure renegotiation which may be unsafe and allow Denial of Service attacks.
SERVER PREFERRED CIPHER SUITES Preferred cipher suite for each protocol supported (except SSLv2). Expected configuration are ciphers allowed by PCI DSS and enabling PFS: TLSv1.1 TLS_RSA_WITH_3DES_EDE_CBC_SHA - Misconfiguration or weakness TLSv1.2 TLS_RSA_WITH_3DES_EDE_CBC_SHA - Misconfiguration or weakness
These are the same weaknesses I still have as well. So we are finally at the same configuration - except I still got the A- instead of A for using a self signed certificate. And I did not add the HSTS header yet, so I got this additional warning. Did you add this header?
A DHE for PFS needs to be set programmatically: http://linux.die.net/man/3/ssl_ctx_set_tmp_dh There is currently no config option. It can be done using the 'init_ssl` callback. Setting SSL_OP_CIPHER_SERVER_PREFERENCE can be done in this callback as well, so there is no need to change civetweb.c. You need to add the cipher as well (see https://www.openssl.org/docs/manmaster/apps/ciphers.html, https://testssl.sh/openssl-rfc.mappping.html, https://support.kemptechnologies.com/hc/en-us/articles/204148725-How-do-I-get-an-A-rating-at-SSL-Labs- ): Secure negotiation can be solved by the ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS; above (although I would do it differently, but this will not be detected by the test).
Yes I got
SERVER DOES NOT PROVIDE HSTS The server does not send the HTTP-Strict-Transport-Security. We advise to enable it to enforce the user to browse the website in HTTPS.
BUT, I got that on my https port too (which got a+), so apparently thats not a problem.
So you got an A+ rating with CivetWeb now?
Not on civetweb no.
Did you try the steps above? In particular, did you try setting DHE?
Not yet, this is kind of a lot to learn. I would rather have it just work. Haha.
I have this
static int init_ssl_callback(void *ssl_context, void *user_data)
{
struct mg_connection *conn = (struct mg_connection *)user_data;
BIO *bio = BIO_new_file(PEM_PATH, "r");
DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
SSL_CTX_set_tmp_dh(conn->ctx->ssl_ctx, dh); // <---- problem with this
DH_free(dh);
}
but ssl_context does not work in SSL_CTX_set_tmp_dh(ssl_context,dh) and it is saying conn->ctx->ssl_ctx is an incomplete type.
If we can get this to work it would be good to add to the examples.
There are examples in the OpenSSL Wiki: https://wiki.openssl.org/index.php/Diffie-Hellman_parameters
The callback in civetweb must look like (not tested yet):
int init_ssl(void *ssl_context, void *user_data) {
DH *dh = get_dh2236 ();
if (! dh) return -1;
if (1 != SSL_CTX_set_tmp_dh (ctx, dh)) return -1;
DH_free (dh);
EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
if (! ecdh) return -1;
if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) return -1;
EC_KEY_free (ecdh);
return 0;
}
No, I mean it would be good to get this in the civetweb example code
I'm not sure how to do this as an example. It's basically a process, starting by first getting your own DH parameters. From the CMD window in Windows (or the Linux shell):
D:\civetweb>openssl dhparam -C 2236
Generating DH parameters, 2236 bit long safe prime, generator 2
This is going to take a long time
..............................+.......+.................................................................................
...................................................+...................+................................................
........................................................................................................................
............................................................+................+..........................................
............+...........................+.................................+.......+.....................................
.........+.............................................................+................................................
....................+.........+.........................................................................................
......................+.................................................................................................
........................................................................................................................
.................................................+......................................................................
........................................................................................................................
............+.......................................................+.........................+.........................
..........................................................................................................+.............
.........................+........................................+.....................................................
......................................+.................................................................................
..................................................+.................................+...................................
..............................................................+.......................................................+.
..........................................................+.............................................................
..................+.....................................................................................................
........................................................................................................................
........................................................................................................................
...............................+.........+..............................................................................
........................................................................................................................
...................................................................+............+.......................................
........................................................................................................................
.............................................................................................+..........................
...........................................................+............................................................
........................................................................................................................
..................+......................................+..............................................................
...............................................................+........................................................
......+.................................................................................................................
........................................................................................................................
......................................................++*++*
#ifndef HEADER_DH_H
#include <openssl/dh.h>
#endif
DH *get_dh2236()
{
static unsigned char dh2236_p[]={
0x0E,0x97,0x6E,0x6A,0x88,0x84,0xD2,0xD7,0x55,0x6A,0x17,0xB7,
0x81,0x9A,0x98,0xBC,0x7E,0xD1,0x6A,0x44,0xB1,0x18,0xE6,0x25,
0x3A,0x62,0x35,0xF0,0x41,0x91,0xE2,0x16,0x43,0x9D,0x8F,0x7D,
0x5D,0xDA,0x85,0x47,0x25,0xC4,0xBA,0x68,0x0A,0x87,0xDC,0x2C,
0x33,0xF9,0x75,0x65,0x17,0xCB,0x8B,0x80,0xFE,0xE0,0xA8,0xAF,
0xC7,0x9E,0x82,0xBE,0x6F,0x1F,0x00,0x04,0xBD,0x69,0x50,0x8D,
0x9C,0x3C,0x41,0x69,0x21,0x4E,0x86,0xC8,0x2B,0xCC,0x07,0x4D,
0xCF,0xE4,0xA2,0x90,0x8F,0x66,0xA9,0xEF,0xF7,0xFC,0x6F,0x5F,
0x06,0x22,0x00,0xCB,0xCB,0xC3,0x98,0x3F,0x06,0xB9,0xEC,0x48,
0x3B,0x70,0x6E,0x94,0xE9,0x16,0xE1,0xB7,0x63,0x2E,0xAB,0xB2,
0xF3,0x84,0xB5,0x3D,0xD7,0x74,0xF1,0x6A,0xD1,0xEF,0xE8,0x04,
0x18,0x76,0xD2,0xD6,0xB0,0xB7,0x71,0xB6,0x12,0x8F,0xD1,0x33,
0xAB,0x49,0xAB,0x09,0x97,0x35,0x9D,0x4B,0xBB,0x54,0x22,0x6E,
0x1A,0x33,0x18,0x02,0x8A,0xF4,0x7C,0x0A,0xCE,0x89,0x75,0x2D,
0x10,0x68,0x25,0xA9,0x6E,0xCD,0x97,0x49,0xED,0xAE,0xE6,0xA7,
0xB0,0x07,0x26,0x25,0x60,0x15,0x2B,0x65,0x88,0x17,0xF2,0x5D,
0x2C,0xF6,0x2A,0x7A,0x8C,0xAD,0xB6,0x0A,0xA2,0x57,0xB0,0xC1,
0x0E,0x5C,0xA8,0xA1,0x96,0x58,0x9A,0x2B,0xD4,0xC0,0x8A,0xCF,
0x91,0x25,0x94,0xB4,0x14,0xA7,0xE4,0xE2,0x1B,0x64,0x5F,0xD2,
0xCA,0x70,0x46,0xD0,0x2C,0x95,0x6B,0x9A,0xFB,0x83,0xF9,0x76,
0xE6,0xD4,0xA4,0xA1,0x2B,0x2F,0xF5,0x1D,0xE4,0x06,0xAF,0x7D,
0x22,0xF3,0x04,0x30,0x2E,0x4C,0x64,0x12,0x5B,0xB0,0x55,0x3E,
0xC0,0x5E,0x56,0xCB,0x99,0xBC,0xA8,0xD9,0x23,0xF5,0x57,0x40,
0xF0,0x52,0x85,0x9B,
};
static unsigned char dh2236_g[]={
0x02,
};
DH *dh;
if ((dh=DH_new()) == NULL) return(NULL);
dh->p=BN_bin2bn(dh2236_p,sizeof(dh2236_p),NULL);
dh->g=BN_bin2bn(dh2236_g,sizeof(dh2236_g),NULL);
if ((dh->p == NULL) || (dh->g == NULL))
{ DH_free(dh); return(NULL); }
return(dh);
}
-----BEGIN DH PARAMETERS-----
MIIBHwKCARgOl25qiITS11VqF7eBmpi8ftFqRLEY5iU6YjXwQZHiFkOdj31d2oVH
JcS6aAqH3Cwz+XVlF8uLgP7gqK/HnoK+bx8ABL1pUI2cPEFpIU6GyCvMB03P5KKQ
j2ap7/f8b18GIgDLy8OYPwa57Eg7cG6U6Rbht2Muq7LzhLU913TxatHv6AQYdtLW
sLdxthKP0TOrSasJlzWdS7tUIm4aMxgCivR8Cs6JdS0QaCWpbs2XSe2u5qewByYl
YBUrZYgX8l0s9ip6jK22CqJXsMEOXKihlliaK9TAis+RJZS0FKfk4htkX9LKcEbQ
LJVrmvuD+Xbm1KShKy/1HeQGr30i8wQwLkxkEluwVT7AXlbLmbyo2SP1V0DwUoWb
AgEC
-----END DH PARAMETERS-----
Then you copy this code into the application you compile.
Maybe I find some better way.
Ok, using that with
static int init_ssl_callback(void *ssl_context, void *user_data)
{
struct ssl_ctx_st *ctx = (struct ssl_ctx_st *)ssl_context;
SSL_CTX_set_tmp_dh(ctx, get_dh2236());
}
Completely destroyed all SSL and got grade F
It looks like using this callback at all (even an empty callback) gets grade F.
Maybe SSL initialization failed completely then. All return values OK?
Yes ssl initialization fails when using init_ssl_callback at all.
static int init_ssl_callback(void *ssl_context, void *user_data)
{
// empty callback
}
in main()
CivetCallbacks cbs;
cbs.init_ssl = init_ssl_callback;
CivetServer server(options, &cbs);
You need to return 0 from the callback.
Ok I have everything working except the renegotiation. I think adding renegotiation should give me an A+ but I am currently at an A.
Had to include this:
Here is my cipher list for the server options (same ciphers being used by apache2):
#define SSL_CIPHERS "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA"
Added the code from 'openssl dhparam -C 2236' (although 2048 can get you an A+ too)
_edit: Added DH_free _ My callback:
static int init_ssl_callback(void *ssl_context, void *user_data)
{
struct ssl_ctx_st *ctx = (struct ssl_ctx_st *)ssl_context;
SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE );
DH *dh = get_dh2236();
SSL_CTX_set_tmp_dh(ctx,dh );
DH_free(dh);
return(0);
}
And my callback code in main()
CivetCallbacks cbs;
cbs.init_ssl = init_ssl_callback;
CivetServer server(options, &cbs);
I think your callback causes a minor memory leak (DH_free is missing) - a couple of bytes every mg_start
/mg_stop
- so probably not an issue if you anyway start and stop the server with the application.
You don't need the elliptic curve part?
EC_KEY *ecdh = EC_KEY_new_by_curve_name (NID_X9_62_prime256v1);
if (! ecdh) return -1;
if (1 != SSL_CTX_set_tmp_ecdh (ctx, ecdh)) return -1;
EC_KEY_free (ecdh);
I found somewhere, to disable renegotiation, you need to to use SSL_set_info_callback(ctx, ssl_info_callback) to add a callback, and you need to define a function like:
void ssl_info_callback(const SSL *ssl, int what, int ret) {
if (what & SSL_CB_HANDSHAKE_DONE) {
ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
}
}
So you need to access the members of the SSL structure directly - it seems there is no API.
http://openssl.6102.n7.nabble.com/Disabling-Secure-Renegotiation-in-0-9-8-td46938.html
Maybe ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
can be done in sslize
in civetweb.c
after SSL_new
instead of the callback - I did not test this.
I put in a ssl_info callback but conn->ssl->s3->flags keeps giving me "error: dereferencing pointer to incomplete type" and I can't figure out why. Ideas? ssl->s3->flags should be included in ssl.h shouldn't they? Anyway here is most of it.
#define SSL_set_info_callback \
(*(void(*)(SSL*,void *))ssl_sw[32].ptr)
in static struct ssl_func ssl_sw[] ...
{"SSL_set_info_callback", NULL},
...
static void
ssl_info_callback(SSL *ssl, int where, int ret)
{
(void)ret;
// SSL_CB_HANDSHAKE_DONE
if ((where & 0x10) != 0) {
// SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS
ssl->s3->flags |= 0x0001;
}
}
...
SSL_set_info_callback(conn->ssl, ssl_info_callback);
NO_SSL_DL
compile option? civetweb.c
? Did you include ssl.h directly in this file?This is all in civetweb.c, and not using NO_SSL_DL option (if I do I get all sorts of undefined reference errors, even though I have libssl-dev installed).
Then, of course you get an "incomplete type".
In line 1010:
#if defined(NO_SSL_DL)
#include <openssl/ssl.h> --- this is not used
...
#else
/* SSL loaded dynamically from DLL.
* I put the prototypes here to be independent from OpenSSL source
* installation. */
typedef struct ssl_st SSL; --- this is an incomplete type
There is no definition of struct ssl_st in civetweb.c, so you cannot access the members.
You will have to deal with your build environment to get NO_SSL_DL working. OR you move the callback to a different file and include ssl.h there OR you copy the definition of the SSL structure from this header (for a test - but you must take care of the license)
I ended up just setting up apache2 to proxy civetweb.. easy a+.
In the last year, there are ware several security improvements for version 1.10 (currently in release candidate state). There is also an example for a HTTPS configuration with strict security settings here - it passes different SSL, HTTPS and HTTP-security-header tests.
Since the original issue was solved a year ago with a proxy anyway, I think it's time to close this issue. The current source passes the security test without a proxy, if the configuration is set properly.
I need to use SSL for webhook callbacks but my provider refuses to accept SSL as handled by civetweb.
You can test it here (this test will accept specific ports to test): https://www.htbridge.com/ssl/
It receives a grade of C while port 443 on my server receives a A+
"The server is vulnerable to POODLE over SSL"
""SERVER DOES NOT HAVE CIPHER PREFERENCE The server does not have preferred cipher suites. We advise to enable this feature in order to use only the strongest suite available."
"SERVER SUPPORTS CLIENT-INITIATED SECURE RENEGOTIATION The server supports client-initiated secure renegotiation which may be unsafe and allow Denial of Service attacks."