Cross-site scripting precautions within Miva SMT templates

Posted on June 14th, 2007 by Luke Visinoni

As I’ve grown familiar with Miva Merchant, I’ve become very wary of Miva SMT entities. SMT entities are basically to Miva Merchant what variables are to any other language. If you have developed anything in PHP, you are likely aware of the security implications of having register_globals turned on. In Miva Merchant, the same sort of implications exist because Miva Merchant converts all CGI environment variables into SMT entities (variables) upon startup.

All available CGI environment variables are automatically converted into static MIVA Script system variables upon start-up. All HTTP headers are saved in environment variables and therefore are also converted to MIVA Script static variables.

So why is that bad?

The problem is that many of the CGI environment variables come directly from the user, meaning if you use them incorrectly or carelessly, you open yourself up to all kinds of malicious attacks. One such attack is called a cross site scripting or XSS attack (a form of script/code injection). This type of attack is very common, and you would be surprised just how many sites leave themselves vulnerable to it.

A website is vulnerable to XSS attacks if it accepts input from the user (this can be through the url, through a form, etc.) and then outputs it unchecked and unmodified. For example, on a search form, generally a web developer will repopulate the search textbox with the term the user searched for. Something like the following:

 <mvt:if expr="NOT ISNULL g.search">
 
  <h1>Product Search</h1>
 
   <form method="get" action="&mvt:global:sessionurl;"> 
    <label>
     Search For The Following Word(s):
     <input type="text" name="search" value="&mvt:global:search;" />
    </label>
    <input value="Go" type="submit" />
   </form>
 
 </mvt:if>

With that code, user input is outputted to the html page, completely unchecked and unmodified. This means that a malicious user (let’s call her Mallory) could inject html code into your script (since she is allowed to enter characters such as < and >). If Mallory can inject html code into your script, I wonder what else she could inject in there. What if she entered something like the following?

" /><script>alert('Insert Malicious Javascript Here');</script>
<input type="hidden" name="irrelevant" value="

With our existing template code, that would result in the following html being output to the browser:

  <h1>Product Search</h1>
 
   <form method="get" action="http://www.example.com"> 
    <label>
     Search For The Following Word(s):
     <input type="text" name="search" value="" />
<script>alert('Insert Malicious Javascript Here');</script>
<input type="hidden" name="irrelevant" value="" />
    </label>
    <input value="Go" type="submit" />
   </form>

Now, because Miva Merchant converts all environment variables to SMT entities, whether they came from a form via POST or from the url (via GET), Mallory can attach her malicious javascript code to the end of a URL and trick some unsuspecting victim (we’ll call him Adam) into clicking on it (perhaps through an email forged to look like it came from your website). Adam clicks on the link, and logs in, and now Mallory’s malicious script has access to Adam’s session and therefor, Adam’s account information.

Preventing cross-site scripting

In many languages, to prevent this sort of attack, you simply escape user-submitted content before outputting it again. This is generally done with some sort of function. For example, in PHP you would use a function such as htmlspecialchars or htmlentities. This is not necessary in SMT templates, because Miva has taken the liberty of providing 3 versions of every one of these variables for you.

From Miva’s documentation:

Entities start with &mvt, and can have an optional additional character, either an e, or a, for entity encoding or attribute encoding, respectively.

Entities beginning with &mvt are replaced directly in the HTML code with the information they represent. So in bgcolor=”&mvt:colors:lhdr_bg;”, the entity would be replaced with the actual list header color number in hex, giving bgcolor=”#000080″.

Entities beginning with &mvte are “entity encoded”. Their values will be formatted to appear on the screen, with any special characters being displayed verbatim (“as is”), rather than being interpreted according to their special meaning. If the entity you want to display includes the “<” character (“less-than” sign), entity encoding will cause that character to appear, unchanged, on the screen, rather than being interpreted as the beginning of an HTML tag.

So, to sum up the documentation, if you are going to be outputting any kind of variable to the screen, you would use the &mvte prefix. This way, special characters such as < and > would be escaped, so the user cannot inject scripts into your code. So now, let’s adjust our code from up above so that it is no longer an XSS vulnerability. To do that, we simply change the entity prefix from &mvt to &mvte. Pretty painless!

 <mvt:if expr="NOT ISNULL g.search">
 
  <h1>Product Search</h1>
 
   <!-- this variable does not need to be escaped -->
   <form method="get" action="&mvt:global:sessionurl;"> 
    <label>
     Search For The Following Word(s):
     <!-- this user-supplied variable does -->
     <input type="text" name="search" value="&mvte:global:search;" />
    </label>
    <input value="Go" type="submit" />
   </form>
 
 </mvt:if>

With this modification, if Mallory were to try the same attack, it would result in the following (completely harmless) html being output to the browser.

  <h1>Product Search</h1>
 
   <form method="get" action="http://www.example.com"> 
    <label>
     Search For The Following Word(s):
     <input type="text" name="search" value="&amp;quot; /scriptalert&amp;#40;'Inse" />
    </label>
    <input value="Go" type="submit" />
   </form>

Miva also supplies a third version of every SMT variable for use in a URL.

Entities beginning with &mvta, are “attribute encoded”. That is, their values will be formatted so they can be included in a URL, with any special characters being transformed into characters that can be understood by a web browser. For instance, you have probably seen attribute-encoded characters in URLs, such as space characters that are represented as %20. When a category name, for instance, is to be included in a URL, and may contain characters that would require this special formatting, use &mvta.

Places where you may not suspect you need to use escaped entities

There are several Miva Merchant modules out there that allow you to assign your own variables within the template. For example, Emporium Plus’s (exremely useful) toolkit module. Let’s say you want some promotional text to be available on several of your miva templates. With the toolkit module, you simply create a variable within your global head tag with the following template item:

<mvt:item name="toolkit" param="sassign|promotext|One day only! 15 foobars for $1" />

Now, you put the &mvt:global:promotext; in your global header, and only the pages with the toolkit item assigned to them will now render this text, right? WRONG! Because Miva Merchant converts all environment variables into global SMT entities, your script is now open to XSS attacks again. Mallory simply has to craft a link like the following and get Adam to click on it.

Hello Adam, <a href="http://www.example.com/mm5/merchant.mvc?Screen=ACNT&Store_Code=YOURSTORE&
promotext=%3Cscript%3Ealert('malicious%20code');%3C/script%3E">Log in to your account</a>?

Since you didn’t assign the toolkit module to the ACNT screen, and you outputted the value of the promotext variable without escaping, your site once again has an XSS vulnerability.

So, what have we learned?

First of all, never trust user-submitted data. Secondly, you need to be paranoid about outputting any kind of data, unescaped to the browser. Even if it seems as though it couldn’t have been tainted by the user, think of it from all angles.

Comments are closed.