Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Max basic authentication password length restricted by base64 encoded linefeed #7664

Closed
arendst opened this issue Oct 21, 2020 · 2 comments · Fixed by #7676
Closed

Max basic authentication password length restricted by base64 encoded linefeed #7664

arendst opened this issue Oct 21, 2020 · 2 comments · Fixed by #7676
Assignees

Comments

@arendst
Copy link

arendst commented Oct 21, 2020

While finding an answer to a question regarding the max allowed webserver password length in Tasmota (arendst/Tasmota#9587) I stumbled across a hard limit of 47 characters.

The HTTP Basic Authorization userid password as used in ESP8266WebServer-impl.h uses function base64_encode_chars to encode the userid:password. This function inserts linefeeds/carriage returns every 72 encoded characters as defined in cencode.h (#define BASE64_CHARS_PER_LINE 72).

In the case of Tasmota, where the userid is fixed set to admin, this allows for 47 characters in the password. Any more characters will insert a linefeed which isn't available in the HTTP request header.

As an example if a user uses a password of 12345678901234567890123456789012345678901234567890 it results in an base64 encoded string like

YWRtaW46MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4
OTA=

so with a linefeed after ..Njc4. The HTTP request header contains:

Authorization: Basic YWRtaW46MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTA=

The compare using function authReq.equalsConstantTime(encoded) will fail caused by the inserted linefeed.

As a possible solution I suggest to replace function authReq.equalsConstantTime(encoded) by a function discarding any control characters in the base64 encoded string before comparing.

EDIT: It works fine on the ESP32 as there the linefeed is not inserted in the base64 encoded data.

@arendst
Copy link
Author

arendst commented Oct 21, 2020

I see it relates to #6604 too

@arendst
Copy link
Author

arendst commented Oct 21, 2020

A possible solution we currently use in our core image is this:

int base64_encode_chars(const char* plaintext_in, int length_in, char* code_out){
  base64_encodestate _state;
  base64_init_encodestate_nonewlines(&_state);
  int len = base64_encode_block(plaintext_in, length_in, code_out, &_state);
  return len + base64_encode_blockend((code_out + len), &_state);
}

where line 120 in file cencode.cpp is changed to base64_init_encodestate_nonewlines.

@earlephilhower earlephilhower self-assigned this Oct 24, 2020
earlephilhower added a commit to earlephilhower/Arduino that referenced this issue Oct 24, 2020
Use a base64 encode that doesn't add CRs to the output when comparing
username:password values for authentication.

Fixes esp8266#7664
earlephilhower added a commit that referenced this issue Oct 25, 2020
Use a base64 encode that doesn't add CRs to the output when comparing
username:password values for authentication.

Fixes #7664
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants