From 68f0af2bf1e8e7762f33c3b3f3b5bf1ecfb043a9 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 22 Aug 2023 22:49:14 +0200 Subject: [PATCH] test SSL MitM attack verify that --ssl-verify-server-cert detects cert mismatch, but with --disable-ssl-verify-server-cert the connection succeeds --- mysql-test/lib/ssl-mitm.pl | 95 ++++++++++++++++++++++++ mysql-test/main/ssl_autoverify,win.rdiff | 17 +++++ mysql-test/main/ssl_autoverify.result | 10 +++ mysql-test/main/ssl_autoverify.test | 23 ++++++ 4 files changed, 145 insertions(+) create mode 100755 mysql-test/lib/ssl-mitm.pl diff --git a/mysql-test/lib/ssl-mitm.pl b/mysql-test/lib/ssl-mitm.pl new file mode 100755 index 00000000000..73652f0fbc9 --- /dev/null +++ b/mysql-test/lib/ssl-mitm.pl @@ -0,0 +1,95 @@ +#!/usr/bin/env perl + +# mitm for mariadb procotol with ssl + +use strict; +use warnings; +use autodie; +use Getopt::Long; +use Socket qw(PF_INET SOCK_STREAM INADDR_ANY INADDR_LOOPBACK sockaddr_in SO_REUSEADDR SOL_SOCKET); +use Net::SSLeay; + +my $opt_listen_port; +my $opt_connect_port; +my $opt_key; +my $opt_cert; +my $opt_ca; + +my %options=( + 'listen-on=i' => \$opt_listen_port, + 'connect-to=i' => \$opt_connect_port, + 'ssl-key=s' => \$opt_key, + 'ssl-cert=s' => \$opt_cert, + 'ssl-ca=s' => \$opt_ca, +); + +GetOptions(%options) or usage("Can't read options"); +die "not all options set" unless $opt_listen_port and $opt_connect_port + and $opt_key and $opt_cert and $opt_ca; + +Net::SSLeay::load_error_strings(); +Net::SSLeay::SSLeay_add_ssl_algorithms(); + +my $servctx = Net::SSLeay::CTX_new(); +my $servssl = Net::SSLeay::new($servctx); + +my $clictx = Net::SSLeay::CTX_new(); +Net::SSLeay::CTX_load_verify_locations($clictx, $opt_ca, ''); +Net::SSLeay::set_cert_and_key($clictx, $opt_cert, $opt_key); +my $clissl = Net::SSLeay::new($clictx); + +socket(my $listen, PF_INET, SOCK_STREAM, getprotobyname('tcp')); +setsockopt($listen, SOL_SOCKET, SO_REUSEADDR, pack("l", 1)); +bind($listen, sockaddr_in($opt_listen_port, INADDR_ANY)); +listen($listen, 1); +warn "$$: listening"; + +print ">> MitM active <<\n"; +close STDOUT; + +fork and exit; +warn "$$: forked"; + +accept(my $client, $listen); +warn "$$: accepted"; + +socket(my $server, PF_INET, SOCK_STREAM, getprotobyname('tcp')); +connect($server, sockaddr_in($opt_connect_port, INADDR_LOOPBACK)); +warn "$$: connected"; + +# handshake server -> client +recv $server, $_, 1e6, 0; +send $client, $_, 0; +warn "$$: handshake server -> client (".length.")"; + +# client replies with a dummy +recv $client, $_, 36, 0; +send $server, $_, 0; +warn "$$: client replies with a dummy (".length.")"; + +# SSL with server +Net::SSLeay::set_fd($servssl, fileno($server)); +Net::SSLeay::connect($servssl); +warn "$$: ssl connect server"; + +# SSL accept client +Net::SSLeay::set_fd($clissl, fileno($client)); +Net::SSLeay::accept($clissl); +warn "$$: ssl accept client"; + +while (1) { + $_=Net::SSLeay::read($clissl) or last; + warn "$$: ssl read client ".length.")"; + s/Detecting MitM/No MitM found!/; + Net::SSLeay::write($servssl, $_) or last; + warn "$$: ssl write server ".length.")"; + $_=Net::SSLeay::read($servssl) or last; + warn "$$: ssl read server ".length.")"; + Net::SSLeay::write($clissl, $_) or last; + warn "$$: ssl write client ".length.")"; +} + +close($server); +close($client); +close($listen); +warn "$$: ----------\n"; diff --git a/mysql-test/main/ssl_autoverify,win.rdiff b/mysql-test/main/ssl_autoverify,win.rdiff index 2477a42485b..a2e3f26ecb5 100644 --- a/mysql-test/main/ssl_autoverify,win.rdiff +++ b/mysql-test/main/ssl_autoverify,win.rdiff @@ -12,3 +12,20 @@ # mysql -unative -pfoo --ssl-verify-server-cert -e "select test.have_ssl()" test.have_ssl() yes +@@ -38,16 +38,6 @@ + # mysql -umulti -ppw2 --ssl-verify-server-cert -e "select test.have_ssl()" + test.have_ssl() + yes +->> MitM active << +-# mysql -uroot --disable-ssl-verify-server-cert -e "select 'Detecting MitM' as MitM, test.have_ssl()" +-MitM test.have_ssl() +-No MitM found! yes +->> MitM active << +-# mysql -unative -pfoo --ssl-verify-server-cert -e "select 'Detecting MitM', test.have_ssl()" +-ERROR 2026 (HY000): TLS/SSL error: Failed to verify the server certificate +->> MitM active << +-# mysql -ued -pbar --ssl-verify-server-cert -e "select 'Detecting MitM', test.have_ssl()" +-ERROR 2026 (HY000): TLS/SSL error: Failed to verify the server certificate + drop function have_ssl; + drop user native@'%'; + drop user ed@'%'; diff --git a/mysql-test/main/ssl_autoverify.result b/mysql-test/main/ssl_autoverify.result index 5eabad8a098..0e7a3dc9b94 100644 --- a/mysql-test/main/ssl_autoverify.result +++ b/mysql-test/main/ssl_autoverify.result @@ -38,6 +38,16 @@ yes # mysql -umulti -ppw2 --ssl-verify-server-cert -e "select test.have_ssl()" test.have_ssl() yes +>> MitM active << +# mysql -uroot --disable-ssl-verify-server-cert -e "select 'Detecting MitM' as MitM, test.have_ssl()" +MitM test.have_ssl() +No MitM found! yes +>> MitM active << +# mysql -unative -pfoo --ssl-verify-server-cert -e "select 'Detecting MitM', test.have_ssl()" +ERROR 2026 (HY000): TLS/SSL error: Failed to verify the server certificate +>> MitM active << +# mysql -ued -pbar --ssl-verify-server-cert -e "select 'Detecting MitM', test.have_ssl()" +ERROR 2026 (HY000): TLS/SSL error: Failed to verify the server certificate drop function have_ssl; drop user native@'%'; drop user ed@'%'; diff --git a/mysql-test/main/ssl_autoverify.test b/mysql-test/main/ssl_autoverify.test index 8ade01483ca..907817d677d 100644 --- a/mysql-test/main/ssl_autoverify.test +++ b/mysql-test/main/ssl_autoverify.test @@ -75,6 +75,29 @@ if ($MTR_COMBINATION_WIN) { --echo # mysql -umulti -ppw2 --ssl-verify-server-cert -e "select test.have_ssl()" --exec $MYSQL --protocol tcp -umulti -ppw2 --ssl-verify-server-cert -e "select test.have_ssl()" 2>&1 +# +# Now try MitM +# +if (!$MTR_COMBINATION_WIN) { +let mitm_port=$MASTER_MYPORT; +inc $mitm_port; +--exec perl lib/ssl-mitm.pl --listen-on $mitm_port --connect-to $MASTER_MYPORT --ssl-ca std_data/cacert.pem --ssl-key std_data/server-new-key.pem --ssl-cert std_data/server-new-cert.pem +--echo # mysql -uroot --disable-ssl-verify-server-cert -e "select 'Detecting MitM' as MitM, test.have_ssl()" +--exec $MYSQL --port $mitm_port --disable-ssl-verify-server-cert -uroot -e "select 'Detecting MitM' as MitM, test.have_ssl()" 2>&1 + +--exec perl lib/ssl-mitm.pl --listen-on $mitm_port --connect-to $MASTER_MYPORT --ssl-ca std_data/cacert.pem --ssl-key std_data/server-new-key.pem --ssl-cert std_data/server-new-cert.pem +--echo # mysql -unative -pfoo --ssl-verify-server-cert -e "select 'Detecting MitM', test.have_ssl()" +--replace_regex /TLS\/SSL error.*certificate[^\n]*/TLS\/SSL error: Failed to verify the server certificate/ +--error 1 +--exec $MYSQL --port $mitm_port -unative -pfoo --ssl-verify-server-cert -e "select 'Detecting MitM', test.have_ssl()" 2>&1 + +--exec perl lib/ssl-mitm.pl --listen-on $mitm_port --connect-to $MASTER_MYPORT --ssl-ca std_data/cacert.pem --ssl-key std_data/server-new-key.pem --ssl-cert std_data/server-new-cert.pem +--echo # mysql -ued -pbar --ssl-verify-server-cert -e "select 'Detecting MitM', test.have_ssl()" +--replace_regex /TLS\/SSL error.*certificate[^\n]*/TLS\/SSL error: Failed to verify the server certificate/ +--error 1 +--exec $MYSQL --port $mitm_port -ued -pbar --ssl-verify-server-cert -e "select 'Detecting MitM', test.have_ssl()" 2>&1 +} + drop function have_ssl; drop user native@'%'; drop user ed@'%';