In this post, I will discuss an interesting case of XSS i.e., when a classical reflected XSS becomes stored XSS. The transition from reflected to stored happens because developers convert user-supplied input into some form of encoding, make it part of a URL and permanently store it in the database. I was thinking why developers do this at first place? The apparent reason, I can think of from the top of my head is tracking or for analytic purpose e.g., popular searches. If you know any other reason, please let me know. At the same time, I think, this type of practice makes the exploitation easy i.e., an attacker may hide the payload as a part of legit URL. Vishal Sharma in his blog-post also points out that cloud-based WAF can be bypassable with the help of this feature of web application because WAF never sees the harmful payload unless decode.
Lets see this with two real life examples from the wild. On the following URL: http://www.akc.org/, if you will enter a letter `a` in the main search bar and hit enter. The site will give you a URL that looks like: http://www.akc.org/search/YQ/. Now if you will query for the letter `b` in the search feature then site will ends up on a URL like: http://www.akc.org/search/Yg/. You may continue to see the behavior of web application on different inputs and may try to figure out the type of encoding in place. Lets input our harmless probe string "xxxxxxxx'yyyyy</img and as a result the site will give you a URL: http://www.akc.org/search/Inh4eHh4eHh4J3l5eXl5PC9pbWc/. The source code inspection shows the reflection of our interest in the following screen-shot.
Now see another example in the wild (sorry for hiding the URL). The screen-shot shows the reflection of probe string but if you will see the value of SysSearch GET parameter, you will find some sort of encoding in the URL instead of hard-coded probe string ("xxxxxxxx'yyyyy</img). The screen-shot also show that < is not encoded in an HTML context. The game is over for them given < is not filtered or encoded in an HTML context.
The next screen-shot shows XSS with the help of simple and popular payload i.e., <img src=x onerror=confirm(1)>. The payload does not start with ' or " quotes because we're in HTML context. Please look at the value of SysSearch GET parameter. It is not hard-coded XSS payload but you will find encoded form.
If as a developer you still wants to use this type of feature then please make sure to follow the basic , well known and million dollar principle of "Filter Input, Encode Output".