Uploaded image for project: 'MariaDB Connector/C'
  1. MariaDB Connector/C
  2. CONC-648

Client improperly accepts error packets prior to TLS handshake

Details

    Description

      If the MariaDB client is running with --ssl --ssl-verify-server-cert, it should not trust any application-level traffic received prior to the completion of the TLS handshake and the validation of the server's TLS certificate.

      The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly specified --ssl --ssl-verify-server-cert.

      Demonstration:

      1. Build dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability
        • This commit modifies the server to unconditionally send an error packet to the client, prior to authentication and prior to TLS handshake and server certificate validation:

          diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
          index 80d52ce18fc..283b095f2eb 100644
          --- a/sql/sql_acl.cc
          +++ b/sql/sql_acl.cc
          @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
               DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                           mpvio.status == MPVIO_EXT::SUCCESS);
             }
          +  else if (1)
          +  {
          +    my_error(ER_INTERNAL_ERROR, MYF(0),
          +             "Client will accept this error as genuine even if running with "
          +             "--ssl --ssl-verify-server-cert, and even though this error is "
          +             "sent in plaintext PRIOR TO TLS HANDSHAKE.");
          +    res= CR_ERROR;
          +  }
             else
             {
               /* mark the thd as having no scramble yet */

      2. Start the server, e.g.

        $ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
        2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
        Version: '10.11.4-MariaDB-debug'  socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock'  port: 3306  Source distribution

      3. Attempt to connect to it with --ssl --ssl-verify-server-cert:

        $ client/mariadb -h 127.0.0.1
        ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.

      Running tcpdump in the background confirms that the client is improperly accepting the error packet, even though it has been sent in plaintext and without a TLS handshake:

      $ sudo tcpdump -n -X -i lo tcp port 3306
      tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
      listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
      15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
              0x0000:  4500 003c 2b03 4000 8006 d1b6 7f00 0001  E..<+.@.........       # TCP handshake, no application-level content
              0x0010:  7f00 0001 9d2a 0cea 5c31 bae3 0000 0000  .....*..\1......
              0x0020:  a002 ffd7 fe30 0000 0204 ffd7 0402 080a  .....0..........
              0x0030:  06c3 d238 0000 0000 0103 0307            ...8........
      15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
              0x0000:  4500 003c 0000 4000 8006 fcb9 7f00 0001  E..<..@.........       # TCP handshake, no application-level content
              0x0010:  7f00 0001 0cea 9d2a c10b a17f 5c31 bae4  .......*....\1..
              0x0020:  a012 ffcb fe30 0000 0204 ffd7 0402 080a  .....0..........
              0x0030:  06c3 d238 06c3 d238 0103 0307            ...8...8....
      15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
              0x0000:  4500 0034 2b04 4000 8006 d1bd 7f00 0001  E..4+.@.........       # TCP handshake, no application-level content
              0x0010:  7f00 0001 9d2a 0cea 5c31 bae4 c10b a180  .....*..\1......
              0x0020:  8010 0200 fe28 0000 0101 080a 06c3 d238  .....(.........8
              0x0030:  06c3 d238                                ...8
      15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
              0x0000:  4508 00f0 622c 4000 8006 99d1 7f00 0001  E...b,@.........
              0x0010:  7f00 0001 0cea 9d2a c10b a180 5c31 bae4  .......*....\1..
              0x0020:  8018 0200 fee4 0000 0101 080a 06c3 d23b  ...............;
              0x0030:  06c3 d238 b800 0000 ff17 0749 6e74 6572  ...8.......Inter       # [b8 00 00 00]: header { [b8 00 00] = length following header, 0xb8 bytes, [00]: sequence number (https://mariadb.com/kb/en/0-packet) }
              0x0040:  6e61 6c20 6572 726f 723a 2043 6c69 656e  nal.error:.Clien       #     [ff]: ERR_Packet (https://mariadb.com/kb/en/err_packet/)
              0x0050:  7420 7769 6c6c 2061 6363 6570 7420 7468  t.will.accept.th       #     [17 07]: error ER_INTERNAL_ERROR (https://mariadb.com/kb/en/mariadb-error-codes)
              0x0060:  6973 2065 7272 6f72 2061 7320 6765 6e75  is.error.as.genu       #     [remaining 0xb5 bytes] human-readable message = "Internal error: Client … TLS HANDSHAKE."
              0x0070:  696e 6520 6576 656e 2069 6620 7275 6e6e  ine.even.if.runn
              0x0080:  696e 6720 7769 7468 202d 2d73 736c 202d  ing.with.--ssl.-
              0x0090:  2d73 736c 2d76 6572 6966 792d 7365 7276  -ssl-verify-serv
              0x00a0:  6572 2d63 6572 742c 2061 6e64 2065 7665  er-cert,.and.eve
              0x00b0:  6e20 7468 6f75 6768 2074 6869 7320 6572  n.though.this.er
      	0x00c0:  726f 7220 6973 2073 656e 7420 696e 2070  ror.is.sent.in.p
      	0x00d0:  6c61 696e 7465 7874 2050 5249 4f52 2054  laintext.PRIOR.T
      	0x00e0:  4f20 544c 5320 4841 4e44 5348 414b 452e  O.TLS.HANDSHAKE.
      

      Attachments

        Issue Links

          Activity

            dlenski Daniel Lenski (Inactive) created issue -
            dlenski Daniel Lenski (Inactive) made changes -
            Field Original Value New Value
            Description If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly
            specified {{--ssl --ssl-verify-server-cert}}{color:red}.

            Demonstration:

            # Build https://github.com/dlenski/mariadb-server/commit/11f27fc57596f29e874e8a4cc8c142b624f07191
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting
            the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly
            specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build https://github.com/dlenski/mariadb-server/commit/11f27fc57596f29e874e8a4cc8c142b624f07191
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting
            the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            dlenski Daniel Lenski (Inactive) made changes -
            Description If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly
            specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build https://github.com/dlenski/mariadb-server/commit/11f27fc57596f29e874e8a4cc8c142b624f07191
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting
            the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly
            specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build https://github.com/dlenski/mariadb-server/commit/ef6c7521146aa229785552228d095bd5b2446c65
            #* This commit modifies the server to unconditionally send an error packet to the client, prior to authentication _and_ prior to TLS handshake and server certificate validation: {code:c}diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
            index 80d52ce18fc..283b095f2eb 100644
            --- a/sql/sql_acl.cc
            +++ b/sql/sql_acl.cc
            @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
                 DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                             mpvio.status == MPVIO_EXT::SUCCESS);
               }
            + else if (1)
            + {
            + my_error(ER_INTERNAL_ERROR, MYF(0),
            + "Client will accept this error as genuine even if running with "
            + "--ssl --ssl-verify-server-cert, and even though this error is "
            + "sent in plaintext PRIOR TO TLS HANDSHAKE.");
            + res= CR_ERROR;
            + }
               else
               {
                 /* mark the thd as having no scramble yet */{code}
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting
            the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            dlenski Daniel Lenski (Inactive) made changes -
            Description If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly
            specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build https://github.com/dlenski/mariadb-server/commit/ef6c7521146aa229785552228d095bd5b2446c65
            #* This commit modifies the server to unconditionally send an error packet to the client, prior to authentication _and_ prior to TLS handshake and server certificate validation: {code:c}diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
            index 80d52ce18fc..283b095f2eb 100644
            --- a/sql/sql_acl.cc
            +++ b/sql/sql_acl.cc
            @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
                 DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                             mpvio.status == MPVIO_EXT::SUCCESS);
               }
            + else if (1)
            + {
            + my_error(ER_INTERNAL_ERROR, MYF(0),
            + "Client will accept this error as genuine even if running with "
            + "--ssl --ssl-verify-server-cert, and even though this error is "
            + "sent in plaintext PRIOR TO TLS HANDSHAKE.");
            + res= CR_ERROR;
            + }
               else
               {
                 /* mark the thd as having no scramble yet */{code}
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting
            the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly
            specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build [dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability|https://github.com/dlenski/mariadb-server/commit/demonstration_of_CONC-648_vulnerability]
            #* This commit modifies the server to unconditionally send an error packet to the client, prior to authentication _and_ prior to TLS handshake and server certificate validation: {code:c}diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
            index 80d52ce18fc..283b095f2eb 100644
            --- a/sql/sql_acl.cc
            +++ b/sql/sql_acl.cc
            @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
                 DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                             mpvio.status == MPVIO_EXT::SUCCESS);
               }
            + else if (1)
            + {
            + my_error(ER_INTERNAL_ERROR, MYF(0),
            + "Client will accept this error as genuine even if running with "
            + "--ssl --ssl-verify-server-cert, and even though this error is "
            + "sent in plaintext PRIOR TO TLS HANDSHAKE.");
            + res= CR_ERROR;
            + }
               else
               {
                 /* mark the thd as having no scramble yet */{code}
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting
            the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            dlenski Daniel Lenski (Inactive) made changes -
            Description If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly
            specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build [dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability|https://github.com/dlenski/mariadb-server/commit/demonstration_of_CONC-648_vulnerability]
            #* This commit modifies the server to unconditionally send an error packet to the client, prior to authentication _and_ prior to TLS handshake and server certificate validation: {code:c}diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
            index 80d52ce18fc..283b095f2eb 100644
            --- a/sql/sql_acl.cc
            +++ b/sql/sql_acl.cc
            @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
                 DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                             mpvio.status == MPVIO_EXT::SUCCESS);
               }
            + else if (1)
            + {
            + my_error(ER_INTERNAL_ERROR, MYF(0),
            + "Client will accept this error as genuine even if running with "
            + "--ssl --ssl-verify-server-cert, and even though this error is "
            + "sent in plaintext PRIOR TO TLS HANDSHAKE.");
            + res= CR_ERROR;
            + }
               else
               {
                 /* mark the thd as having no scramble yet */{code}
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting
            the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly
            specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build [dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability|https://github.com/dlenski/mariadb-server/commit/demonstration_of_CONC-648_vulnerability]
            #* This commit modifies the server to unconditionally send an error packet to the client, prior to authentication _and_ prior to TLS handshake and server certificate validation: {code:c}diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
            index 80d52ce18fc..283b095f2eb 100644
            --- a/sql/sql_acl.cc
            +++ b/sql/sql_acl.cc
            @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
                 DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                             mpvio.status == MPVIO_EXT::SUCCESS);
               }
            + else if (1)
            + {
            + my_error(ER_INTERNAL_ERROR, MYF(0),
            + "Client will accept this error as genuine even if running with "
            + "--ssl --ssl-verify-server-cert, and even though this error is "
            + "sent in plaintext PRIOR TO TLS HANDSHAKE.");
            + res= CR_ERROR;
            + }
               else
               {
                 /* mark the thd as having no scramble yet */{code}
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            dlenski Daniel Lenski (Inactive) made changes -
            Description If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly
            specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build [dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability|https://github.com/dlenski/mariadb-server/commit/demonstration_of_CONC-648_vulnerability]
            #* This commit modifies the server to unconditionally send an error packet to the client, prior to authentication _and_ prior to TLS handshake and server certificate validation: {code:c}diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
            index 80d52ce18fc..283b095f2eb 100644
            --- a/sql/sql_acl.cc
            +++ b/sql/sql_acl.cc
            @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
                 DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                             mpvio.status == MPVIO_EXT::SUCCESS);
               }
            + else if (1)
            + {
            + my_error(ER_INTERNAL_ERROR, MYF(0),
            + "Client will accept this error as genuine even if running with "
            + "--ssl --ssl-verify-server-cert, and even though this error is "
            + "sent in plaintext PRIOR TO TLS HANDSHAKE.");
            + res= CR_ERROR;
            + }
               else
               {
                 /* mark the thd as having no scramble yet */{code}
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build [dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability|https://github.com/dlenski/mariadb-server/commit/demonstration_of_CONC-648_vulnerability]
            #* This commit modifies the server to unconditionally send an error packet to the client, prior to authentication _and_ prior to TLS handshake and server certificate validation: {code:c}diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
            index 80d52ce18fc..283b095f2eb 100644
            --- a/sql/sql_acl.cc
            +++ b/sql/sql_acl.cc
            @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
                 DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                             mpvio.status == MPVIO_EXT::SUCCESS);
               }
            + else if (1)
            + {
            + my_error(ER_INTERNAL_ERROR, MYF(0),
            + "Client will accept this error as genuine even if running with "
            + "--ssl --ssl-verify-server-cert, and even though this error is "
            + "sent in plaintext PRIOR TO TLS HANDSHAKE.");
            + res= CR_ERROR;
            + }
               else
               {
                 /* mark the thd as having no scramble yet */{code}
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}

            I based demonstration_of_CONC-648_vulnerability against MariaDB server 10.11 and client v3.3.5, but it's trivial to demonstrate that earlier versions are equally vulnerable.

            dlenski Daniel Lenski (Inactive) added a comment - I based demonstration_of_CONC-648_vulnerability against MariaDB server 10.11 and client v3.3.5, but it's trivial to demonstrate that earlier versions are equally vulnerable.

            Do you think it's a problem? An "untrusted on-path attacker" can send TCP RST flag to abort the connection, wouldn't it basically have the same effect?

            serg Sergei Golubchik added a comment - Do you think it's a problem? An "untrusted on-path attacker" can send TCP RST flag to abort the connection, wouldn't it basically have the same effect?
            serg Sergei Golubchik made changes -
            Status Open [ 1 ] Needs Feedback [ 10501 ]

            Do you think it's a problem?

            Yes, I think it's a major vulnerability if a client is intended not to trust unencrypted communications, and yet it turns out to trusts unencrypted communication.

            I've merely made an extremely simple demo of the vulnerability here, but it's quite likely that it's worse than this, and that the client will also trust other types of traffic before completing the TLS handshake.

            An "untrusted on-path attacker" can send TCP RST flag to abort the connection, wouldn't it basically have the same effect?

            An attacker interfering with layers below a TLS-based channel can disrupt communication between the peers, but should not be able to inject traffic that either peer accepts as genuine. A deviation from that (such as CVE-2009-3555 in which an attacker can inject TLS renegotiations along with unauthenticated data) is a vulnerability.

            Due to this vulnerability in MariaDB, an on-path attacker can signal an arbitrary error to a client, which might (for example) cause the client to alter its retry behavior or to misdiagnose a connection problem.

            And it can get much worse than that: I discovered this vulnerability in MariaDB because I'm working on an approach to MDEV-15935 ("server redirection mechanism") in which the server tells the client to switch to another server using an error packet. If error packets are indeed chosen as the mechanism for server redirection, this means that attackers would be able to redirect clients to arbitary attacker-controlled servers even when the clients think they are using TLS.

            dlenski Daniel Lenski (Inactive) added a comment - Do you think it's a problem? Yes, I think it's a major vulnerability if a client is intended not to trust unencrypted communications, and yet it turns out to trusts unencrypted communication. I've merely made an extremely simple demo of the vulnerability here, but it's quite likely that it's worse than this, and that the client will also trust other types of traffic before completing the TLS handshake. An "untrusted on-path attacker" can send TCP RST flag to abort the connection, wouldn't it basically have the same effect? An attacker interfering with layers below a TLS-based channel can disrupt communication between the peers, but should not be able to inject traffic that either peer accepts as genuine. A deviation from that (such as CVE-2009-3555 in which an attacker can inject TLS renegotiations along with unauthenticated data) is a vulnerability. Due to this vulnerability in MariaDB, an on-path attacker can signal an arbitrary error to a client, which might (for example) cause the client to alter its retry behavior or to misdiagnose a connection problem. And it can get much worse than that: I discovered this vulnerability in MariaDB because I'm working on an approach to MDEV-15935 ("server redirection mechanism") in which the server tells the client to switch to another server using an error packet . If error packets are indeed chosen as the mechanism for server redirection, this means that attackers would be able to redirect clients to arbitary attacker-controlled servers even when the clients think they are using TLS .
            dlenski Daniel Lenski (Inactive) made changes -
            Description If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build [dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability|https://github.com/dlenski/mariadb-server/commit/demonstration_of_CONC-648_vulnerability]
            #* This commit modifies the server to unconditionally send an error packet to the client, prior to authentication _and_ prior to TLS handshake and server certificate validation: {code:c}diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
            index 80d52ce18fc..283b095f2eb 100644
            --- a/sql/sql_acl.cc
            +++ b/sql/sql_acl.cc
            @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
                 DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                             mpvio.status == MPVIO_EXT::SUCCESS);
               }
            + else if (1)
            + {
            + my_error(ER_INTERNAL_ERROR, MYF(0),
            + "Client will accept this error as genuine even if running with "
            + "--ssl --ssl-verify-server-cert, and even though this error is "
            + "sent in plaintext PRIOR TO TLS HANDSHAKE.");
            + res= CR_ERROR;
            + }
               else
               {
                 /* mark the thd as having no scramble yet */{code}
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@.........
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            {noformat}
            If the MariaDB client is running with {{--ssl --ssl-verify-server-cert}}, it *should not trust* any application-level traffic received prior to the completion of the TLS handshake _and_ the validation of the server's TLS certificate.

            The MariaDB client (as built from [v3.3.5](https://github.com/mariadb-corporation/mariadb-connector-c/releases/tag/v3.3.5)) violates this expectation, {color:red}making it trivially susceptible to DOS by untrusted on-path attackers, even when the user has explicitly specified {{--ssl --ssl-verify-server-cert}}{color}.

            Demonstration:

            # Build [dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability|https://github.com/dlenski/mariadb-server/commit/demonstration_of_CONC-648_vulnerability]
            #* This commit modifies the server to unconditionally send an error packet to the client, prior to authentication _and_ prior to TLS handshake and server certificate validation: {code:c}diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
            index 80d52ce18fc..283b095f2eb 100644
            --- a/sql/sql_acl.cc
            +++ b/sql/sql_acl.cc
            @@ -14457,6 +14457,14 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len)
                 DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                             mpvio.status == MPVIO_EXT::SUCCESS);
               }
            + else if (1)
            + {
            + my_error(ER_INTERNAL_ERROR, MYF(0),
            + "Client will accept this error as genuine even if running with "
            + "--ssl --ssl-verify-server-cert, and even though this error is "
            + "sent in plaintext PRIOR TO TLS HANDSHAKE.");
            + res= CR_ERROR;
            + }
               else
               {
                 /* mark the thd as having no scramble yet */{code}
            # Start the server, e.g. {noformat}$ DIR=$(mktemp -d); mkdir -p $DIR/data; sql/mariadbd --no-defaults --datadir=$DIR/data --socket=$DIR/mysql.sock --skip-grant-tables --debug
                   …
            2023-06-05 15:24:07 0 [Note] sql/mariadbd: ready for connections.
            Version: '10.11.4-MariaDB-debug' socket: '/tmp/tmp.P4FvcEcKrH/mysql.sock' port: 3306 Source distribution{noformat}
            # Attempt to connect to it with {{--ssl --ssl-verify-server-cert}}: {noformat}$ client/mariadb -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.{noformat}

            Running {{tcpdump}} in the background confirms that the client is improperly accepting the error packet, even though it has been {color:red}sent in plaintext and without a TLS handshake{color}:

            {noformat}
            $ sudo tcpdump -n -X -i lo tcp port 3306
            tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
            listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
            15:24:46.182853 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [S], seq 1546762979, win 65495, options [mss 65495,sackOK,TS val 113496632 ecr 0,nop,wscale 7], length 0
                    0x0000: 4500 003c 2b03 4000 8006 d1b6 7f00 0001 E..<+.@......... # TCP handshake, no application-level content
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae3 0000 0000 .....*..\1......
                    0x0020: a002 ffd7 fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 0000 0000 0103 0307 ...8........
            15:24:46.182917 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [S.], seq 3238764927, ack 1546762980, win 65483, options [mss 65495,sackOK,TS val 113496632 ecr 113496632,nop,wscale 7], length 0
                    0x0000: 4500 003c 0000 4000 8006 fcb9 7f00 0001 E..<..@......... # TCP handshake, no application-level content
                    0x0010: 7f00 0001 0cea 9d2a c10b a17f 5c31 bae4 .......*....\1..
                    0x0020: a012 ffcb fe30 0000 0204 ffd7 0402 080a .....0..........
                    0x0030: 06c3 d238 06c3 d238 0103 0307 ...8...8....
            15:24:46.182957 IP 127.0.0.1.40234 > 127.0.0.1.3306: Flags [.], ack 1, win 512, options [nop,nop,TS val 113496632 ecr 113496632], length 0
                    0x0000: 4500 0034 2b04 4000 8006 d1bd 7f00 0001 E..4+.@......... # TCP handshake, no application-level content
                    0x0010: 7f00 0001 9d2a 0cea 5c31 bae4 c10b a180 .....*..\1......
                    0x0020: 8010 0200 fe28 0000 0101 080a 06c3 d238 .....(.........8
                    0x0030: 06c3 d238 ...8
            15:24:46.185305 IP 127.0.0.1.3306 > 127.0.0.1.40234: Flags [P.], seq 1:189, ack 1, win 512, options [nop,nop,TS val 113496635 ecr 113496632], length 188
                    0x0000: 4508 00f0 622c 4000 8006 99d1 7f00 0001 E...b,@.........
                    0x0010: 7f00 0001 0cea 9d2a c10b a180 5c31 bae4 .......*....\1..
                    0x0020: 8018 0200 fee4 0000 0101 080a 06c3 d23b ...............;
                    0x0030: 06c3 d238 b800 0000 ff17 0749 6e74 6572 ...8.......Inter # [b8 00 00 00]: header { [b8 00 00] = length following header, 0xb8 bytes, [00]: sequence number (https://mariadb.com/kb/en/0-packet) }
                    0x0040: 6e61 6c20 6572 726f 723a 2043 6c69 656e nal.error:.Clien # [ff]: ERR_Packet (https://mariadb.com/kb/en/err_packet/)
                    0x0050: 7420 7769 6c6c 2061 6363 6570 7420 7468 t.will.accept.th # [17 07]: error ER_INTERNAL_ERROR (https://mariadb.com/kb/en/mariadb-error-codes)
                    0x0060: 6973 2065 7272 6f72 2061 7320 6765 6e75 is.error.as.genu # [remaining 0xb5 bytes] human-readable message = "Internal error: Client … TLS HANDSHAKE."
                    0x0070: 696e 6520 6576 656e 2069 6620 7275 6e6e ine.even.if.runn
                    0x0080: 696e 6720 7769 7468 202d 2d73 736c 202d ing.with.--ssl.-
                    0x0090: 2d73 736c 2d76 6572 6966 792d 7365 7276 -ssl-verify-serv
                    0x00a0: 6572 2d63 6572 742c 2061 6e64 2065 7665 er-cert,.and.eve
                    0x00b0: 6e20 7468 6f75 6768 2074 6869 7320 6572 n.though.this.er
            0x00c0: 726f 7220 6973 2073 656e 7420 696e 2070 ror.is.sent.in.p
            0x00d0: 6c61 696e 7465 7874 2050 5249 4f52 2054 laintext.PRIOR.T
            0x00e0: 4f20 544c 5320 4841 4e44 5348 414b 452e O.TLS.HANDSHAKE.
            {noformat}
            georg Georg Richter added a comment -

            The client always has to accept error packages before TLS handshake is completed, since the handshake itself may fail. Everything which happens before the TLS handshake has completed succesfully should be considered as insecure.

            In the comments of MDEV-15935 I suggested that both client and server should indicate redirection via capability flag, additionally there should be an option to allow redirection only for secure connections.

            georg Georg Richter added a comment - The client always has to accept error packages before TLS handshake is completed, since the handshake itself may fail. Everything which happens before the TLS handshake has completed succesfully should be considered as insecure. In the comments of MDEV-15935 I suggested that both client and server should indicate redirection via capability flag, additionally there should be an option to allow redirection only for secure connections.
            dlenski Daniel Lenski (Inactive) added a comment - - edited

            Everything which happens before the TLS handshake has completed succesfully should be considered as insecure.

            I completely agree with that, but the MySQL/MariaDB Connector/C libraries fail in this regard, because they do not allow consumers to distinguish errors that happen after the TLS handshake from errors that happen before/during the TLS handshake. Contrast this with basically every other TLS client.

            Every modern HTTP client clearly distinguishes errors before TLS handshake from errors after

            Errors before/during establishment of TLS

            Try cURLing {expired,untrusted-root,self-signed,revoked}.badssl.com as a useful source of reproducible TLS errors …

            $ curl -f https://expired.badssl.com; echo $?
            curl: (60) SSL certificate problem: certificate has expired
            More details here: https://curl.haxx.se/docs/sslcerts.html
             
            curl failed to verify the legitimacy of the server and therefore could not
            establish a secure connection to it. To learn more about this situation and
            how to fix it, please visit the web page mentioned above.
            60      # ← This error code indicates that 
                    # "Peer certificate cannot be authenticated with known CA certificates."
            

            Application-level errors after establishment of TLS

            $ curl -f 'https://google.com/path/that/does/not/exist'; echo $?
            curl: (22) The requested URL returned error: 404 
            22     # ← This error code indicates that
                   # "HTTP page not retrieved. The requested url was not found or returned another error with the HTTP error code being 400 or above. This return code only appears if -f, --fail is used."
            

            or

            $ curl -f https://httpbin.org/status/500; echo $?
            curl: (22) The requested URL returned error: 500 
            22      # ← This error code indicates that
                    # "HTTP page not retrieved. The requested url was not found or returned another error with the HTTP error code being 400 or above. This return code only appears if -f, --fail is used."
            

            mariadb CLI does not distinguish errors sent before or after TLS establishment

            Error that is sent by the server, but clearly should not be trusted by the client:

            (with my trivially modified server from dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability)

            $ mariadb --ssl --ssl-verify-server-cert -uUsername -pVerySecretPassword -h 127.0.0.1
            ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE.
            

            Error that should be trusted because it is sent after the TLS handshake:

            $ mariadb --ssl --ssl-verify-server-cert -uUsername -pVerySecretPassword -h $NORMAL_MARIADB10.6.14_SERVER
            ERROR 1045 (28000): Access denied for user 'Username'@'A.B.C.D' (using password: YES)
            

            As far as I can tell, there is no way for a consumer of MariaDB Connector/C to distinguish these untrustworthy pre-handshake and trustworthy post-handshake errors, so it would be completely unsafe to base any automated redirection mechanism on the interpretation of an error packet.

            dlenski Daniel Lenski (Inactive) added a comment - - edited Everything which happens before the TLS handshake has completed succesfully should be considered as insecure. I completely agree with that, but the MySQL/MariaDB Connector/C libraries fail in this regard, because they do not allow consumers to distinguish errors that happen after the TLS handshake from errors that happen before/during the TLS handshake. Contrast this with basically every other TLS client. Every modern HTTP client clearly distinguishes errors before TLS handshake from errors after Errors before/during establishment of TLS Try cURLing { expired,untrusted-root,self-signed,revoked}.badssl.com as a useful source of reproducible TLS errors … $ curl -f https://expired.badssl.com; echo $? curl: (60) SSL certificate problem: certificate has expired More details here: https://curl.haxx.se/docs/sslcerts.html   curl failed to verify the legitimacy of the server and therefore could not establish a secure connection to it. To learn more about this situation and how to fix it, please visit the web page mentioned above. 60 # ← This error code indicates that # "Peer certificate cannot be authenticated with known CA certificates." Application-level errors after establishment of TLS $ curl -f 'https://google.com/path/that/does/not/exist'; echo $? curl: (22) The requested URL returned error: 404 22 # ← This error code indicates that # "HTTP page not retrieved. The requested url was not found or returned another error with the HTTP error code being 400 or above. This return code only appears if -f, --fail is used." or $ curl -f https://httpbin.org/status/500; echo $? curl: (22) The requested URL returned error: 500 22 # ← This error code indicates that # "HTTP page not retrieved. The requested url was not found or returned another error with the HTTP error code being 400 or above. This return code only appears if -f, --fail is used." mariadb CLI does not distinguish errors sent before or after TLS establishment Error that is sent by the server, but clearly should not be trusted by the client: (with my trivially modified server from dlenski/mariadb-server:demonstration_of_CONC-648_vulnerability ) $ mariadb --ssl --ssl-verify-server-cert -uUsername -pVerySecretPassword -h 127.0.0.1 ERROR 1815 (HY000): Internal error: Client will accept this error as genuine even if running with --ssl --ssl-verify-server-cert, and even though this error is sent in plaintext PRIOR TO TLS HANDSHAKE. Error that should be trusted because it is sent after the TLS handshake: $ mariadb --ssl --ssl-verify-server-cert -uUsername -pVerySecretPassword -h $NORMAL_MARIADB10.6.14_SERVER ERROR 1045 (28000): Access denied for user 'Username'@'A.B.C.D' (using password: YES) As far as I can tell, there is no way for a consumer of MariaDB Connector/C to distinguish these untrustworthy pre-handshake and trustworthy post-handshake errors, so it would be completely unsafe to base any automated redirection mechanism on the interpretation of an error packet .

            In the comments of MDEV-15935 I suggested … there should be an option to allow redirection only for secure connections.

            If the client libraries continue to handle untrustworthy pre-TLS-handshake errors in a way that's indistinguishable from trustworthy post-TLS-handshake errors, any flag sent by the server to indicate (only allow redirection for secure connections) will be ineffectual.

            dlenski Daniel Lenski (Inactive) added a comment - In the comments of MDEV-15935 I suggested … there should be an option to allow redirection only for secure connections. If the client libraries continue to handle untrustworthy pre-TLS-handshake errors in a way that's indistinguishable from trustworthy post-TLS-handshake errors, any flag sent by the server to indicate (only allow redirection for secure connections) will be ineffectual.
            dlenski Daniel Lenski (Inactive) added a comment - - edited

            I've submitted mariadb-connector-c PR #223 which mitigates at least one avenue by which a TLS-enabled client can be tricked into improperly trusting an application-layer error packet received before completion of the TLS handshake.

            (ping otto)

            dlenski Daniel Lenski (Inactive) added a comment - - edited I've submitted mariadb-connector-c PR #223 which mitigates at least one avenue by which a TLS-enabled client can be tricked into improperly trusting an application-layer error packet received before completion of the TLS handshake. (ping otto )
            georg Georg Richter added a comment -

            Do you really think it's more safe to send another error message and to hide the original one (which makes it even more difficult to find reasons for connection errors) ? Then it would be also logical to change the message when a TLS alert has occurred before the handshake has completed, since an alert could be sent by a MIM. This would make it impossible to analyze possible TLS problems.

            Any error packet which the client retrieves before the handshake completed (e.g. "No more connections available", "Server can't create new thread", including all critical TLS alerts) forces the client to abort the connection. So I don't really see any vulnerability here.

            georg Georg Richter added a comment - Do you really think it's more safe to send another error message and to hide the original one (which makes it even more difficult to find reasons for connection errors) ? Then it would be also logical to change the message when a TLS alert has occurred before the handshake has completed, since an alert could be sent by a MIM. This would make it impossible to analyze possible TLS problems. Any error packet which the client retrieves before the handshake completed (e.g. "No more connections available", "Server can't create new thread", including all critical TLS alerts) forces the client to abort the connection. So I don't really see any vulnerability here.

            Do you really think it's more safe to send another error message and to hide the original one (which makes it even more difficult to find reasons for connection errors) ?

            Yes, I do. If the server inadvisably sends such error responses prior to the completion of the TLS handshake, then yes I think it is unsafe for the error to be relayed to the client in a form where the client could vary its behavior based on the contents of the error response. Replacing the untrusted-origin error with a generic one seems like the only safe mitigation.

            Clearly, a much better approach would be to handshake and switch to TLS handshake immediately upon connection rather than having it happen several packets later. That's how TLS is supposed to be used and how almost every other TLS-secured protocol works.

            Any error packet which the client retrieves before the handshake completed (e.g. "No more connections available", "Server can't create new thread", including all critical TLS alerts) forces the client to abort the connection.

            The fact that the connection is aborted following the error does not in any way mitigate the fact that the error conveys information to the client, which the client should not trust.

            In https://github.com/mariadb-corporation/mariadb-connector-c/pull/223, I give a brief description of a very plausible scenario in which clients can be induced to modify their behavior by sending such packets.

            And as I explained above, this vulnerability is going make it completely unsafe to build any automated redirection mechanism based on the handling of error packets immediate following initial connection.

            So I don't really see any vulnerability here.

            I'm very surprised that you don't see this as a serious vulnerability.

            Suppose that $SPY_AGENCY or $INTERNET_CENSOR wants to write a tool to degrade and interfere with TLS-secured MariaDB client→server connections. The issue discovered here makes it almost trivial to do so. Just detect the unencrypted pre-handshake MySQL server/client greeting packets and inject whichever application-layer error packets you think will interfere.

            dlenski Daniel Lenski (Inactive) added a comment - Do you really think it's more safe to send another error message and to hide the original one (which makes it even more difficult to find reasons for connection errors) ? Yes, I do. If the server inadvisably sends such error responses prior to the completion of the TLS handshake , then yes I think it is unsafe for the error to be relayed to the client in a form where the client could vary its behavior based on the contents of the error response. Replacing the untrusted-origin error with a generic one seems like the only safe mitigation. Clearly, a much better approach would be to handshake and switch to TLS handshake immediately upon connection rather than having it happen several packets later. That's how TLS is supposed to be used and how almost every other TLS-secured protocol works. Any error packet which the client retrieves before the handshake completed (e.g. "No more connections available", "Server can't create new thread", including all critical TLS alerts) forces the client to abort the connection. The fact that the connection is aborted following the error does not in any way mitigate the fact that the error conveys information to the client, which the client should not trust . In https://github.com/mariadb-corporation/mariadb-connector-c/pull/223 , I give a brief description of a very plausible scenario in which clients can be induced to modify their behavior by sending such packets. And as I explained above, this vulnerability is going make it completely unsafe to build any automated redirection mechanism based on the handling of error packets immediate following initial connection. So I don't really see any vulnerability here. I'm very surprised that you don't see this as a serious vulnerability. Suppose that $SPY_AGENCY or $INTERNET_CENSOR wants to write a tool to degrade and interfere with TLS-secured MariaDB client→server connections. The issue discovered here makes it almost trivial to do so. Just detect the unencrypted pre-handshake MySQL server/client greeting packets and inject whichever application-layer error packets you think will interfere.
            dlenski Daniel Lenski (Inactive) made changes -

            I was asked to review this by dlenski, I have been through it and here are my comments:

            This does appear to be a cut and dry MITM attack, and if MDEV-15935 is implemented in such a way that the feature is possible to use before TLS handshake it becomes an even more serious MITM attack.

            Right now it is important but I don't think critical. It is possible to make an application behave badly due to it being developed to respond a certain way based on an error code. For example, connect to server B because A returned a max connections error. This may sound benign, but I suspect there are ways to abuse this.

            All that being said, I'm not sure the current PR is 100% the correct approach. You do want the error codes to remain as-is because this will break applications. I don't think an additional error code / message at the same time is possible, so the library should probably inject a prefix to the message which states that this message came before the handshake. If well documented, this could be something applications can watch for. Even better if it can be some kind of flag or API call to check if the message came prior to encryption.

            TheLinuxJedi Andrew Hutchings (Inactive) added a comment - I was asked to review this by dlenski , I have been through it and here are my comments: This does appear to be a cut and dry MITM attack, and if MDEV-15935 is implemented in such a way that the feature is possible to use before TLS handshake it becomes an even more serious MITM attack. Right now it is important but I don't think critical. It is possible to make an application behave badly due to it being developed to respond a certain way based on an error code. For example, connect to server B because A returned a max connections error. This may sound benign, but I suspect there are ways to abuse this. All that being said, I'm not sure the current PR is 100% the correct approach. You do want the error codes to remain as-is because this will break applications. I don't think an additional error code / message at the same time is possible, so the library should probably inject a prefix to the message which states that this message came before the handshake. If well documented, this could be something applications can watch for. Even better if it can be some kind of flag or API call to check if the message came prior to encryption.
            dlenski Daniel Lenski (Inactive) added a comment - - edited

            TheLinuxJedi wrote:

            All that being said, I'm not sure the current PR is 100% the correct approach. You do want the error codes to remain as-is because this will break applications.

            Disagree. I think that (1) the security concern should trump any backwards-compatibility concern, and (2) there is no evidence that there is any real backwards-compatibility concern.

            For (2), I don't find any evidence that real/non-malicious servers (MySQL, MariaDB, Percona, etc.) actually send pre-handshake application-level error messages.

            As far as I can tell:

            • Extant, working versions of the MariaDB server do not ever send error messages to TLS-using clients prior to the TLS handshake. (Although it's extremely hard to audit the code to be certain of this given its structure.)
            • The fact that the MariaDB client operating in -ssl mode will accept a pre(TLS handshake) error message is simply a client-side vulnerability.

            I don't think an additional error code / message at the same time is possible, so the library should probably inject a prefix to the message which states that this message came before the handshake.

            What you're proposing here is to push the burden of verifying the transport-layer security onto the client application logic.

            If well documented, this could be something applications can watch for.

            In practice, applications won't watch for it, and pre-existing applications certainly won't watch for it.

            This is why when a vulnerability like this one is discovered (supposedly TLS-secured client is vulnerable to incorrectly trust non-TLS-secured inputs), it's generally good practice to err on the side of breaking backwards-compatibility.

            And anyway, as I describe above, there's no evidence that existing MySQL/MariaDB server implementations will actually send meaningful error packets to TLS-secured clients prior to the TLS handshake, so the backwards compatibility concern appears to be a theoretical one.

            dlenski Daniel Lenski (Inactive) added a comment - - edited TheLinuxJedi wrote: All that being said, I'm not sure the current PR is 100% the correct approach. You do want the error codes to remain as-is because this will break applications. Disagree. I think that (1) the security concern should trump any backwards-compatibility concern, and (2) there is no evidence that there is any real backwards-compatibility concern. For (2), I don't find any evidence that real/non-malicious servers (MySQL, MariaDB, Percona, etc.) actually send pre-handshake application-level error messages . As far as I can tell: Extant, working versions of the MariaDB server do not ever send error messages to TLS-using clients prior to the TLS handshake. (Although it's extremely hard to audit the code to be certain of this given its structure.) The fact that the MariaDB client operating in - ssl mode will accept a pre (TLS handshake) error message is simply a client-side vulnerability. I don't think an additional error code / message at the same time is possible, so the library should probably inject a prefix to the message which states that this message came before the handshake. What you're proposing here is to push the burden of verifying the transport -layer security onto the client application logic. If well documented, this could be something applications can watch for. In practice, applications won't watch for it, and pre-existing applications certainly won't watch for it. This is why when a vulnerability like this one is discovered (supposedly TLS-secured client is vulnerable to incorrectly trust non-TLS-secured inputs), it's generally good practice to err on the side of breaking backwards-compatibility . And anyway, as I describe above, there's no evidence that existing MySQL/MariaDB server implementations will actually send meaningful error packets to TLS-secured clients prior to the TLS handshake, so the backwards compatibility concern appears to be a theoretical one.
            • Extant, working versions of the MariaDB server do not ever send error messages to TLS-using clients prior to the TLS handshake. (Although it's extremely hard to audit the code to be certain of this given its structure.)

            And anyway, as I describe above, there's no evidence that existing MySQL/MariaDB server implementations will actually send meaningful error packets to TLS-secured clients prior to the TLS handshake, so the backwards compatibility concern appears to be a theoretical one.

            The only exception I can find to this is that if the client requests an auth plugin which the server can't load, then the server will send this back to the client as an unencrypted error packet even if the client wants TLS/SSL: https://github.com/MariaDB/server/blob/11.0/sql/sql_acl.cc#L14331-L14338

            dlenski Daniel Lenski (Inactive) added a comment - Extant, working versions of the MariaDB server do not ever send error messages to TLS-using clients prior to the TLS handshake. (Although it's extremely hard to audit the code to be certain of this given its structure.) And anyway, as I describe above, there's no evidence that existing MySQL/MariaDB server implementations will actually send meaningful error packets to TLS-secured clients prior to the TLS handshake, so the backwards compatibility concern appears to be a theoretical one. The only exception I can find to this is that if the client requests an auth plugin which the server can't load, then the server will send this back to the client as an unencrypted error packet even if the client wants TLS/SSL: https://github.com/MariaDB/server/blob/11.0/sql/sql_acl.cc#L14331-L14338
            georg Georg Richter added a comment -

            There are 3 possible errors which the server can send before the handshake succeeded:

            • too many connections
            • server ran out of threads
            • a TLS error/alert, e.g. no matching protocol, unsupported cipher suite, ....

            plugin errors will be sent after the handshake, since the client hello packet will be encrypted.

            georg Georg Richter added a comment - There are 3 possible errors which the server can send before the handshake succeeded: too many connections server ran out of threads a TLS error/alert, e.g. no matching protocol, unsupported cipher suite, .... plugin errors will be sent after the handshake, since the client hello packet will be encrypted.

            There are 3 possible errors which the server can send before the handshake succeeded:

            too many connections
            server ran out of threads
            a TLS error/alert, e.g. no matching protocol, unsupported cipher suite, ....

            plugin errors will be sent after the handshake, since the client hello packet will be encrypted.

            That is fewer than I thought, which is good to know. I do think it is important to know which one of these has been hit, particularly a differentiator between the first two and the last one. At least logged somewhere for debugging / post-mortem purposes. Even if the original error code is not maintained.

            TheLinuxJedi Andrew Hutchings (Inactive) added a comment - There are 3 possible errors which the server can send before the handshake succeeded: too many connections server ran out of threads a TLS error/alert, e.g. no matching protocol, unsupported cipher suite, .... plugin errors will be sent after the handshake, since the client hello packet will be encrypted. That is fewer than I thought, which is good to know. I do think it is important to know which one of these has been hit, particularly a differentiator between the first two and the last one. At least logged somewhere for debugging / post-mortem purposes. Even if the original error code is not maintained.

            georg wrote:

            There are 3 possible errors which the server can send before the handshake succeeded:

            • too many connections
            • server ran out of threads
            • a TLS error/alert, e.g. no matching protocol, unsupported cipher suite, ....

            These cases need to be distinguished:

            The "too many connections" and "out of threads" errors are application-level errors: they are sent *by the server to the client.

            The fact that these are sent by the server before the TLS handshake happens is bad. As I described above, the client may vary its retry behavior based on exactly what error it receives, and this could enable a variety of attacks… which rapidly get much, much more serious if the client starts automatically trying to connect to different servers based on errors it receives.

            • TLS errors/alerts are transport-level errors: they are generated by the client as a result of an inability to construct a satisfactorily-secure TLS channel between it and the server. Assuming they all get the same error code (CR_SSL_CONNECTION_ERROR, I think?) then an attacker can prevent a connection from succeeding, but can't cause a client to vary its behavior based on the contents of the error. (If a client receives a CR_SSL_CONNECTION_ERROR, it shouldn't vary its behavior based on the detailed error message; "TLS alert X" vs "not allowed cipher Y", etc.)

            TheLinuxJedi, perhaps my statements above about this previously were unclear: it's not that the client needs to hide the details of any error which it encounters before the TLS handshake. It's just that the client should hide the details of an application-level error which it appears to have received from the server before the TLS handshake (because that error could actually be from a MITM attacker).

            And indeed that is what my PR does in its current form: "Do not trust error packets received from the server prior to TLS handshake completion". It does not prevent the client from returning unique error codes for other conditions which are unrelated to application-layer traffic ("hostname not found", "TLS alert", "conflicting connection parameters don't make sense", etc).

            dlenski Daniel Lenski (Inactive) added a comment - georg wrote: There are 3 possible errors which the server can send before the handshake succeeded: too many connections server ran out of threads a TLS error/alert, e.g. no matching protocol, unsupported cipher suite, .... These cases need to be distinguished: The "too many connections" and "out of threads" errors are application -level errors: they are sent *by the server to the client. The fact that these are sent by the server before the TLS handshake happens is bad. As I described above , the client may vary its retry behavior based on exactly what error it receives, and this could enable a variety of attacks… which rapidly get much, much more serious if the client starts automatically trying to connect to different servers based on errors it receives. TLS errors/alerts are transport -level errors: they are generated by the client as a result of an inability to construct a satisfactorily-secure TLS channel between it and the server. Assuming they all get the same error code ( CR_SSL_CONNECTION_ERROR , I think?) then an attacker can prevent a connection from succeeding, but can't cause a client to vary its behavior based on the contents of the error. (If a client receives a CR_SSL_CONNECTION_ERROR , it shouldn't vary its behavior based on the detailed error message; "TLS alert X" vs "not allowed cipher Y", etc.) TheLinuxJedi , perhaps my statements above about this previously were unclear: it's not that the client needs to hide the details of any error which it encounters before the TLS handshake. It's just that the client should hide the details of an application-level error which it appears to have received from the server before the TLS handshake (because that error could actually be from a MITM attacker). And indeed that is what my PR does in its current form: "Do not trust error packets received from the server prior to TLS handshake completion". It does not prevent the client from returning unique error codes for other conditions which are unrelated to application-layer traffic ("hostname not found", "TLS alert", "conflicting connection parameters don't make sense", etc).

            I've counted 13 errors that a server can legally send before TLS is established.

            Four of them can only happen before authentication (before TLS, if requested):

            • ER_BAD_HOST_ERROR
            • ER_CANT_CREATE_THREAD
            • ER_HOST_IS_BLOCKED
            • ER_HOST_NOT_PRIVILEGED

            Others can happen before or after TLS:

            • EE_OUTOFMEMORY
            • ER_CONNECTION_KILLED
            • ER_HANDSHAKE_ERROR
            • ER_NET_FCNTL_ERROR
            • ER_NET_PACKET_TOO_LARGE
            • ER_NET_READ_ERROR
            • ER_NET_READ_INTERRUPTED
            • ER_NET_UNCOMPRESS_ERROR
            • ER_OUT_OF_RESOURCES

            Even if we only consider the first four errors, ER_CANT_CREATE_THREAD is transient and the client might want to retry, ER_HOST_IS_BLOCKED and ER_HOST_NOT_PRIVILEGED are permanent. A client cannot just ignore those errors. And in the MitM case they can be spoofed indeed. I don't see how you can possibly solve this.

            ER_ACCESS_DENIED can never come before TLS and a client can safely ignore it and all errors that aren't in the list above. But errors from the above list are more than enough for MitM to use.

            serg Sergei Golubchik added a comment - I've counted 13 errors that a server can legally send before TLS is established. Four of them can only happen before authentication (before TLS, if requested): ER_BAD_HOST_ERROR ER_CANT_CREATE_THREAD ER_HOST_IS_BLOCKED ER_HOST_NOT_PRIVILEGED Others can happen before or after TLS: EE_OUTOFMEMORY ER_CONNECTION_KILLED ER_HANDSHAKE_ERROR ER_NET_FCNTL_ERROR ER_NET_PACKET_TOO_LARGE ER_NET_READ_ERROR ER_NET_READ_INTERRUPTED ER_NET_UNCOMPRESS_ERROR ER_OUT_OF_RESOURCES Even if we only consider the first four errors, ER_CANT_CREATE_THREAD is transient and the client might want to retry, ER_HOST_IS_BLOCKED and ER_HOST_NOT_PRIVILEGED are permanent. A client cannot just ignore those errors. And in the MitM case they can be spoofed indeed. I don't see how you can possibly solve this. ER_ACCESS_DENIED can never come before TLS and a client can safely ignore it and all errors that aren't in the list above. But errors from the above list are more than enough for MitM to use.
            dlenski Daniel Lenski (Inactive) made changes -
            Attachment screenshot-1.png [ 70760 ]
            dlenski Daniel Lenski (Inactive) added a comment - - edited

            I've counted 13 errors that a server can legally send before TLS is established.

            serg, thanks for researching this!

            Even if we only consider the first four errors, ER_CANT_CREATE_THREAD is transient and the client might want to retry, ER_HOST_IS_BLOCKED and ER_HOST_NOT_PRIVILEGED are permanent. A client cannot just ignore those errors. And in the MitM case they can be spoofed indeed. I don't see how you can possibly solve this.

            You can solve this by designing the applications (client+server) and the protocol to ensure an appropriate separation of concerns between the transport layer (TLS to ensure authenticity of the server and end-to-end encryption of the communications with it) and the application layer (validating the user's credentials to access the database).

            If a TCP-based client-server protocol wants to use TLS, then wrapping the TCP socket in a TLS socket should be the very first thing that happens, before any communication over the socket. There shouldn't be any exchange of plaintext packets prior to the TLS handshake.

            Modern web browsers using TLS (especially TLSv1.3 with ECH), and VoIP apps, and TLS-based VPNs (like those supported by openconnect, which I contribute to) basically get this right, and leak no application-layer information prior to TLS establishment… but MariaDB does this quite badly and leaks a ton of information. This seems to be largely a consequence of the unstructured approach to bolting TLS on to the client and server code. The description of the connection protocol appears to have been written after-the-fact to reflect how MariaDB server and Connector/C use TLS, rather than designed in advance.

            Even in the happy case where the server doesn't send any pre-handshake error to the client, the server sends a "greeting" packet to the client (containing server version information) and the client sends back a login request packet (with no credentials, but with the client's charset and flags) in plaintext before the TLS handshake starts:

            This makes MariaDB client-server connections an exploitable and target-rich environment for pervasive MITM attackers. A government agency could, for example, fingerprint the plaintext client+server greeting packets to determine the exact versions, pull out the ones that appear to be from interesting parts of the world based on the plaintext preferred client charset, and manipulate them in various ways with MITM and downgrade attacks using this vulnerability, as well as the long-known MDEV-28634… and all of that without needing to actually do any TLS cracking.

            For all I know, the NSA or CSIC or GCHQ or יחידה 8200 or the Chinese/Iranian/Indian/Russian/$COUNTRY equivalents have already figured this out themselves, and have been MITM'ing MariaDB connections on the Internet at massive scale for years.

            (UPDATE: Spun this off into CONC-654 and MDEV-31585; it turns out that there's a server-side mistake in TLS setup, which makes it impossible to fix the client-side leakage without a server-side fix as well.)


            I've been studying the client-server protocol and implementations pretty carefully for a couple weeks now, and I'm convinced that these vulnerabilities are entirely solvable and in a backwards-compatible way, but it'd require a concerted effort to prioritize the code and design changes.

            dlenski Daniel Lenski (Inactive) added a comment - - edited I've counted 13 errors that a server can legally send before TLS is established. serg , thanks for researching this! Even if we only consider the first four errors, ER_CANT_CREATE_THREAD is transient and the client might want to retry, ER_HOST_IS_BLOCKED and ER_HOST_NOT_PRIVILEGED are permanent. A client cannot just ignore those errors. And in the MitM case they can be spoofed indeed. I don't see how you can possibly solve this. You can solve this by designing the applications (client+server) and the protocol to ensure an appropriate separation of concerns between the transport layer (TLS to ensure authenticity of the server and end-to-end encryption of the communications with it) and the application layer (validating the user's credentials to access the database). If a TCP-based client-server protocol wants to use TLS, then wrapping the TCP socket in a TLS socket should be the very first thing that happens , before any communication over the socket. There shouldn't be any exchange of plaintext packets prior to the TLS handshake. Modern web browsers using TLS (especially TLSv1.3 with ECH ), and VoIP apps, and TLS-based VPNs (like those supported by openconnect , which I contribute to) basically get this right , and leak no application-layer information prior to TLS establishment… but MariaDB does this quite badly and leaks a ton of information. This seems to be largely a consequence of the unstructured approach to bolting TLS on to the client and server code. The description of the connection protocol appears to have been written after-the-fact to reflect how MariaDB server and Connector/C use TLS, rather than designed in advance. Even in the happy case where the server doesn't send any pre-handshake error to the client, the server sends a "greeting" packet to the client ( containing server version information ) and the client sends back a login request packet (with no credentials, but with the client's charset and flags ) in plaintext before the TLS handshake starts : This makes MariaDB client-server connections an exploitable and target-rich environment for pervasive MITM attackers. A government agency could, for example, fingerprint the plaintext client+server greeting packets to determine the exact versions, pull out the ones that appear to be from interesting parts of the world based on the plaintext preferred client charset , and manipulate them in various ways with MITM and downgrade attacks using this vulnerability, as well as the long-known MDEV-28634 … and all of that without needing to actually do any TLS cracking. For all I know, the NSA or CSIC or GCHQ or יחידה 8200 or the Chinese/Iranian/Indian/Russian/$COUNTRY equivalents have already figured this out themselves, and have been MITM'ing MariaDB connections on the Internet at massive scale for years. (UPDATE: Spun this off into CONC-654 and MDEV-31585 ; it turns out that there's a server-side mistake in TLS setup, which makes it impossible to fix the client-side leakage without a server-side fix as well.) I've been studying the client-server protocol and implementations pretty carefully for a couple weeks now, and I'm convinced that these vulnerabilities are entirely solvable and in a backwards-compatible way, but it'd require a concerted effort to prioritize the code and design changes.
            dlenski Daniel Lenski (Inactive) made changes -
            serg Sergei Golubchik made changes -
            Assignee Georg Richter [ georg ] Sergei Golubchik [ serg ]
            serg Sergei Golubchik made changes -
            Status Needs Feedback [ 10501 ] Open [ 1 ]
            serg Sergei Golubchik made changes -
            Fix Version/s 3.1 [ 23223 ]
            Fix Version/s 3.3 [ 26080 ]
            serg Sergei Golubchik made changes -
            Status Open [ 1 ] In Progress [ 3 ]
            serg Sergei Golubchik made changes -
            Status In Progress [ 3 ] In Review [ 10002 ]

            Connector/C PR #223 has now been merged to the 3.3 branch, but not yet tagged in a release.

            dlenski Daniel Lenski (Inactive) added a comment - Connector/C PR #223 has now been merged to the 3.3 branch, but not yet tagged in a release.
            georg Georg Richter made changes -
            Fix Version/s 3.1.24 [ 29603 ]
            Fix Version/s 3.3.10 [ 29809 ]
            Fix Version/s 3.1 [ 23223 ]
            Fix Version/s 3.3 [ 26080 ]
            georg Georg Richter made changes -
            Component/s TLS/SSL [ 16815 ]
            Resolution Fixed [ 1 ]
            Status In Review [ 10002 ] Closed [ 6 ]

            People

              serg Sergei Golubchik
              dlenski Daniel Lenski (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              7 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.