[ 
https://issues.apache.org/jira/browse/SOLR-16077?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Ben updated SOLR-16077:
-----------------------
    Description: 
I'm working with Solr 7 because reasons, but the issue also seems to persist in 
the current code base.
h2. Documentation

Here's the Solr 8.1 documentation for the [Basic Authentication 
Plugin|[https://solr.apache.org/guide/8_1/basic-authentication-plugin.html]]. 
In the security.json example, we see
{code:java}
"credentials":{"solr":"IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= 
Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c="}, {code}
but the only explanation given for this is "A user called 'solr', with a 
password {{'SolrRocks'}} has been defined."

What's missing is:
 * Explanation of how to produce such a credential string. In psuedocode, this 
amounts to:
 ** 
{code:java}
encode_base64(sha256(sha256(salt + password))) + " " + encode_base64(salt){code}

 * The salt used, in addition to the password used, so that users can test that 
their produced credentials will match Solr's handling.

I've spent a good bit of searching through articles and watching videos, and I 
couldn't find any that actually explained this until I saw the source code. The 
only explanation I've seen for adding users was to first stand up an 
unauthenticated instance, and then add them via the API, which doesn't 
translate well into automated deployments.
h2. Code

Let's get back to that pseudocode.
{code:java}
encode_base64(sha256(sha256(salt + password))) + " " + encode_base64(salt){code}
Strangely, we're hashing twice! Here it is in [the 
source|https://github.com/apache/solr/blob/main/solr/core/src/java/org/apache/solr/security/Sha256AuthenticationProvider.java#L129].
 In more detail:
{code:java}
    if (saltKey != null) {
      digest.reset();
      digest.update(Base64.getDecoder().decode(saltKey));
    }

    byte[] btPass = digest.digest(password.getBytes(StandardCharsets.UTF_8));
    digest.reset();
    btPass = digest.digest(btPass);
    return Base64.getEncoder().encodeToString(btPass); {code}
Some issues:
 * Nit: the salt is base64'd before being passed to the function then 
immediately unbase64'd again, but that's beside the point.
 * The salt is added to the message, then the password, and then digest() is 
called. This produces a SHA256 hash digest.
 * digest() [basically calls 
reset()|https://docs.oracle.com/javase/8/docs/api/java/security/MessageDigest.html],
 so there's no need to call reset()
 * The previous digest is then hashed again!

h2. Outro

I'm not too familiar with secure coding practices, especially in Java, so 
perhaps this was to work around some sort of limitation with 
java.secure.MessageDigest when this particular code was produced 7 years ago. 
It certainly seems strange to do this in terms of code quality, but I feel like 
my more immediate issue is that it's incredibly non-obvious to an end user just 
trying to secure a Solr instance.

Is there a reason it's coded this way? How should end-users learn how to 
configure security.json? If the code is updated to use only a single round of 
SHA256 hashing, how will existing Solr deployments update smoothly?

Thanks!

  was:
I'm working with Solr 7 because reasons, but the issue also seems to persist in 
the current code base.
h2. Documentation

Here's the Solr 8.1 documentation for the [Basic Authentication 
Plugin|[https://solr.apache.org/guide/8_1/basic-authentication-plugin.html]|https://solr.apache.org/guide/8_1/basic-authentication-plugin.html].].
 In the security.json example, we see
{code:java}
"credentials":{"solr":"IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= 
Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c="}, {code}
but the only explanation given for this is "A user called 'solr', with a 
password {{'SolrRocks'}} has been defined."

What's missing is:
 * Explanation of how to produce such a credential string. In psuedocode, this 
amounts to:
 ** 
{code:java}
encode_base64(sha256(sha256(salt + password))) + " " + encode_base64(salt){code}

 * The salt used, in addition to the password used, so that users can test that 
their produced credentials will match Solr's handling.

I've spent a good bit of searching through articles and watching videos, and I 
couldn't find any that actually explained this until I saw the source code. The 
only explanation I've seen for adding users was to first stand up an 
unauthenticated instance, and then add them via the API, which doesn't 
translate well into automated deployments.
h2. Code

Let's get back to that pseudocode.
{code:java}
encode_base64(sha256(sha256(salt + password))) + " " + encode_base64(salt){code}
Strangely, we're hashing twice! Here it is in [the 
source|https://github.com/apache/solr/blob/main/solr/core/src/java/org/apache/solr/security/Sha256AuthenticationProvider.java#L129].
 In more detail:
{code:java}
    if (saltKey != null) {
      digest.reset();
      digest.update(Base64.getDecoder().decode(saltKey));
    }

    byte[] btPass = digest.digest(password.getBytes(StandardCharsets.UTF_8));
    digest.reset();
    btPass = digest.digest(btPass);
    return Base64.getEncoder().encodeToString(btPass); {code}
Some issues:
 * Nit: the salt is base64'd before being passed to the function then 
immediately unbase64'd again, but that's beside the point.
 * The salt is added to the message, then the password, and then digest() is 
called. This produces a SHA256 hash digest.
 * digest() [basically calls 
reset()|https://docs.oracle.com/javase/8/docs/api/java/security/MessageDigest.html],
 so there's no need to call reset()
 * The previous digest is then hashed again!

h2. Outro

I'm not too familiar with secure coding practices, especially in Java, so 
perhaps this was to work around some sort of limitation with 
java.secure.MessageDigest when this particular code was produced 7 years ago. 
It certainly seems strange to do this in terms of code quality, but I feel like 
my more immediate issue is that it's incredibly non-obvious to an end user just 
trying to secure a Solr instance.

Is there a reason it's coded this way? How should end-users learn how to 
configure security.json? If the code is updated to use only a single round of 
SHA256 hashing, how will existing Solr deployments update smoothly?

Thanks!


> Solr basic authentication is undocumented and a bit strange
> -----------------------------------------------------------
>
>                 Key: SOLR-16077
>                 URL: https://issues.apache.org/jira/browse/SOLR-16077
>             Project: Solr
>          Issue Type: Bug
>      Security Level: Public(Default Security Level. Issues are Public) 
>          Components: Authentication
>            Reporter: Ben
>            Priority: Major
>              Labels: documentation, easyfix, security
>
> I'm working with Solr 7 because reasons, but the issue also seems to persist 
> in the current code base.
> h2. Documentation
> Here's the Solr 8.1 documentation for the [Basic Authentication 
> Plugin|[https://solr.apache.org/guide/8_1/basic-authentication-plugin.html]]. 
> In the security.json example, we see
> {code:java}
> "credentials":{"solr":"IV0EHq1OnNrj6gvRCwvFwTrZ1+z1oBbnQdiVC3otuq0= 
> Ndd7LKvVBAaZIF0QAVi1ekCfAJXr1GGfLtRUXhgrF8c="}, {code}
> but the only explanation given for this is "A user called 'solr', with a 
> password {{'SolrRocks'}} has been defined."
> What's missing is:
>  * Explanation of how to produce such a credential string. In psuedocode, 
> this amounts to:
>  ** 
> {code:java}
> encode_base64(sha256(sha256(salt + password))) + " " + 
> encode_base64(salt){code}
>  * The salt used, in addition to the password used, so that users can test 
> that their produced credentials will match Solr's handling.
> I've spent a good bit of searching through articles and watching videos, and 
> I couldn't find any that actually explained this until I saw the source code. 
> The only explanation I've seen for adding users was to first stand up an 
> unauthenticated instance, and then add them via the API, which doesn't 
> translate well into automated deployments.
> h2. Code
> Let's get back to that pseudocode.
> {code:java}
> encode_base64(sha256(sha256(salt + password))) + " " + 
> encode_base64(salt){code}
> Strangely, we're hashing twice! Here it is in [the 
> source|https://github.com/apache/solr/blob/main/solr/core/src/java/org/apache/solr/security/Sha256AuthenticationProvider.java#L129].
>  In more detail:
> {code:java}
>     if (saltKey != null) {
>       digest.reset();
>       digest.update(Base64.getDecoder().decode(saltKey));
>     }
>     byte[] btPass = digest.digest(password.getBytes(StandardCharsets.UTF_8));
>     digest.reset();
>     btPass = digest.digest(btPass);
>     return Base64.getEncoder().encodeToString(btPass); {code}
> Some issues:
>  * Nit: the salt is base64'd before being passed to the function then 
> immediately unbase64'd again, but that's beside the point.
>  * The salt is added to the message, then the password, and then digest() is 
> called. This produces a SHA256 hash digest.
>  * digest() [basically calls 
> reset()|https://docs.oracle.com/javase/8/docs/api/java/security/MessageDigest.html],
>  so there's no need to call reset()
>  * The previous digest is then hashed again!
> h2. Outro
> I'm not too familiar with secure coding practices, especially in Java, so 
> perhaps this was to work around some sort of limitation with 
> java.secure.MessageDigest when this particular code was produced 7 years ago. 
> It certainly seems strange to do this in terms of code quality, but I feel 
> like my more immediate issue is that it's incredibly non-obvious to an end 
> user just trying to secure a Solr instance.
> Is there a reason it's coded this way? How should end-users learn how to 
> configure security.json? If the code is updated to use only a single round of 
> SHA256 hashing, how will existing Solr deployments update smoothly?
> Thanks!



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

---------------------------------------------------------------------
To unsubscribe, e-mail: issues-unsubscr...@solr.apache.org
For additional commands, e-mail: issues-h...@solr.apache.org

Reply via email to