CalvinKirs opened a new issue, #66152:
URL: https://github.com/apache/doris/issues/66152

   ### Description
   
   Doris stores local account passwords using MySQL's two-stage SHA-1 scheme 
(`mysql_native_password`):
   
   - `fe/fe-core/src/main/java/org/apache/doris/mysql/MysqlPassword.java` — 
`makeScrambledPassword()` computes `SHA1(SHA1(password))` and stores it as a 
`*HEX` string
   - `fe/fe-core/src/main/java/org/apache/doris/mysql/privilege/Auth.java` — 
the same scheme is used for the initial root password
   
   No salt, no key stretching, one SHA-1 round per stage.
   
   Upstream has moved off it. MySQL deprecated `mysql_native_password` in 8.4 
and **removed it entirely in 9.0**, replacing it with `caching_sha2_password` 
(SHA-256, per-account salt, 5000 iterations). MariaDB still ships the old 
plugin but discourages it:
   
   > It is not recommended to use the mysql_native_password authentication 
plugin for new installations that require high password security. If someone is 
able to both listen to the connection protocol and get a copy of the mysql.user 
table, then the person would be able to use this information to connect to the 
MariaDB server.
   
   That last sentence is the actual threat model, and both halves of it are 
reachable in a default Doris deployment:
   
   1. **The stored hash.** `SHA1(SHA1(pw))` is unsalted, so identical passwords 
produce identical hashes across accounts and across clusters, and double-SHA-1 
is among the cheapest hashes to attack on commodity GPUs. Anyone who can read 
FE metadata — the `doris-meta` directory, an image file, a metadata backup, a 
copy of the edit log — gets every account's hash.
   2. **The handshake.** `enable_ssl` defaults to `false`, so the 
challenge-response exchange is observable on the wire by default. Combined with 
the stored stage-2 hash, an observer can recover the stage-1 value `SHA1(pw)`, 
which is permanently sufficient to authenticate as that account — no cracking 
required.
   
   Neither half alone is fatal, but the combination is realistic and there is 
currently no defence in depth against it. In OWASP terms this is A02:2021 
Cryptographic Failures.
   
   There is also a plain compatibility angle: as MySQL 9.x clients drop 
`mysql_native_password`, Doris authentication becomes the thing that has to be 
worked around.
   
   ### Current state in the codebase
   
   The plugin groundwork already exists, which makes this cheaper than it might 
look:
   
   - `fe/fe-authentication/fe-authentication-api` defines `CredentialType`, 
currently only `MYSQL_NATIVE_PASSWORD`
   - 
`fe/fe-authentication/fe-authentication-plugins/fe-authentication-plugin-password`
 implements the local password plugin
   - `fe/fe-core/src/main/java/org/apache/doris/mysql/authenticate/` has 
`AuthenticateType`, `AuthenticatorFactory`, and the LDAP / integration / plugin 
authenticators
   
   What's missing:
   
   - **No strong local credential type.** `caching_sha2_password` and 
`sha256_password` appear nowhere in FE or BE; the only reference is a comment 
in `NativePasswordResolver`.
   - **No per-user plugin selection.** The grammar only supports `IDENTIFIED BY 
PASSWORD? <string>` (`DorisParser.g4`) — there is no `IDENTIFIED WITH 
<plugin>`. The authentication method is a cluster-level config 
(`authenticate_type`), not a per-account property. Noted independently in 
#66115: *"No per-user authentication plugins in Doris."*
   - **LDAP does not close the gap.** The LDAP authenticator falls back to 
native password authentication, so the weak path stays reachable in LDAP 
deployments too.
   
   ### Proposed solution
   
   **Phase 1 — implement `caching_sha2_password` as an additional local 
credential type behind the existing SPI.**
   
   Add it as a new `CredentialType` in `fe-authentication-plugin-password`. 
This means SHA-256 with a per-account salt and 5000 iterations for storage, 
plus the fast-auth / full-auth handshake so standard MySQL clients work 
unchanged. The storage format needs a per-account marker so both schemes can 
coexist in `Password` and in the FE image. No behaviour change for existing 
accounts.
   
   Choosing `caching_sha2_password` over a Doris-specific scheme is deliberate: 
it is what current MySQL clients already speak, so it costs users nothing on 
the client side and it is the direction the ecosystem has already committed to.
   
   **Phase 2 — make it selectable per account.**
   
   - `IDENTIFIED WITH <plugin> BY '<password>'` on `CREATE USER` and `ALTER 
USER`, matching MySQL syntax
   - Expose the plugin per account in `SHOW GRANTS` / `information_schema`, so 
operators can audit which accounts are still on the legacy scheme
   - A config for the default plugin used by `CREATE USER` and by the initial 
root account — defaulting to native for compatibility, flippable to 
`caching_sha2_password`
   
   **Migration.** Existing accounts keep working unchanged. Hashes cannot be 
converted without the plaintext, so migration is `ALTER USER ... IDENTIFIED 
WITH caching_sha2_password BY '<password>'` at the operator's own pace. Worth 
noting that #66115 (dual password / `RETAIN CURRENT PASSWORD`), if it lands, 
provides exactly the overlap window this migration needs — the two features 
complement each other well.
   
   **Interim hardening**, independent of the above and much cheaper:
   
   - Document the `enable_ssl` recommendation prominently for any deployment on 
an untrusted network — it removes the "listen to the protocol" half of the 
threat
   - Document that FE metadata (`doris-meta`, images, backups) has to be 
treated as credential material
   
   ### Use case
   
   - Deployments with password-strength or credential-storage requirements 
(financial, public sector, anything under an internal crypto standard) that 
currently cannot pass review on unsalted double-SHA-1.
   - Users on MySQL 9.x clients and tooling, where `mysql_native_password` no 
longer exists.
   - Operators who want to audit and migrate off the legacy scheme account by 
account rather than all at once.
   
   ### Out of scope
   
   - Changing the default authentication plugin — a separate compatibility 
decision once Phase 1 exists
   - BE-side and Arrow Flight changes beyond what the new credential type 
requires
   
   ### Related issues
   
   - #66115 (dual password support — provides the rotation window Phase 2 
migration would use)
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to