simonw / datasette-css-properties

Experimental Datasette output plugin using CSS properties
15 stars 1 forks source link

Is ?_raw=column an XSS security hole? #1

Open simonw opened 3 years ago

simonw commented 3 years ago

The ?_raw=column mechanism makes me a little nervous. It feels like it could be used for XSS, since it allows attackers to inject exact values into a page that is served by Datasette - e.g. https://latest-with-plugins.datasette.io/fixtures.css?sql=select+%27%3Cscript%3Ealert(%22evil%2C+perhaps%22)%3C%2Fscript%3E%27+as+evil%3B&_raw=evil

:root {
  --evil: <script>alert("evil, perhaps")</script>;
}

But that page is served with the text/css content-type - it's not HTML.

Could a browser be tricked into rendering it as HTML, in which case it would open up a XSS hole in the hosting Datasette instance?

simonw commented 3 years ago

I'm going to add the "X-Content-Type-Options": "nosniff" header to the CSS output.

simonw commented 3 years ago

That content sniffing vulnerability isn't necessarily limited to pages that use ?_raw= - if a browser decides to render the dynamically generated CSS as HTML it's probably possible to construct an evil string which could be executed even with CSS string quoting rules applied to it.

simonw commented 3 years ago

Version 0.2 now sets that header, and is deployed to the demo.

simonw commented 3 years ago

If this does turn out to be a problem one potential solution would be to allow plugin authors to configure a subdomain to be used for this output, which they could then point at their Datasette as an additional DNS CNAME. Imagine configuring Datasette so the .css output format is always rendered on https://my-safe-domain.net/ where the rest of your instance renders content on https://my-regular-site.com.

I considered this previously for the .blob mechanism in https://github.com/simonw/datasette/issues/1036

simonw commented 3 years ago

Tweeted about this issue here: https://twitter.com/simonw/status/1347287093660184576 - also wrote about it in https://simonwillison.net/2021/Jan/7/css-apis-no-javascript/

marksteward commented 3 years ago

You can also leak data by injecting into CSS, e.g. input[value^="a"] { background-image: url(...) }, so make sure it's not possible to specify the _raw argument via the HTML pages themselves.

simonw commented 3 years ago

I think of things like that more as being self-inflicted XSS holes: if you as a page author chose to link to <link href="stylesheet" href="https://datasette-.../?sql=evil-css-to-run-on-your-page"> there's not much I can do to protect you.

My big concern here is any attacks which mean that just running datasette install dataasette-css-properties will open up an XSS hole in your own (potentially authentication-protected) Datasette instance - because an attacker could send you a link to http://your-datasette/...?sql=evil and following that link would execute JavaScript with access to your cookies and browser page session.

marksteward commented 3 years ago

Yep, and it's a fairly fiddly attack mechanism. But this feature is at its heart CSS injection so probably deserves a hazmat label. Any column specified with ?_raw= must be trusted.