I had an interesting experience when ordering a gift for my wife online at a popular personalized gift store. We love drinking wine, so my plan was to inscribe a set of 6 wine glasses. Like many couples that haven’t hit the 10 year anniversary yet, we have nicknames for each other; and, also like many couples we text each other frequently. I call my wife Babydoll and usually sign off on a text thread with <kiss>. Those of you who know a thing about reflective cross-site scripting can probably see where this is heading.
I start by entering text into the website form field. On the front I wanted Babydoll’s wine and on the back <kiss>. Being in the security field, I wondered how the site would handle a few things in my input:
- Would it strip out the single quote in Babydoll’s wine? Single quote is often used in SQL injection attacks and some websites blocklist the character, much to the chagrin of folks with the last name of O’Reily, O’Mally, et al.
- Would it show me the correct rendering of <kiss> on the “proof” screen? If this is not encoded properly to ensure it’s shown as the text I intend, there’d be a threat of cross-site scripting (XSS). In that case, instead of putting kiss inside those angle brackets, an attacker could put a script command…and rather than displaying the text, the browser would interpret the script and execute the command(s) with potentially damaging consequences.
Below are some screenshots of what the site displayed.
OK, this tells me a couple of things:
1. The site is using an image to reflect my input. That’s good! It avoids the potential XSS I was concerned about.
2. The site accurately displayed my input, single quote and all. So far so good.
Now let’s take a look at the back…
Interesting…. the site stripped out the angle brackets – even in the image rendering. OK, so maybe their developers know about reflective XSS and decided to avoid all things with angle brackets just to be safe.
But I’m in the application security profession… so I poke around a little, changing a couple of things (all legally of course – one shouldn’t pen test a website without permission since in most countries it’s illegal.)
Perhaps a font change will render something different?...
Sure enough! Certain fonts display the angle brackets and others don’t. Now I’m baffled. Why would this be the case? I decide to ignore the “why” for now and just move on. After all, I need to order my Valentine’s Day present in enough time to pick it up for my wife at the local mall after I place the order online. So I stick with the font that displays the <kiss> and move on to checkout.
I proceed, happy that the site has gotten it right (or at least right enough for me.) Here’s my confirmation screen with all the correct info:
In stock and ready to be picked up in plenty of time for Valentine’s Day. At least this year I won’t be in the proverbial dog house!
I’m traveling the week the glasses will be ready, so I send my niece to pick them up. I ask her to check them before she leaves the store because I’m still skeptical they’ll come out alright. She reviews them and leaves the store, satisfied they are correct.
Here’s where things get a little wonky….
When I bring the box home and open them up, I find that the engraving on the front of the glass is perfect; however, on the back this is what is on all 6 glasses:
Naturally, I’m disappointed with the engraving; but I’m also curious – what the heck is that character?
My wife works in the security field, too, so I decide to show her the glasses ahead of time and move on to a different Valentine’s Day gift. She finds the matter as humorous as I do, thankfully…but now of course I need to find another gift!
Unsatisfied that I understand what’s going on, I return to the site to test a few more things. Would other special characters produce funky results (even on-screen)?
Indeed they do! Here’s one such screen shot:
I put <Love> into the text box, then I tried escaping the ">" with a backslash. The web application is doing something with this input, though I’m not sure what. I ask one of our engineers and his best guess is that “par” might be “parse error” truncated, a variable name, or some other mangled interpretation of the parameter encoding and sanitization that the developer tried to put in place for user input.
This experience leaves me with a few interesting observations:
- Kudos to this website’s developers for at least doing something toward sanitizing user input. They clearly didn’t get it all right, but at least they’re thinking defensively, which is a good start! But they’ve got some business logic issues between the client and server side of their personalization website because the order confirmation showed me exactly what I expected but the resulting engraving didn’t match.
- Could this website have implemented defensive coding measures better so that it was still secure but didn’t negatively impact functionality? I’m sure the answer to this is yes… there are known best practices for input sanitization and output encoding that probably should have been implemented.
- There is something missing with this website’s quality assurance testing. I’m guessing the security and quality testing activities are segregated, with little communication between the two.
- I also would have loved for the store itself to verify that the order placed online is the same as what was produced (clearly this was not the case here.) With a simple comparison between the order confirmation screen (and email they sent me of the same) and the end product, it would have been clear that the wrong inscription was put on the glasses.
If you've got any further thoughts on this (or an idea for my wife's Valentine's Day gift), please let me know!