reptile7's JavaScript blog
Monday, September 24, 2007
Bouncer Script A
Blog Entry #89

About a year ago, we discussed the JavaScript validation of passwords in Blog Entry #51; specifically, we used regular expressions to ensure that a user-chosen password meets certain character requirements. We return to the topic of passwords for the next few posts as we consider a set of three scripts that password-protect Web pages and that are the focus of HTML Goodies' JavaScript Script Tips #73, #74, and #75, respectively.

Each of the Script Tips #73-75 Scripts is hosted by a firewall document that stands between the user and a target Web page. Upon accessing the firewall page, the user is solicited by the script for a password and is linked to the target page if the password is correct; the user is sent to another page if the password is incorrect.

I recognize that those of you who are fully committed to the free flow of information on the Web might oppose such 'bouncer' scripts as a matter of principle, and I share your concerns. Of course, however, it would be deeply unprofessional on our part to let philosophical objections stand in the way of our analyses of these scripts, so let's get on with it, shall we? Today's entry takes up the Script Tip #73 Script, which is given below:

<script language="javascript">

var getin = prompt("What is the password?","");
if (getin == "peppermint")
alert("You got it! In you go...");
location.href = "scripttip73correct.html";
if (getin == "null")
{ location.href = "nope2.,html"; }
if (getin != "peppermint")
{ location.href = "nope.html"; }

Here's what happens when the user follows Script Tip #73's "Here's the Script" link to the scripttip73effect.html firewall/demo page:

var getin = prompt("What is the password?","");

The user is first greeted by the prompt( ) box below:

The 'What is the password?' prompt( ) box

The user types (or does not type) a password into the prompt( ) input field; after the OK or Cancel button is clicked, the prompt( ) output is assigned to the variable getin.

if (getin == "peppermint") {
alert("You got it! In you go...");
location.href = "scripttip73correct.html"; }

If the user enters peppermint, the correct password, into the prompt( ) box and clicks the OK button, then a "You got it! In you go..." alert( ) message pops up

The 'You got it! In you go...' alert( ) box

and, after the OK button on the alert( ) box is clicked, the user is taken to the scripttip73correct.html target page.

else {
if (getin == "null") { location.href = "nope2.,html"; }

This conditional is meant to come into play if the user clicks the prompt( ) box's Cancel button, in which case (and whether or not a password was typed into the input field) the primitive value null will be assigned to getin. However, like the Boolean values true and false, the null value is not quoted. For the getin == "null" condition to return true, the user must literally enter null as a string value into the prompt( ) input field and then click the OK button; I would tell you that only then is the user taken to a separate nope2.,html page, but there is in fact no nope2.,html page in HTML Goodies' /legacy/beyond/javascript/stips/ subdirectory and a "404 - File not found" page comes up instead.

And what about that comma in nope2.,html, huh? This is obviously a typo, but I nonetheless wondered, "Can you even have commas in URLs?" It turns out, somewhat to my surprise, that yes, commas can appear in URLs if and only if they are used as "sub-delimiters", e.g., for separating parameter data when they appear in a URL.

if (getin != "peppermint") { location.href = "nope.html"; } }

For any getin value not equal to the peppermint string (or the null string), this conditional would link the user to a nope.html page if one existed in the /legacy/beyond/javascript/stips/ subdirectory; in practice, the user is again taken to a "404 - File not found" page.

Tightening up the code

The script's 'outer' else block encompassing the if (getin == null) and if (getin != "peppermint") conditionals can be condensed to:

else {
location.href = "nope.html";
if (getin == null) location.href = "nope2.html"; }

With this formulation, the if (getin == null) conditional must appear last; otherwise, clicking the prompt( ) Cancel button will send the user to nope.html. If you'd rather route all non-peppermint getins to nope.html, however, then

else location.href = "nope.html";

is all you need.

'Defeating' the script (or not)

So, how effective of a barrier is the Script Tip #73 Script? You can see for yourself that both the peppermint password and the scripttip73correct.html target page URL appear in the script's code. Can or cannot this data be fished out of the firewall document's source?

Regarding the script's design, Joe says:
The reason [accessing the password is] difficult was the way the script was put together. None of the password elements ran before prompt or alert elements. That way it was impossible to get the page by itself without some type of JavaScript element taking the focus of the browser. The moment you'd click to lose one item - another would pop up.
At the script's demo page, I can easily put the underlying "Testing...testing...testing..." main window on top of either the prompt( ) box or the alert( ) box by
(a) first moving from the browser to another application via the application menu or by typing command-tab, and then
(b) clicking the main window's Password Required title bar
when using MSIE 5.1.6 (but not Netscape 7.02, whose response to this process was a bit strange - I'll spare you the details). Now in front, the main window nonetheless does not have "focus" - e.g., I can't highlight the "Testing...testing...testing..." with the mouse cursor and I can't change the URL in the window's address bar - but I can at least now click on the menu bar's View menu, whose Source command is grayed out:

The View menu with a grayed-out Source command

The source is unavailable because the document hasn't loaded yet. When I wrapped the script element code in a function bouncer( ) { ... } container and called the bouncer( ) function with an onload="bouncer( );" body element attribute, I was indeed able to access the document source by bringing the main window forward and going to the View menu.

There's a simpler way to try to defeat the Script Tip #73 Script, however. I go to the demo page, type peppermint into the prompt( ) box and click OK, and the alert( ) box pops up. I simultaneously position my left hand over the return key and the mouse cursor over the View menu heading at the top of the screen. On your mark...get set...go!! I hit the return key and immediately click on the View menu and go to the Source command. Lo and behold, I can consistently access the firewall document source in this way when using Netscape (but not MSIE); however, I was unable to reproduce this result when I reran the script offline on my hard disk with downloaded scripttip73effect.html and scripttip73correct.html files. Given that linking from scripttip73effect.html to scripttip73correct.html is much faster on my hard disk than on the server machine, it would seem that my Netscape 'success' in defeating the script at Joe's demo page is much more reflective of the antiquity of my computer than of a reliable way to get ahold of the password.

One more thing I found out: unlike MSIE, Netscape will make a document's source available before the document has completely loaded. In my scripttip73effect.html file, I added an

<h2>This line marks the end of the document body.</h2>

element after the script element (just before the body element end-tag) and changed the if (getin == "peppermint") location to, which loads slowly on my machine. Online and with Netscape, I am in this case again able to access the scripttip73effect.html source via the click-the-alert( )-OK-button-and-instantly-go-to-the-View-menu method described above; at no point do I ever see the This line marks the end of the document body string on the scripttip73effect.html page (it appears in the source window) before it links to

Spilling the beans somewhat, Joe points out that you can access the source of his own scripttip73effect.html page by
(a) right-clicking on the aforementioned "Here's the Script" link,
(b) selecting the Download Link to Disk (MSIE) or Save Link Target As... (Netscape) option and
(c) downloading the scripttip73effect.html file, and then finally
(d) opening the file with a text editor or a word processor;
of course, you couldn't do this if you were to arrive at the scripttip73effect.html page via entering its URL into the browser's address bar.

Let me wrap up this entry by answering the question I posed earlier: all in all, I would say that, notwithstanding its simplicity, the Script Tip #73 Script does a reasonably good job at password-protecting a Web page; the script does contain its password and the target Web page URL but it cleverly exploits the timing of browser/script events to hide this information most of the time.

We'll check over Script Tip #74's password-protection script in the next post.


Comments: Post a Comment

<< Home

Powered by Blogger

Actually, reptile7's JavaScript blog is powered by Café La Llave. ;-)