In a recent web app pen test, we discovered an interesting Cross-site scripting (XSS) vulnerability. As we review our findings, hopefully, it will give you some ideas for how to poke at edge cases in the apps you are testing. Buckle in, this one’s creative.
For background, the company that makes the web app hosts and maintains it and adds new features so you don’t have to ~~punish~~ pay your own developers to code and maintain it. The app organizes employee information; you know, the type of web app that every company needs but nobody wants to write. While testing this web app, we found a few XSS in a few fields, but it was obvious that the developers had, in large part, attempted to sanitize user input. Yay!
An Innocent Feature Enhancement
Ok, the scene is set. So what does a customer do? Complain of course!
>Having to input 500 employees into the web app is tedious, so why don’t we do a bulk import? The developers already have an API and unit tests and all the things, so the easiest way to implement this is to slap a CSV format together so the human resources customers can use their favorite program, Microsoft Excel, to bulk import the data.
So now, the intrepid developer can write an uploader and call all the same functions the front-end web app was calling, and Ta-Da! Bulk Import added! Users are happy, developers are happy, and everyone is happy.
>*Did you sanitize your bulk uploader?*
>*Sanitize my bulk uploader? It’s CSV, it doesn’t need sanitization*
So, what does a pentester do? Throw XSS into every field of course! Yes, including the bulk uploader’s `template.csv`.
![Bulk Uploader template.csv](images/2021.12.20_21-16-56.png)
When saving this, you’ll be giving options to quote the comma seperated value (CSV) file. This is an important feature of CSV that enables you to legitimately use a comma in a CSV. It’s even in [RFC 4180](https://datatracker.ietf.org/doc/html/rfc4180):
6. Fields containing line breaks (CRLF), double quotes, and commas
should be enclosed in double-quotes. For example:
7. If double-quotes are used to enclose fields, then a double-quote
appearing inside a field must be escaped by preceding it with
another double quote. For example:
Did you know CSV had a formal RFC? For XSS testings, this may be an important feature and may cause different behavior. Think like the developer: did they use a CSV library or write their own code because it’s “*so simple*”? Did they want to challenge themselves and write a regular expression?
Make sure you test with and without quotes. In this case, quoting didn’t matter. XSS worked both with or without CSV quoting.
After uploading this to the webapp and reloading the employee grid, we were rewarded with this:
As a former developer, I can see exactly how this happens:
1. Developer writes and tests a feature.
2. QA and security team review the feature and deem it acceptable.
3. Customer feedback asks for *a minor* change (or what appears to be a minor change) and the Developer makes a change that skips careful QA and security team review because it was a *minor* change.
4. **BOOM!** XSS vulnerability.
In summary, sanitize your user input. Yes, all of it.