You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bu...@apache.org on 2025/10/15 08:43:31 UTC
[Bug 69852] New: {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
Bug ID: 69852
Summary: {MD5}, {SHA} and {SSHA} not honored with
Realm/CredentialHandler
Product: Tomcat 11
Version: 11.0.13
Hardware: PC
OS: Linux
Status: NEW
Severity: normal
Priority: P2
Component: Util
Assignee: dev@tomcat.apache.org
Reporter: gr.grzybek@gmail.com
Target Milestone: -------
According to
https://tomcat.apache.org/tomcat-11.0-doc/config/credentialhandler.html#MessageDigestCredentialHandler
I can declare a digest algorithm to use for tomcat-users.xml like this:
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase">
<CredentialHandler
className="org.apache.catalina.realm.MessageDigestCredentialHandler"
algorithm="SHA-384" />
</Realm>
</Realm>
Also I can use various formats for the passwords and these two should use the
configured algorithm:
- encodedCredential - a hex encoded digest of the password digested using the
configured digest
- salt$iterationCount$encodedCredential - a hex encoded salt, iteration code
and a hex encoded credential, each separated by $
However there are 3 formats where `algorithm="SHA-384"` should be overriden:
- {MD5}encodedCredential - a Base64 encoded MD5 digest of the password
- {SHA}encodedCredential - a Base64 encoded SHA1 digest of the password
- {SSHA}encodedCredential - 20 character salt followed by the salted SHA1
digest Base64 encoded
`org.apache.catalina.realm.MessageDigestCredentialHandler#matches()` doesn't
use MD5/SHA1/SHA1 respectively for {MD5}/{SHA}/{SSHA} prefixed passwords.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
Mark Thomas <ma...@apache.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|--- |FIXED
Status|REOPENED |RESOLVED
--- Comment #11 from Mark Thomas <ma...@apache.org> ---
Back-ports have been completed and the identified bugs have been fixed in:
- 11.0.x for 11.0.14 onwards
- 10.1.x for 10.1.49 onwards
- 9.0.x for 9.0.112 onwards
If using the algorithm defined in the credential string is still a requirement,
please open a separate enhancement request for that.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
--- Comment #7 from Grzegorz Grzybek <gr...@gmail.com> ---
Oh - I love digging in history - I had to reason about code from early 2000s to
understand the consequences in 2020s...
True - I was thinking about {SHA}xxx format for LDAP passwords. I didn't find
exact RFC, but there's
https://datatracker.ietf.org/doc/html/draft-stroeder-hashed-userpassword-values
specifying prefixes like {SHA} or even {SSHA512}.
This draft introduces this scheme:
{<digest-alg>}<base64(password-hash salt)>
RFC 3112 LDAP Authentication Password Schema has different syntax - '$'
separated values.
Tomcat's
https://tomcat.apache.org/tomcat-11.0-doc/config/credentialhandler.html#MessageDigestCredentialHandler
defines/documents SSHA as:
20 character salt followed by the salted SHA1 digest Base64 encoded
However in the code
https://github.com/apache/tomcat/blob/51fd0788b401d589acb9bede8cbd6a495a9ca943/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java#L117
we have
// "{SSHA}<sha-1 digest:20><salt:n>"
...
// Extract the first 20 bytes containing the SHA-1 digest
final int digestLength = 20;
...
System.arraycopy(serverDigestPlusSaltBytes, 0, serverDigestBytes, 0,
digestLength);
...
System.arraycopy(serverDigestPlusSaltBytes, digestLength, serverSaltBytes,
0, saltLength);
so the documentation is wrong and should be:
20 bytes of SHA1 digest of password and the salt, followed by the salt
bytes ,Base64 encoded
Apache Directory Server also uses password+salt digest (in this order):
https://github.com/apache/directory-ldap-api/blob/master/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java#L446-L478
And base64 encodes the hash+salt (in this order):
https://github.com/apache/directory-ldap-api/blob/be233029e53c7914d3e2588ec151c325cf54b771/ldap/model/src/main/java/org/apache/directory/api/ldap/model/password/PasswordUtil.java#L258
So here, Tomcat code, ApacheDS code and this IETF drafts are consistent, but
Tomcat documentation is not.
While I agree that using:
<CredentialHandler
className="org.apache.catalina.realm.MessageDigestCredentialHandler"
algorithm="SHA-384" />
means that the user knows what's being done, when you're NOT configuring this
handler we can assume that tomcat-users.xml like this:
<tomcat-users>
<user username="tomcat" password="tomcat=" roles="..."/>
<user username="tomcat2" password="{MD5}GzWdh1OFi1W++gRBBnqu0w=="
roles="..."/>
<user username="tomcat3"
password="{SSHA}iVkga68v3vXOzrB7OuNiD5gzaaeOMrVbUjPdZxTGurtfZ/bpHRTvEZAFmvEvhtlFeTV0vhZZg3ZrEQ=="
roles="..."/>
</tomcat-users>
should be fine. But it's not - passwords for tomcat2 and tomcat3 users are
compared directly because of:
if (getAlgorithm() == null) {
// No digests, compare directly
return DigestCredentialHandlerBase.equals(inputCredentials,
storedCredentials, false);
Let's not discuss the strength of MD5 or using Memory/UserDatabaseRealm for
serious use. I'm just trying to clear the confusion ;)
Oh and I just tried to check
`{SSHA}iVkga68v3vXOzrB7OuNiD5gzaaeOMrVbUjPdZxTGurtfZ/bpHRTvEZAFmvEvhtlFeTV0vhZZg3ZrEQ==`
('tomcat' password with 38 bytes salt and SHA-1) and when checking the incoming
password, first the password is digested then the salt:
// Generate the digested form of the user provided password
// using the salt
byte[] userDigestBytes = ConcurrentMessageDigest.digest(getAlgorithm(),
inputCredentials.getBytes(StandardCharsets.ISO_8859_1),
serverSaltBytes);
While when checking $-separated password (salt $ ic $ digest),
org.apache.catalina.realm.MessageDigestCredentialHandler#mutate first digests
the salt and then the password...
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
--- Comment #6 from Christopher Schultz <ch...@christopherschultz.net> ---
IIRC, this was originally supported because services like LDAP will often
return user passwords like {SHA}a1ecb2eb1a33ceb1... and we wanted to be able to
support those systems. I checked the history, and it looks like we have always
been using THE algorithm for the credential handler and not adapting to match
that of the stored credential. I guess the idea was that the LDAP, etc. server
was probably being consistent, so we'd also be consistent and just use the
statically-configured algorithm.
I think being able to support multiple digest algorithms would be handy, so I'd
be in support of making the modification to explicitly use e.g. SHA1 when {SHA}
is found in the credential. But I'd also be strongly in support of everyone
migrating from such old algorithms to newer, more secure algorithms.
If you are using a file-based authentication which it seems like you are, there
doesn't seem to be a reason to use multiple different types of hashes in your
file. In that case, use the best algorithm you can tolerate and use it
consistently.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
--- Comment #3 from Grzegorz Grzybek <gr...@gmail.com> ---
I mean even if some digest algorithm is specified in <CredentialHandler
algorithm="xyz" />, when password is prefixed with {MD5} or {SHA}, these should
be used instead the configured one.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
--- Comment #5 from Grzegorz Grzybek <gr...@gmail.com> ---
I may understand this decision.
I was only hoping that you can mix different digests for different passwords
even if you have single, say:
<CredentialHandler
className="org.apache.catalina.realm.MessageDigestCredentialHandler"
algorithm="SHA-384" />
Currently (I checked) when you have the above, password like:
<user username="tomcat"
password="{SSHA}QxsCbkrZwiLgvTnvdlGW2KI/EfIr4M7y7o4nnG1VqsaRKl6ISrDcYg==" />
simply fails, because the digest used for incoming password is SHA-384. it'd
work if the digest was `SHA-1`.
Also
https://tomcat.apache.org/tomcat-11.0-doc/realm-howto.html#Digested_Passwords
says:
> When the authenticate() method of the Realm is called, the (cleartext) password specified by the user is itself digested by the same algorithm, and the result is compared with the value returned by the Realm.
"the same algorithm" confused me, because it's NOT SHA-1, but the one I
specified in <CredentialHandler>
Sure - MD5 is not that good for some scenarios, but just enough (with salt and
ic) for less critical ones.
TL;DR - `{SHA}<base64 of SHA-1 digest of cleartext password>` will never work
if you don't have `SHA-1` specified in `<CredentialHandler>`
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
Remy Maucherat <re...@apache.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |NEEDINFO
--- Comment #1 from Remy Maucherat <re...@apache.org> ---
Can you clarify the issue some more ?
The algorithm you specify in your configuration is used:
https://github.com/apache/tomcat/blob/main/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java#L107
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
--- Comment #10 from Mark Thomas <ma...@apache.org> ---
Bugs fixed in main for 12.0.x. Just waiting for feedback before back-porting.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
Mark Thomas <ma...@apache.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|RESOLVED |REOPENED
Resolution|WONTFIX |---
--- Comment #8 from Mark Thomas <ma...@apache.org> ---
Re-opening as we have at least one bug here.
(In reply to Grzegorz Grzybek from comment #7)
> So here, Tomcat code, ApacheDS code and this IETF drafts are consistent, but
> Tomcat documentation is not.
That is an easy fix. Correct the documentation. Patch/PR welcome.
> While when checking $-separated password (salt $ ic $ digest),
> org.apache.catalina.realm.MessageDigestCredentialHandler#mutate first
> digests the salt and then the password...
That appears to be contrary to RFC 3112. Fixing that would be a breaking
change. Not sure how many users would be affected. I think we'd need to make
the order configurable. I'd suggest it defaulted to the RFC order.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
--- Comment #2 from Grzegorz Grzybek <gr...@gmail.com> ---
But check
https://github.com/apache/tomcat/blob/1da17751e26e77d6382b20701fe450282750aa34/java/org/apache/catalina/realm/MessageDigestCredentialHandler.java#L111-L112
there's:
```
if (storedCredentials.startsWith("{MD5}") ||
storedCredentials.startsWith("{SHA}")) {
// Server is storing digested passwords with a prefix indicating
// the digest type
String base64ServerDigest = storedCredentials.substring(5);
byte[] userDigest = ConcurrentMessageDigest.digest(getAlgorithm(),
inputCredentials.getBytes(StandardCharsets.ISO_8859_1));
String base64UserDigest = Base64.getEncoder().encodeToString(userDigest);
return DigestCredentialHandlerBase.equals(base64UserDigest,
base64ServerDigest, false);
}
```
so instead of `MD5` or `SHA-1`, `getAlgorithm()` is passed to
`ConcurrentMessageDigest.digest()`.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
--- Comment #9 from Grzegorz Grzybek <gr...@gmail.com> ---
Please excuse me for being annoying and digging to much in the history ;)
I'll prepare a PR and also an issue report about
https://bz.apache.org/bugzilla/show_bug.cgi?id=69802 at
https://github.com/jakartaee/servlet about CLIENT-CERT.
But this week I have to finish some other stuff, so this will have to wait.
I agree that this one about salt/password order is probably not critical -
tomcat-users.xml is usually for storing plain text passwords at dev time.
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
[Bug 69852] {MD5}, {SHA} and {SSHA} not honored with Realm/CredentialHandler
Posted by bu...@apache.org.
https://bz.apache.org/bugzilla/show_bug.cgi?id=69852
Remy Maucherat <re...@apache.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|--- |WONTFIX
Status|NEEDINFO |RESOLVED
--- Comment #4 from Remy Maucherat <re...@apache.org> ---
Ok, I understand better. SHA means some SHA based algorithm that you will
configure using the algorithm attribute, and as you can see the other prefixes
then trigger different (better) strategies.
MD5 is obviously never going to be used.
As a result, I don't see anything to fix, except than maybe eventually remove
the MD5 prefix since it is obsolete. TBD
--
You are receiving this mail because:
You are the assignee for the bug.
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org