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

Authorization header parsing is prone to issues #4739

Open
nielsvanvelzen opened this issue Dec 8, 2020 · 6 comments
Open

Authorization header parsing is prone to issues #4739

nielsvanvelzen opened this issue Dec 8, 2020 · 6 comments

Comments

@nielsvanvelzen
Copy link
Member

@nielsvanvelzen nielsvanvelzen commented Dec 8, 2020

Describe the bug

The current implementation of the authorization header parsing has (at least) the following issues:

  • A value can't contain any commas
  • A value can't start or end with a doublequote
  • A value can't contain special characters
    • HTTP Headers only allow ASCII characters
    • There is no option to encode/decode the values (using base64 or urlencoding)
  • When a value contains HTML characters like < it will htmlencode them
    • This causes issues when displaying the names in non-web clients
    • Web does not escape the HTML
    • This was some sort of "fix" for XSS issues

Sources

private Dictionary<string, string> GetAuthorization(string authorizationHeader)
{
if (authorizationHeader == null)
{
return null;
}
var parts = authorizationHeader.Split(' ', 2);
// There should be at least to parts
if (parts.Length != 2)
{
return null;
}
var acceptedNames = new[] { "MediaBrowser", "Emby" };
// It has to be a digest request
if (!acceptedNames.Contains(parts[0], StringComparer.OrdinalIgnoreCase))
{
return null;
}
// Remove uptil the first space
authorizationHeader = parts[1];
parts = authorizationHeader.Split(',');
var result = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var item in parts)
{
var param = item.Trim().Split('=', 2);
if (param.Length == 2)
{
var value = NormalizeValue(param[1].Trim('"'));
result[param[0]] = value;
}
}
return result;
}

private static string NormalizeValue(string value)
{
return string.IsNullOrEmpty(value) ? value : WebUtility.HtmlEncode(value);
}
}

Proposed changes

Fixing the XSS thingy needs changes in jellyfin-web. The others could be fixed by rewriting the header parsing and allowing some sort of encoding. This could easily be done with backwards compatibility.

Related issues
jellyfin/jellyfin-web#718

@tommasodotNET
Copy link

@tommasodotNET tommasodotNET commented Dec 13, 2020

I was taking a look at this. Since the comma is used to split the authorization headers, another separator character should be chosen.

@nielsvanvelzen
Copy link
Member Author

@nielsvanvelzen nielsvanvelzen commented Dec 13, 2020

I don't think we can change that part. That would break all existing clients. I don't think we need to change it too, a value can be wrapped in double quotes so we should just not split on the comma inside of quotes.

@tommasodotNET
Copy link

@tommasodotNET tommasodotNET commented Dec 13, 2020

That makes sense. And is linked to the second point of your list "A value can't start or end with a double quote".

@nielsvanvelzen
Copy link
Member Author

@nielsvanvelzen nielsvanvelzen commented Dec 13, 2020

Some quick thoughts (I think I mentioned a few in the start post):

  • values not wrapped in a double quote are allowed but can not contain special characters or commas
  • values wrapped in double quote can contain anything allowed in a header (ASCII), including a comma
    • the current implementation always strips all doublequotes from start and end of string, even multiples. We will use this existing behavior but use it for something useful
  • values may be urlencoded (they will always be urldecoded)
    • this one makes sure we can use special charaters
    • this one might change existing behavior slightly but I consider it "worth it" - it won't break anything
  • no html encoding happens in server, a client should escape it
@tommasodotNET
Copy link

@tommasodotNET tommasodotNET commented Dec 14, 2020

I see. So in order to split the values by commas allowing to have commas inside the value would be something like
parts = authorizationHeader.Split("\",");

@nielsvanvelzen
Copy link
Member Author

@nielsvanvelzen nielsvanvelzen commented Dec 14, 2020

I'd say don't use the Split function but write a parser that loops trough all characters instead. That way you can easily add escaping etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants