JavaScript Injection - or, "The code that loved me, but hated forms"

by A5an0

A little more than a year ago, I submitted an article to 2600 called "JavaScript Injection."  It was originally three pages long, but in the editorial process, it got stripped down to a page and a half.  That other page and a half never saw the light of day.  Until now.  As a gift to the community, I am posting the full original text of the article here.  I hope you all enjoy it.

A Short Rambling/Introduction

You know, web hacking is a very different game than traditional "own-the-box" hacking.  Instead of taking control of a target system, you usually try to exploit some flaw in the site's design to get information.  Credit card info, Social Security Numbers, breast sizes, they're all fair game once someone types them into a form.  The most publicized attacks of late have frequently been SQL injection (injecting SQL commands into a poorly written form that doesn't parse user input).

Well, the beautiful thing about information is that you can never have too much of it.  While snacking on Oreo's and Slashdot the other night, I stumbled across a little design flaw that can be easily exploited with good old fashioned JavaScript injection.  That's right!  No a' or 1 = 1 -- for us!  We're hacking right from the URL.  PHP and SQL squeezed all the JavaScript out of your head?  Come child (or kiddie, you make the call), lets dive right into the void.

The Discovery - or, "Oreo's and Inputs mix well"

Note: I will not be mentioning the REAL names of any involved parties, for their protection.

This story begins as any great one does: It was late and I had sugar.  Well, while surfing along the great flood of packets we all know and love, I stumbled upon the webpage for a conference company.  I'm sure you've seen them before.  This is the kind of business that will put together a convention or conference, and then have you pay a registration fee either in advance or at the door (think DEFCON, DallasCon, SummerCon, or any other *Con).  Well, this particular company was hosting some pretty cool sounding conferences coming up in a few months.  So, a little curious, I drifted over to the "Registration" page.  Scrolling down, I see the "Early Registration" price.  $20?  $50?  $100?  Nope.  $950.  Ouch!  Well, the conference looked good, but not $950 good.

Being curious, bored, and a little hyper, I decided to keep looking around.  Oddly enough, I found a little "Payment Services by VeriSign" banner across multiple pages.  Hmm...  Well, the cream filling was starting to work its way into my bloodstream, so I check the source of the Registration page.  I scrolled down, and I find a few interesting tags:

<FORM action="" method="post" target="_blank">
<INPUT type="hidden" value="jblow" name="LOGIN"> 
<INPUT type="hidden" value="Verisign" name="PARTNER"> 
<INPUT type="hidden" value="950.00" name="AMOUNT"> 
<INPUT type="hidden" value="S" name="TYPE">
<INPUT type="hidden" value="SecurTek.Conference" name="DESCRIPTION"> 
<INPUT type="submit" value="Early Registration"> 


The Exploit - or, "4.99-finger-discount"

Now, in case you have yet to realize it, my goal at this point isn't to steal card numbers or email addresses, I just want to go to this conference.  Looking at the above HTML, I see one line that stands out most:

<INPUT type="hidden" value="950.00" name="AMOUNT">

Hmm...  it seems that the payment engine gets all the price and event information right from this page.  Well, looks like this is gonna be a quickie.

O.K., so, it would be really cool if I could lower the price of this conference.  The price is right in this tag.  Logical conclusion: change the tag!  Now, any weenie with a dial-up would tell you to download the source and change the tag, click the button, and poof!  Guess again techno-weenies.  Most of these pages have a small referrer built into them that will keep you from doing this.  So, we're gonna hit it with style: JavaScript.

First things first: I need to figure out what number form this is on the page, so I can change it.  Easy enough: I whip open the source and just count the number of <FORM> tags I see before this one.  (Note: The first <FORM> is number 0, not 1.  Keep that in mind, or it will be Hell.)  O.K., cool, this is form number 1 (actually the second one).

Next step: Make sure that I have the right form.  To the address bar Batman!  I bang out a quick:


into the address bar in Firefox (IE users, no worries, this will work on Internet Exploder as well).

Now, let me break down what I just did.

                                                     ^                  ^     ^     ^  
                                                     |                  |     |     | 
This tells the browser to alert me ----------------- |                  |     |     |
   This tells the browser which form I'm interested in------------------|     |     | 
                  This is the name in the INPUT tag --------------------------|     |
                   This tells the browser I'm interested in the value of the form --|

When I press Enter, this little snippet of code causes an alert box to pop-up displaying 950.00.  Sweet.

Forget the foreplay.  It's time to hack.  Now that I'm sure that I'm dealing with the right info, I make my move.  I just plug:


into the address bar and hit Enter.

(You can probably infer what all of this code does.  The only real change that may not make sense is the "void".  All you need to know is that "void" tells the JavaScript to change something.)  Well, I hit Enter, and nothing happens.  Cool... I hope.

So, just to be safe, I drop our good friend:


back in, and he just says 1.00.

The final step in our dirty little dance: Now that the value for AMOUNT has been changed from $950 to $1, I think I can finally afford that conference.  Let's see if my sugar induced orgy of code was worth it.  I click the button.  And to my absolute joy, I see a page asking me to enter my credit card information, as well as name, address, etc.  The sweet part is that this page is asking me to authorize a charge of $1 to my card for this event.  Needless to say, if you have come up with a root dance over the years, this is when you do it.

Conclusion - or, "Pull the needle out of your box, the injection's done"

I'm sure that anyone can find a practicality flaw in this particular application, but that's not the point.  While getting a 99.89% discount is a sweet deal, what I hope you got out of this article is a basic understanding of a technique that, sadly, isn't so common anymore today.  Don't get me wrong.  I love SQL, PHP, and I get giddy every time I get my hands on a new 0-day, but sometimes the easiest route is the simplest.  I hope you learned something that you can use, or at least think about.  Enjoy and keep learning!  I need sleep.  Have a nice day.

Props to A. Witt for showing me the way to make formatting not die in wikis!