├── chrome.manifest ├── content ├── AttackHttpResponseObserver.js ├── AttackRunner.js ├── FieldResult.js ├── PrefObserver.js ├── Results.js ├── ResultsManager.js ├── TestManager.js ├── TestRunnerContainer.js ├── XSS-strings.xml ├── about.xul ├── addAttack.js ├── addAttack.xul ├── addError.js ├── attackStringContainer.js ├── io.js ├── json.js ├── overlay.js ├── overlay.xul ├── preferenceStringContainer.js ├── preferences.fx2.js ├── preferences.fx3.js ├── preferences.js ├── preferences.xul ├── progressListener.js ├── results.html ├── sidebarBuilder.js ├── tabbrowsermanager.js ├── util.js ├── whiletestruns.js ├── whiletestruns.xul ├── xssme_StreamListener.js ├── xssme_sidebar.js ├── xssme_sidebar.xul └── xssmeevaluators.js ├── defaults └── preferences │ └── xssme.js ├── gpl-3.0.txt ├── install.rdf ├── locale └── en-US │ ├── overlay.dtd │ ├── prefwindow.dtd │ ├── xssme.dtd │ └── xssme.properties ├── readme.txt └── skin ├── overlay.css ├── preferences.css ├── small_logo_sc.png ├── tiny_logo.png ├── toolbar-button.png ├── whiletestruns.css └── xssme_sidebar.css /chrome.manifest: -------------------------------------------------------------------------------- 1 | content xssme content/ 2 | locale xssme en-US locale/en-US/ 3 | skin xssme classic/1.0 skin/ 4 | overlay chrome://browser/content/browser.xul chrome://xssme/content/overlay.xul 5 | style chrome://global/content/customizeToolbar.xul chrome://xssme/skin/overlay.css 6 | # *SHOCK* Fx2 and Fx3 are have a moderately different API here's some overriding 7 | override chrome://xssme/content/preferences.js chrome://xssme/content/preferences.fx2.js appversion<3.0 8 | override chrome://xssme/content/preferences.js chrome://xssme/content/preferences.fx3.js appversion>=3.0 9 | 10 | -------------------------------------------------------------------------------- /content/AttackHttpResponseObserver.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * AttackHttpResponseObserver.js 25 | */ 26 | const AttackHttpResponseObserver_topic = 'http-on-examine-response'; 27 | 28 | function AttackHttpResponseObserver(attackRunner, resultsManager){ 29 | 30 | this.attackRunner = attackRunner; 31 | this.resultsManager = resultsManager; 32 | 33 | } 34 | 35 | AttackHttpResponseObserver.prototype = { 36 | 37 | QueryInterface: function(iid) { 38 | if (iid.equals(Components.interfaces.nsIObserver) || 39 | iid.equals(Components.interfaces.nsISupports)) 40 | { 41 | return this; 42 | } 43 | 44 | throw Components.results.NS_ERROR_NO_INTERFACE; 45 | }, 46 | 47 | observe: function(subject, topic, data) { 48 | 49 | if (topic == AttackHttpResponseObserver_topic){ 50 | try { 51 | this.resultsManager.gotChannelForAttackRunner(subject. 52 | QueryInterface(Components.interfaces.nsIHttpChannel), 53 | this.attackRunner); 54 | } 55 | catch(err) { 56 | dump('AttackHttpResponseObserver::observe: ' + err + '\n'); 57 | } 58 | } 59 | 60 | } 61 | 62 | }; -------------------------------------------------------------------------------- /content/AttackRunner.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * AttackRunner.js 25 | * @requires ResultsManager 26 | * @requires TabManager 27 | * @requires AttackHttpResponseObserver 28 | */ 29 | 30 | /** 31 | * @class AttackRunner 32 | */ 33 | function AttackRunner(){ 34 | 35 | this.className = "AttackRunner"; 36 | /** 37 | * uniqueID is important for heuristic tests which need a random string in 38 | * order to find the char they sent 39 | */ 40 | this.uniqueID = Math.floor(Date.now() * Math.random()); 41 | 42 | } 43 | 44 | AttackRunner.prototype = { 45 | testData: null 46 | , 47 | submitForm: function(browser, formIndex){ 48 | var forms = browser.webNavigation.document.forms; 49 | var formFound = false; 50 | for (var i = 0; i < forms.length && !formFound; i++){ 51 | if (i == formIndex){ 52 | dump('submitting form ... ' + i + ' ' + (i == formIndex) + '\n'); 53 | if (forms[i].target) forms[i].target = null; 54 | forms[i].submit(); 55 | formFound = true; 56 | } 57 | //debug code.. 58 | else { 59 | dump('this form is not it... ' + i + ' ' + (i == formIndex) + '\n'); 60 | } 61 | } 62 | return formFound; 63 | } 64 | , 65 | /** 66 | * Begin an individual test. 67 | * @param formPanel currently unused 68 | * @param formIndex index, in the list of forms, of the one being tested 69 | * @param field the field to inject 70 | * @param testValue the input containing the injection 71 | * @param resultsManager evaluates the results of the test 72 | * @param tabWrapper contains the tab to run the test in 73 | * @param tabManager provides information about the target page 74 | */ 75 | do_test: function(formPanel, formIndex, field, testValue, resultsManager, 76 | tabWrapper, tabManager) 77 | { 78 | var wroteTabData = false; 79 | var self = this; //make sure we always have a reference to this object 80 | var browser = tabWrapper.tab.linkedBrowser; 81 | 82 | this.testValue = testValue; 83 | this.formIndex = formIndex; 84 | this.fieldIndex = field.index; 85 | this.field = field; 86 | browser.webNavigation.stop(Components.interfaces.nsIWebNavigation.STOP_ALL); 87 | 88 | setTimeout(function() {afterWorkTabStopped()}, 10); 89 | 90 | function afterWorkTabStopped(){ 91 | browser.addEventListener('pageshow', 92 | afterWorkTabHasLoaded, false); 93 | tabManager.loadTargetPage(browser); 94 | } 95 | 96 | function afterWorkTabHasLoaded(event) { 97 | 98 | var formData = null; 99 | browser.removeEventListener('pageshow', 100 | afterWorkTabHasLoaded, false); 101 | 102 | var loadSuccessful = compareContentDocuments(tabManager.targetContentDocument, browser.contentDocument) 103 | 104 | if (loadSuccessful === false) { 105 | getTestManager().cannotRunTests(); 106 | return; 107 | } 108 | 109 | //this will copy all the form data... 110 | try { 111 | if (field) 112 | { 113 | tabManager.writeTabForms(browser.contentDocument. 114 | forms, formIndex, field.index, testValue); 115 | formData = tabManager.getFormDataForURL(browser. 116 | contentDocument.forms, formIndex, field.index, 117 | testValue); 118 | } 119 | else 120 | { 121 | tabManager.writeTabForms(browser.contentDocument. 122 | forms, formIndex, null, null); 123 | formData = tabManager.getFormDataForURL(browser. 124 | contentDocument.forms, formIndex, null, null); 125 | } 126 | } 127 | catch(e) { 128 | Components.utils.reportError(e + " " + (browser.webNavigation.currentURI?browser.webNavigation.currentURI.spec:"null")) 129 | } 130 | dump('AttackRunner::afterWorkTabHasLoaded testValue===' + testValue + '\n'); 131 | 132 | 133 | self.testData = tabManager.getTabData(browser. 134 | contentDocument.forms, formIndex, field.index); 135 | 136 | self.do_source_test(formPanel, formIndex, field, testValue, 137 | resultsManager, browser, 138 | formData); 139 | 140 | //if (window.navigator.platform.match("win", "i")) { 141 | browser.addEventListener('pageshow', 142 | afterWorkTabHasSubmittedAndLoaded, false); 143 | //} 144 | //else { 145 | // setTimeout(function(){browser.addEventListener('pageshow', 146 | // afterWorkTabHasSubmittedAndLoaded, false)}, 0); 147 | //} 148 | 149 | 150 | var formGotSubmitted = self.submitForm(browser, formIndex); 151 | 152 | } 153 | 154 | //this should fire only *after* the form has been sumbitted and the new 155 | //page has loaded. 156 | function afterWorkTabHasSubmittedAndLoaded(event){ 157 | 158 | browser.removeEventListener('pageshow', afterWorkTabHasSubmittedAndLoaded, false); 159 | var results = resultsManager.evaluate(event.currentTarget, self); 160 | /* @todo this should be moved to resultsmanager */ 161 | for each (result in results){ 162 | tabManager.addFieldData(result); 163 | } 164 | tabWrapper.inUse = false; 165 | 166 | 167 | } 168 | 169 | 170 | 171 | } 172 | , 173 | do_source_test:function(formPanel, formIndex, field, testValue, 174 | resultsManager, browser, formData) 175 | { 176 | // the IO service 177 | var ioService = Components.classes['@mozilla.org/network/io-service;1'] 178 | .getService(Components.interfaces.nsIIOService); 179 | var formURL = browser.contentDocument.URL; 180 | var form = browser.contentDocument.forms[formIndex]; 181 | var formAction = form.action ? form.action : browser.contentDocument. 182 | location.toString(); 183 | 184 | dump('AttackRunner::do_source_test formAction=== '+formAction+'\n'); 185 | if (form.method.toLowerCase() != 'post'){ 186 | formAction += formAction.indexOf('?') === -1 ? '?' : '&'; 187 | formAction += formData; 188 | } 189 | 190 | dump('attackrunner::do_source_test::formAction == ' + formAction + '\n'); 191 | dump('attackrunner::do_source_test::formData == ' + formData + '\n'); 192 | 193 | var uri = ioService.newURI(formAction, null, null); 194 | var referingURI = ioService.newURI(formURL, null, null); 195 | var channel = ioService.newChannelFromURI(uri); 196 | channel.QueryInterface(Components.interfaces.nsIHttpChannel). 197 | referrer = referingURI; 198 | 199 | if (form.method.toLowerCase() == 'post'){ 200 | var inputStream = Components. 201 | classes['@mozilla.org/io/string-input-stream;1']. 202 | createInstance(Components.interfaces.nsIStringInputStream); 203 | inputStream.setData(formData, formData.length); 204 | channel.QueryInterface(Components.interfaces.nsIUploadChannel). 205 | setUploadStream(inputStream, 206 | 'application/x-www-form-urlencoded', -1); 207 | channel.QueryInterface(Components.interfaces.nsIHttpChannel). 208 | requestMethod = 'POST'; 209 | } 210 | 211 | var streamListener = new StreamListener(this, resultsManager); 212 | streamListener.testData = this.testData; 213 | resultsManager.addSourceListener(streamListener); 214 | 215 | channel.asyncOpen(streamListener, null); 216 | 217 | } 218 | 219 | } 220 | -------------------------------------------------------------------------------- /content/FieldResult.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * FieldResult.js 25 | * A FieldResult represents the resulting "value" of a form's field after all 26 | * testing has been performed. 27 | * It holds all the results generated for a field. 28 | * This object is used for sorting. 29 | * @requires result.js 30 | */ 31 | function FieldResult(field){ 32 | this.field = field; 33 | this.results = new Array(); 34 | this.maxValue = 0; 35 | this.maxValueType = 0; 36 | this.state = 0; 37 | } 38 | 39 | /** 40 | * These consts are used to check what kind of rsults does this fieldresult 41 | * have. 42 | */ 43 | const fieldresult_has_pass = 0x0001; 44 | const fieldresult_has_warn = 0x0002; 45 | const fieldresult_has_error = 0x0004; 46 | 47 | FieldResult.prototype = { 48 | addResults: function (resultsToAdd) { 49 | 50 | for each(var result in resultsToAdd) { 51 | if (this.maxValueType < result.type){ 52 | this.maxValue = result.value; 53 | this.maxValueType = result.type; 54 | } 55 | else if (this.maxValueType === result.type ) { 56 | if (this.maxValue < result.value) { 57 | this.maxValue = result.value; 58 | } 59 | } 60 | this.state = this.state | result.type; 61 | this.results.push(result); 62 | } 63 | } 64 | , 65 | count: function(){ 66 | var numTestsRun = 0; 67 | var numPasses = 0; 68 | var numWarnings = 0; 69 | var numFailes = 0; 70 | for each(var r in this.results) { 71 | numTestsRun++; 72 | switch(r.type){ 73 | case RESULT_TYPE_ERROR: 74 | numFailes++; 75 | break; 76 | case RESULT_TYPE_WARNING: 77 | numWarnings++; 78 | break; 79 | case RESULT_TYPE_PASS: 80 | numPasses++; 81 | break; 82 | } 83 | } 84 | return [numTestsRun, numFailes, numWarnings, numPasses]; 85 | } 86 | , 87 | getSubmitState: function(){ 88 | return this.results[0].testData; 89 | } 90 | , 91 | sort: function(){ 92 | var errors = new Array(); 93 | var warnings = new Array(); 94 | var passes = new Array(); 95 | 96 | for each(var result in this.results) { 97 | switch(result.type){ 98 | case RESULT_TYPE_ERROR: 99 | errors.push(result); 100 | break; 101 | case RESULT_TYPE_WARNING: 102 | warnings.push(result); 103 | break; 104 | case RESULT_TYPE_PASS: 105 | passes.push(result); 106 | break; 107 | } 108 | } 109 | 110 | return this.results = errors.concat(warnings, passes); 111 | } 112 | } -------------------------------------------------------------------------------- /content/PrefObserver.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * PrefObserver.js 25 | * This provides a class that can be used to watch arbitrary preferences and do 26 | * artibrary things based on them. 27 | * This assumes will act on all preferences being watched (that is all children 28 | * of this preference as well as the preference itself). 29 | */ 30 | 31 | function Xss_PrefObserver(functionToCall){ 32 | this.funcToCall = functionToCall; 33 | 34 | } 35 | 36 | Xss_PrefObserver.prototype = { 37 | observe: function(subject, topic, data) { 38 | dump('Xss_PrefObserver::Observe topic == ' + topic + '\n'); 39 | if (topic == "nsPref:changed") { 40 | this.funcToCall(subject, topic, data); 41 | } 42 | } 43 | , 44 | QueryInterface : function(aIID) { 45 | if (aIID.equals(Components.interfaces.nsIObserver)) { 46 | return this; 47 | } 48 | 49 | throw Components.results.NS_NOINTERFACE; 50 | } 51 | }; -------------------------------------------------------------------------------- /content/Results.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * Result.js 25 | */ 26 | 27 | const RESULT_TYPE_ERROR = 0x0004; 28 | const RESULT_TYPE_WARNING =0x0002; 29 | const RESULT_TYPE_PASS = 0x0001; 30 | 31 | /** 32 | * The Result object is returned by evalutors. 33 | * The type defines whether the test resulted in an error, warning, or pass. 34 | * The value is used for sorting errors, warnings, and passes (usually doesn't 35 | * matter for passes) 36 | * The message is what is to be displayed to the user. 37 | */ 38 | function Result(type, value, message){ 39 | this.value = value; 40 | this.type = type; 41 | this.message = message; 42 | dump('Result::Ctor (' + type+ ' ' + value+ ' ' + message + '\n'); 43 | } 44 | 45 | -------------------------------------------------------------------------------- /content/TestManager.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2008 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * TestManager 25 | * The TestManager is responsible for making sure that tests are run properly. 26 | * It does not actually run the tests, just preps them. The TestRunnerContainer 27 | * is responsible for running the tests. 28 | */ 29 | 30 | /** 31 | * TestManager ctor 32 | */ 33 | function TestManager(){ 34 | 35 | /** 36 | * an array of vulnerable fields, used in heuristic testing 37 | */ 38 | this.vulnerableFields = new Array(); 39 | this.controller = null; 40 | this.resultsManager = null; 41 | this.waitingForHeuristicTests = false; 42 | this.testType = null; 43 | this.resultsStillExpected = 0; 44 | 45 | } 46 | 47 | TestManager.prototype = { 48 | /** 49 | * Runs a test on the passed fields. 50 | * @param testType whether to test with all the strings or just with the top strings 51 | * @param fieldsToTest the fields to test with this battery 52 | * @param tabManager information about the target page 53 | * @param heuristicTestChars a string, the characters to inject 54 | */ 55 | runTest: function (testType, fieldsToTest, tabManager, heuristicTestChars) { 56 | this.testType = testType; 57 | 58 | this.clear(); 59 | 60 | this.fieldsToTest = fieldsToTest; 61 | this.heuristicTestChars = heuristicTestChars; 62 | this.tabManager = tabManager; 63 | 64 | if (testType.heuristicTest) { 65 | this.waitingForHeuristicTests = true; 66 | this.runHeuristicTest(); 67 | } 68 | else { 69 | this.runThoroughTest(testType, fieldsToTest); 70 | } 71 | } 72 | , 73 | /** 74 | * This is a function that AttackRunner requires its resultsmanager to have 75 | */ 76 | addSourceListener: function(sourceListener, attackRunner) { 77 | 78 | } 79 | , 80 | /** 81 | * called by testRunners to report their results 82 | * @param browser a browser instance with the results 83 | * @param 84 | */ 85 | evaluate: function(browser, attackRunner) { 86 | 87 | } 88 | , 89 | /** 90 | * called by a streamlistener to report the results of a source test 91 | * @param streamListener the streamListener that is reporting the results 92 | */ 93 | evaluateSource: function(streamListener) { 94 | 95 | var resultData = streamListener.data; 96 | var testValue = streamListener.attackRunner.testValue; 97 | 98 | if (resultData.indexOf(testValue.string) !== -1) { 99 | var vulnerableField = streamListener.attackRunner.field; 100 | var isVulnerablFieldAlreadyLogged = false; 101 | if (this.vulnerableFields.length > 0) { 102 | for each (var value in this.vulnerableFields) { 103 | var areFormIndexsSame = value.formIndex === vulnerableField.formIndex; 104 | if (areFormIndexsSame) { 105 | var areFieldsSame = value.index === vulnerableField.index; 106 | if (areFieldsSame) { 107 | value.vulnerableChars += testValue.string[testValue.string.length-1]; 108 | isVulnerablFieldAlreadyLogged = true; 109 | break; 110 | } 111 | } 112 | } 113 | } 114 | 115 | if (isVulnerablFieldAlreadyLogged === false) { 116 | streamListener.attackRunner.field.vulnerableChars = testValue.string[testValue.string.length-1]; 117 | this.vulnerableFields.push(streamListener.attackRunner.field); 118 | } 119 | 120 | } 121 | 122 | this.controller.finishedTest(); 123 | 124 | this.resultsStillExpected--; 125 | } 126 | , 127 | /** 128 | * Runs the heuristic tests. 129 | */ 130 | runHeuristicTest: function() { 131 | var self = this; 132 | var testRunnerContainer = getTestRunnerContainer(); 133 | 134 | testRunnerContainer.clear(); 135 | 136 | for each (var c in this.heuristicTestChars) { 137 | for each (var field in this.fieldsToTest) { 138 | var testRunner = new AttackRunner(); 139 | 140 | var testValue = new Object(); 141 | testValue.string = testRunner.uniqueID.toString() + c.toString(); 142 | 143 | this.resultsStillExpected++; 144 | 145 | testRunnerContainer.addTestRunner(testRunner, 146 | null, 147 | field.formIndex, 148 | field, 149 | testValue, 150 | self); 151 | 152 | } 153 | } 154 | 155 | getTestRunnerContainer(getMainWindow().document. 156 | getElementById('content').mTabs.length, self); 157 | 158 | if (testRunnerContainer.keepChecking === false) { 159 | testRunnerContainer.keepChecking = true; 160 | } 161 | 162 | testRunnerContainer.start(this.tabManager); 163 | } 164 | , 165 | /** 166 | * runs non-heuristic tests on the fields. 167 | * @param testType with all strings or just the top strings. 168 | * @param vulnerableFields fields painted by the heuristic tests 169 | */ 170 | runThoroughTest: function(testType, vulnerableFields) { 171 | 172 | this.resultsManager = new ResultsManager(this.controller); 173 | 174 | this.resultsManager.addEvaluator(checkForVulnerableElement); 175 | this.resultsManager.addSourceEvaluator(checkForExactAttackText); 176 | 177 | getTestRunnerContainer().clear(); 178 | var testStrings = getAttackStringContainer().getStrings(); 179 | var numberOfTests; 180 | if (testType.allTests) 181 | numberOfTests = testStrings.length; 182 | else { 183 | numberOfTests = this.controller.getPreferredNumberOfAttacks(); 184 | } 185 | 186 | for each (var field in vulnerableFields) { 187 | 188 | for (var n = 0; n < numberOfTests && testStrings[n]; n++) { 189 | 190 | var testRunner = new AttackRunner(); 191 | this.resultsManager.registerAttack(testRunner); 192 | 193 | getTestRunnerContainer().addTestRunner(testRunner, null, 194 | field.formIndex, field, testStrings[n], 195 | this.resultsManager); 196 | 197 | } 198 | 199 | } 200 | 201 | var self = this; 202 | var testRunnerContainer = getTestRunnerContainer(getMainWindow(). 203 | document.getElementById('content').mTabs.length, self); 204 | 205 | if (testRunnerContainer.keepChecking === false) { 206 | testRunnerContainer.keepChecking = true; 207 | } 208 | testRunnerContainer.start(this.tabManager); 209 | 210 | } 211 | , 212 | /** 213 | * this is called by the testRunnerContainer when all tests are definitely 214 | * complete. 215 | */ 216 | doneTesting: function() { 217 | var self = this; 218 | function checkAgain() { 219 | self.doneTesting(); 220 | } 221 | if (this.waitingForHeuristicTests === true) { 222 | 223 | if (this.resultsStillExpected === 0) { 224 | this.waitingForHeuristicTests = false; 225 | if (this.vulnerableFields.length > 0) { 226 | this.waitingForHeuristicTests = false; 227 | function doRunThoroughTests(){ 228 | getTestRunnerContainer().clearWorkTabs(); 229 | self.controller.warningDialog.startThoroughTesting(self.vulnerableFields.length, self.testType); 230 | self.runThoroughTest(self.testType, self.vulnerableFields); 231 | } 232 | window.setTimeout(doRunThoroughTests, 0); 233 | } 234 | else { 235 | this.resultsManager = new ResultsManager(self.controller) 236 | this.resultsManager.showResults(this); 237 | getTestRunnerContainer().clearWorkTabs(); 238 | this.controller.postTest(); 239 | } 240 | } 241 | else { 242 | window.setTimeout(checkAgain, 1); 243 | } 244 | } 245 | else if (this.controller) { 246 | if (this.resultsManager.allResultsLogged === false){ 247 | dump('\nnot done yet...'); 248 | window.setTimeout(checkAgain, 100); 249 | //Components.utils.reportError('results not all logged yet'); 250 | return 251 | } 252 | getTestRunnerContainer().clearWorkTabs(); 253 | this.resultsManager.showResults(this); 254 | this.controller.postTest(); 255 | } 256 | 257 | } 258 | , 259 | /** 260 | * clears the object and makes it ready for use for a new set of tests. 261 | */ 262 | clear: function() { 263 | this.resultsManager = null; 264 | 265 | this.vulnerableFields.splice(0,this.vulnerableFields.length); 266 | 267 | } 268 | , 269 | /** 270 | * Called when an AttackRunner cannot test because it is in an error state. 271 | */ 272 | cannotRunTests: function() { 273 | getTestRunnerContainer().stop(); 274 | getTestRunnerContainer().clearWorkTabs(); 275 | 276 | var resultsManager = null; 277 | if (this.resultsManager) { 278 | resultsManager = this.resultsManager; 279 | } 280 | else { 281 | resultsManager = new ResultsManager(this.controller); 282 | } 283 | resultsManager.showResults(this, "There was an error while testing this site. This was likely due to Mozilla bug 420025. Please help us track this bug by either emailing us the url to this site or commenting on the bug. We apologize for the inconvenience and hope to have this fixed soon."); 284 | this.controller.postTest(); 285 | 286 | Components.utils.reportError( 287 | 'The loading of this page in a work tab as not successful: ' + 288 | getMainHTMLDoc().documentURI); 289 | } 290 | } 291 | 292 | /** 293 | * The getInstance method for the TestManager singleton 294 | */ 295 | function getTestManager(controller) { 296 | if (typeof(xssme__testmanager__) == 'undefined' || 297 | !xssme__testmanager__) 298 | { 299 | xssme__testmanager__ = new TestManager(); 300 | } 301 | // @todo: there has to be a better way... 302 | if (controller) { 303 | xssme__testmanager__.controller = controller; 304 | } 305 | 306 | return xssme__testmanager__; 307 | } 308 | 309 | -------------------------------------------------------------------------------- /content/TestRunnerContainer.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * TestRunnerContainer.js 25 | */ 26 | 27 | /** 28 | * Based around a poor man's semaphore concept. 29 | */ 30 | function TestRunnerContainer() { 31 | this.testRunners = new Array(); //All these arrays are parallell 32 | this.formPanels = new Array(); 33 | this.formIndexes = new Array(); 34 | this.fields = new Array(); 35 | this.testValues = new Array(); 36 | this.resultsManagers = new Array(); 37 | this.testManager = null; 38 | this.keepChecking = true; 39 | } 40 | 41 | TestRunnerContainer.prototype = { 42 | addTestRunner: function(testRunner, formPanel, formIndex, field, 43 | testValue, resultsManager) 44 | { 45 | this.testRunners.push(testRunner); 46 | this.formPanels.push(formPanel); 47 | this.formIndexes.push(formIndex); 48 | this.fields.push(field); 49 | this.testValues.push(testValue); 50 | this.resultsManagers.push(resultsManager); 51 | } 52 | , 53 | /* Called to begin a new test battery in this container. 54 | * @param tabManager information about the target of this battery 55 | */ 56 | start: function (tabManager) { 57 | // Has another part of the program halted the testing? 58 | if (!this.keepChecking) return; 59 | 60 | // Do we have any more tests to run? 61 | if (!this.testRunners.length) { 62 | this.keepChecking = false; 63 | this.testManager.doneTesting(); 64 | return; 65 | } 66 | 67 | // Begin the next test in the first available tab and move that tab to the back of the queue. 68 | for (var i = 0; i < this.tabWrappers.length; i++) { 69 | if (!this.tabWrappers[i].inUse) { 70 | this.tabWrappers[i].inUse = true; 71 | this.testRunners.pop().do_test(this.formPanels.pop(), 72 | this.formIndexes.pop(), 73 | this.fields.pop(), 74 | this.testValues.pop(), 75 | this.resultsManagers.pop(), 76 | this.tabWrappers[i], 77 | tabManager); 78 | this.tabWrappers.push(this.tabWrappers.splice(i, 1)[0]); 79 | break; 80 | } 81 | } 82 | 83 | var self = this; 84 | setTimeout(function() { self.start(tabManager); }, 1); 85 | } 86 | , 87 | numWorkTabs: 6 88 | , 89 | getNumWorkTabs: function(){ 90 | var prefService = Components.classes['@mozilla.org/preferences-service;1']. 91 | getService(Components.interfaces.nsIPrefService); 92 | var branch = prefService.getBranch('extensions.xssme.'); 93 | if (branch.prefHasUserValue('numtabstouse') ){ 94 | return branch.getIntPref('numtabstouse'); 95 | } 96 | else { 97 | return this.numWorkTabs; 98 | } 99 | } 100 | , 101 | clear: function (){ 102 | this.testRunners.splice(0, this.testRunners.length); 103 | this.formPanels.splice(0, this.formPanels.length); 104 | this.formIndexes.splice(0, this.formPanels.length); 105 | this.fields.splice(0, this.formPanels.length); 106 | this.testValues.splice(0, this.formPanels.length); 107 | this.resultsManagers.splice(0, this.formPanels.length); 108 | //if (this.tabWrappers) 109 | // this.tabWrappers.splice(0, this.tabWrappers.length); 110 | } 111 | , 112 | /** 113 | * Creates the tabs whose browsers will be used to run individual tests. 114 | * @param testManager will be reported to when test battery is complete. 115 | */ 116 | setup: function(testManager) { 117 | this.testManager = testManager; 118 | this.tabWrappers = new Array(); 119 | for (var i = 0; i < this.getNumWorkTabs(); i++) { 120 | this.tabWrappers[i] = { 121 | inUse: false, 122 | tab: getMainWindow().document.getElementById('content').addTab('about:blank') 123 | }; 124 | } 125 | } 126 | , 127 | clearWorkTabs: function () { 128 | for (var i = 0; i < this.tabWrappers.length; i++) 129 | getMainWindow().gBrowser.removeTab(this.tabWrappers[i].tab); 130 | } 131 | , 132 | /** 133 | * Stops the running of tests in the TestRunnerContainer. 134 | */ 135 | stop: function(){ 136 | this.keepChecking = false; 137 | this.clear(); 138 | } 139 | }; 140 | 141 | /** 142 | * If currentNumTabs is provided, the container is cleared. 143 | */ 144 | function getTestRunnerContainer(currentNumTabs, testManager){ 145 | 146 | if (typeof(xssme__testrunnercontainer__) == 'undefined' || 147 | !xssme__testrunnercontainer__ ) 148 | { 149 | xssme__testrunnercontainer__ = new TestRunnerContainer(); 150 | } 151 | 152 | if (currentNumTabs && testManager) { 153 | xssme__testrunnercontainer__.setup(testManager); 154 | 155 | } 156 | 157 | return xssme__testrunnercontainer__; 158 | 159 | } -------------------------------------------------------------------------------- /content/XSS-strings.xml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SecurityCompass/XSSMe/1e87473220231ceb135c5d9eab6570b45fd693eb/content/XSS-strings.xml -------------------------------------------------------------------------------- /content/about.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /content/addAttack.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | function onOk() { 24 | var stringTxtBox = document.getElementById('attackstringtxtbox'); 25 | var sigTxtBox = document.getElementById('sigtxtbox'); 26 | var attackStrContainer = window.arguments[0]; 27 | var prefController = window.arguments[1]; 28 | var prefWindow = window.arguments[2]; 29 | 30 | 31 | if (!stringTxtBox.value.length) 32 | { 33 | alert("Please enter an attack string"); 34 | stringTxtBox.select(); 35 | return false; 36 | } 37 | if (!sigTxtBox.value.length){ 38 | alert("Please enter a signature to identify you by."); 39 | sigTxtBox.select(); 40 | return false; 41 | } 42 | 43 | if (attackStrContainer.addString(stringTxtBox.value, sigTxtBox.value)){ 44 | prefController.makeUI(attackStrContainer.getStrings(), prefWindow, 45 | 'existingSQLIstrings'); 46 | return true; 47 | } 48 | else{ 49 | alert("couldn't add your attack string"); 50 | return false; 51 | } 52 | 53 | 54 | } 55 | 56 | function onCancel(){ 57 | 58 | return true; 59 | } -------------------------------------------------------------------------------- /content/addAttack.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 12 | 33 | 51 | 52 | -------------------------------------------------------------------------------- /content/addError.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | function onOk() { 24 | var stringTxtBox = document.getElementById('errorstringtxtbox'); 25 | var errorStrContainer = window.arguments[0]; 26 | var prefController = window.arguments[1]; 27 | var prefWindow = window.arguments[2]; 28 | 29 | 30 | if (!stringTxtBox.value.length) 31 | { 32 | alert("Please enter an error string"); 33 | stringTxtBox.select(); 34 | return false; 35 | } 36 | var wasStringAdded = errorStrContainer.addString(stringTxtBox.value, null); 37 | 38 | dump('was this string (' + stringTxtBox.value + ') added? ' + 39 | wasStringAdded + '\n'); 40 | 41 | if (wasStringAdded){ 42 | prefController.makeUI(errorStrContainer.getStrings(), prefWindow, 43 | 'existingSQLIerrStrings'); 44 | return true; 45 | } 46 | else{ 47 | alert("couldn't add your error string"); 48 | return false; 49 | } 50 | 51 | 52 | } 53 | 54 | function onCancel(){ 55 | 56 | return true; 57 | } -------------------------------------------------------------------------------- /content/attackStringContainer.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * AttackStringContainer.js 25 | * requires preferenceStringContainer.js 26 | */ 27 | 28 | 29 | /** 30 | *this object is responsible for dealing with the Attack Strings. 31 | */ 32 | function AttackStringContainer() { 33 | this.init(); 34 | } 35 | AttackStringContainer.prototype = new PreferenceStringContainer(); 36 | dump('creating... AttackStringContainer object\n'); 37 | AttackStringContainer.prototype.init = function (){ 38 | 39 | var attackStrings; 40 | 41 | this.prefBranch = this.prefService.getBranch('extensions.xssme.'); 42 | this.prefDefaultBranch = this.prefService.getDefaultBranch('extensions.xssme.') 43 | if (this.prefBranch.prefHasUserValue('attacks')){ 44 | attackStrings = this.prefBranch.getCharPref('attacks'); 45 | this.strings = JSON.parse(attackStrings); 46 | } 47 | else { 48 | var ioService = Components.classes["@mozilla.org/network/io-service;1"]. 49 | getService(Components.interfaces.nsIIOService); 50 | var chromeURL = ioService. 51 | newURI("chrome://xssme/content/XSS-strings.xml", null, null); 52 | 53 | var chromeRegistry = Components.classes["@mozilla.org/chrome/chrome-registry;1"] 54 | .getService(Components.interfaces.nsIChromeRegistry); 55 | var defaultAttacksURL= chromeRegistry.convertChromeURL(chromeURL); 56 | var defaultAttacksChannel= ioService.newChannelFromURI(defaultAttacksURL); 57 | var defaultAttacksXML = FileIO.readChannel(defaultAttacksChannel, null); 58 | 59 | 60 | importAttackFromXMLString(defaultAttacksXML, this); 61 | 62 | } 63 | 64 | }; 65 | AttackStringContainer.prototype.save = function() { 66 | this.prefBranch.setCharPref('attacks', JSON.stringify(this.strings)); 67 | 68 | } 69 | 70 | 71 | function getAttackStringContainer(){ 72 | if (typeof(attackStringContainer) === 'undefined' || !attackStringContainer){ 73 | attackStringContainer = new AttackStringContainer(); 74 | } 75 | return attackStringContainer; 76 | } 77 | -------------------------------------------------------------------------------- /content/io.js: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////// 2 | ///////////////////////////////////////////////// 3 | // 4 | // Basic JavaScript File and Directory IO module 5 | // By: MonkeeSage, v0.1 6 | // 7 | ///////////////////////////////////////////////// 8 | ///////////////////////////////////////////////// 9 | 10 | 11 | if (typeof(JSIO) != 'boolean') { 12 | 13 | var JSIO = true; 14 | 15 | ///////////////////////////////////////////////// 16 | // Basic file IO object based on Mozilla source 17 | // code post at forums.mozillazine.org 18 | ///////////////////////////////////////////////// 19 | 20 | // Example use: 21 | // var fileIn = FileIO.open('/test.txt'); 22 | // if (fileIn.exists()) { 23 | // var fileOut = FileIO.open('/copy of test.txt'); 24 | // var str = FileIO.read(fileIn); 25 | // var rv = FileIO.write(fileOut, str); 26 | // alert('File write: ' + rv); 27 | // rv = FileIO.write(fileOut, str, 'a'); 28 | // alert('File append: ' + rv); 29 | // rv = FileIO.unlink(fileOut); 30 | // alert('File unlink: ' + rv); 31 | // } 32 | 33 | var FileIO = { 34 | 35 | localfileCID : '@mozilla.org/file/local;1', 36 | localfileIID : Components.interfaces.nsILocalFile, 37 | 38 | finstreamCID : '@mozilla.org/network/file-input-stream;1', 39 | finstreamIID : Components.interfaces.nsIFileInputStream, 40 | 41 | foutstreamCID : '@mozilla.org/network/file-output-stream;1', 42 | foutstreamIID : Components.interfaces.nsIFileOutputStream, 43 | 44 | sinstreamCID : '@mozilla.org/scriptableinputstream;1', 45 | sinstreamIID : Components.interfaces.nsIScriptableInputStream, 46 | 47 | suniconvCID : '@mozilla.org/intl/scriptableunicodeconverter', 48 | suniconvIID : Components.interfaces.nsIScriptableUnicodeConverter, 49 | 50 | open : function(path) { 51 | try { 52 | var file = Components.classes[this.localfileCID] 53 | .createInstance(this.localfileIID); 54 | file.initWithPath(path); 55 | return file; 56 | } 57 | catch(e) { 58 | return false; 59 | } 60 | }, 61 | readChannel : function(channel, charset){ 62 | var data = new String(); 63 | var inStream = channel.open(); 64 | var scriptableInStream = Components.classes["@mozilla.org/scriptableinputstream;1"]. 65 | createInstance().QueryInterface(Components.interfaces.nsIScriptableInputStream); 66 | scriptableInStream.init(inStream); 67 | 68 | data = scriptableInStream.read(scriptableInStream.available()); 69 | 70 | return data; 71 | }, 72 | read : function(file, charset) { 73 | try { 74 | var data = new String(); 75 | var fiStream = Components.classes[this.finstreamCID] 76 | .createInstance(this.finstreamIID); 77 | var siStream = Components.classes[this.sinstreamCID] 78 | .createInstance(this.sinstreamIID); 79 | fiStream.init(file, 1, 0, false); 80 | siStream.init(fiStream); 81 | data += siStream.read(-1); 82 | siStream.close(); 83 | fiStream.close(); 84 | if (charset) { 85 | data = this.toUnicode(charset, data); 86 | } 87 | return data; 88 | } 89 | catch(e) { 90 | return false; 91 | } 92 | }, 93 | 94 | write : function(file, data, mode, charset) { 95 | try { 96 | var foStream = Components.classes[this.foutstreamCID] 97 | .createInstance(this.foutstreamIID); 98 | if (charset) { 99 | data = this.fromUnicode(charset, data); 100 | } 101 | var flags = 0x02 | 0x08 | 0x20; // wronly | create | truncate 102 | if (mode == 'a') { 103 | flags = 0x02 | 0x10; // wronly | append 104 | } 105 | foStream.init(file, flags, 0664, 0); 106 | foStream.write(data, data.length); 107 | // foStream.flush(); 108 | foStream.close(); 109 | return true; 110 | } 111 | catch(e) { 112 | return false; 113 | } 114 | }, 115 | 116 | create : function(file) { 117 | try { 118 | file.create(0x00, 0664); 119 | return true; 120 | } 121 | catch(e) { 122 | return false; 123 | } 124 | }, 125 | 126 | unlink : function(file) { 127 | try { 128 | file.remove(false); 129 | return true; 130 | } 131 | catch(e) { 132 | return false; 133 | } 134 | }, 135 | 136 | path : function(file) { 137 | try { 138 | return 'file:///' + file.path.replace(/\\/g, '\/') 139 | .replace(/^\s*\/?/, '').replace(/\ /g, '%20'); 140 | } 141 | catch(e) { 142 | return false; 143 | } 144 | }, 145 | 146 | toUnicode : function(charset, data) { 147 | try{ 148 | var uniConv = Components.classes[this.suniconvCID] 149 | .createInstance(this.suniconvIID); 150 | uniConv.charset = charset; 151 | data = uniConv.ConvertToUnicode(data); 152 | } 153 | catch(e) { 154 | // foobar! 155 | } 156 | return data; 157 | }, 158 | 159 | fromUnicode : function(charset, data) { 160 | try { 161 | var uniConv = Components.classes[this.suniconvCID] 162 | .createInstance(this.suniconvIID); 163 | uniConv.charset = charset; 164 | data = uniConv.ConvertFromUnicode(data); 165 | // data += uniConv.Finish(); 166 | } 167 | catch(e) { 168 | // foobar! 169 | } 170 | return data; 171 | } 172 | 173 | } 174 | 175 | 176 | ///////////////////////////////////////////////// 177 | // Basic Directory IO object based on JSLib 178 | // source code found at jslib.mozdev.org 179 | ///////////////////////////////////////////////// 180 | 181 | // Example use: 182 | // var dir = DirIO.open('/test'); 183 | // if (dir.exists()) { 184 | // alert(DirIO.path(dir)); 185 | // var arr = DirIO.read(dir, true), i; 186 | // if (arr) { 187 | // for (i = 0; i < arr.length; ++i) { 188 | // alert(arr[i].path); 189 | // } 190 | // } 191 | // } 192 | // else { 193 | // var rv = DirIO.create(dir); 194 | // alert('Directory create: ' + rv); 195 | // } 196 | 197 | // --------------------------------------------- 198 | // ----------------- Nota Bene ----------------- 199 | // --------------------------------------------- 200 | // Some possible types for get are: 201 | // 'ProfD' = profile 202 | // 'DefProfRt' = user (e.g., /root/.mozilla) 203 | // 'UChrm' = %profile%/chrome 204 | // 'DefRt' = installation 205 | // 'PrfDef' = %installation%/defaults/pref 206 | // 'ProfDefNoLoc' = %installation%/defaults/profile 207 | // 'APlugns' = %installation%/plugins 208 | // 'AChrom' = %installation%/chrome 209 | // 'ComsD' = %installation%/components 210 | // 'CurProcD' = installation (usually) 211 | // 'Home' = OS root (e.g., /root) 212 | // 'TmpD' = OS tmp (e.g., /tmp) 213 | 214 | var DirIO = { 215 | 216 | sep : '/', 217 | 218 | dirservCID : '@mozilla.org/file/directory_service;1', 219 | 220 | propsIID : Components.interfaces.nsIProperties, 221 | 222 | fileIID : Components.interfaces.nsIFile, 223 | 224 | get : function(type) { 225 | try { 226 | var dir = Components.classes[this.dirservCID] 227 | .createInstance(this.propsIID) 228 | .get(type, this.fileIID); 229 | return dir; 230 | } 231 | catch(e) { 232 | return false; 233 | } 234 | }, 235 | 236 | open : function(path) { 237 | return FileIO.open(path); 238 | }, 239 | 240 | create : function(dir) { 241 | try { 242 | dir.create(0x01, 0664); 243 | return true; 244 | } 245 | catch(e) { 246 | return false; 247 | } 248 | }, 249 | 250 | read : function(dir, recursive) { 251 | var list = new Array(); 252 | try { 253 | if (dir.isDirectory()) { 254 | if (recursive == null) { 255 | recursive = false; 256 | } 257 | var files = dir.directoryEntries; 258 | list = this._read(files, recursive); 259 | } 260 | } 261 | catch(e) { 262 | // foobar! 263 | } 264 | return list; 265 | }, 266 | 267 | _read : function(dirEntry, recursive) { 268 | var list = new Array(); 269 | try { 270 | while (dirEntry.hasMoreElements()) { 271 | list.push(dirEntry.getNext() 272 | .QueryInterface(FileIO.localfileIID)); 273 | } 274 | if (recursive) { 275 | var list2 = new Array(); 276 | for (var i = 0; i < list.length; ++i) { 277 | if (list[i].isDirectory()) { 278 | files = list[i].directoryEntries; 279 | list2 = this._read(files, recursive); 280 | } 281 | } 282 | for (i = 0; i < list2.length; ++i) { 283 | list.push(list2[i]); 284 | } 285 | } 286 | } 287 | catch(e) { 288 | // foobar! 289 | } 290 | return list; 291 | }, 292 | 293 | unlink : function(dir, recursive) { 294 | try { 295 | if (recursive == null) { 296 | recursive = false; 297 | } 298 | dir.remove(recursive); 299 | return true; 300 | } 301 | catch(e) { 302 | return false; 303 | } 304 | }, 305 | 306 | path : function (dir) { 307 | return FileIO.path(dir); 308 | }, 309 | 310 | split : function(str, join) { 311 | var arr = str.split(/\/|\\/), i; 312 | str = new String(); 313 | for (i = 0; i < arr.length; ++i) { 314 | str += arr[i] + ((i != arr.length - 1) ? 315 | join : ''); 316 | } 317 | return str; 318 | }, 319 | 320 | join : function(str, split) { 321 | var arr = str.split(split), i; 322 | str = new String(); 323 | for (i = 0; i < arr.length; ++i) { 324 | str += arr[i] + ((i != arr.length - 1) ? 325 | this.sep : ''); 326 | } 327 | return str; 328 | } 329 | 330 | } 331 | 332 | if (navigator.platform.toLowerCase().indexOf('win') > -1) { 333 | DirIO.sep = '\\'; 334 | } 335 | 336 | } 337 | -------------------------------------------------------------------------------- /content/json.js: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 5 | * 1.1 (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * http://www.mozilla.org/MPL/ 8 | * 9 | * Software distributed under the License is distributed on an "AS IS" basis, 10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing rights and limitations under the 12 | * License. 13 | * 14 | * The Original Code is Mozilla code. 15 | * 16 | * The Initial Developer of the Original Code is 17 | * Simon Bünzli 18 | * Portions created by the Initial Developer are Copyright (C) 2006-2007 19 | * the Initial Developer. All Rights Reserved. 20 | * 21 | * Contributor(s): 22 | * 23 | * Alternatively, the contents of this file may be used under the terms of 24 | * either the GNU General Public License Version 2 or later (the "GPL"), or 25 | * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 26 | * in which case the provisions of the GPL or the LGPL are applicable instead 27 | * of those above. If you wish to allow use of your version of this file only 28 | * under the terms of either the GPL or the LGPL, and not to allow others to 29 | * use your version of this file under the terms of the MPL, indicate your 30 | * decision by deleting the provisions above and replace them with the notice 31 | * and other provisions required by the GPL or the LGPL. If you do not delete 32 | * the provisions above, a recipient may use your version of this file under 33 | * the terms of any one of the MPL, the GPL or the LGPL. 34 | * 35 | * ***** END LICENSE BLOCK ***** */ 36 | 37 | /* downloaded from http://lxr.mozilla.org/seamonkey/source/js/src/xpconnect/loader/JSON.jsm?raw=1 */ 38 | 39 | 40 | /** 41 | * Utilities for JavaScript code to handle JSON content. 42 | * See http://www.json.org/ for comprehensive information about JSON. 43 | * 44 | * Import this module through 45 | * 46 | * Components.utils.import("resource://gre/modules/JSON.jsm"); 47 | * 48 | * Usage: 49 | * 50 | * var newJSONString = JSON.stringify( GIVEN_JAVASCRIPT_OBJECT ); 51 | * var newJavaScriptObject = JSON.parse( GIVEN_JSON_STRING ); 52 | * 53 | * Note: For your own safety, Objects/Arrays returned by 54 | * JSON.fromString aren't instanceof Object/Array. 55 | */ 56 | 57 | // The following code is a loose adaption of Douglas Crockford's code 58 | // from http://www.json.org/json.js (public domain'd) 59 | 60 | // Notable differences: 61 | // * Unserializable values such as |undefined| or functions aren't 62 | // silently dropped but always lead to a TypeError. 63 | // * An optional key blacklist has been added to JSON.stringify 64 | 65 | // If canonical parser is installed, don't bother 66 | if ( typeof( JSON ) === "undefined" || !JSON ) { 67 | JSON = { 68 | /** 69 | * Converts a JavaScript object into a JSON string. 70 | * 71 | * @param aJSObject is the object to be converted 72 | * @param aKeysToDrop is an optional array of keys which will be 73 | * ignored in all objects during the serialization 74 | * @return the object's JSON representation 75 | * 76 | * Note: aJSObject MUST not contain cyclic references. 77 | */ 78 | stringify: function JSON_toString(aJSObject, aKeysToDrop) { 79 | // these characters have a special escape notation 80 | const charMap = { "\b": "\\b", "\t": "\\t", "\n": "\\n", "\f": "\\f", 81 | "\r": "\\r", '"': '\\"', "\\": "\\\\" }; 82 | 83 | // we use a single string builder for efficiency reasons 84 | var pieces = []; 85 | 86 | // this recursive function walks through all objects and appends their 87 | // JSON representation (in one or several pieces) to the string builder 88 | function append_piece(aObj) { 89 | if (typeof aObj == "boolean") { 90 | pieces.push(aObj ? "true" : "false"); 91 | } 92 | else if (typeof aObj == "number" && isFinite(aObj)) { 93 | // there is no representation for infinite numbers or for NaN! 94 | pieces.push(aObj.toString()); 95 | } 96 | else if (typeof aObj == "string") { 97 | aObj = aObj.replace(/[\\"\x00-\x1F\u0080-\uFFFF]/g, function($0) { 98 | // use the special escape notation if one exists, otherwise 99 | // produce a general unicode escape sequence 100 | return charMap[$0] || 101 | "\\u" + ("0000" + $0.charCodeAt(0).toString(16)).slice(-4); 102 | }); 103 | pieces.push('"' + aObj + '"') 104 | } 105 | else if (aObj === null) { 106 | pieces.push("null"); 107 | } 108 | // if it looks like an array, treat it as such - this is required 109 | // for all arrays from either outside this module or a sandbox 110 | else if (aObj instanceof Array || 111 | typeof aObj == "object" && "length" in aObj && 112 | (aObj.length === 0 || aObj[aObj.length - 1] !== undefined)) { 113 | pieces.push("["); 114 | for (var i = 0; i < aObj.length; i++) { 115 | append_piece(aObj[i]); 116 | pieces.push(","); 117 | } 118 | if (pieces[pieces.length - 1] == ",") 119 | pieces.pop(); // drop the trailing colon 120 | pieces.push("]"); 121 | } 122 | else if (typeof aObj == "object") { 123 | pieces.push("{"); 124 | for (var key in aObj) { 125 | // allow callers to pass objects containing private data which 126 | // they don't want the JSON string to contain (so they don't 127 | // have to manually pre-process the object) 128 | if (aKeysToDrop && aKeysToDrop.indexOf(key) != -1) 129 | continue; 130 | 131 | append_piece(key.toString()); 132 | pieces.push(":"); 133 | append_piece(aObj[key]); 134 | pieces.push(","); 135 | } 136 | if (pieces[pieces.length - 1] == ",") 137 | pieces.pop(); // drop the trailing colon 138 | pieces.push("}"); 139 | } 140 | else { 141 | throw new TypeError("No JSON representation for this object!"); 142 | } 143 | } 144 | append_piece(aJSObject); 145 | 146 | return pieces.join(""); 147 | }, 148 | 149 | /** 150 | * Converts a JSON string into a JavaScript object. 151 | * 152 | * @param aJSONString is the string to be converted 153 | * @return a JavaScript object for the given JSON representation 154 | */ 155 | parse: function JSON_fromString(aJSONString) { 156 | if (!this.isMostlyHarmless(aJSONString)) 157 | throw new SyntaxError("No valid JSON string!"); 158 | 159 | var s = new Components.utils.Sandbox("about:blank"); 160 | return Components.utils.evalInSandbox("(" + aJSONString + ")", s); 161 | }, 162 | 163 | /** 164 | * Checks whether the given string contains potentially harmful 165 | * content which might be executed during its evaluation 166 | * (no parser, thus not 100% safe! Best to use a Sandbox for evaluation) 167 | * 168 | * @param aString is the string to be tested 169 | * @return a boolean 170 | */ 171 | isMostlyHarmless: function JSON_isMostlyHarmless(aString) { 172 | const maybeHarmful = /[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/; 173 | const jsonStrings = /"(\\.|[^"\\\n\r])*"/g; 174 | 175 | return !maybeHarmful.test(aString.replace(jsonStrings, "")); 176 | } 177 | }; 178 | } -------------------------------------------------------------------------------- /content/overlay.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * This function checks whether the context menu needs to be dispalyed and then 25 | * makes sure that that is the state of the context menu 26 | */ 27 | 28 | function checkContextMenu() { 29 | var prefService = Components.classes['@mozilla.org/preferences-service;1']. 30 | getService(Components.interfaces.nsIPrefService); 31 | var branch = prefService.getBranch('extensions.xssme.'); 32 | var showContextMenu = true; //default 33 | 34 | if (branch.prefHasUserValue('showcontextmenu')) { 35 | showContextMenu = branch.getBoolPref('showcontextmenu'); 36 | } 37 | 38 | var contextMenu = document.getElementById('xssmecontextmenu'); 39 | contextMenu.setAttribute('collapsed', !showContextMenu); 40 | } 41 | 42 | function XssOverlay() {} 43 | 44 | XssOverlay.prototype = { 45 | contextMenuObserver: null 46 | , 47 | onLoad: function() { 48 | 49 | var prefService = Components.classes['@mozilla.org/preferences-service;1']. 50 | getService(Components.interfaces.nsIPrefService); 51 | 52 | var branch = prefService.getBranch(''); 53 | 54 | var observableBranch = branch. 55 | QueryInterface(Components.interfaces.nsIPrefBranch2); 56 | 57 | this.contextMenuObserver = new Xss_PrefObserver(checkContextMenu); 58 | 59 | checkContextMenu(); 60 | 61 | dump('mainwindow::onLoad contextMenuObserver ==' + this.contextMenuObserver +'\n'); 62 | 63 | 64 | observableBranch.addObserver('extensions.xssme.showcontextmenu', this.contextMenuObserver, false); 65 | } 66 | , 67 | onUnload: function() { 68 | dump('XssOverlay::onUnload this.contextMenuObserver' + this.contextMenuObserver + '\n'); 69 | //Do nothing right now. 70 | var prefService = Components.classes['@mozilla.org/preferences-service;1']. 71 | getService(Components.interfaces.nsIPrefService); 72 | 73 | var branch = prefService.getBranch(''); 74 | 75 | var observableBranch = branch. 76 | QueryInterface(Components.interfaces.nsIPrefBranch2); 77 | 78 | observableBranch.removeObserver('extensions.xssme.showcontextmenu', this.contextMenuObserver) 79 | } 80 | }; 81 | 82 | var xssOverlay = new XssOverlay(); 83 | 84 | window.addEventListener('load', xssOverlay.onLoad, false); 85 | window.addEventListener('unload', xssOverlay.onUnload, false); 86 | -------------------------------------------------------------------------------- /content/overlay.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 26 | 112 | 113 | -------------------------------------------------------------------------------- /content/progressListener.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | const STATE_START = Components.interfaces.nsIWebProgressListener.STATE_START; 24 | const STATE_STOP = Components.interfaces.nsIWebProgressListener.STATE_STOP; 25 | const STATE_IS_WINDOW = Components.interfaces.nsIWebProgressListener.STATE_IS_WINDOW; 26 | const STATE_IS_DOCUMENT = Components.interfaces.nsIWebProgressListener.STATE_IS_DOCUMENT; 27 | 28 | const LISTEN_ON_WINDOW = 1; 29 | const LISTEN_ON_DOCUMENT = 2; 30 | 31 | function xssmeProgressListener(funcToCall, listenOn) { 32 | 33 | this.func = funcToCall 34 | this.listenOn = listenOn != null ? listenOn : STATE_IS_WINDOW; 35 | dump('created a listener... mode is ' + listenOn + '\n'); 36 | this.interfaceName = "nsIWebProgressListener"; 37 | }; 38 | 39 | xssmeProgressListener.prototype = 40 | { 41 | QueryInterface: function(aIID) 42 | { 43 | if (aIID.equals(Components.interfaces.nsIWebProgressListener) || 44 | aIID.equals(Components.interfaces.nsISupportsWeakReference) || 45 | aIID.equals(Components.interfaces.nsISupports)) 46 | { 47 | return this; 48 | } 49 | throw Components.results.NS_NOINTERFACE; 50 | return null; 51 | }, 52 | 53 | onStateChange: function(aProgress, aRequest, aFlag, aStatus) 54 | { 55 | //dump('got a state change. aFlag is ' + aFlag.toString(16) + '\n'); 56 | //dump('got a state change. we are listening on ' + 57 | // this.listenOn.toString(16) + '\n'); 58 | // Components sometimes seems to disappear or or malfunction so we're 59 | // just using the literal constant here. 60 | // if((aFlag & 0x00000010) && 61 | // (aFlag & 0x00080000) ) 62 | if ((aFlag & STATE_STOP) && (aFlag & this.listenOn)) { 63 | this.func(); 64 | } 65 | return 0; 66 | }, 67 | 68 | onLocationChange: function(aProgress, aRequest, aURI) 69 | { 70 | 71 | return 0; 72 | }, 73 | 74 | // For definitions of the remaining functions see XULPlanet.com 75 | onProgressChange: function() {return 0;}, 76 | onStatusChange: function() {return 0;}, 77 | onSecurityChange: function() {return 0;}, 78 | onLinkIconAvailable: function() {return 0;} 79 | }; 80 | -------------------------------------------------------------------------------- /content/results.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 9 | Results for http://www.domain.tld/url.ext 10 | 45 | 46 | 47 | 48 | 49 | 50 |

XSS Me Test Results for http://domain.tld/url.ext

51 |

Here are the results for the 9999 tests run:

52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 64 | 65 | 66 | 67 | 68 | 69 | 70 |
Failed:
 
Warning:
 
63 |
Passed:
 
71 |
72 |
73 |
74 | 75 | Form 1 76 |
77 | Test 1 78 |

Result: Failed

79 |
    80 |
  • Field 1: value1
  • 81 |
  • Field 2: value2
  • 82 |
83 |
84 |
85 | Test 2 86 |

Result: Warning

87 |
    88 |
  • Field 1: value1
  • 89 |
  • Field 2: value2
  • 90 |
91 |
92 |
93 | Test 1 94 |

Result: Passed

95 |
    96 |
  • Field 1: value1
  • 97 |
  • Field 2: value2
  • 98 |
99 |
100 |
101 | 102 | 103 | -------------------------------------------------------------------------------- /content/sidebarBuilder.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2008 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | function SidebarBuilder(){ 24 | 25 | this.toBeAdded = new Array(); 26 | var prefService = Components.classes['@mozilla.org/preferences-service;1']. 27 | getService(Components.interfaces.nsIPrefService); 28 | var branch = prefService.getBranch('extensions.xssme.'); 29 | 30 | this.time = branch.getIntPref('sidebarbuildingstop'); 31 | this.isRunning = true; 32 | } 33 | 34 | SidebarBuilder.prototype = { 35 | setup: function(){ 36 | this.isRunning = true; 37 | this.toBeAdded = new Array(); 38 | } 39 | , 40 | start: function(self){ 41 | if (!self) { 42 | self = this; 43 | } 44 | if (self.toBeAdded.length > 0 && self.isRunning) { 45 | 46 | var parent, child, postFunc; 47 | 48 | [parent, child, postFunc] = self.toBeAdded.shift(); 49 | 50 | parent.appendChild(child); 51 | 52 | if (postFunc) postFunc(parent, child); 53 | 54 | setTimeout(self.start, self.time, self); 55 | 56 | } 57 | 58 | 59 | } 60 | , 61 | add: function(parent, child, postFunc) { 62 | this.toBeAdded.push([parent,child, postFunc]); 63 | } 64 | , 65 | stop: function() { 66 | this.isRunning = false; 67 | this.toBeAdded = null; 68 | } 69 | } 70 | 71 | function getSidebarBuilder() { 72 | if (typeof(__xssme_sidebar_builder__) == 'undefined' || 73 | !__xssme_sidebar_builder__) 74 | { 75 | __xssme_sidebar_builder__ = new SidebarBuilder(); 76 | } 77 | return __xssme_sidebar_builder__; 78 | } 79 | -------------------------------------------------------------------------------- /content/tabbrowsermanager.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * tabbrowsermanager.js 25 | * Much of this system relies on working with the tab browser. This file 26 | * encapsulates all that functionality. 27 | */ 28 | 29 | /** 30 | * Captures information about the target page from the browser in the foreground tab, 31 | * since the user may change the state of that browser while the tests are in progress. 32 | * @param browser a browser pointed at the page that the test battery will be run against 33 | * @return a (new) TabManager object for use with the current test battery 34 | */ 35 | function TabManager(browser){ 36 | 37 | // Cache the URL, referrer and postdata of the browser, for access via loadTargetPage(). 38 | // Cache its contentDocument as a basis for comparison, to ensure other browsers have loaded correctly. 39 | this.targetContentDocument = browser.contentDocument; 40 | this.targetPagePostData = null; 41 | var sh = browser.sessionHistory; 42 | if (sh.count) { 43 | var currentEntry = sh.getEntryAtIndex((sh.index), false); 44 | if (currentEntry.postData) { 45 | var postDataStream = Components.classes["@mozilla.org/scriptableinputstream;1"] 46 | .createInstance(Components.interfaces.nsIScriptableInputStream); 47 | postDataStream.init(currentEntry.postData); 48 | // Supposedly it's bad to retrieve all postData at once, 49 | // in case there's a lot of it, because other pseudothreads can't interrupt? 50 | var buffer = null; 51 | while (foo = postDataStream.read(512)) { 52 | this.targetPostData += buffer; 53 | } 54 | } 55 | this.targetPage = currentEntry.URI.spec; 56 | this.targetPageReferrer = currentEntry.referrerURI || null; 57 | } 58 | else { 59 | this.targetPage = browser.webNavigation.currentURI.spec; 60 | this.targetPageReferrer = null; 61 | } 62 | 63 | // Extract a list of the forms on the page. 64 | this.tabForms = new Array(); 65 | var forms = browser.docShell.document.forms; 66 | for (var i = 0; i < forms.length; i++) { 67 | this.tabForms[i] = new Array(); 68 | for (var j = 0; j < forms[i].elements.length; j++) { 69 | var elem = forms[i].elements[j]; 70 | switch (elem.nodeName.toLowerCase()) { 71 | case 'submit': 72 | case 'reset': 73 | case 'image': 74 | case 'button': 75 | case 'fieldset': 76 | this.tabForms[i].push(null); 77 | break; 78 | case 'checkbox': 79 | case 'radio': 80 | this.tabForms[i].push(elem.checked); 81 | break; 82 | default: 83 | this.tabForms[i].push(elem.value); 84 | } 85 | } 86 | } 87 | 88 | this.index = browser.webNavigation.sessionHistory.index; 89 | } 90 | 91 | TabManager.prototype = { 92 | /** 93 | * Point a browser at the target page recorded by this TabManager. 94 | * @param browser the browser to point to the target page 95 | */ 96 | loadTargetPage: function (browser) { 97 | browser.webNavigation.loadURI(this.targetPage, 0, this.targetPageReferrer, this.targetPagePostData, null); 98 | } 99 | , 100 | writeTabForms: function(forms, testFormIndex, testFieldIndex, testValue){ 101 | if (forms[testFormIndex] === undefined){ 102 | Components.utils.reportError('Received an undfined form: ') 103 | } 104 | for (var formIndex = 0; 105 | formIndex < forms.length; 106 | formIndex++) 107 | { 108 | for (var elementIndex = 0; 109 | elementIndex < forms[formIndex].elements.length; 110 | elementIndex++) 111 | { 112 | var element = forms[formIndex].elements[elementIndex]; 113 | if (formIndex !== null && 114 | formIndex === testFormIndex && 115 | elementIndex === testFieldIndex && 116 | testValue !== null 117 | ) 118 | { 119 | if(element.nodeName.toLowerCase() === 'select') { 120 | var newOption = forms[formIndex].ownerDocument.createElement('option'); 121 | var grabTextWithOutTrailingWhitespaceRegExp = /^(.*[^\s])\s*$/; 122 | var attackString = 123 | grabTextWithOutTrailingWhitespaceRegExp. 124 | exec(testValue.string)[1]; 125 | 126 | newOption.setAttribute('value', attackString); 127 | newOption.innerHTML = testValue.string; 128 | element.options[element.options.length] = newOption; 129 | element.selectedIndex = element.options.length - 1; 130 | } 131 | else { 132 | element.value = testValue.string; 133 | } 134 | } 135 | else if (element.nodeName.toLowerCase() == 'submit' || 136 | element.nodeName.toLowerCase() == 'reset' || 137 | element.nodeName.toLowerCase() == 'image' || 138 | element.nodeName.toLowerCase() == 'button') 139 | { 140 | // don't care, this is here just to make sure the elements 141 | // are parallel. 142 | } 143 | else if (element.nodeName.toLowerCase() == 'checkbox' || 144 | element.nodeName.toLowerCase() == 'radio') 145 | { 146 | element.checked = this.tabForms[formIndex][elementIndex]; 147 | } 148 | else { 149 | element.value = this.tabForms[formIndex][elementIndex]; 150 | } 151 | } 152 | } 153 | } 154 | , 155 | getTabData: function(forms, testFormIndex, testFieldIndex){ 156 | var rv = new Array(); 157 | var formIndex = testFormIndex; 158 | 159 | for (var elementIndex = 0; 160 | elementIndex < forms[formIndex].elements.length; 161 | elementIndex++) 162 | { 163 | var element = forms[formIndex].elements[elementIndex]; 164 | var fieldInfo = new Object(); 165 | fieldInfo.name = element.name; 166 | fieldInfo.data = element.value; 167 | fieldInfo.tested = (elementIndex == testFieldIndex); 168 | rv.push(fieldInfo); 169 | } 170 | return rv; 171 | } 172 | , 173 | /** 174 | * This returns the data in a form 175 | */ 176 | getFormDataForURL: function(forms, testFormIndex, testFieldIndex, 177 | testValue) 178 | { 179 | var formIndex = testFormIndex; 180 | var rv = ''; 181 | for (var elementIndex = 0; 182 | elementIndex < forms[testFormIndex].elements.length; 183 | elementIndex++) 184 | { 185 | var element = forms[testFormIndex].elements[elementIndex]; 186 | if (element.value) { 187 | if (rv.length != 0){ 188 | rv+='&'; 189 | } 190 | rv += element.name +'='+element.value; 191 | } 192 | } 193 | return rv; 194 | 195 | } 196 | }; -------------------------------------------------------------------------------- /content/util.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * util.js 25 | * Utility Functions. 26 | */ 27 | 28 | const EXTENSION_NAME = 'xssme@security.compass'; 29 | 30 | /** 31 | * This takes a string of a piece of encoded XML and decodes it. 32 | * Specifically, this checks checks for encoded nested ]]> code. 33 | * Note: No XML parsing or checking is done. 34 | * @param xmlString 35 | * @returns a decoded string of a piece of XML (same piece) 36 | */ 37 | function decodeXML(xmlString) { 38 | 39 | var regex = ']]]]>'; 41 | 42 | return xmlString.replace(regex, replaced, 'gm'); 43 | 44 | } 45 | 46 | /** 47 | * This takes a string of a piece of XML and decodes it. 48 | * Specifically, this checks checks for nested ']]>' code. 49 | * Note: No XML parsing or checking is done. 50 | * @param xmlString 51 | * @returns an encoded string of a piece of XML (same piece) 52 | */ 53 | function encodeXML(xmlString) { 54 | 55 | var regex = ']]>'; 56 | var replaced = ']]]]>1?'s':'')+' encountered.') 163 | } 164 | } 165 | else { 166 | alert("Couldn't find any attacks. No Attacks imported."); 167 | return false; 168 | } 169 | } 170 | 171 | function importAttacksFromXMLFile(importFile, container) { 172 | var fileContents = FileIO.read(importFile); 173 | return importAttackFromXMLString(fileContents, container); 174 | } 175 | 176 | function getMonthName(monthNumber) { 177 | var months = new Array(); 178 | months[0] = "January"; 179 | months[1] = "February"; 180 | months[2] = "March"; 181 | months[3] = "April"; 182 | months[4] = "May"; 183 | months[5] = "June"; 184 | months[6] = "July"; 185 | months[7] = "August"; 186 | months[8] = "September"; 187 | months[9] = "October"; 188 | months[10] = "November"; 189 | months[11] = "December"; 190 | return months[monthNumber]; 191 | } 192 | 193 | /** 194 | * This function checks the success whether the work tab's content document 195 | * match the original tab's content document (in ways that we care about). 196 | * @returns true if same otherwise false. 197 | */ 198 | function compareContentDocuments(origTabContentDocument, workTabContentDocument) { 199 | var rv = true; 200 | if (workTabContentDocument.forms) { 201 | if (origTabContentDocument.forms.length === 202 | workTabContentDocument.forms.length) 203 | { 204 | for (var i = 0; i < origTabContentDocument.forms.length && rv; i++) { 205 | if (workTabContentDocument.forms[i]){ 206 | if (workTabContentDocument.forms[i].elements){ 207 | for (var n = 0; n < origTabContentDocument.forms[i].elements.length && rv; n++){ 208 | if (workTabContentDocument.forms[i].elements[i]) { 209 | if (origTabContentDocument.forms[i].elements[i].type != 210 | workTabContentDocument.forms[i].elements[i].type) { 211 | rv = false; 212 | } 213 | } 214 | } 215 | } 216 | else { 217 | rv = false; 218 | } 219 | } 220 | else { 221 | rv = false; 222 | } 223 | } 224 | } 225 | else { 226 | rv = false; 227 | } 228 | } 229 | else { 230 | rv = false; 231 | } 232 | return rv 233 | } 234 | 235 | function getHTMLFormElementNameOrLabel(element) { 236 | return element.name?element.name:element.id; 237 | } 238 | -------------------------------------------------------------------------------- /content/whiletestruns.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * NOTE: in this file all uses of the keyword *this* refer to the window. 25 | * We're modifying this window so that other windows (e.g. the sidebar) can 26 | * interact with it directly. 27 | */ 28 | 29 | /** 30 | * whiletestruns.js 31 | * Holding JS code for whiletestruns.xul 32 | */ 33 | function OK(){ 34 | 35 | var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] 36 | .getService(Components.interfaces.nsIPromptService); 37 | var rv = false; 38 | 39 | rv = prompts.confirmEx(null, "Warning! Closing this dialog box will not terminate the XSS Me test.", 40 | "Warning! Closing this dialog box will not terminate the XSS Me test. If you wish to terminate the test, you may do so by closing the XSS Me sidebar. This is not recommended as it may result in a slight memory leak.", 41 | prompts.STD_YES_NO_BUTTONS, "", "", "", null, new Object()); 42 | 43 | return !rv; 44 | 45 | } 46 | 47 | /** 48 | * This function is called when a test is finished 49 | */ 50 | this.finishedTest = function() { 51 | this.numTestsComplete++; 52 | if (this.numTestsComplete > this.maxNumTests) { 53 | Components.utils.reportError('Too many tests have been completed'); 54 | } 55 | } 56 | 57 | this.clearNumTests = function() { 58 | this.numTestsComplete = 0; 59 | } 60 | 61 | this.updateUI = function() { 62 | 63 | this.bar.value = this.numTestsComplete / this.maxNumTests * 100 64 | this.span.innerHTML = this.numTestsComplete.toString() + '/' + this.maxNumTests.toString(); 65 | 66 | } 67 | 68 | this.startThoroughTesting = function(numVulnerableFields) { 69 | this.bar.value = 100; 70 | this.span.innerHTML = this.maxNumTests.toString() + '/' + this.maxNumTests.toString(); 71 | 72 | this.bar = document.getElementById('thoroughBar'); 73 | this.span = document.getElementById('thoroughTestCount'); 74 | 75 | this.maxNumTests = 2*numVulnerableFields*this.testType.count; 76 | this.numTestsComplete = 0; 77 | 78 | //document.getElementById('heuristicsComplete').style.visibility = 'visible'; 79 | } 80 | 81 | function onUnLoad() { 82 | //alert(this.numTestsComplete + ' of ' +this.maxNumTests); 83 | this.bar = null; 84 | this.span = null; 85 | } 86 | 87 | /** 88 | * called when the page loads 89 | */ 90 | function onLoad() { 91 | this.clearNumTests(); 92 | window.centerWindowOnScreen(); 93 | this.maxNumTests = window.arguments[0]; 94 | this.testType = window.arguments[1]; 95 | this.bar = null; 96 | this.span = null; 97 | 98 | if (this.testType.heuristicTest) { 99 | document.getElementById('heuristicTestingBox').style.visibility = 'visible'; 100 | //document.getElementById('heuristicsComplete').style.visibility = 'hidden'; 101 | this.bar = document.getElementById('heuristicBar'); 102 | this.span = document.getElementById('heuristicTestCount'); 103 | } 104 | else { 105 | this.bar = document.getElementById('thoroughBar'); 106 | this.span = document.getElementById('thoroughTestCount'); 107 | } 108 | 109 | //update UI every 1/5 second 110 | window.setInterval(this.updateUI, 200); 111 | } 112 | -------------------------------------------------------------------------------- /content/whiletestruns.xul: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 38 | 111 | 112 | -------------------------------------------------------------------------------- /content/xssmeevaluators.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /** 24 | * xssmeevaluators.js 25 | * This file holds a number of JS evaluators 26 | * @require Results.js 27 | */ 28 | 29 | function xssmeTrimRight( s ) { 30 | if ( typeof( String.prototype.trimRight ) === 'undefined' || !String.prototype.trimRight ) { 31 | return s.replace( /\s+$/, '' ); 32 | } 33 | 34 | return s.trimRight(); 35 | } 36 | 37 | function checkForVulnerableElement(browser, attackRunner) { 38 | 39 | var rv = null; 40 | var document = browser.contentDocument; 41 | 42 | dump('xssmeevaluator on page ' + document.location); 43 | dump(' is ' + (document.wrappedJSObject.vulnerable ) + ' '); 44 | dump((document.wrappedJSObject.vulnerable == true) + '\n'); 45 | 46 | if (document.wrappedJSObject.vulnerable && document.wrappedJSObject.vulnerable == true){ 47 | 48 | rv = new Result(RESULT_TYPE_ERROR, 100, "DOM was modified by attack string. Field appears to be very vulnerable to XSS String.");// ('"+attackRunner.testValue.string+"')"); 49 | 50 | } 51 | else { 52 | 53 | rv = new Result(RESULT_TYPE_PASS, 100, "DOM was not modified by attack string. Field does not appear vulnerable to XSS String");//('"+attackRunner.testValue.string+"')"); 54 | 55 | } 56 | 57 | return [rv]; 58 | 59 | } 60 | 61 | function checkForExactAttackText(streamListener){ 62 | 63 | var rv = null; 64 | var searchString = xssmeTrimRight( streamListener.attackRunner.testValue.string ); 65 | var specials = [ 66 | '/', '.', '*', '+', '?', '|', 67 | '(', ')', '[', ']', '{', '}', '\\']; 68 | var regex = new RegExp('(\\' + specials.join('|\\') + ')', 'g'); 69 | searchString = searchString.replace(regex, '\\$1'); 70 | var regex = new RegExp(searchString, 'gm'); 71 | dump('xssmeevaluators::checkForExactAttackText: checking for ' + 72 | 'attackRunner.testValue: ' + streamListener.attackRunner.testValue.string + '\n'); 73 | /*dump('xssmeevaluators::checkForExactAttackText::streamListener.data '+streamListener.data+'\n');*/ 74 | var doesMatch = streamListener.data.match(regex); 75 | 76 | if (doesMatch) { 77 | 78 | rv = new Result(RESULT_TYPE_WARNING, 100, "The unencoded attack string was found in the html of the document. Other browsers may be vulnerable to this XSS string."); //('"+streamListener.attackRunner.testValue.string + "')"); 79 | 80 | } 81 | else { 82 | 83 | rv = new Result(RESULT_TYPE_PASS, 100, "The unencoded attack string was not found in the html of the document.");//('"+streamListener.attackRunner.testValue.string + "')"); 84 | 85 | } 86 | 87 | return [rv]; 88 | 89 | } 90 | 91 | -------------------------------------------------------------------------------- /defaults/preferences/xssme.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | pref("extensions.xssme.prefnumattacks", 9); 24 | pref("extensions.xssme.showcontextmenu", true); 25 | pref("extensions.xssme.numtabstouse", 6); 26 | pref("extensions.xssme.testchars", ";\\/<>\"'="); 27 | pref("extensions.xssme.useheuristictests", true); 28 | pref("extensions.xssme.sidebarbuildingstop", 3); 29 | pref("extensions.xssme.reportbuilding.showPass", false); 30 | -------------------------------------------------------------------------------- /install.rdf: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | xssme@security.compass 6 | XSS Me 7 | 0.4.6 8 | 2 9 | Security Compass 10 | An extension to test for Cross Site Scripting vulnerabilities 11 | chrome://xssme/content/preferences.xul 12 | chrome://xssme/skin/tiny_logo.png 13 | 14 | 15 | {ec8030f7-c20a-464f-9b0e-13a3a9e97384} 16 | 2.0.0.8 17 | 11.* 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /locale/en-US/overlay.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /locale/en-US/prefwindow.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /locale/en-US/xssme.dtd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SecurityCompass/XSSMe/1e87473220231ceb135c5d9eab6570b45fd693eb/locale/en-US/xssme.dtd -------------------------------------------------------------------------------- /locale/en-US/xssme.properties: -------------------------------------------------------------------------------- 1 | extensions.xssme.description=An extension to test for Cross Site Scripting vulnerabilities -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | XSS-Me 2 | ====== 3 | XSS-Me is a part of the Security Compass Exploit-Me series of tools. XSS-Me is 4 | designed to aid in the detection of Cross-Site scripting vulnerabilities. The 5 | tool is a Firefox extenstion that will execute specific attack strings against 6 | forms on your website. 7 | 8 | 9 | Limitations 10 | ----------- 11 | Currently XSS-Me is focused on detecting reflected Cross-Site scripting 12 | attacks. While we have plans to implement the detection of stored Cross-Site 13 | scripting we are currently focusing on the speed and accuracy of the reflected 14 | portions of the tool. 15 | 16 | 17 | More Information 18 | ---------------- 19 | For more information on XSS-Me please visit: 20 | http://www.securitycompass.com/exploitme.shtml. If you've got any questions, 21 | comments, or suggestions regarding XSS-Me please send them to 22 | tools@securitycompass.com. 23 | 24 | 25 | License 26 | ------- 27 | XSS-Me is released under the GNU GPLv3 a copy of which should be included in 28 | this distribution. -------------------------------------------------------------------------------- /skin/overlay.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | /* This is just an example. You shouldn't do this. */ 24 | #xssme-hello 25 | { 26 | } 27 | #xssme-toolbar-button 28 | { 29 | list-style-image: url("chrome://xssme/skin/toolbar-button.png"); 30 | -moz-image-region: rect(0px 24px 24px 0px); 31 | } 32 | #xssme-toolbar-button:hover 33 | { 34 | -moz-image-region: rect(24px 24px 48px 0px); 35 | } 36 | [iconsize="small"] #xssme-toolbar-button 37 | { 38 | -moz-image-region: rect( 0px 40px 16px 24px); 39 | } 40 | [iconsize="small"] #xssme-toolbar-button:hover 41 | { 42 | -moz-image-region: rect(24px 40px 40px 24px); 43 | } 44 | -------------------------------------------------------------------------------- /skin/preferences.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | radio { 24 | list-style-image: url("chrome://browser/skin/preferences/Options.png"); 25 | } 26 | 27 | radio[pane=xssgen] { 28 | -moz-image-region: rect(0px, 32px, 32px, 0px); 29 | } 30 | 31 | radio[pane=xssstrings] { 32 | -moz-image-region: rect(0px, 128px, 32px, 96px); 33 | } -------------------------------------------------------------------------------- /skin/small_logo_sc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SecurityCompass/XSSMe/1e87473220231ceb135c5d9eab6570b45fd693eb/skin/small_logo_sc.png -------------------------------------------------------------------------------- /skin/tiny_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SecurityCompass/XSSMe/1e87473220231ceb135c5d9eab6570b45fd693eb/skin/tiny_logo.png -------------------------------------------------------------------------------- /skin/toolbar-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SecurityCompass/XSSMe/1e87473220231ceb135c5d9eab6570b45fd693eb/skin/toolbar-button.png -------------------------------------------------------------------------------- /skin/whiletestruns.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2008 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | #heuristicTestingBox 24 | { 25 | visibility: collapse; 26 | } 27 | 28 | #heuristcsComplete { 29 | visibility: collapse; 30 | color: green; 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /skin/xssme_sidebar.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2007 Security Compass 3 | 4 | This file is part of XSS Me. 5 | 6 | XSS Me is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | 11 | XSS Me is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with XSS Me. If not, see . 18 | 19 | If you have any questions regarding XSS Me please contact 20 | tools@securitycompass.com 21 | */ 22 | 23 | #form1_field1_menulist.activated .menulist-editable-input, 24 | #form1_field2_menulist.activated .menulist-editable-input, 25 | .activated .menulist-editable-input 26 | { 27 | background-color: #FFFF11 !important; 28 | } 29 | 30 | #form1_field1_checkbox .checkbox-label-box, 31 | #form1_field2_checkbox .checkbox-label-box, 32 | .nolabel .checkbox-label-box 33 | { 34 | display: none; 35 | } 36 | 37 | .title { 38 | color: #405068 !important; 39 | } --------------------------------------------------------------------------------