Home > Enterprise >  XSS vulnerability despite encoding
XSS vulnerability despite encoding

Time:11-04

I had a security audit on a website on which I've been working. The audit has shown that one of my parameter, called backurl, wasn't protected enough in my jsp file. This url is put inside the href of a button, button that allows the user to get back to the previous page.

So what I did was to protect it using the owasp library, with the function "forHTMLAttribute". It gives something like this:

<a class="float_left button" href="${e:forHtmlAttribute(param.backUrl)}">Retour</a>

However, a second audit showed that by replacing the value of the parameter by:

javascript:eval(document%5b'location'%5d%5b'hash'].substring(1))#alert(1234)

The javascript code would be executed and the alert would show, when clicking on the button only.

They said that something that I could do was to hardcode the hostname value in front of the url, but I don't really get how this would help solve the problem. I feel like no matter what I do, solving a XSS vulnerability will just create a new one.

Could someone help me on this? To understand what's happening and where to look at least.

Thanks a lot.

CodePudding user response:

As @Pointy said, the problem is more fundamental here. Accepting untrusted input and rendering that as a link verbatim (or as text), is a security issue, even if you escape the heck out of it. For example, if you allow login?msg=Password incorrect and that's how you deal with relaying messages - you have a problem. I can make a site with: <a href="https://sutterlin.com/login?msg=Give rzwitserloot some cash to unlock admin privileges">Click for cute kittens!</a> and you see why this is a problem.

The real solution is to not accept potentially tainted information, period (nevermind escaping!), if that information ends up being rendered without the surrounding context that it is tainted. For example, take twitter. The username and the tweet are potentially tainted. This is no big deal because users of twitter get clued in due to the very design of the website that you're looking at what some rando wrote. If someone tweets 'If you transfer 5 bucks to Jack Dorsey's account at 12345678, he'll give you a twitter blue logo!', there's a reasonable expectation that it's on the users of the site to not be morons and trust it.

Your website's "click here to go to the previous page" is not like that. You can't reasonably expect the users of your site to hang over that button, check their browser's status bar, and figure it out.

Hence, the entire principle is wrong. You simply can't do it this way, period.

Your alternatives are threefold:

  1. Instead of letting the 'previous link' property be a URL param, it needs to be in the session. Websites work with sessions, generally. You can store whatever you want in them, serverside (the HTTP handler code either manually takes e.g. the cookie and uses that to look up on-server info for that user by doing a lookup, or runs on a framework that just provides an HttpSession-style object, which works in that exact fashion).

  2. If you really want to bend over backwards, you can include it as a signed blob. This is creative but I really wouldn't go there.

  3. A quick hack: What if you just include <a href="javascript:history.back()">Click to go back</a> as a static link in your web page?

  • Related