cssinjs / jss

JSS is an authoring tool for CSS which uses JavaScript as a host language.
https://cssinjs.org
MIT License
7.07k stars 397 forks source link

Ensure escaping during SSR #1265

Open kof opened 4 years ago

kof commented 4 years ago

Script injection

Expected behavior: CSS rendered serverside needs HTML escaping by default because of script injection attack.

Describe the bug:

There is a known security issue with rendering CSS serverside and interpolating user content into it. It's the same issue that plagues all backend frameworks forever. React is very explicit about it by providing only one way to render unescaped HTML using dangerouslySetInnerHTML

In JSS this is also possible since any enduser's value can be used and if devs (JSS users) don't escape the attacker can do this:

{
  root: {
    backgroundColor: "#FFF;}</style><script>alert(document.cookie)</script>"
  }
}

In the case of JSS this is only possible with SSR, because the techniques we use on the client style.textContent and sheet.insertRule don't evaluate HTML.

Codesandbox link: https://codesandbox.io/s/elated-jepsen-qox0m

Versions (please complete the following information):

Solution:

When we call registry.toString() we can escape closing tags example implementation I don't know if we need to escape anything else except of the closing </style tag, since this is the only way I can think of how an attacker can inject script. Let me know if there is any other way.

CSS injection attack

There is another attack vector with CSS injection, which is discussed here.

The problem is well described by @jamesknelson https://frontarm.com/james-k-nelson/how-can-i-use-css-in-js-securely/

TLDR if attacker is able to inject custom CSS, they can capture key strokes and send requests using background images more about it here

Same issue at styled components

Janpot commented 4 years ago

FYI: My mitigation as a quick fix was to escape all / characters in the SSRed CSS.

sheets.toString().replace(/(?<!\\)\//g, '\\/');

For context: I raised this issue initially with @material-ui.

kof commented 4 years ago

@Janpot as a hot fix this is ok. For a library it needs more than that.

Janpot commented 4 years ago

I agree. Also, just want to note that the SSR issue is slightly different than the one raised by @jamesknelson. It has a much higher impact as it allows for arbitrary javascript execution, while the other issue only is about making arbitrary requests. Not that it matters much, just want to make sure there's two issues here, and fixing the script injection solves only half of the problem. I'm not exactly sure how that other issue could be solved though. (Or whether it should be solved at all by CSS-in-JS libraries)