1

I have a service which allows the user to specify a callback function name that wraps the data being returned to support jsonp callbacks. I want to make sure that I am covering all of my bases in regards to preventing XSS attacks.

Note, I have read through the OWASP security checklist but none of the recommendations seem to directly address this question.

These are the currently supported methods for specifying the jsonp function where the function name is cbFn and cbFn is declared on its own, a method on an object, or being accessed from an object/array:

https://service.com/cbFn
https://service.com/?callback=cbFn
https://service.com/?callback=obj.cbFn
https://service.com/?callback=obj['cbFn']
https://service.com/?callback=obj[1]

These return:

cbFn({data: 'data being returned'})
obj.cbFn({data: 'data being returned'})
obj['cbFn']({data: 'data being returned'})
obj[1]({data: 'data being returned'})

However the following requests also work and are the known XSS issues I want to circumvent:

// executes an anonymous function
https://service.com/?callback=(()=%3E{alert(1)})
// replaces the user's callback function with our own
https://service.com/?callback=cbFn=((data)=>{alert(data)})

Is it enough to just replace/remove the characters ()=> in the callback name to prevent XSS vulnerabilities? I want to allow the full valid javascript character set for function names, so restricting the valid character range to /[$_\w]+/ (alphanumeric plus $ and _) doesn't seem to be a good option.

  • 1
    If the returned response is JavaScript, you shouldn't worry about character limits. And to avoid MIME sniffing, specify X-Content-Type-Options: nosniff. This ensures that the response isn't interpreted as HTML even if XSS payloads are reflected in response unmodified. – 1lastBr3ath Aug 25 '18 at 20:17
  • @1lastBr3ath if the returned response is JavaScript, you shouldn't worry about character limits This sounds like bad advice. You totally have to worry about this. If it wasn't super clear, I'm asking about how to make the callback function names provided in the request safe to prevent executing arbitrary js when its executed in the context of the user's site. – Geuis Aug 25 '18 at 20:22
  • 1
    The user can execute anything in his/her site. S/he doesn't need your script to execute defined function. As long as your jsonp endpoint returns 'application/javascript', no browsers will render the content (except IE) which ultimately neutralizes your concern. – 1lastBr3ath Aug 25 '18 at 20:25
  • From the examples it looks like you not only want to have a fixed callback name but that you want to allow to use expressions which ultimately result in a function, i.e. obj['cbFn'], obj.cbFN etc. I don't think this is a good idea since then it is hard to restrict something like this. Apart from that, why use JSONP in the first place instead of CORS? JSONP is more considered a hack needed at a time proper cross-origin-XHR (i.e. CORS) was not possible. – Steffen Ullrich Aug 25 '18 at 20:29
  • 1
    @Geuis: The argument from 1lastBr3ath was that you don't need to worry about the callback names at all since the callback names are given by the third party and they are executed in the website of the same third party - so they could only do harm to themselves. Since you are worried about the callback names anyway you must envision that the JSONP gets included some other way apart from <script> - and that's where the argument about the content-type fits in. – Steffen Ullrich Aug 25 '18 at 20:44
2

It sounds like you are asking from the context of the service provider protecting a remote client in which case the answer is simple:

As the service provider, you can't protect against XSS at all, and you might as well not bother

Keep in mind, I'm normally big on "defense in depth" and putting in security walls every step of the way. However I think this is literally one of the few places where your concern isn't worth worrying about. There are two reasons why:

1. Under normal usage the executing client has full control over the request, and so there is no reason to expect payloads like this

There isn't much more to say about this actually, because this isn't what you are concerned about. But just to say out loud: the client itself is providing the JSONP callback, and so if they choose to ask you to return actual javascript, then there isn't much of a reason for you to stop them (especially since doing so would be silly and I doubt anyone would bother). The only other time someone might request a "dangerous" callback from your server is if The remote client has had an XSS breach and malicious javascript has taken over their system. However, if that happens:

2. The malicious javascript has full control over the remote client and doesn't need you to execute arbitrary javascript anyway

Which is equally simple: if an attacker has managed an XSS attack against a client using your service, they don't have to inject malicious javascript into the callback. They can just replace the callback method in the local client with their own. In fact, that's much easier. As a result, there is literally no reason why someone would attempt to use your service as an XSS injection endpoint into the remote client. To put it simply:

If an attacker has managed an XSS attack against a client using your service, then they've already won and they have no reason to pass XSS payloads into your service. It would just reflect back on the page they have already taken over.

I suppose there might be some developer out there that came up with some crazy (dangerous) scheme whereby user input on their site is used to build the JSONP callback passed into your service, and it becomes a first-order XSS vulnerability weakness. However, there is no practical reason why anyone would ever do something like that (having used lots of these kinds of services myself, you would have to go out of your way to setup something that dangerous), so much so that I don't think it is worth spending any amount of your time trying to protect your users from that level of silliness. You're more likely to accidentally introduce negative side-effects to your regular users than protect someone against the level of poor-planning that would be required for this protection on your end to do anything.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.