What I learned from suffering my first and last XSS attack
livesshattack.net
livesshattack.net
- Content-Security-Policy https://developer.mozilla.org/en-US/docs/Web/Security/CSP/In...
- The sandbox attribute on iframes: https://developer.mozilla.org/en/docs/Web/HTML/Element/ifram...
XSS is one of the hardest things to keep under control at scale.
CSP prevents an attacker from executing scripts, but the attacker can still corrupt your HTML.
APIs like jQuery are worse because you end up treating strings as HTML without even realizing it. Example from the article:
$("#tail-here").prepend(newlines);
There's no hint on that line that the `newlines` variable is interpreted as HTML instead of text. content
Type: >>htmlString<< or Element or Array or jQuery
You could argue that the API is bad for allowing HTML strings as arguments, but it's not really surprising that a function does what it is documented to do. Especially since these are DOM manipulation, not string manipulation functions.The only native DOM API calls that can get you an XSS vulnerability are sets to `innerHTML`, `outerHTML`, and maybe some few others. Most of the methods for getting things done don't have any possibility of introducing an XSS issue. With jQuery, many methods including every method capable of inserting elements is also capable of introducing an XSS issue depending on the types passed to them. So you when you're reviewing for XSS issues, you have many more places to check, and analyzing the calls to jQuery methods to see if they have the potential for XSS is much more difficult because you have to trace the path backwards from every single call to see what types are set into the variables passed to the methods.
That is exactly what I’m arguing, yes.
> but it's not really surprising that a function does what it is documented to do
It doesn’t have to be surprising or undocumented to be stupid.
> You could argue that the API is bad for allowing HTML strings as arguments
That is exactly what I’m arguing, yes.
And how native DOM helps there?jQuery has text()[0], but because most of its API takes strings to start with, it's very convenient to do the wrong thing and shove untrusted strings into unsafe methods.
jQuery calls unsafe API which should only be handled trusted strings but makes it easy and convenient to give them untrusted string and thus introduce exploit vectors.
Furthermore it's also significantly more difficult to audit the code, using the regular DOM there are only a pair of attributes to check, whereas pretty much any jQuery method call is a potential security hole.
tldr: jQuery makes doing things wrong very easy, much easier than doing things right.
It's like what ASLR and stack canaries do for buffer overflow vulnerabilities in C/C++. You still should try to avoid writing buffer overflow bugs, but if/when they do happen, the protections mean that the issue will probably just be a denial-of-service issue rather than an issue that lets an attacker execute code on your systems.
There's no excuse to not start new projects off with a CSP rule like that. Doing it from the start means you won't ever have to comb through your codebase later to remove all bits of inline javascript that you depend on to get the benefits.
https://github.com/paragonie/csp-builder
I'm working this week to integrate it into another project we're developing. (It's MIT licensed, so have fun with it.)
security@ my company's domain name
I'm pretty sure HN doesn't have PMs.React and Angular (and maybe Ember too?) similarly auto-escape any strings to be rendered and only provide very explicit ways to circumvent that (in React it's even called "dangerouslySetInnerHTML" and takes an object with a property called "__html" rather than a string[0]).
You can avoid XSS in dynamically typed languages. You just need to make it easier to do the safe thing than the difficult thing.
[0]: I really like React's approach to naming APIs you should think twice about using. For legacy reasons ReactDOM is still bundled as part of React and exposed with a property but the name of that property is "__SECRET_DOM_DO_NOT_USE_OR_YOU_WILL_BE_FIRED" (presumably to prevent React maintainers / Facebook employees from using it).
It is interesting to see that other frameworks are using similar ideas to my own though. Maybe not surprising; but at least reassuring to know that my own quirky API design isn't as leftfield as it felt when I was developing it.
That's good, but it's not ideal as it confuses HTML/unsafe. An unwary developer could output untrusted text "safely" and still open up an XSS vulnerability – because they could be outputting to JavaScript embedded within HTML. Yes, Jinja will encode it as HTML by default, rendering it "safe" in terms of the HTML parser, but that still doesn't make it actually safe.
Example:
alert("Hello, {{user.name}}!");
By default, Jinja will encode this as HTML, meaning that you can't trick the HTML parser into injecting your HTML. But it is still completely vulnerable to the exact same security vulnerability, except by tricking the JavaScript parser.We should recognise what's actually the issue at play here. It's not really about whether data is safe or not. It's about correctly encoding data in a manner that's suitable for the context in which it is being output. Sometimes that's HTML, sometimes it's JavaScript, sometimes it's CSS, etc.
One could create the more comprehensive "html"/"css"/"javascript"/"text" set in dynamic languages too, but Jinja doesn't.
Similar to how Google Page Speed Insights and SEO tools which detect errors such as "You haven't minified your CSS", "You haven't set a title and description for your page" etc.
(edit: full disclosure, I'm one of the founders)
Other famous tools are nessus, and accunetix: https://www.tenable.com/products/nessus-vulnerability-scanne..., http://www.acunetix.com/vulnerability-scanner/
These scanners are usually used by security consultants to test a complete internal network of a client.
For a full list, some of which are open source, check this link: https://www.owasp.org/index.php/Category:Vulnerability_Scann...