nodeSolidServer/node-solid-server

Permission escalation because user-uploaded html files can use session cookie

Otto-AA opened this issue · 9 comments

Edit: I've replaced localStorage from the initial comment with cookies, my initial idea that localStorage is the problem was wrong.
Edit 2: Updated whole issue to say it is not mashlib related, but only requires any app login

Description

When logging in, solidcommunity stores a session cookie (nssidp.sid) that can be used for authentication. For html files running on *.solidcommunity.net this cookie will be attached to the request. If a malicious user creates a html file on victim.solidcommunity.net and the victim is logged, opening this html file gives the attacker full access to the pod.

Exploit

Preconditions:

  1. Alice has used any app to login with NSS, thus the nssidp.sid session cookie is stored.
  2. Alice gave Evil append access to a folder or file on Alice's pod

A simple exploit could look like this:

  1. Evil saves exploit.html on Alice's pod (see below for example content)
  2. Alice opens exploit.html, for instance by clicking on a link or being redirect by an app
  3. requests made by exploit.html automatically attach the session cookies, and thus have read/write/create permissions of the whole pod (the same permissions as the logged in person)
  4. exploit.html can make arbitrary requests on Alice's pod

exploit.html could be similar to following (abusing read access to private resources):

<script>
  fetch('/private/secret.txt')
    .then(res => res.text())
    .then(text => alert(text))
</script>

Impact

The result is, that an app or webId can escalate their permissions to the level of the logged in user. Thus, giving anyone append permissions to one file gives them control over the whole pod.

The required user interactions are either:

  • logged in with any app and using an app that has append permissions on a file
  • logged in with any app and giving a user append permissions on 1+ files and clicking on a phishing link

Note that I would have expected the exploit would work even if the html file is hosted on another pod (evil.solidcommunity.net). However, it seems it sends the session cookie but results in 403 when accessing the private resources. For me this 403 is unexpected, but I guess the server checks the sender domain with regards to the session cookie.

Migitation

The problem arises, because NSS sets a session cookie on solidcommunity.net and serves user-generated html files on solidcommunity.net. This cookie is attached to requests to solidcommunity.net and subdomains.

The solutions I see currently are:

  1. remove the cookie
  2. sandbox served html files
  3. not serve html files

All of these are breaking changes.

Remarks

Related to: https://forum.solidproject.org/t/is-it-secure-for-pods-to-serve-html-files/6379/6 (about sandboxing / not serving html files)

I'm sorry to not understand your point. But I am not an expert and even less in security.

A Solid Pod is a web server. As such should serve html files.
In NSS and certain flavour of CSS mashlib is used as an integrated web app and as such served from the same domain.

You can use mashlib as a web app see https://solidos.github.io/mashlib/dist/browse.html

exploit.html is a compiled version of (as seen here):

return Not Authenticated and do not display anything. I don't thing the script code is run

exploit.html uses the credentials from localStorage and has read/write/create permissions of the whole pod (the same permissions as mashlib)

To my understanding DPOP authorization do not give access to the credentials in localStorage.
It used to be the case with the prior legacy authorization in NSS.

I've tried to replicate it with CSS+mashlib, however it seems not exploitable there. A request there results with 401, my guess is because no authorization header is sent and CSS requires this.

NSS on the other hand does not seem to require the authorization header, only the nssidp.sid is necessary to authenticate.

@bourgeoa Is there any further information I could provide to help resolving this issue? I understand that this is a bigger change and thus needs time, just want to be sure it's not taking more time than necessary because of missing information.

I don't fully understand the cookie settings yet, but my guess is that cross-origin they are not included in the requests.

My guess was wrong, the cookie is set in both ways on solidcommunity.net, so it is not cross-origin in the first place. So moving mashlib to a different origin does not help the problem. I've updated the original post and removed outdated comments. . Maybe it would make sense to remove the outdated comments. While understanding the issue better, I've updated the original issue a lot and most of the comments are outdated/wrong with regards to the better understanding.

@Otto-AA Hello Otto.
I am very sorry for a late reply.

I think any MIME type that uses a DOM-style model can execute javascript, such as text/html, svg, xml, and definitely others I am unaware of. If you would like to help me understand what session cookie is doing versus authentications, and what sort of MIME types use a DOM, I can potentially work on having the Content-Disposition: attachment header set if any response type being sent is under those content types.

If that is too difficult, if you could provide more information about the security flaws I can take a look at a change that may not break backwards compatibility.

Edit: And if you can also perhaps point to the code snippet that is only using the session cookie as the authorization method in NSS.

Hi @zg009

In general, I think there are two problems. (1) that NSS allows cookie authentication, so any html/etc file that is stored on the pod can make authenticated requests (this github issue). (2) that NSS (and CSS) do not restrict serving user-created html/etc files, so these can run in the browser under the pods origin (see solid/specification#514).

It could be, that all problems of (1) are solved if (2) is addressed, I didn't think much about this yet. In other words, it could be, that we do not need to change/remove the cookie authentication if we implement some restriction on serving user-created html/etc files (eg adding the CSP sandbox header to all files).

If this is the case, I think the priority would be to address (2), and not the cookie issue. To understand the impact it would have and which mechanism is suitable to address the issue. This is more of a general Solid issue and less NSS specific (thus the general issue in the specification repository).

I think any MIME type that uses a DOM-style model can execute javascript, such as text/html, svg, xml, and definitely others I am unaware of.

Good point. From what I know, javascript is possible in Html and Svg. Xml does not work, but I guess XHtml also works 🤷.

Edit: And if you can also perhaps point to the code snippet that is only using the session cookie as the authorization method in NSS.

I'm not sure if NSS itself relies on the cookie. Maybe it does so for account management (login, registration, account deletion if it has such).

I think SolidOS relies on cookies to display iframes of html files. So if you have myPage.html stored in your pod and open it via SolidOS (the default file browser for NSS), then it creates an IFrame with src = ...../myPage.html. I think this relies on cookie to properly fetch the html file for the iframe. The iframe creation code is here: https://github.com/SolidOS/solid-panes/blob/main/src/humanReadablePane.js

It could be, that all problems of (1) are solved if (2) is addressed, I didn't think much about this yet. In other words, it could be, that we do not need to change/remove the cookie authentication if we implement some restriction on serving user-created html/etc files (eg adding the CSP sandbox header to all files).

@Otto-AA I am making the assumption here that this flaw occurs only under the condition that Alice (victim) gave Eve (malicious actor) append access to her pod on NSS and Eve uploaded an file capable of injecting javascript which can abuse the session key authentication.

Isolating all MIME types may be difficult, and there is some discussion I saw about rendering HTML and JS files being necessary for some things Solid should be used to achieve. I am not a session/cookie expert by any means, but it looks like disabling scripts running from HTML files would solve this issue, but overlaps with the fact you may want scripts to do a certain task for a non-malicious actor.

Exfiltration itself isn't even the biggest issue since any method would work theoretically with owner-level authentication, and the resource can't be secured with extra cookies, so I'm pretty sure this is a strictly server-side issue.

Can you think of any use cases where a user would be executing content in an HTML file uploaded by a malicious actor against their own Pod? Assuming this malicious actor only has append permissions. I am also assuming if a malicious actor has read-only permissions then this attack isn't feasible. But having write + append access has the same/worse outcome.

I'm not sure if NSS itself relies on the cookie. Maybe it does so for account management (login, registration, account deletion if it has such).

I've looked at some of the code itself and as far as account management and creation I have not run into the section which uses the cookie yet, as I've toyed around with the code myself some for fixing a couple of issues and pet projects, so I'll look further into it.

I am making the assumption here that this flaw occurs only under the condition that Alice (victim) gave Eve (malicious actor) append access to her pod on NSS and Eve uploaded an file capable of injecting javascript which can abuse the session key authentication.

Yes, at least Append is necessary. However, if I remember correctly, by default everybody has Append access to the inbox on NSS.
Also, the victim needs to open the malicious file, however that should be quite easy from an attackers perspective (eg by sending a mail that includes the link and the victim opens it; or opening it from another malicious website).

Isolating all MIME types may be difficult [...]

A server could simply add the CSP sandbox header to all files, regardless of their MIME type. For the files that can execute javascript (html, etc) it would put them into their own sandbox. For other files, it won't have an effect.

[...] there is some discussion I saw about rendering HTML and JS files being necessary for some things Solid should be used to achieve. I am not a session/cookie expert by any means, but it looks like disabling scripts running from HTML files would solve this issue, but overlaps with the fact you may want scripts to do a certain task for a non-malicious actor.

Yes, it's a good question what the usability impact would be when fixing (1) NSS cookies or (2) or same-site hosting of html/... files. For latter, there are some example usages mentioned in the main issue for this security issue: solid/specification#514

Can you think of any use cases where a user would be executing content in an HTML file uploaded by a malicious actor against their own Pod? Assuming this malicious actor only has append permissions.

I'm not sure I understand what you mean with "use case" (for me, this means a way a user uses the application, not something connected to a malicious actor).

I've looked at some of the code itself and as far as account management and creation I have not run into the section which uses the cookie yet, as I've toyed around with the code myself some for fixing a couple of issues and pet projects, so I'll look further into it.

I wish you good luck at finding the usages :)

However, to be honest I wouldn't spend too much time into this cookie issue, as it is likely solved by solid/specification#514 anyway. (For that, trying to understand the implications of the CSP Sandbox header for end-users would be good. We likely want to know which use cases exist, that make use of html/... content on the pod and would be broken with this, before implementing it).

I've read the discussion at the specification you linked, and it looks like it is still in the works.

However, I can create a branch of NSS as it is and add a middleware that will attach a CSP sandbox header on successful GET requests before they are sent. I'll also see if it breaks the test suite in any meaningful way, and potentially write tests that may break. I'll leave this open for now until the specification gets finalized, and then work from there.