├── chrome.manifest
├── content
├── AttackHttpResponseObserver.js
├── AttackRunner.js
├── ErrorStringContainer.js
├── FieldResult.js
├── PrefObserver.js
├── Results.js
├── ResultsManager.js
├── StreamListener.js
├── TestManager.js
├── TestRunnerContainer.js
├── about.xul
├── addAttack.js
├── addAttack.xul
├── addError.js
├── addError.xul
├── attackStringContainer.js
├── htmlStringEncoder.js
├── io.js
├── json.js
├── overlay.js
├── overlay.xul
├── preferenceStringContainer.js
├── preferences.fx2.js
├── preferences.fx3.js
├── preferences.xul
├── progressListener.js
├── results.html
├── sidebarBuilder.js
├── sqlime.js
├── sqlime_sidebar.js
├── sqlime_sidebar.xul
├── sqlimeevaluators.js
├── tabbrowsermanager.js
├── util.js
├── whiletestruns.js
└── whiletestruns.xul
├── defaults
└── preferences
│ └── sqlime.js
├── gpl-3.0.txt
├── install.rdf
├── locale
└── en-US
│ ├── overlay.dtd
│ ├── prefwindow.dtd
│ ├── sqlime.dtd
│ └── sqlime.properties
├── readme.txt
├── skin
├── logo_sc.png
├── overlay.css
├── preferences.css
├── results.css
├── small_logo_sc.png
├── sqlime_sidebar.css
├── tiny_logo.png
├── toolbar-button.png
└── whiletestruns.css
└── update.rdf
/chrome.manifest:
--------------------------------------------------------------------------------
1 | content sqlime content/
2 | locale sqlime en-US locale/en-US/
3 | skin sqlime classic/1.0 skin/
4 | overlay chrome://browser/content/browser.xul chrome://sqlime/content/overlay.xul
5 | style chrome://global/content/customizeToolbar.xul chrome://sqlime/skin/overlay.css
6 | # Firefox 2 & Firefox 3 differences
7 | override chrome://sqlime/content/preferences.js chrome://sqlime/content/preferences.fx2.js appversion<3.0
8 | override chrome://sqlime/content/preferences.js chrome://sqlime/content/preferences.fx3.js appversion>=3.0
--------------------------------------------------------------------------------
/content/AttackHttpResponseObserver.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 | className: 'AttackHttpResponseObserver'
37 | ,
38 | QueryInterface: function(iid) {
39 | if (iid.equals(Components.interfaces.nsIObserver) ||
40 | iid.equals(Components.interfaces.nsISupports))
41 | {
42 | return this;
43 | }
44 |
45 | throw Components.results.NS_ERROR_NO_INTERFACE;
46 | },
47 |
48 | observe: function(subject, topic, data) {
49 |
50 | if (topic == AttackHttpResponseObserver_topic){
51 | try {
52 | var channel = subject.
53 | QueryInterface(Components.interfaces.nsIHttpChannel)
54 | if (channel.responseStatus < 300 ||
55 | channel.responseStatus >= 400)
56 | {
57 | this.resultsManager.gotChannelForAttackRunner(channel,
58 | this);
59 | }
60 | }
61 | catch(err) {
62 | dump('AttackHttpResponseObserver::observe: ' + err + '\n');
63 | for(var k in err)
64 | dump('AttackHttpResponseObserver::observe: err['+k+'] ==' + err[k] + '\n')
65 | }
66 | }
67 |
68 | }
69 |
70 | };
--------------------------------------------------------------------------------
/content/AttackRunner.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 | /**
38 | * uniqueID is important for heuristic tests which need a random string in
39 | * order to find the char they sent
40 | */
41 | this.uniqueID = Math.floor(Date.now() * Math.random());
42 |
43 | this.tabWrapper = null;
44 |
45 | this.resultsWrappers = new Array();
46 |
47 | }
48 |
49 | AttackRunner.prototype = {
50 | testData: null
51 | ,
52 | submitForm: function(browser, formIndex){
53 | var forms = browser.webNavigation.document.forms;
54 | var formFound = false;
55 | for (var i = 0; i < forms.length && !formFound; i++){
56 | if (i == formIndex){
57 | dump('submitting form ... ' + i + ' ' + (i == formIndex) + '\n');
58 | if (forms[i].target) forms[i].target = null;
59 | forms[i].submit();
60 | formFound = true;
61 | }
62 | //debug code..
63 | else {
64 | dump('this form is not it... ' + i + ' ' + (i == formIndex) + '\n');
65 | }
66 | }
67 | return formFound;
68 | }
69 | ,
70 | /**
71 | * Begin an individual test.
72 | * @param formPanel currently unused
73 | * @param formIndex index, in the list of forms, of the one being tested
74 | * @param field the field to inject
75 | * @param testValue the input containing the injection
76 | * @param resultsManager evaluates the results of the test
77 | * @param tabWrapper contains the tab to run the test in
78 | * @param tabManager provides information about the target page
79 | */
80 | do_test: function(formPanel, formIndex, field, testData, resultsManager,
81 | tabWrapper, tabManager)
82 | {
83 | var wroteTabData = false;
84 | var self = this;
85 | var formData = null;
86 |
87 | this.formIndex = formIndex;
88 | this.fieldIndex = field.index;
89 | this.field = field;
90 | this.tabWrapper = tabWrapper
91 |
92 |
93 | if (field) {
94 | formData = tabManager.getFormDataForURL(formIndex, field.index,
95 | testData.string);
96 | }
97 | else {
98 | formData = tabManager.getFormDataForURL(formIndex, null, testData.string);
99 | }
100 | this.testData = tabManager.getTabData(formIndex, field.index, testData.string);
101 | dump('\ndoing source test...');
102 | this.do_source_test(formIndex, formIndex, field, testData,
103 | resultsManager, formData, tabManager);
104 |
105 | }
106 | ,
107 | do_source_test:function(formPanel, formIndex, field, testData,
108 | resultsManager, formData, tabManager) {
109 | var streamListener = new StreamListener(this, resultsManager);
110 | resultsManager.addSourceListener(streamListener);
111 |
112 | // the IO service
113 | var ioService = Components.classes['@mozilla.org/network/io-service;1']
114 | .getService(Components.interfaces.nsIIOService);
115 |
116 |
117 | var form = tabManager.tabForms[formIndex];
118 | var formAction = form.action;
119 | var formURL = (form.action.indexOf("?") == -1) ? formAction : formAction.split("?")[0];
120 |
121 | dump('AttackRunner::do_source_test formAction=== '+formAction+'\n');
122 | if (form.method.toLowerCase() != 'post'){
123 | formAction += formAction.indexOf('?') === -1 ? '?' : '&';
124 | formAction += formData;
125 | formURL = formAction;
126 | }
127 |
128 | dump('attackrunner::do_source_test::formAction == ' + formAction + '\n');
129 | dump('attackrunner::do_source_test::formData == ' + formData + '\n');
130 |
131 | var uri = ioService.newURI(formURL, null, null);
132 | Components.utils.reportError("got a " + uri.toString() + " from a " + formURL)
133 |
134 | this.channel = ioService.newChannelFromURI(uri);
135 |
136 |
137 | if (form.method.toLowerCase() == 'post'){
138 | var inputStream = Components.
139 | classes['@mozilla.org/io/string-input-stream;1'].
140 | createInstance(Components.interfaces.nsIStringInputStream);
141 | inputStream.setData(formData, formData.length);
142 | this.channel.QueryInterface(Components.interfaces.nsIUploadChannel).
143 | setUploadStream(inputStream,
144 | 'application/x-www-form-urlencoded', -1);
145 | this.channel.QueryInterface(Components.interfaces.nsIHttpChannel).
146 | requestMethod = 'POST';
147 | }
148 |
149 | streamListener.testData = this.testData;
150 | this.channel.asyncOpen(streamListener, null);
151 | resultsManager.extensionManager.finishedTest();
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/content/ErrorStringContainer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject Me please contact
20 | tools@securitycompass.com
21 | */
22 |
23 | /**
24 | * ErrorStringContainer.js
25 | * @requires PreferenceStringContainer.js
26 | */
27 | function ErrorStringContainer(){
28 | this.init();
29 | }
30 | ErrorStringContainer.prototype = new PreferenceStringContainer();
31 | dump('creating... ErrorStringContainer object\n');
32 | ErrorStringContainer.prototype.init = function (){
33 |
34 | var attackStrings;
35 |
36 | this.prefBranch = this.prefService.getBranch('extensions.sqlime.');
37 | attackStrings = this.prefBranch.getCharPref('errorstrings');
38 | this.strings = sqlime.JSON.fromString(attackStrings);
39 | };
40 |
41 | ErrorStringContainer.prototype.save = function() {
42 | dump('ErrorStringContainer::save this.strings ' +this.strings + '\n');
43 | dump('ErrorStringContainer::save typeof(this.strings) ' +typeof( this.strings )+ '\n');
44 | this.prefBranch.setCharPref('errorstrings', sqlime.JSON.toString(this.strings));
45 | }
46 |
47 |
48 | function getErrorStringContainer(){
49 |
50 | if (typeof(errorStringContainer) === 'undefined' || !errorStringContainer) {
51 | errorStringContainer = new ErrorStringContainer();
52 | }
53 |
54 | return errorStringContainer;
55 | }
56 |
--------------------------------------------------------------------------------
/content/FieldResult.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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(formIndex, fieldIndex){
32 | this.fieldIndex = fieldIndex;
33 | this.formIndex = formIndex;
34 | this.results = new Array();
35 | this.maxValue = 0;
36 | this.maxValueType = 0;
37 | this.state = 0;
38 | }
39 |
40 | /**
41 | * These consts are used to check what kind of rsults does this fieldresult
42 | * have.
43 | */
44 | const fieldresult_has_pass = 0x0001;
45 | const fieldresult_has_warn = 0x0002;
46 | const fieldresult_has_error = 0x0004;
47 |
48 | FieldResult.prototype = {
49 | addResults: function (resultsToAdd) {
50 |
51 | for each(var result in resultsToAdd) {
52 | if (this.maxValueType < result.type){
53 | this.maxValue = result.value;
54 | this.maxValueType = result.type;
55 | }
56 | else if (this.maxValueType === result.type ) {
57 | if (this.maxValue < result.value) {
58 | this.maxValue = result.value;
59 | }
60 | }
61 | this.state = this.state | result.type;
62 | this.results.push(result);
63 | }
64 | }
65 | ,
66 | getLength: function(){
67 | var numTestsRun = 0;
68 | var numPasses = 0;
69 | var numWarnings = 0;
70 | var numFailes = 0;
71 | for each(var r in this.results) {
72 | numTestsRun++;
73 | switch(r.type){
74 | case RESULT_TYPE_ERROR:
75 | numFailes++;
76 | break;
77 | case RESULT_TYPE_WARNING:
78 | numWarnings++;
79 | break;
80 | case RESULT_TYPE_PASS:
81 | numPasses++;
82 | break;
83 | }
84 | }
85 | return [numTestsRun, numFailes, numWarnings, numPasses];
86 | }
87 | ,
88 | getSubmitState: function(){
89 | return this.results[0].testData;
90 | }
91 | ,
92 | sort: function(){
93 | var errors = new Array();
94 | var warnings = new Array();
95 | var passes = new Array();
96 |
97 | for each(var result in this.results) {
98 | switch(result.type){
99 | case RESULT_TYPE_ERROR:
100 | errors.push(result);
101 | break;
102 | case RESULT_TYPE_WARNING:
103 | warnings.push(result);
104 | break;
105 | case RESULT_TYPE_PASS:
106 | passes.push(result);
107 | break;
108 | }
109 | }
110 |
111 | return this.results = errors.concat(warnings, passes);
112 | }
113 | }
--------------------------------------------------------------------------------
/content/PrefObserver.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 | }
43 |
44 |
--------------------------------------------------------------------------------
/content/StreamListener.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject Me please contact
20 | tools@securitycompass.com
21 | */
22 |
23 | /**
24 | * StreamListener
25 | */
26 | function StreamListener(attackRunner, resultsManager) {
27 | this.attackRunner = attackRunner;
28 | this.resultsManager = resultsManager;
29 | this.done = false;
30 | this.data = "";
31 | }
32 |
33 | StreamListener.prototype = {
34 | // nsIStreamListener
35 | onStartRequest: function (aRequest, aContext) {
36 | //do nothing...
37 | }
38 | ,
39 | onDataAvailable: function (aRequest, aContext, aStream, aSourceOffset, aLength) {
40 | var scriptableInputStream =
41 | Components.classes["@mozilla.org/scriptableinputstream;1"]
42 | .createInstance(Components.interfaces.nsIScriptableInputStream);
43 | scriptableInputStream.init(aStream);
44 |
45 | this.data += scriptableInputStream.read(aLength);
46 | }
47 | ,
48 | onStopRequest: function (aRequest, aContext, aStatus) {
49 | if (this.done === false) {
50 | this.done = true;
51 |
52 | dump('\n---- Here is the raw source of the result:----\n')
53 | dump(this.data);
54 | dump('\n--- end of raw source ---');
55 |
56 | this.resultsManager.evaluateSource(this);
57 | }
58 | }
59 | ,
60 | // nsIChannelEventSink
61 | onChannelRedirect: function (aOldChannel, aNewChannel, aFlags) {
62 | },
63 | // nsIInterfaceRequestor
64 | getInterface: function (aIID) {
65 | try {
66 | return this.QueryInterface(aIID);
67 | } catch (e) {
68 | throw Components.results.NS_NOINTERFACE;
69 | }
70 | }
71 | ,
72 | // nsIProgressEventSink (not implementing will cause annoying exceptions)
73 | onProgress : function (aRequest, aContext, aProgress, aProgressMax) {
74 | }
75 | ,
76 | onStatus : function (aRequest, aContext, aStatus, aStatusArg) {
77 | }
78 | ,
79 | // nsIHttpEventSink (not implementing will cause annoying exceptions)
80 | onRedirect : function (aOldChannel, aNewChannel) {
81 | }
82 | ,
83 | // we are faking an XPCOM interface, so we need to implement QI
84 | QueryInterface : function(aIID) {
85 | if (aIID.equals(Components.interfaces.nsISupports) ||
86 | aIID.equals(Components.interfaces.nsIInterfaceRequestor) ||
87 | aIID.equals(Components.interfaces.nsIChannelEventSink) ||
88 | aIID.equals(Components.interfaces.nsIProgressEventSink) ||
89 | aIID.equals(Components.interfaces.nsIHttpEventSink) ||
90 | aIID.equals(Components.interfaces.nsIStreamListener))
91 | {
92 | return this;
93 | }
94 |
95 | throw Components.results.NS_NOINTERFACE;
96 | }
97 | };
98 |
--------------------------------------------------------------------------------
/content/TestManager.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2008 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 | */
54 | runTest: function (testType, fieldsToTest, tabManager) {
55 |
56 | this.testType = testType;
57 |
58 | this.clear();
59 |
60 | this.fieldsToTest = fieldsToTest;
61 |
62 | this.tabManager = tabManager;
63 |
64 | this.runThoroughTest(testType, fieldsToTest);
65 | }
66 | ,
67 | /**
68 | * This is a function that AttackRunner requires its resultsmanager to have
69 | */
70 | addSourceListener: function(sourceListener, attackRunner) {
71 |
72 | }
73 | ,
74 | /**
75 | * called by testRunners to report their results
76 | * @param browser a browser instance with the results
77 | * @param
78 | */
79 | evaluate: function(browser, attackRunner) {
80 |
81 | }
82 | ,
83 | /**
84 | * called by a streamlistener to report the results of a source test
85 | * @param streamListener the streamListener that is reporting the results
86 | */
87 | evaluateSource: function(streamListener) {
88 |
89 | var resultData = streamListener.data;
90 | var testData = streamListener.attackRunner.testData;
91 |
92 | if (resultData.indexOf(testData.string) !== -1) {
93 | var vulnerableField = streamListener.attackRunner.field;
94 | var isVulnerablFieldAlreadyLogged = false;
95 | if (this.vulnerableFields.length > 0) {
96 | for each (var value in this.vulnerableFields) {
97 | var areFormIndexsSame = value.formIndex === vulnerableField.formIndex;
98 | if (areFormIndexsSame) {
99 | var areFieldsSame = value.index === vulnerableField.index;
100 | if (areFieldsSame) {
101 | value.vulnerableChars += testData.string[testData.string.length-1];
102 | isVulnerablFieldAlreadyLogged = true;
103 | break;
104 | }
105 | }
106 | }
107 | }
108 |
109 | if (isVulnerablFieldAlreadyLogged === false) {
110 | streamListener.attackRunner.field.vulnerableChars = testData.string[testData.string.length-1];
111 | this.vulnerableFields.push(streamListener.attackRunner.field);
112 | }
113 |
114 | }
115 |
116 | this.resultsStillExpected--;
117 | }
118 | ,
119 | /**
120 | * runs non-heuristic tests on the fields.
121 | * @param testType with all strings or just the top strings.
122 | */
123 | runThoroughTest: function(testType, vulnerableFields) {
124 |
125 | this.resultsManager = new ResultsManager(this.controller);
126 |
127 | this.resultsManager.addSourceEvaluator(checkSrcForErrorString);
128 | this.resultsManager.addSourceEvaluator(checkForServerResponseCode);
129 |
130 | getTestRunnerContainer().clear();
131 | var testStrings = getAttackStringContainer().getStrings();
132 | var numberOfTests;
133 | if (testType.allTests)
134 | numberOfTests = testStrings.length;
135 | else {
136 | numberOfTests = this.controller.getPreferredNumberOfAttacks();
137 | }
138 |
139 | for each (var field in vulnerableFields) {
140 |
141 | for (var n = 0; n < numberOfTests && testStrings[n]; n++) {
142 |
143 | var testRunner = new AttackRunner();
144 | this.resultsManager.registerAttack(testRunner);
145 |
146 | getTestRunnerContainer().addTestRunner(testRunner, null,
147 | field.formIndex, field, testStrings[n],
148 | this.resultsManager);
149 |
150 | }
151 |
152 | }
153 |
154 | var self = this;
155 |
156 | var testRunnerContainer = getTestRunnerContainer(self);
157 |
158 | if (testRunnerContainer.keepChecking === false) {
159 | testRunnerContainer.keepChecking = true;
160 | }
161 | testRunnerContainer.start(this.tabManager);
162 |
163 | }
164 | ,
165 | /**
166 | * this is called by the testRunnerContainer when all tests are definitely
167 | * complete.
168 | */
169 | doneTesting: function() {
170 | var self = this;
171 | function checkAgain() {
172 | self.doneTesting();
173 | }
174 | if (this.controller) {
175 | if (this.resultsManager.allResultsLogged === false){
176 | dump('\nnot done yet...');
177 | window.setTimeout(checkAgain, 100);
178 | //Components.utils.reportError('results not all logged yet');
179 | return
180 | }
181 | dump('\ndone now.')
182 | getTestRunnerContainer().clearWorkTabs();
183 | this.controller.generatingReport();
184 | this.resultsManager.showResults(this);
185 |
186 | }
187 |
188 | }
189 | ,
190 | /**
191 | * postReport is called after the report is generated
192 | */
193 | postReport: function() {
194 | this.controller.postTest();
195 | }
196 | ,
197 | /**
198 | * clears the object and makes it ready for use for a new set of tests.
199 | */
200 | clear: function() {
201 | this.resultsManager = null;
202 |
203 | this.vulnerableFields.splice(0,this.vulnerableFields.length);
204 |
205 | }
206 | ,
207 | /**
208 | * Called when an AttackRunner cannot test because it is in an error state.
209 | */
210 | cannotRunTests: function() {
211 | getTestRunnerContainer().stop();
212 | getTestRunnerContainer().clearWorkTabs();
213 |
214 | var resultsManager = null;
215 | if (this.resultsManager) {
216 | resultsManager = this.resultsManager;
217 | }
218 | else {
219 | resultsManager = new ResultsManager(this.controller);
220 | }
221 | resultsManager.showResults(this, "There was an error while testing this site. This was likely due to Mozilla bug 420025 which only affects Fx2. We're working on making SQL Inject Me work with FireFox 3. 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.");
222 | this.controller.postTest();
223 |
224 | Components.utils.reportError(
225 | 'The loading of this page in a work tab as not successful: ' +
226 | getMainHTMLDoc().documentURI);
227 | }
228 | }
229 |
230 | /**
231 | * The getInstance method for the TestManager singleton
232 | */
233 | function getTestManager(controller) {
234 | if (typeof(xssme__testmanager__) == 'undefined' ||
235 | !xssme__testmanager__)
236 | {
237 | xssme__testmanager__ = new TestManager();
238 | }
239 | // @todo: there has to be a better way...
240 | if (controller) {
241 | xssme__testmanager__.controller = controller;
242 | }
243 |
244 | return xssme__testmanager__;
245 | }
246 |
247 |
--------------------------------------------------------------------------------
/content/TestRunnerContainer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 | dump("check for more attacks: " + this.testRunners.length);
60 | // Do we have any more tests to run?
61 | if (this.testRunners.length == 0) {
62 | Components.utils.reportError("so done checking? kthxbye");
63 | this.keepChecking = false;
64 | this.testManager.doneTesting();
65 | return;
66 | }
67 |
68 | // Begin the next test in the first available tab and move that tab to the back of the queue.
69 | for (var i = 0; i < this.tabWrappers.length; i++) {
70 | if (!this.tabWrappers[i].inUse) {
71 | this.tabWrappers[i].inUse = true;
72 | this.testRunners.pop().do_test(this.formPanels.pop(),
73 | this.formIndexes.pop(),
74 | this.fields.pop(),
75 | this.testValues.pop(),
76 | this.resultsManagers.pop(),
77 | this.tabWrappers[i],
78 | tabManager);
79 | this.tabWrappers.push(this.tabWrappers.splice(i, 1)[0]);
80 | Components.utils.reportError("Running a test");
81 | break;
82 | }
83 | }
84 |
85 | var self = this;
86 | setTimeout(function() { self.start(tabManager); }, 1);
87 | }
88 | ,
89 | numWorkTabs: 6
90 | ,
91 | getNumWorkTabs: function(){
92 | var prefService = Components.classes['@mozilla.org/preferences-service;1'].
93 | getService(Components.interfaces.nsIPrefService);
94 | var branch = prefService.getBranch('extensions.sqlime.');
95 | if (branch.prefHasUserValue('numtabstouse') ){
96 | return branch.getIntPref('numtabstouse');
97 | }
98 | else {
99 | return this.numWorkTabs;
100 | }
101 | }
102 | ,
103 | clear: function (){
104 | this.testRunners.splice(0, this.testRunners.length);
105 | this.formPanels.splice(0, this.formPanels.length);
106 | this.formIndexes.splice(0, this.formPanels.length);
107 | this.fields.splice(0, this.formPanels.length);
108 | this.testValues.splice(0, this.formPanels.length);
109 | this.resultsManagers.splice(0, this.formPanels.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: null
123 | };
124 | }
125 | }
126 | ,
127 | clearWorkTabs: function () {
128 | //not needed any more.
129 | }
130 | ,
131 | /**
132 | * Stops the running of tests in the TestRunnerContainer.
133 | */
134 | stop: function(){
135 | this.keepChecking = false;
136 | this.clear();
137 | }
138 | };
139 |
140 | /**
141 | * If currentNumTabs is provided, the container is cleared.
142 | */
143 | function getTestRunnerContainer(testManager){
144 |
145 | if (typeof(xssme__testrunnercontainer__) == 'undefined' ||
146 | !xssme__testrunnercontainer__ )
147 | {
148 | xssme__testrunnercontainer__ = new TestRunnerContainer();
149 | }
150 |
151 | if (testManager) {
152 | xssme__testrunnercontainer__.setup(testManager);
153 |
154 | }
155 |
156 | return xssme__testrunnercontainer__;
157 |
158 | }
159 |
--------------------------------------------------------------------------------
/content/about.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
40 |
--------------------------------------------------------------------------------
/content/addAttack.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 |
--------------------------------------------------------------------------------
/content/addError.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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/addError.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/content/attackStringContainer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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.sqlime.');
42 | this.prefDefaultBranch = this.prefService.getDefaultBranch('extensions.sqlime.')
43 | attackStrings = this.prefBranch.getCharPref('attacks');
44 | this.strings = sqlime.JSON.fromString(attackStrings);
45 |
46 |
47 | };
48 | AttackStringContainer.prototype.save = function() {
49 | this.prefBranch.setCharPref('attacks', sqlime.JSON.toString(this.strings));
50 |
51 | }
52 |
53 |
54 | function getAttackStringContainer(){
55 | if (typeof(attackStringContainer) === 'undefined' || !attackStringContainer){
56 | attackStringContainer = new AttackStringContainer();
57 | }
58 | return attackStringContainer;
59 | }
60 |
--------------------------------------------------------------------------------
/content/htmlStringEncoder.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2008 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject Me please contact
20 | tools@securitycompass.com
21 | */
22 |
23 | /**
24 | * HTMLStringEncoder is used to encode strings so that they don't cause
25 | * problems in HTML.
26 | * This object is prefered over the using encodeString() directly as it
27 | * provides a cache so the expensive (O(n)) action of generating encoded
28 | * strings has to only be done once.
29 | * This cache does not check itself to make sure it doesn't grow too big. That's
30 | * up to its user.
31 | * @requires util.js this is a wrapper around the util encodeString function
32 | */
33 | function HTMLStringEncoder(){
34 | /**
35 | * the cache, a hash. All keys should be prefixed with
36 | * HTMLStringEncoder.prefix
37 | */
38 | this.cache = new Object();
39 | }
40 |
41 | HTMLStringEncoder.prototype = {
42 | /**
43 | * prefix is used to prefix all cache keys
44 | */
45 | prefix: "html_"
46 | ,
47 | /**
48 | * returns an encoded version of str. Checks cache first.
49 | * @returns an encoded version of str
50 | */
51 | encodeString: function(str) {
52 | var rv = this.cache[this.prefix + str];
53 | if (rv === undefined ){
54 | rv = this.cache[this.prefix + str] = encodeString(str);
55 | }
56 | return rv;
57 | }
58 | ,
59 | /**
60 | * clears the cache
61 | */
62 | clear: function(){
63 | this.cache = new Object();
64 | }
65 |
66 | }
67 |
68 | function getHTMLStringEncoder() {
69 | if (typeof(__security_compass_html_string_encoder__) === 'undefined') {
70 | __security_compass_html_string_encoder__ = new HTMLStringEncoder;
71 | }
72 | return __security_compass_html_string_encoder__;
73 | }
74 |
--------------------------------------------------------------------------------
/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.toString( GIVEN_JAVASCRIPT_OBJECT );
51 | * var newJavaScriptObject = JSON.fromString( 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.toString
64 |
65 | sqlime.JSON = {
66 | /**
67 | * Converts a JavaScript object into a JSON string.
68 | *
69 | * @param aJSObject is the object to be converted
70 | * @param aKeysToDrop is an optional array of keys which will be
71 | * ignored in all objects during the serialization
72 | * @return the object's JSON representation
73 | *
74 | * Note: aJSObject MUST not contain cyclic references.
75 | */
76 | toString: function JSON_toString(aJSObject, aKeysToDrop) {
77 | // these characters have a special escape notation
78 | const charMap = { "\b": "\\b", "\t": "\\t", "\n": "\\n", "\f": "\\f",
79 | "\r": "\\r", '"': '\\"', "\\": "\\\\" };
80 |
81 | // we use a single string builder for efficiency reasons
82 | var pieces = [];
83 |
84 | // this recursive function walks through all objects and appends their
85 | // JSON representation (in one or several pieces) to the string builder
86 | function append_piece(aObj) {
87 | if (typeof aObj == "boolean") {
88 | pieces.push(aObj ? "true" : "false");
89 | }
90 | else if (typeof aObj == "number" && isFinite(aObj)) {
91 | // there is no representation for infinite numbers or for NaN!
92 | pieces.push(aObj.toString());
93 | }
94 | else if (typeof aObj == "string") {
95 | aObj = aObj.replace(/[\\"\x00-\x1F\u0080-\uFFFF]/g, function($0) {
96 | // use the special escape notation if one exists, otherwise
97 | // produce a general unicode escape sequence
98 | return charMap[$0] ||
99 | "\\u" + ("0000" + $0.charCodeAt(0).toString(16)).slice(-4);
100 | });
101 | pieces.push('"' + aObj + '"')
102 | }
103 | else if (aObj === null) {
104 | pieces.push("null");
105 | }
106 | // if it looks like an array, treat it as such - this is required
107 | // for all arrays from either outside this module or a sandbox
108 | else if (aObj instanceof Array ||
109 | typeof aObj == "object" && "length" in aObj &&
110 | (aObj.length === 0 || aObj[aObj.length - 1] !== undefined)) {
111 | pieces.push("[");
112 | for (var i = 0; i < aObj.length; i++) {
113 | append_piece(aObj[i]);
114 | pieces.push(",");
115 | }
116 | if (pieces[pieces.length - 1] == ",")
117 | pieces.pop(); // drop the trailing colon
118 | pieces.push("]");
119 | }
120 | else if (typeof aObj == "object") {
121 | pieces.push("{");
122 | for (var key in aObj) {
123 | // allow callers to pass objects containing private data which
124 | // they don't want the JSON string to contain (so they don't
125 | // have to manually pre-process the object)
126 | if (aKeysToDrop && aKeysToDrop.indexOf(key) != -1)
127 | continue;
128 |
129 | append_piece(key.toString());
130 | pieces.push(":");
131 | append_piece(aObj[key]);
132 | pieces.push(",");
133 | }
134 | if (pieces[pieces.length - 1] == ",")
135 | pieces.pop(); // drop the trailing colon
136 | pieces.push("}");
137 | }
138 | else {
139 | throw new TypeError("No JSON representation for this object!");
140 | }
141 | }
142 | append_piece(aJSObject);
143 |
144 | return pieces.join("");
145 | },
146 |
147 | /**
148 | * Converts a JSON string into a JavaScript object.
149 | *
150 | * @param aJSONString is the string to be converted
151 | * @return a JavaScript object for the given JSON representation
152 | */
153 | fromString: function JSON_fromString(aJSONString) {
154 | if (!this.isMostlyHarmless(aJSONString))
155 | throw new SyntaxError("No valid JSON string!");
156 |
157 | var s = new Components.utils.Sandbox("about:blank");
158 | return Components.utils.evalInSandbox("(" + aJSONString + ")", s);
159 | },
160 |
161 | /**
162 | * Checks whether the given string contains potentially harmful
163 | * content which might be executed during its evaluation
164 | * (no parser, thus not 100% safe! Best to use a Sandbox for evaluation)
165 | *
166 | * @param aString is the string to be tested
167 | * @return a boolean
168 | */
169 | isMostlyHarmless: function JSON_isMostlyHarmless(aString) {
170 | const maybeHarmful = /[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/;
171 | const jsonStrings = /"(\\.|[^"\\\n\r])*"/g;
172 |
173 | return !maybeHarmful.test(aString.replace(jsonStrings, ""));
174 | }
175 | };
176 |
--------------------------------------------------------------------------------
/content/overlay.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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.sqlime.');
32 | var showContextMenu = true; //default
33 | dump('::checkContextMenu branch.prefHasUserValue(\'showcontextmenu\') == ');
34 | dump(branch.prefHasUserValue('showcontextmenu'));
35 | dump('\n');
36 | if (branch.prefHasUserValue('showcontextmenu')) {
37 | showContextMenu = branch.getBoolPref('showcontextmenu');
38 | }
39 |
40 | var contextMenu = document.getElementById('sqlimecontextmenu');
41 | dump('::checkContextMenu contextMenu == ' + contextMenu + '\n');
42 | dump('::checkContextMenu showcontextmenu == ');
43 | dump(showContextMenu +'\n');
44 | contextMenu.setAttribute('collapsed', !showContextMenu);
45 | }
46 |
47 | function XssOverlay() {}
48 |
49 | XssOverlay.prototype = {
50 | contextMenuObserver: null
51 | ,
52 | onLoad: function() {
53 |
54 | var prefService = Components.classes['@mozilla.org/preferences-service;1'].
55 | getService(Components.interfaces.nsIPrefService);
56 |
57 | var branch = prefService.getBranch('');
58 |
59 | var observableBranch = branch.
60 | QueryInterface(Components.interfaces.nsIPrefBranch2);
61 |
62 | this.contextMenuObserver = new Xss_PrefObserver(checkContextMenu);
63 |
64 | checkContextMenu();
65 |
66 | dump('mainwindow::onLoad contextMenuObserver ==' + this.contextMenuObserver +'\n');
67 |
68 |
69 | observableBranch.addObserver('extensions.sqlime.showcontextmenu', this.contextMenuObserver, false);
70 | }
71 | ,
72 | onUnload: function() {
73 | var prefService = Components.classes['@mozilla.org/preferences-service;1'].
74 | getService(Components.interfaces.nsIPrefService);
75 |
76 | var branch = prefService.getBranch('');
77 |
78 | var observableBranch = branch.
79 | QueryInterface(Components.interfaces.nsIPrefBranch2);
80 |
81 | observableBranch.removeObserver('extensions.sqlime.showcontextmenu', this.contextMenuObserver)
82 | }
83 | };
84 |
85 | var xssOverlay = new XssOverlay();
86 |
87 | window.addEventListener('load', xssOverlay.onLoad, false);
88 | window.addEventListener('unload', xssOverlay.onUnload, false);
89 |
--------------------------------------------------------------------------------
/content/overlay.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
26 |
27 |
28 |
29 |
30 |
31 |
45 |
46 |
47 |
54 |
55 |
56 |
57 |
58 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/content/preferenceStringContainer.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject Me please contact
20 | tools@securitycompass.com
21 | */
22 |
23 | /**
24 | * preferenceStringContainer.js
25 | * requires JSON.
26 | */
27 |
28 |
29 | /**
30 | * the PreferenceStringContainer object is a base class for any kind of object
31 | * which has deal with an array of strings held in preferences.
32 | * (e.g. AttackStringContainer, ResultStringContainer).
33 | */
34 | function PreferenceStringContainer() {
35 | this.strings = Array();
36 | this.prefBranch = null;
37 | this.prefService = Components.classes['@mozilla.org/preferences-service;1'].
38 | getService(Components.interfaces.nsIPrefService);
39 | }
40 | dump('creating... preferenceStringContainer object\n');
41 | PreferenceStringContainer.prototype = {
42 | /**
43 | * init is responsible for reading and loading a preference into
44 | */
45 | init: function() {
46 |
47 | }
48 | ,
49 | getStrings: function(force){
50 | if (force === true){
51 | this.init();
52 | }
53 | return this.strings;
54 | }
55 | ,
56 | addString: function(string, signature) {
57 | dump('PreferenceStringContainer::addString: ' + string+ ' ' + signature + '\n');
58 | if (!string) {
59 | return false;
60 | }
61 |
62 | var preference = new Object();
63 | preference.string = string;
64 | preference.sig = signature;
65 | if (this.strings.every(checkUnique, preference)){
66 | this.strings.push(preference);
67 | dump('PreferenceStringContainer::addString preference == ' +
68 | preference + '\n');
69 | this.save();
70 | return true;
71 | }
72 | else {
73 | return false;
74 | }
75 | }
76 | ,
77 | /**
78 | * save is responsible for taking this.strings and saving it into
79 | * preferences.
80 | */
81 | save: function() {
82 | }
83 | ,
84 | swap: function (index1, index2){
85 | if (typeof(this.strings[index1]) === "undefined" ||
86 | this.strings[index1] === null ||
87 | typeof(this.strings[index2]) === "undefined" ||
88 | this.strings[index2] === null)
89 | {
90 | return false;
91 | }
92 |
93 | [this.strings[index2], this.strings[index1]] =
94 | [this.strings[index1], this.strings[index2]]
95 |
96 | this.save();
97 |
98 | return true;
99 | }
100 | };
101 |
102 | /**
103 | * used by addString to ensure that a given (in this.string) is not in the
104 | * container
105 | */
106 | function checkUnique(element, index, array){
107 | dump("checkunique: " + (this.string) + " " + (element.string) + " \n");
108 | dump("checkunique: " + (this.string != element.string) + " \n");
109 | return this.string != element.string;
110 | }
111 |
--------------------------------------------------------------------------------
/content/preferences.fx2.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject Me please contact
20 | tools@securitycompass.com
21 | */
22 |
23 | /* prefereneces.js
24 | * @requires JSON
25 | * @requires AttackStringContainer
26 | * @requires util.js
27 | */
28 |
29 | function PreferencesController() {
30 | this.init();
31 | }
32 |
33 | PreferencesController.prototype = {
34 | init: function(){
35 |
36 | var attacks = getAttackStringContainer().getStrings();
37 | var errorStrings = getErrorStringContainer().getStrings();
38 |
39 | if (attacks.length) {
40 | this.makeUI(attacks, null, 'existingSQLIstrings');
41 | }
42 | else {
43 | var label = document.getElementById('noattackslbl');
44 | label.style.visibility = 'visible';
45 | }
46 |
47 | if (errorStrings.length){
48 | this.makeUI(errorStrings, null, 'existingSQLIerrStrings');
49 | }
50 | else {
51 | var label = document.getElementById('noerrorslbl');
52 | label.style.visibility = 'visible';
53 | }
54 | }
55 | ,
56 | makeUI: function(attacks, aWindow, listboxID){
57 | var theWindow
58 | if (typeof(aWindow) === 'undefined' || aWindow === null || !aWindow){
59 | theWindow = window;
60 | }
61 | else {
62 | theWindow = aWindow;
63 | }
64 |
65 | var listbox = theWindow.document.getElementById(listboxID);
66 |
67 | while(listbox.itemCount > 0){
68 | listbox.removeItemAt(0);
69 | }
70 |
71 | for(var i = 0; i < attacks.length; i++){
72 | listbox.appendItem(attacks[i].string, i);
73 | }
74 | }
75 | ,
76 | removeError: function(){
77 | this.removeItem(getErrorStringContainer(), 'existingSQLIerrStrings');
78 | }
79 | ,
80 | removeAttack: function(){
81 | this.removeItem(getAttackStringContainer(), 'existingSQLIstrings');
82 | }
83 | ,
84 | removeItem: function(container, listboxID){
85 | var listbox = document.getElementById(listboxID);
86 | var selectedAttacks = listbox.selectedItems;
87 | var strings = container.getStrings();
88 | var n = 0;
89 | for (var i = 0; i < selectedAttacks.length; i++){
90 | strings[selectedAttacks[i].value] = null;
91 | }
92 | while (n < strings.length){
93 | if (strings[n] === null){
94 | strings.splice(n, 1);
95 | }
96 | else{
97 | n++; //only incrememnt if attacks[n]!==null. Otherwise we'll
98 | // strings which are adjacent.
99 | }
100 | }
101 | container.save();
102 | this.makeUI(container.getStrings(), window, listboxID);
103 | }
104 | ,
105 | exportAttacks: function(){
106 | var exportDoc = document.implementation.createDocument("", "", null);
107 | var root = exportDoc.createElement('exportedattacks');
108 | var xmlAttacks = exportDoc.createElement('attacks');
109 | getAttackStringContainer();
110 | var attacks = attackStringContainer.getStrings();
111 | for each (var attack in attacks){
112 | var xmlAttack = exportDoc.createElement('attack');
113 | var xmlString = exportDoc.createElement('attackString');
114 | var xmlSig = exportDoc.createElement('signature');
115 | var txtString = exportDoc.createCDATASection(
116 | encodeXML(attack.string));
117 | var txtSig = exportDoc.createTextNode(attack.sig);
118 | xmlString.appendChild(txtString);
119 | xmlSig.appendChild(txtSig);
120 | xmlAttack.appendChild(xmlString);
121 | xmlAttack.appendChild(xmlSig);
122 | xmlAttacks.appendChild(xmlAttack);
123 | }
124 | root.appendChild(xmlAttacks);
125 | var xmlErrStrings = exportDoc.createElement('results');
126 | var errorStrings = getErrorStringContainer().getStrings();
127 | for each (var errStr in errorStrings){
128 | var xmlError = exportDoc.createElement('resultString');
129 | var txtString = exportDoc.
130 | createCDATASection(encodeXML(errStr.string));
131 | xmlError.appendChild(txtString);
132 | xmlErrStrings.appendChild(xmlError);
133 | }
134 | root.appendChild(xmlErrStrings);
135 | exportDoc.appendChild(root);
136 | var serializer = new XMLSerializer();
137 | var xml = serializer.serializeToString(exportDoc);
138 | dump(xml);dump('\n');
139 |
140 | var nsIFilePicker = Components.interfaces.nsIFilePicker;
141 | var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
142 | picker.init(window, "Select File To Export To", nsIFilePicker.modeSave);
143 | picker.appendFilter('XML Files', '*.xml');
144 | picker.appendFilter('All Files', '*');
145 | picker.defaultExtension - '.xml';
146 | var resultOfPicker = picker.show();
147 | if (resultOfPicker == nsIFilePicker.returnCancel){
148 | return false;
149 | }
150 | var exportFile = picker.file;
151 |
152 | var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
153 | .createInstance(Components.interfaces.nsIFileOutputStream);
154 |
155 | foStream.init(exportFile, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate
156 | foStream.write(xml, xml.length);
157 | foStream.close();
158 | return true;
159 |
160 | }
161 | ,
162 | importAttacks: function(){
163 | var nsIFilePicker = Components.interfaces.nsIFilePicker;
164 | var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
165 | picker.init(window, "Select File To Import From", nsIFilePicker.modeOpen);
166 | picker.appendFilter('XML Files', '*.xml');
167 | picker.appendFilter('All Files', '*');
168 | var resultOfPicker = picker.show();
169 | if (resultOfPicker == nsIFilePicker.returnCancel){
170 | return false;
171 | }
172 | var importFile = picker.file;
173 |
174 | var fileContents = FileIO.read(importFile);
175 | var domParser = new DOMParser();
176 | var dom = domParser.parseFromString(fileContents, "text/xml");
177 |
178 | if(dom.documentElement.nodeName == "parsererror"){
179 | alert("error while parsing document, ensure that the document is complete and uncorrupted.");
180 | return false;
181 | }
182 |
183 | var attacksTags = dom.getElementsByTagName("attacks");
184 | if (attacksTags.length != 1){
185 | alert("couldn't find attacks tag. Error while processing document.");
186 | return false;
187 | }
188 |
189 | var attacksTag = attacksTags[0];
190 | var attackTags = new Array();
191 | var attackStringContainer = getAttackStringContainer();
192 |
193 | for (var i = 0; i < attacksTag.childNodes.length; i++){
194 | dump("::importAttacks()... (" + attacksTag + "== attacksTag) attacksTag[" + i + "] == " + attacksTag.childNodes[i] + "\n");
195 | if ("attack" === attacksTag.childNodes[i].nodeName){
196 | attackTags.push(attacksTag.childNodes[i]);
197 | }
198 | }
199 | if (attackTags.length){
200 | for each(var attackTag in attackTags){
201 | var stringTag = null;
202 | var sigTag = null;
203 | for each(var tag in attackTag.childNodes){
204 | dump("::importAttacks()... (looking for attackString and sig) " + tag.nodeName + "\n");
205 | if (tag.nodeName === "attackString"){
206 | dump("got attackString\n");
207 | stringTag = tag;
208 | }
209 | else if (tag.nodeName === "signature"){
210 | dump("got sigString\n");
211 | sigTag = tag;
212 | }
213 | }
214 | if (stringTag === null || sigTag === null){
215 | alert("Couldn't import attack. Couldn't find stringAttack or signature tags. Error while processing the document. ");
216 | this.makeUI(attackStringContainer.getStrings(), window); // just in case.
217 | return false;
218 | }
219 | else{
220 | if (stringTag.childNodes.length !== 0)
221 | {
222 |
223 | attackStringContainer.addString(
224 | decodeXML(stringTag.textContent),
225 | sigTag.firstChild.nodeValue);
226 | }
227 | else {
228 | alert("Couldn't import attack. attackString is empty. Error while processing the document. ");
229 | this.makeUI(attackStringContainer.getStrings(), window); // just in case.
230 | return false;
231 | }
232 | }
233 | }
234 | }
235 | else {
236 | alert("Couldn't find any attacks. No Attacks imported.");
237 | return false;
238 | }
239 |
240 | var errStrings = dom.getElementsByTagName('results');
241 | if (errStrings.length === 1) {
242 | var errStrings = errStrings[0];
243 | var errTags = new Array();
244 | for each(var errTag in errStrings.childNodes){
245 | if (errTag.nodeName == 'resultString') {
246 | errTags.push(errTag);
247 | }
248 | }
249 |
250 | if (errTags.length) {
251 | var errStringContainer = getErrorStringContainer();
252 | for each(var errTag in errTags) {
253 | dump('preference.js::importAttacks errTag.textContent == ' + errTag.textContent + '\n');
254 | errStringContainer.addString(decodeXML(errTag.textContent), null);
255 | }
256 | }
257 | }
258 | this.makeUI(getAttackStringContainer().getStrings(), window, 'existingSQLIstrings');
259 | this.makeUI(getErrorStringContainer().getStrings(), window, 'existingSQLIerrStrings');
260 | return true;
261 | }
262 | ,
263 | moveAttackStringUp: function(){
264 | this.moveItemUp(getAttackStringContainer(), 'existingSQLIstrings');
265 | }
266 | ,
267 | moveErrorStringUp: function(){
268 | this.moveItemUp(getErrorStringContainer(), 'existingSQLIerrStrings');
269 | }
270 | ,
271 | moveItemUp: function(container, listboxID){
272 | var listbox = document.getElementById(listboxID);
273 | var selectedIndex = listbox.selectedIndex;
274 | var selectedItemValue = listbox.selectedItem.value
275 | var selectedItemLabel = listbox.selectedItem.label;
276 | if (listbox.selectedItem.previousSibling == null) {
277 | return false;
278 | }
279 | var newValue = listbox.selectedItem.previousSibling.value;
280 | if (listbox.selectedItems.length != 1){
281 | alert("sorry, only one item can be moved at a time");
282 | return false;
283 | }
284 |
285 | container.swap(listbox.selectedItem.value,
286 | listbox.selectedItem.previousSibling.value);
287 | container.save();
288 |
289 | listbox.ensureIndexIsVisible(selectedIndex - 1);
290 |
291 | listbox.selectedItem.previousSibling.value = selectedItemValue
292 |
293 | listbox.removeItemAt(selectedIndex)
294 | listbox.insertItemAt(selectedIndex-1, selectedItemLabel, newValue)
295 |
296 | listbox.selectedIndex = selectedIndex - 1;
297 | return true;
298 |
299 | }
300 | ,
301 | moveAttackStringDown: function(){
302 | this.moveItemDown(getAttackStringContainer(), 'existingSQLIstrings');
303 | }
304 | ,
305 | moveErrorStringDown: function(){
306 | this.moveItemDown(getErrorStringContainer(), 'existingSQLIerrStrings');
307 | }
308 | ,
309 | moveItemDown: function(container, listboxID){
310 | var listbox = document.getElementById(listboxID);
311 | var selectedIndex = listbox.selectedIndex;
312 | var selectedItem = listbox.selectedItem;
313 | if (selectedIndex + 1 >= listbox.getRowCount()) {
314 | return true;
315 | }
316 | var selectedItemValue = listbox.selectedItem.value
317 | var selectedItemLabel = listbox.selectedItem.label
318 | if (listbox.selectedItem.nextSibling == null) {
319 | return false;
320 | }
321 | var newValue = listbox.selectedItem.nextSibling.value;
322 | if (listbox.selectedItems.length != 1){
323 | alert("sorry, only one item can be moved at a time");
324 | return false;
325 | }
326 |
327 | container.swap(listbox.selectedItem.value, listbox.selectedItem.nextSibling.value);
328 | container.save();
329 |
330 | listbox.selectedItem.nextSibling.value = selectedItemValue
331 |
332 | listbox.removeItemAt(selectedIndex)
333 | if (selectedIndex + 1 >= listbox.getRowCount()) {
334 |
335 | listbox.appendChild(selectedItem)
336 | listbox.selectedIndex = selectedIndex = listbox.getRowCount()-1;
337 |
338 | }
339 | else {
340 | listbox.insertItemAt(selectedIndex+1, selectedItemLabel, newValue)
341 | listbox.selectedIndex = ++selectedIndex ;
342 | }
343 |
344 | listbox.ensureIndexIsVisible(selectedIndex );
345 |
346 | return true;
347 | }
348 | };
349 |
350 |
--------------------------------------------------------------------------------
/content/preferences.fx3.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject Me please contact
20 | tools@securitycompass.com
21 | */
22 |
23 | /* prefereneces.js
24 | * @requires JSON
25 | * @requires AttackStringContainer
26 | * @requires util.js
27 | */
28 |
29 | function PreferencesController() {
30 | this.init();
31 | }
32 |
33 | PreferencesController.prototype = {
34 | init: function(){
35 |
36 | var attacks = getAttackStringContainer().getStrings();
37 | var errorStrings = getErrorStringContainer().getStrings();
38 |
39 | if (attacks.length) {
40 | this.makeUI(attacks, null, 'existingSQLIstrings');
41 | }
42 | else {
43 | var label = document.getElementById('noattackslbl');
44 | label.style.visibility = 'visible';
45 | }
46 |
47 | if (errorStrings.length){
48 | this.makeUI(errorStrings, null, 'existingSQLIerrStrings');
49 | }
50 | else {
51 | var label = document.getElementById('noerrorslbl');
52 | label.style.visibility = 'visible';
53 | }
54 | }
55 | ,
56 | makeUI: function(attacks, aWindow, listboxID){
57 | var theWindow
58 | if (typeof(aWindow) === 'undefined' || aWindow === null || !aWindow){
59 | theWindow = window;
60 | }
61 | else {
62 | theWindow = aWindow;
63 | }
64 |
65 | var listbox = theWindow.document.getElementById(listboxID);
66 |
67 | while(listbox.itemCount > 0){
68 | listbox.removeItemAt(0);
69 | }
70 |
71 | for(var i = 0; i < attacks.length; i++){
72 | listbox.insertItemAt(i, attacks[i].string, i);
73 | }
74 | }
75 | ,
76 | removeError: function(){
77 | this.removeItem(getErrorStringContainer(), 'existingSQLIerrStrings');
78 | }
79 | ,
80 | removeAttack: function(){
81 | this.removeItem(getAttackStringContainer(), 'existingSQLIstrings');
82 | }
83 | ,
84 | removeItem: function(container, listboxID){
85 | var listbox = document.getElementById(listboxID);
86 | var selectedAttacks = listbox.selectedItems;
87 | var strings = container.getStrings();
88 | var n = 0;
89 | for (var i = 0; i < selectedAttacks.length; i++){
90 | strings[selectedAttacks[i].value] = null;
91 | }
92 | while (n < strings.length){
93 | if (strings[n] === null){
94 | strings.splice(n, 1);
95 | }
96 | else{
97 | n++; //only incrememnt if attacks[n]!==null. Otherwise we'll
98 | // strings which are adjacent.
99 | }
100 | }
101 | container.save();
102 | this.makeUI(container.getStrings(), window, listboxID);
103 | }
104 | ,
105 | exportAttacks: function(){
106 | var exportDoc = document.implementation.createDocument("", "", null);
107 | var root = exportDoc.createElement('exportedattacks');
108 | var xmlAttacks = exportDoc.createElement('attacks');
109 | getAttackStringContainer();
110 | var attacks = attackStringContainer.getStrings();
111 | for each (var attack in attacks){
112 | var xmlAttack = exportDoc.createElement('attack');
113 | var xmlString = exportDoc.createElement('attackString');
114 | var xmlSig = exportDoc.createElement('signature');
115 | var txtString = exportDoc.createCDATASection(
116 | encodeXML(attack.string));
117 | var txtSig = exportDoc.createTextNode(attack.sig);
118 | xmlString.appendChild(txtString);
119 | xmlSig.appendChild(txtSig);
120 | xmlAttack.appendChild(xmlString);
121 | xmlAttack.appendChild(xmlSig);
122 | xmlAttacks.appendChild(xmlAttack);
123 | }
124 | root.appendChild(xmlAttacks);
125 | var xmlErrStrings = exportDoc.createElement('results');
126 | var errorStrings = getErrorStringContainer().getStrings();
127 | for each (var errStr in errorStrings){
128 | var xmlError = exportDoc.createElement('resultString');
129 | var txtString = exportDoc.
130 | createCDATASection(encodeXML(errStr.string));
131 | xmlError.appendChild(txtString);
132 | xmlErrStrings.appendChild(xmlError);
133 | }
134 | root.appendChild(xmlErrStrings);
135 | exportDoc.appendChild(root);
136 | var serializer = new XMLSerializer();
137 | var xml = serializer.serializeToString(exportDoc);
138 | dump(xml);dump('\n');
139 |
140 | var nsIFilePicker = Components.interfaces.nsIFilePicker;
141 | var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
142 | picker.init(window, "Select File To Export To", nsIFilePicker.modeSave);
143 | picker.appendFilter('XML Files', '*.xml');
144 | picker.appendFilter('All Files', '*');
145 | picker.defaultExtension - '.xml';
146 | var resultOfPicker = picker.show();
147 | if (resultOfPicker == nsIFilePicker.returnCancel){
148 | return false;
149 | }
150 | var exportFile = picker.file;
151 |
152 | var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
153 | .createInstance(Components.interfaces.nsIFileOutputStream);
154 |
155 | foStream.init(exportFile, 0x02 | 0x08 | 0x20, 0666, 0); // write, create, truncate
156 | foStream.write(xml, xml.length);
157 | foStream.close();
158 | return true;
159 |
160 | }
161 | ,
162 | importAttacks: function(){
163 | var nsIFilePicker = Components.interfaces.nsIFilePicker;
164 | var picker = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
165 | picker.init(window, "Select File To Import From", nsIFilePicker.modeOpen);
166 | picker.appendFilter('XML Files', '*.xml');
167 | picker.appendFilter('All Files', '*');
168 | var resultOfPicker = picker.show();
169 | if (resultOfPicker == nsIFilePicker.returnCancel){
170 | return false;
171 | }
172 | var importFile = picker.file;
173 |
174 | var fileContents = FileIO.read(importFile);
175 | var domParser = new DOMParser();
176 | var dom = domParser.parseFromString(fileContents, "text/xml");
177 |
178 | if(dom.documentElement.nodeName == "parsererror"){
179 | alert("error while parsing document, ensure that the document is complete and uncorrupted.");
180 | return false;
181 | }
182 |
183 | var attacksTags = dom.getElementsByTagName("attacks");
184 | if (attacksTags.length != 1){
185 | alert("couldn't find attacks tag. Error while processing document.");
186 | return false;
187 | }
188 |
189 | var attacksTag = attacksTags[0];
190 | var attackTags = new Array();
191 | var attackStringContainer = getAttackStringContainer();
192 |
193 | for (var i = 0; i < attacksTag.childNodes.length; i++){
194 | dump("::importAttacks()... (" + attacksTag + "== attacksTag) attacksTag[" + i + "] == " + attacksTag.childNodes[i] + "\n");
195 | if ("attack" === attacksTag.childNodes[i].nodeName){
196 | attackTags.push(attacksTag.childNodes[i]);
197 | }
198 | }
199 | if (attackTags.length){
200 | for each(var attackTag in attackTags){
201 | var stringTag = null;
202 | var sigTag = null;
203 | for each(var tag in attackTag.childNodes){
204 | dump("::importAttacks()... (looking for attackString and sig) " + tag.nodeName + "\n");
205 | if (tag.nodeName === "attackString"){
206 | dump("got attackString\n");
207 | stringTag = tag;
208 | }
209 | else if (tag.nodeName === "signature"){
210 | dump("got sigString\n");
211 | sigTag = tag;
212 | }
213 | }
214 | if (stringTag === null || sigTag === null){
215 | alert("Couldn't import attack. Couldn't find stringAttack or signature tags. Error while processing the document. ");
216 | this.makeUI(attackStringContainer.getStrings(), window); // just in case.
217 | return false;
218 | }
219 | else{
220 | if (stringTag.childNodes.length !== 0)
221 | {
222 |
223 | attackStringContainer.addString(
224 | decodeXML(stringTag.textContent),
225 | sigTag.firstChild.nodeValue);
226 | }
227 | else {
228 | alert("Couldn't import attack. attackString is empty. Error while processing the document. ");
229 | this.makeUI(attackStringContainer.getStrings(), window); // just in case.
230 | return false;
231 | }
232 | }
233 | }
234 | }
235 | else {
236 | alert("Couldn't find any attacks. No Attacks imported.");
237 | return false;
238 | }
239 |
240 | var errStrings = dom.getElementsByTagName('results');
241 | if (errStrings.length === 1) {
242 | var errStrings = errStrings[0];
243 | var errTags = new Array();
244 | for each(var errTag in errStrings.childNodes){
245 | if (errTag.nodeName == 'resultString') {
246 | errTags.push(errTag);
247 | }
248 | }
249 |
250 | if (errTags.length) {
251 | var errStringContainer = getErrorStringContainer();
252 | for each(var errTag in errTags) {
253 | dump('preference.js::importAttacks errTag.textContent == ' + errTag.textContent + '\n');
254 | errStringContainer.addString(decodeXML(errTag.textContent), null);
255 | }
256 | }
257 | }
258 | this.makeUI(getAttackStringContainer().getStrings(), window, 'existingSQLIstrings');
259 | this.makeUI(getErrorStringContainer().getStrings(), window, 'existingSQLIerrStrings');
260 | return true;
261 | }
262 | ,
263 | moveAttackStringUp: function(){
264 | this.moveItemUp(getAttackStringContainer(), 'existingSQLIstrings');
265 | }
266 | ,
267 | moveErrorStringUp: function(){
268 | this.moveItemUp(getErrorStringContainer(), 'existingSQLIerrStrings');
269 | }
270 | ,
271 | moveItemUp: function(container, listboxID){
272 | var listbox = document.getElementById(listboxID);
273 | var selectedIndex = listbox.selectedIndex;
274 | var selectedItemValue = listbox.selectedItem.value
275 | var selectedItemLabel = listbox.selectedItem.label;
276 | if (listbox.selectedItem.previousSibling == null) {
277 | return false;
278 | }
279 | var newValue = listbox.selectedItem.previousSibling.value;
280 | if (listbox.selectedItems.length != 1){
281 | alert("sorry, only one item can be moved at a time");
282 | return false;
283 | }
284 |
285 | container.swap(listbox.selectedItem.value,
286 | listbox.selectedItem.previousSibling.value);
287 | container.save();
288 |
289 | listbox.ensureIndexIsVisible(selectedIndex - 1);
290 |
291 | listbox.selectedItem.previousSibling.value = selectedItemValue
292 |
293 | listbox.removeItemAt(selectedIndex)
294 | listbox.insertItemAt(selectedIndex-1, selectedItemLabel, newValue)
295 |
296 | listbox.selectedIndex = selectedIndex - 1;
297 | return true;
298 |
299 | }
300 | ,
301 | moveAttackStringDown: function(){
302 | this.moveItemDown(getAttackStringContainer(), 'existingSQLIstrings');
303 | }
304 | ,
305 | moveErrorStringDown: function(){
306 | this.moveItemDown(getErrorStringContainer(), 'existingSQLIerrStrings');
307 | }
308 | ,
309 | moveItemDown: function(container, listboxID){
310 | var listbox = document.getElementById(listboxID);
311 | var selectedIndex = listbox.selectedIndex;
312 | var selectedItem = listbox.selectedItem;
313 |
314 | if (selectedIndex + 1 >= listbox.getRowCount()) {
315 | return true;
316 | }
317 |
318 | var selectedItemValue = listbox.selectedItem.value
319 | var selectedItemLabel = listbox.selectedItem.label;
320 | var newValue = listbox.selectedItem.nextSibling.value;
321 | if (listbox.selectedItems.length != 1){
322 | alert("sorry, only one item can be moved at a time");
323 | return false;
324 | }
325 |
326 | container.swap(listbox.selectedItem.value,
327 | listbox.selectedItem.nextSibling.value);
328 | container.save();
329 |
330 | listbox.ensureIndexIsVisible(selectedIndex + 1);
331 |
332 | listbox.selectedItem.nextSibling.value = selectedItemValue
333 |
334 | if (selectedIndex + 2 >= listbox.getRowCount()) {
335 |
336 | listbox.selectedItem = listbox.getItemAtIndex(listbox.getRowCount() -1)
337 | this.moveItemUp(container, listboxID)
338 | listbox.selectedIndex = listbox.getRowCount() -1
339 |
340 |
341 | }
342 | else {
343 | listbox.removeItemAt(selectedIndex)
344 | listbox.insertItemAt(selectedIndex+1, selectedItemLabel, newValue)
345 | listbox.selectedIndex = ++selectedIndex ;
346 | }
347 |
348 | listbox.ensureIndexIsVisible(selectedIndex );
349 |
350 | return true;
351 | }
352 | };
353 |
354 |
--------------------------------------------------------------------------------
/content/preferences.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
29 |
30 |
34 |
38 |
42 |
46 |
50 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
64 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 | IMPORTANT:Please close then open the sidebar (or refresh the current webpage) to make sure that all new attack strings are reloaded.
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | Result Strings are strings that are found in pages where the result is submitted and signify that the test has FAILED.
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
119 |
120 |
--------------------------------------------------------------------------------
/content/progressListener.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 sqlimeProgressListener(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 | sqlimeProgressListener.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 |
SQL Inject Me Test Results for http://domain.tld/url.ext
50 |
Here are the results for the 9999 tests run:
51 |
52 |
53 |
Passed:
54 |
55 |
45%
56 |
57 |
58 |
59 |
Warning:
60 |
61 |
25%
62 |
63 |
64 |
Failed:
65 |
66 |
30%
67 |
68 |
69 |
70 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/content/sidebarBuilder.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2008 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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.sqlime.');
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.pop();
49 |
50 | dump('\nAdding '+child+'('+ child.nodeName+') -> '+parent + '('+parent.nodeName+')');
51 |
52 | parent.appendChild(child);
53 |
54 | if (postFunc) postFunc(parent, child);
55 |
56 | setTimeout(self.start, self.time, self);
57 |
58 | }
59 |
60 |
61 | }
62 | ,
63 | add: function(parent, child, postFunc) {
64 | this.toBeAdded.push([parent,child, postFunc]);
65 | }
66 | ,
67 | stop: function() {
68 | this.isRunning = false;
69 | this.toBeAdded = null;
70 | }
71 | }
72 |
73 | function getSidebarBuilder() {
74 | if (typeof(__xssme_sidebar_builder__) == 'undefined' ||
75 | !__xssme_sidebar_builder__)
76 | {
77 | __xssme_sidebar_builder__ = new SidebarBuilder();
78 | }
79 | return __xssme_sidebar_builder__;
80 | }
81 |
--------------------------------------------------------------------------------
/content/sqlime.js:
--------------------------------------------------------------------------------
1 | sqlime = {}
--------------------------------------------------------------------------------
/content/sqlime_sidebar.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject Me please contact
20 | tools@securitycompass.com
21 | */
22 |
23 | /**
24 | * Sidebar.js
25 | * @requires AttackRunner.js
26 | */
27 |
28 | /**
29 | * These constants are used as ids for the types of test we can run.
30 | */
31 | const TestType_AllTestsForForm = 1;
32 | const TestType_PrefNumTestsForForm = 2;
33 | const TestType_OneTestForForm = 3;
34 | const TestType_AllTestsForAllForms = 4;
35 |
36 | const STOP_ALL = Components.interfaces.nsIWebNavigation.STOP_ALL;
37 |
38 | const __sqli_me_prefs_to_disable = [
39 | {"name": "security.warn_entering_secure", "type":"bool", "ourValue": false},
40 | {"name": "security.warn_entering_weak", "type":"bool", "ourValue": false},
41 | {"name": "security.warn_leaving_secure", "type":"bool", "ourValue": false},
42 | {"name": "security.warn_submit_insecure", "type":"bool", "ourValue": false},
43 | {"name": "security.warn_viewing_mixed", "type":"bool", "ourValue": false},
44 | {"name": "dom.max_chrome_script_run_time", "type":"int", "ourValue": 0},
45 | {"name": "signon.autofillForms", "type":"bool", "ourValue":false}, /* to remove autofilling forms in Fx3 */
46 | {"name": "signon.prefillForms", "type":"bool", "ourValue":false}, /* same as above but for Fx2 */
47 | {"name": "signon.rememberSignons", "type":"bool", "ourValue":false},
48 | {"name": "accessibility.typeaheadfind.enablesound", "type":"bool", "ourValue":false}
49 | ];
50 |
51 | /**
52 | * get a reference to the main firefox window
53 | */
54 | function getMainWindow(){
55 | var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
56 | .getInterface(Components.interfaces.nsIWebNavigation)
57 | .QueryInterface(Components.interfaces.nsIDocShellTreeItem)
58 | .rootTreeItem
59 | .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
60 | .getInterface(Components.interfaces.nsIDOMWindow);
61 | return mainWindow;
62 | }
63 |
64 | /**
65 | * get a reference to the document object of the page that is being viewed now
66 | */
67 | function getMainHTMLDoc(){
68 | var mainWindow = getMainWindow();
69 | var elTabBrowser = mainWindow.document.getElementById('content');
70 | var currentDocument = elTabBrowser.contentDocument;
71 | return currentDocument;
72 | }
73 |
74 |
75 | function getMainHTMLWindow() {
76 | var mainWindow = getMainWindow();
77 | var elTabBrowser = mainWindow.document.getElementById('content');
78 | var win = elTabBrowser.contentWindow;
79 | return win;
80 | }
81 |
82 | function extension(){
83 | //do nothing right now...
84 | this.plistener = null;
85 | this.warningDialog = null;
86 | this.typeAheadSound = true; //default for
87 | this.prefs = new Array();
88 | }
89 |
90 | extension.prototype = {
91 | getTestType: function(event){
92 | var tabbox = document.getElementById('sidebarformtabbox');
93 | var rv = new Object();
94 | var buttonClicked = event.explicitOriginalTarget;
95 |
96 | if (buttonClicked.className && buttonClicked.className ===
97 | 'run_form_test')
98 | {
99 |
100 | rv.singleFormTest = true;
101 |
102 | if (tabbox.selectedPanel == null) {
103 | tabbox.selectedIndex = 0
104 | }
105 |
106 | if ( tabbox.selectedPanel.
107 | getElementsByAttribute('class', 'TestType').item(0).
108 | selectedItem.value == TestType_AllTestsForForm)
109 | {
110 | rv.allTests = true;
111 | }
112 | else {
113 | rv.allTests = false;
114 | }
115 |
116 | }
117 | else {
118 | rv.singleFormTest = false;
119 | if (buttonClicked.id === 'test_all_forms_with_all_attacks'){
120 | rv.allTests=true;
121 | }
122 | else {
123 | rv.allTests = false;
124 | }
125 | }
126 |
127 | /* cache the number of attacks early */
128 | rv.count = getAttackStringContainer().getStrings().length;
129 | if (rv.allTests === false) {
130 | var prefNumAttacks = this.getPreferredNumberOfAttacks();
131 |
132 | rv.count = (prefNumAttacks > rv.count) ? rv.count : prefNumAttacks;
133 |
134 | }
135 |
136 | return rv;
137 | }
138 | ,
139 | getMarkedFieldsForPanel:function(formPanel, all, formIndex) {
140 | var fieldUIs = formPanel.getElementsByAttribute('class', 'nolabel');
141 | var fieldsToTest = new Array();
142 |
143 | for(var i =0; i < fieldUIs.length; i++){
144 | if (fieldUIs[i].checked || all === true){
145 | var fieldToTest = new Object();
146 | fieldToTest.index = parseInt(fieldUIs[i].getAttribute('formElementIndex'));
147 | fieldToTest.name = getMainHTMLDoc().forms[formIndex].elements[fieldToTest.index].name;
148 | fieldsToTest.push(fieldToTest);
149 | }
150 | }
151 | return fieldsToTest;
152 | }
153 | ,
154 | /**
155 | * iterate through all these fields and find all the marked ones
156 | * @param testType the type of test that is being run.
157 | * @returns a list of fields to test
158 | */
159 | getFieldsToTest: function(testType) {
160 | var rv = null;
161 | var tabbox = document.getElementById('sidebarformtabbox');
162 | var mainDoc = getMainWindow().document.getElementById('content').contentDocument;
163 |
164 | if (testType.singleFormTest) {
165 | rv = this.getMarkedFieldsForPanel(tabbox.selectedPanel, false, tabbox.selectedIndex);
166 | for each (field in rv) {
167 | field.formIndex = tabbox.selectedIndex;
168 | field.formName = getHTMLFormElementNameOrLabel(mainDoc.forms[tabbox.selectedIndex]);
169 | }
170 | }
171 | else {
172 | /* @todo is using ._tabpanels safe here? ._tabpanels is a
173 | cached version of the panels */
174 | for (var n = 0; n < tabbox._tabpanels.childNodes.length; n++) {
175 | /* @todo is using ._tabpanels safe here? ._tabpanels is a
176 | cached version of the panels */
177 | var temp = this.getMarkedFieldsForPanel(tabbox._tabpanels.
178 | childNodes.item(n), true, n);
179 | for each (field in temp) {
180 | field.formIndex = n;
181 | field.formName = getHTMLFormElementNameOrLabel(mainDoc.forms[n]);
182 |
183 | }
184 | if (rv) {
185 | rv = rv.concat(temp);
186 | }
187 | else {
188 | rv = temp;
189 | }
190 | }
191 | }
192 | return rv;
193 | }
194 | ,
195 | run_tests: function(event){
196 |
197 | var canRunTests = this.preTest();
198 |
199 | if (canRunTests == false){
200 | alert('Could not run tests as test are already running. Please ' +
201 | 'wait for these tests to finish.')
202 | return;
203 | }
204 |
205 | var testType = this.getTestType(event);
206 | var fieldsToTest = this.getFieldsToTest(testType);
207 | var testCount = 0;
208 | var tabManager = new TabManager(getMainWindow().getBrowser().selectedTab.linkedBrowser);
209 |
210 | if (fieldsToTest.length === 0) {
211 | alert('Please make sure you have selected fields to test.')
212 | this.postTest();
213 | testCount = fieldsToTest.length * heuristicTestChars.length;
214 | return;
215 | }
216 | else {
217 | testCount = fieldsToTest.length * testType.count;
218 | }
219 |
220 | this.warningDialog = window.openDialog(
221 | 'chrome://sqlime/content/whiletestruns.xul', 'whiletestruns',
222 | 'chrome,dialog,dependant=yes', testCount, testType);
223 |
224 | var testManager = getTestManager(this);
225 |
226 | testManager.runTest(testType, fieldsToTest, tabManager);
227 | }
228 | ,
229 | createActionUI: function() {
230 | var box = document.createElement('hbox');
231 | var menulist = document.createElement('menulist');
232 | var menupopup = document.createElement('menupopup');
233 | var runTests_mi = document.createElement('menuitem');
234 | var runTopTests_mi = document.createElement('menuitem');
235 | var submitThisForm_mi = document.createElement('menuitem');
236 | var button = document.createElement('button');
237 | var rv = new Object();
238 |
239 | rv.menuitems = [];
240 |
241 | runTests_mi.setAttribute('label', "Run all tests");
242 | runTests_mi.setAttribute('value', TestType_AllTestsForForm);
243 | runTests_mi.setAttribute('selected', TestType_AllTestsForForm);
244 |
245 | runTopTests_mi.setAttribute('label', "Run top " + this.
246 | getPreferredNumberOfAttacks() + " tests");
247 | runTopTests_mi.setAttribute('value', TestType_PrefNumTestsForForm);
248 |
249 |
250 | submitThisForm_mi.setAttribute('value', TestType_OneTestForForm);
251 |
252 | rv.menuitems.push(runTopTests_mi);
253 | rv.menuitems.push(runTests_mi);
254 |
255 | //menulist.setAttribute("editable", false);
256 | rv.menupopup= menupopup;
257 |
258 | button.setAttribute('label', "Execute");
259 | button.setAttribute('command', 'sqlime_do_test');
260 | button.className = 'run_form_test';
261 |
262 | menulist.setAttribute('class', 'TestType');
263 | rv.menulist = menulist;
264 |
265 |
266 | rv.button = button;
267 |
268 | rv.box = box;
269 |
270 | return rv;
271 | }
272 | ,
273 | syncSidebarToForm: function(sidebarElement, formElement){
274 |
275 |
276 | var assignSidebarValueToFormElement = function(event){
277 | formElement.value=sidebarElement.value.toString();
278 | }
279 |
280 | var assignFormElementValueToSideBar = function(event){
281 | sidebarElement.value = formElement.value.toString();
282 | }
283 |
284 | var w = window;
285 | var htmlContentWindow = getMainHTMLWindow();
286 |
287 | var releaseMemory = function(event){
288 | formElement.removeEventListener('keypress',
289 | assignFormElementValueToSideBar, true);
290 | formElement.removeEventListener('mouseup',
291 | assignFormElementValueToSideBar, true);
292 | formElement.removeEventListener('change',
293 | assignFormElementValueToSideBar, true);
294 | sidebarElement.removeEventListener('input',
295 | assignSidebarValueToFormElement, true);
296 | sidebarElement.removeEventListener('click',
297 | assignSidebarValueToFormElement, true);
298 | w.removeEventListener('unload', arguments.callee, true);
299 | htmlContentWindow.removeEventListener('unload', arguments.callee,
300 | true);
301 | }
302 |
303 | formElement.addEventListener('keypress', assignFormElementValueToSideBar, true);
304 | formElement.addEventListener('mouseup', assignFormElementValueToSideBar, true);
305 | formElement.addEventListener('change', assignFormElementValueToSideBar, true);
306 | sidebarElement.addEventListener('input', assignSidebarValueToFormElement, true);
307 | sidebarElement.addEventListener('click', assignSidebarValueToFormElement, true);
308 | htmlContentWindow.addEventListener('unload', releaseMemory, true);
309 | w.addEventListener('unload', releaseMemory, true);
310 |
311 |
312 | }
313 | ,
314 | do_generate_form_ui: function() {
315 | var q = 0;
316 | var maindoc = getMainWindow().document.getElementById('content').contentDocument;
317 | var box = document.getElementById('sqlime_here_be_tabs');
318 | var docforms = maindoc.getElementsByTagName('form');
319 | var unnamedFormCounter = 0; //used for generating the unnamed form names
320 | var tabbox = document.createElement('tabbox');
321 | var tabs = document.createElement('tabs');
322 | var tabpanels = document.createElement('tabpanels');
323 | var fieldsLabel = document.createElement('label');
324 | var sidebarBuilder = getSidebarBuilder();
325 | fieldsLabel.setAttribute('value', "These are the fields in this form:");
326 |
327 | tabbox.setAttribute('id', 'sidebarformtabbox');
328 | //we only want to put things in a clean box.
329 | if (box.childNodes.length !== 0) {
330 | for (var i = 0; i < box.childNodes.length; i++) {
331 | box.removeChild(box.childNodes[i]);
332 | }
333 | }
334 |
335 | // create the form UI
336 | // Note that the addition of the DOM is seperated from the creation of
337 | // it in the hopes that it will make for a faster overall operation
338 | // even though it does require a bit more work in the code. This is
339 | // based on Mossop(David Townshed)'s advice.
340 | if (maindoc.forms.length !== 0){
341 | var attackStringContainer = getAttackStringContainer();
342 | attackStringContainer.init();
343 |
344 | var newTabs = [];
345 | var newTabForms= [];
346 | var newTabPanels = [];
347 | var newTabActions = [];
348 | var newTabPanelVbox = [];
349 |
350 | for (var i = 0; i < maindoc.forms.length; i++){
351 |
352 | var aForm = maindoc.forms[i];
353 | var formname = null;
354 | var formPanel = document.createElement("tabpanel");
355 | var fieldsWithUI = new Object();
356 | var formTab = document.createElement("tab");
357 |
358 | dump(q++ + "\n");
359 |
360 | // Since the name attribute is deprecated for the form tag we first
361 | // check the id attribute, then the name attribute and then consider
362 | // it unnamed.
363 | if (aForm.id){
364 | formname = aForm.id;
365 | }
366 | else if (aForm.name){
367 | formname = aForm.name;
368 | }
369 | else {
370 | formname = "Unnamed form " + (++unnamedFormCounter);
371 | }
372 |
373 | formTab.setAttribute("label", formname);
374 |
375 | dump('aForm.elements.length: ' + aForm.elements.length +'\n');
376 |
377 | //iterate through the forms and generate the DOM.
378 | if (aForm.elements.length !== 0){
379 | for (var n = 0; n < aForm.elements.length; n++){
380 | var sidebarElement = null;
381 | dump('aForm.elements[' + n + '] = ' +aForm.elements[n] +
382 | '- ' + aForm.elements[n].id +'\n');
383 | if (aForm.elements[n].name){
384 | sidebarElement =
385 | fieldsWithUI[aForm.elements[n].name] =
386 | createFieldUI(aForm.elements[n], n);
387 | }
388 | else if (aForm.elements[n].id){
389 | sidebarElement =
390 | fieldsWithUI[aForm.elements[n].id] =
391 | createFieldUI(aForm.elements[n], n );
392 | }
393 | else {
394 | sidebarElement =
395 | fieldsWithUI["form" + n + "_"+
396 | Math.round(Math.random() * 10000000)] =
397 | createFieldUI(aForm.elements[n], n);
398 | }
399 | sidebarElement = sidebarElement.getElementsByAttribute('editable', 'true')[0];
400 | this.syncSidebarToForm(sidebarElement, aForm.elements[n]);
401 |
402 | }
403 |
404 | }
405 |
406 | var actionButtons = this.createActionUI();
407 | newTabs.push(formTab);
408 | newTabForms.push(fieldsWithUI);
409 | newTabPanels.push(formPanel);
410 | newTabActions.push(actionButtons);
411 | newTabPanelVbox.push(document.createElement("vbox"));
412 |
413 | }
414 |
415 | /* the order of the below is very important. If the order is
416 | changed then not only will the display change but some things
417 | will break (certain attributes are checked only by grandparents
418 | on addition to the DOM, ex. selected). */
419 |
420 | //Add the form UI to the DOM.
421 | for (var i = newTabs.length-1; i >= 0; i--) {
422 |
423 | for each(var fieldUI in newTabForms[i]) {
424 | sidebarBuilder.add(newTabPanelVbox[i], fieldUI, selectFirstMenuItemForField);
425 | }
426 |
427 | /* the order from here ...*/
428 | sidebarBuilder.add(newTabActions[i].box,
429 | newTabActions[i].menulist);
430 |
431 | sidebarBuilder.add(newTabActions[i].menulist,
432 | newTabActions[i].menupopup);
433 |
434 | for each(var mi in newTabActions[i].menuitems){
435 | //newTabActions[i].menupopup.appendChild(mi);
436 | sidebarBuilder.add(newTabActions[i].menupopup, mi);
437 | }
438 |
439 | /* to here is particularly crucial and annoying */
440 |
441 | sidebarBuilder.add(newTabActions[i].box,
442 | newTabActions[i].button);
443 | sidebarBuilder.add(newTabPanelVbox[i],
444 | newTabActions[i].box);
445 | sidebarBuilder.add(newTabPanels[i], newTabPanelVbox[i]);
446 | sidebarBuilder.add(tabs, newTabs[i]);
447 | sidebarBuilder.add(tabpanels, newTabPanels[i]);
448 | }
449 |
450 |
451 | sidebarBuilder.add(tabbox, tabpanels);
452 | sidebarBuilder.add(tabbox, tabs);
453 |
454 | }
455 | else {
456 |
457 | var noformPanel = document.createElement("tabpanel");
458 | var noformTab = document.createElement("tab");
459 | var labelinpanel = document.createElement("label");
460 | var noformPanelVbox = document.createElement("vbox");
461 |
462 | labelinpanel.setAttribute("value", "Sorry, this page has no forms.");
463 |
464 | noformTab.setAttribute("label", "No Forms");
465 |
466 | sidebarBuilder.add(tabs, noformTab);
467 | sidebarBuilder.add(tabpanels, noformPanel);
468 | sidebarBuilder.add(noformPanel, noformPanelVbox);
469 | sidebarBuilder.add(noformPanelVbox, labelinpanel);
470 | sidebarBuilder.add(tabbox, tabpanels);
471 | sidebarBuilder.add(tabbox, tabs);
472 |
473 | }
474 |
475 | sidebarBuilder.add(box, tabbox);
476 |
477 | sidebarBuilder.start();
478 |
479 | }
480 | ,
481 | addAllMainWindowEventListeners: function() {
482 |
483 | var mainWindow = getMainWindow();
484 | var ourCaller = this;
485 | this.windowEventClosure = function(){ourCaller.do_generate_form_ui()};
486 | mainWindow.getBrowser().tabContainer.
487 | addEventListener("TabSelect",
488 | this.windowEventClosure, false);
489 |
490 | this.plistener = new sqlimeProgressListener(
491 | this.windowEventClosure);
492 |
493 | mainWindow.document.getElementById('content').
494 | addProgressListener(this.plistener,
495 | Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
496 |
497 | this.sidebarBuilderPauseObserver = new Xss_PrefObserver(watchSidebarBuilderPausePref);
498 |
499 | var prefService = Components.classes['@mozilla.org/preferences-service;1'].
500 | getService(Components.interfaces.nsIPrefService);
501 |
502 | var branch = prefService.getBranch('');
503 |
504 | var observableBranch = branch.
505 | QueryInterface(Components.interfaces.nsIPrefBranch2);
506 |
507 | observableBranch.addObserver('extensions.sqlime.sidebarbuildingstop',
508 | this.sidebarBuilderPauseObserver, false);
509 |
510 | }
511 | ,
512 | removeAllMainWindowEventListeners: function (){
513 | var mainWindow = getMainWindow();
514 |
515 | mainWindow.document.getElementById('content').
516 | removeProgressListener(this.plistener);
517 |
518 | if (this.windowEventClosure) {
519 | mainWindow.getBrowser().tabContainer.
520 | removeEventListener('TabSelect',
521 | this.windowEventClosure,
522 | false);
523 | this.windowEventListenerClosure = null;
524 | }
525 | var prefService = Components.classes['@mozilla.org/preferences-service;1'].
526 | getService(Components.interfaces.nsIPrefService);
527 |
528 | var branch = prefService.getBranch('');
529 |
530 | var observableBranch = branch.
531 | QueryInterface(Components.interfaces.nsIPrefBranch2);
532 |
533 | observableBranch.removeObserver('extensions.sqlime.sidebarbuildingstop',
534 | this.sidebarBuilderPauseObserver)
535 |
536 | }
537 | ,
538 | getPreferredNumberOfAttacks: function(){
539 | var prefs = Components.classes["@mozilla.org/preferences-service;1"].
540 | getService(Components.interfaces.nsIPrefService);
541 | var branch = prefs.getBranch("extensions.sqlime.");
542 | return branch.getIntPref("prefnumattacks");
543 | }
544 | ,
545 | /**
546 | * This function does two things:
547 | * 1. Checks if we can run a test
548 | * 2. Preps the browser for testing (changing prefs, etc.)
549 | * @returns true if we can test, false otherwise.
550 | */
551 | preTest: function() {
552 | var rv = false;
553 | if (this.warningDialog === null){
554 | rv = true;
555 |
556 | var prefService = Components.
557 | classes['@mozilla.org/preferences-service;1'].
558 | getService(Components.interfaces.nsIPrefService);
559 | var branch = prefService.getBranch("");
560 | for each (var prefInfo in __sqli_me_prefs_to_disable) {
561 | var origValue;
562 | var errorState = false;
563 | switch(prefInfo.type){
564 | case 'bool':
565 | try {
566 | origValue = branch.getBoolPref(prefInfo.name);
567 | branch.setBoolPref(prefInfo.name, prefInfo.ourValue);
568 | }
569 | catch(e){
570 | Components.utils.reportError(e +' with '+ prefInfo.name);
571 | errorState = true;
572 | }
573 | break;
574 | case 'int':
575 | try {
576 | origValue = branch.getIntPref(prefInfo.name);
577 | branch.setIntPref(prefInfo.name, prefInfo.ourValue);
578 | }
579 | catch(e){
580 | Components.utils.reportError(e + ' with '+ prefInfo.name);
581 | errorState = true
582 | }
583 | break;
584 | }
585 |
586 | if (!errorState) {
587 |
588 | var backupPref = {
589 | 'name': prefInfo.name,
590 | 'type': prefInfo.type,
591 | 'origValue': origValue};
592 |
593 | this.prefs.push(backupPref);
594 | }
595 | }
596 |
597 | }
598 | return rv;
599 |
600 | }
601 | ,
602 | postTest: function(){
603 | this.warningDialog.close();
604 | this.warningDialog = null;
605 | var prefService = Components.
606 | classes['@mozilla.org/preferences-service;1'].
607 | getService(Components.interfaces.nsIPrefService);
608 | var branch = prefService.getBranch("");
609 | for each(var backupPref in this.prefs) {
610 | switch(backupPref.type){
611 | case 'bool':
612 | try {
613 | branch.setBoolPref(backupPref.name, backupPref.origValue);
614 | }
615 | catch(e){
616 | Components.utils.reportError(e +'with '+ backupPref.name);
617 | }
618 | break;
619 | case 'int':
620 | try {
621 | branch.setIntPref(backupPref.name, backupPref.origValue);
622 | }
623 | catch(e){
624 | Components.utils.reportError(e + 'with '+ backupPref.name);
625 | }
626 | break;
627 | }
628 | }
629 |
630 | this.prefs.splice(0, this.prefs.length);
631 | }
632 | ,
633 | calculateWorseCaseNumTestsToRun: function(testType, fieldsToTest) {
634 |
635 | var rv = 0;
636 |
637 | var numFieldsToTest = fieldsToTest.length;
638 |
639 | if (testType.heuristicTest) {
640 |
641 | var numTestChars = this.getHeuristicTestChars().length;
642 |
643 | rv += numFieldsToTest * numTestChars;
644 |
645 | }
646 |
647 | rv += numFieldsToTest*testType.count*2; // *2 because there are both DOM and string tests to run
648 | Components.utils.reportError("worse case num tests = ("+numFieldsToTest+"*" +numTestChars+"+"+numFieldsToTest+ "*"+ testType.count+") = "+
649 | "("+ (numFieldsToTest*numTestChars) +"+"+ (numFieldsToTest*testType.count)+") = " +((numFieldsToTest*numTestChars) + (numFieldsToTest*testType.count))+ " = " + rv);
650 | return rv;
651 |
652 | }
653 | ,
654 | /**
655 | * Notify's the warningDialog (if it exists) that it should change its
656 | * state to notify them
657 | */
658 | generatingReport: function(){
659 | if (this.warningDialog && this.warningDialog.closed === false) {
660 | this.warningDialog.generatingReport();
661 | }
662 | }
663 | ,
664 | /**
665 | * Called by the testmanager and resultsmanager to report that a test has
666 | * been completed so that the popup's UI can be updated
667 | */
668 | finishedTest: function() {
669 | Components.utils.reportError("foo");
670 | if (this.warningDialog.closed === false && typeof(this.warningDialog.finishedTest) == 'function') {
671 | this.warningDialog.finishedTest();
672 | }
673 | else if (typeof(this.warningDialog.finishedTest) != 'function') {
674 | Components.utils.reportError('warning dialog\'s finished test function is missing.');
675 | }
676 | }
677 | }
678 |
679 |
680 | /**
681 | * This function takes a form returns an associative array (Object object) of
682 | * field name => field UI pairs (with the UI being appropriate for plugging
683 | * into a tabpanel for display. Recursive.
684 | * @param form a form
685 | * @param fields
686 | * @returns an associative array (Object) of field name => field UI pairs
687 | */
688 | function getFormFieldsUI(aForm, allFields) {
689 | var fields = allFields ? allFields : new Object();
690 |
691 | for (var child in aForm.elements){
692 | dump('examining child: ' + child + " " + child.nodeName+"\n");
693 | if (isFormField(child)){
694 | if (!fields[child.name]){ //We don't want a million option UIs
695 | // even if there are a million
696 | // options
697 | var childUI = createFieldUI(child);
698 | fields[child.name] = childUI;
699 | }
700 | dump(child.nodeName + "is a form field\n");
701 | }
702 | else {
703 | dump(child.nodeName + "is NOT a form field\n");
704 | fields = getForFieldsUI(child, fields);
705 | }
706 | }
707 |
708 | return fields;
709 | }
710 | /**
711 | * generate the ui for one form field.
712 | * Another option is to use XBL but it really doesn't seem to be worth
713 | * the effort
714 | * @param node a form field
715 | * @param elementIndex the index of the element in the form's elements array.
716 | * @returns the root of the ui for a form field (a groupbox).
717 | */
718 | function createFieldUI(node, elementIndex){
719 |
720 | // var uid = Math.round(Math.random() * 100000000000);
721 | dump("creating field ui\n");
722 | var root = document.createElement("groupbox");
723 | root.setAttribute("flex", 0);
724 |
725 | var caption = document.createElement("caption");
726 |
727 | if (node.name){
728 | caption.setAttribute("label", node.name);
729 | }
730 | else if(node.id){
731 | caption.setAttribute("label", node.id);
732 | }
733 |
734 | var hbox = document.createElement("hbox");
735 | dump("creating field ui...\n");
736 | var checkbox = document.createElement("checkbox");
737 | checkbox.className = "nolabel";
738 | checkbox.setAttribute('formElementIndex', elementIndex);
739 |
740 | var menulist = document.createElement("menulist");
741 | menulist.setAttribute("editable", true);
742 |
743 | dump("creating field ui.......\n");
744 | var menupopup = document.createElement("menupopup");
745 |
746 | var firstMenuItem = document.createElement("menuitem");
747 | if (node.value && node.value.length){
748 | firstMenuItem.setAttribute("label", node.value);
749 | }
750 | else {
751 | firstMenuItem.setAttribute("label",
752 | "Change this to the value you want tested");
753 | }
754 | firstMenuItem.setAttribute("selected", true);
755 |
756 | menupopup.appendChild(firstMenuItem);
757 |
758 | dump("creating field ui............................\n");
759 | var attackStringContainer = getAttackStringContainer();
760 | var attacks = attackStringContainer.getStrings();
761 | for (var i = 0; i < attacks.length; i++){
762 | var aMenuItem = document.createElement("menuitem");
763 | aMenuItem.setAttribute('label', attacks[i].string);
764 | aMenuItem.setAttribute('width', '100');
765 | aMenuItem.setAttribute('crop', 'end');
766 | menupopup.appendChild(aMenuItem);
767 | dump("menupopup childnodes length: " + menupopup.childNodes.length+"\n");
768 | }
769 |
770 | menulist.appendChild(menupopup);
771 | menulist.selectedIndex = 0;
772 |
773 | hbox.appendChild(checkbox);
774 | hbox.appendChild(menulist);
775 |
776 | root.appendChild(caption);
777 | root.appendChild(hbox);
778 | dump("creating field ui................................................\n");
779 | return root;
780 |
781 | }
782 |
783 | /**
784 | * This function checks whether the passed in DOMNode is form field or some
785 | * other type of tag.
786 | * @param node the node to check
787 | * @returns true if the elemenet is a form field, false otherwise
788 | */
789 | function isFormField(node){
790 |
791 | switch (node.tagName.toLowerCase()){
792 | case "input":
793 | case "option":
794 | case "button":
795 | case "textarea":
796 | case "submit":
797 | return true;
798 | default:
799 | return false;
800 | }
801 | }
802 |
803 | /**
804 | * Watches the sidebar builder pause time preference and sets
805 | */
806 | function watchSidebarBuilderPausePref(subject, topic, data) {
807 | var prefService = Components.classes['@mozilla.org/preferences-service;1'].
808 | getService(Components.interfaces.nsIPrefService);
809 | var branch = prefService.getBranch('extensions.sqlime.');
810 |
811 | getSidebarBuilder().time = branch.getIntPref('sidebarbuildingstop');
812 | }
813 | /**
814 | * This function is used to make sure that the first tab panel is selected
815 | * in a tabbox
816 | * @param parent the tabbox
817 | * @param child the tabpanels element
818 | */
819 | function ensureFirstTabPanelIsSelected(parent, child) {
820 | parent.selectedIndex= parent._tabpanels.selectedIndex = 0;
821 | }
822 |
823 | /**
824 | * This function is used to make sure that first child of the menu drop down
825 | * box.
826 | * @param parent
827 | * @param child menu list box.
828 | */
829 | function ensureFirstChildOfMenuBox(parent, child) {
830 | parent.selectedIndex = 0;
831 | dump('changing index.\n')
832 | }
833 |
834 | /**
835 | * Selects the first item in a menubox. Used with the retun value of
836 | * createFieldUI.
837 | * @param parent
838 | * @param child the groupbox holding a field's UI as returned by createFieldUI()
839 | */
840 | function selectFirstMenuItemForField(parent, child) {
841 |
842 | dump("child.childNodes[1].childNodes[1].selectedIndex" + child.childNodes[1].childNodes[1].selectedIndex + " " + typeof(child.childNodes[1].childNodes[1].selectedIndex) + " "+ child.childNodes[1].childNodes[1].nodeName + "\n");
843 | child.childNodes[1].childNodes[1].selectedIndex = 1;
844 | dump("child.childNodes[1].childNodes[1].selectedIndex" + child.childNodes[1].childNodes[1].selectedIndex + " " + typeof(child.childNodes[1].childNodes[1].selectedIndex) + " "+ child.childNodes[1].childNodes[1].nodeName + "\n");
845 | dump('changing fieldUI Index\n')
846 |
847 | }
848 |
--------------------------------------------------------------------------------
/content/sqlime_sidebar.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | SQL Inject Me lets you test the page you're viewing for SQL Injection vulnerabilities.
89 |
90 |
91 | Each tab represents a form on the page and lists all the fields. Just fill in good values for all the fields and mark which ones are to be tested (they will become yellow) then click either "Test with All Attacks" or "Test with Top Attacks".
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
116 |
117 |
--------------------------------------------------------------------------------
/content/sqlimeevaluators.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject Me please contact
20 | tools@securitycompass.com
21 | */
22 |
23 | /**
24 | * sqlimeevaluators.js
25 | * This file holds a number of JS evaluators
26 | * @require Results.js
27 | * @require ErrorStringContainer.js
28 | */
29 |
30 | /**
31 | * Checks the source of a page for stored error strings
32 | */
33 | function checkSrcForErrorString(streamListener) {
34 |
35 | var errorContainer = getErrorStringContainer();
36 | var results = new Array();
37 | var doc = streamListener.data;
38 | var stringEncoder = getHTMLStringEncoder();
39 | dump("\nStart freeze...");
40 | for each (var error in errorContainer.getStrings()){
41 | var result;
42 |
43 | if (doc.indexOf(error.string) !== -1) {
44 | result = new Result(RESULT_TYPE_ERROR, 100, "Error string found: '" + stringEncoder.encodeString(error.string) + "'");
45 | }
46 | else {
47 | result = new Result(RESULT_TYPE_PASS, 100, "Error string not found: '" + stringEncoder.encodeString(error.string) + "'");
48 | }
49 |
50 | results.push(result);
51 | }
52 | dump("\nEnd freeze...");
53 |
54 |
55 | return results;
56 | }
57 |
58 | /**
59 | * Checks the browser for stored error strings.
60 | */
61 | function checkForErrorString(browser) {
62 |
63 | var errorContainer = getErrorStringContainer();
64 | var results = new Array();
65 | var doc = browser.contentDocument.toString();
66 | var stringEncoder = getHTMLStringEncoder();
67 | dump("\nStart freeze...");
68 | for each (var error in errorContainer.getStrings()){
69 | var result;
70 |
71 | if (doc.indexOf(error.string) !== -1) {
72 | result = new Result(RESULT_TYPE_ERROR, 100, "Error string found: '" + stringEncoder.encodeString(error.string) + "'");
73 | }
74 | else {
75 | result = new Result(RESULT_TYPE_PASS, 100, "Error string not found: '" + stringEncoder.encodeString(error.string) + "'");
76 | }
77 |
78 | results.push(result);
79 | }
80 | dump("\nEnd freeze...");
81 |
82 |
83 | return results;
84 | }
85 |
86 | function checkForServerResponseCode(streamListener){
87 | var nsiHttpChannel = streamListener.attackRunner.channel.QueryInterface(Components.interfaces.nsIHttpChannel);
88 | var stringEncoder = getHTMLStringEncoder();
89 | try{
90 | if ((nsiHttpChannel.responseStatus === undefined || nsiHttpChannel.responseStatus === null)){
91 | return null;
92 | }
93 | else {
94 | var result;
95 | var responseCode = nsiHttpChannel.responseStatus;
96 | var displayString = "Server Status Code: " + stringEncoder.encodeString(responseCode.toString()) + " " +
97 | stringEncoder.encodeString(nsiHttpChannel.responseStatusText);
98 | if (responseCode == 200){
99 | result = new Result(RESULT_TYPE_PASS, 100, displayString );
100 | }
101 | else {
102 | result = new Result(RESULT_TYPE_ERROR, 100, displayString);
103 | }
104 | }
105 | return [result];
106 | }
107 | catch(err){
108 | Components.utils.reportError(err);
109 | return [];
110 | }
111 | }
--------------------------------------------------------------------------------
/content/tabbrowsermanager.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 | this.tabForms[i].elements ={};
69 | this.tabForms[i].elements.length = forms[i].elements.length;
70 | this.tabForms[i].action = forms[i].action ? forms[i].action : browser.contentDocument.
71 | location.toString();
72 | this.tabForms[i].method = forms[i].method;
73 |
74 | for (var j = 0; j < forms[i].elements.length; j++) {
75 | var elem = forms[i].elements[j];
76 | var elemToUse = {};
77 | elemToUse.nodeName = elem.nodeName;
78 | elemToUse.name = elem.name;
79 | switch (elem.nodeName.toLowerCase()) {
80 | case 'submit':
81 | case 'reset':
82 | case 'image':
83 | case 'button':
84 | case 'fieldset':
85 | this.tabForms[i].push({});
86 | this.tabForms[i].elements[elem.name] = this.tabForms[i].
87 | elements[j] = {};
88 | break;
89 | case 'checkbox':
90 | case 'radio':
91 | elemToUse.checked = elem.checked;
92 | elemToUse.name = elem.name
93 | this.tabForms[i].push(elemToUse);
94 | this.tabForms[i].elements[elemToUse.name] = this.tabForms[i].
95 | elements[j] = elemToUse;
96 | break;
97 | default:
98 | elemToUse.value = elem.value;
99 | elemToUse.name = elem.name
100 | this.tabForms[i].push(elemToUse);
101 | this.tabForms[i].elements[elemToUse.name] = this.tabForms[i].
102 | elements[j] = elemToUse;
103 | }
104 | }
105 | if (! this.tabForms[forms[i].name]){
106 | this.tabForms[forms[i].name] = this.tabForms[i];
107 | }
108 | }
109 |
110 | this.index = browser.webNavigation.sessionHistory.index;
111 | }
112 |
113 | TabManager.prototype = {
114 | /**
115 | * Point a browser at the target page recorded by this TabManager.
116 | * @param browser the browser to point to the target page
117 | */
118 | loadTargetPage: function (browser) {
119 | browser.webNavigation.loadURI(this.targetPage, 0, this.targetPageReferrer, this.targetPagePostData, null);
120 | }
121 | ,
122 | writeTabForms: function(forms, testFormIndex, testFieldIndex, testData){
123 | dump('-=-=-=-writeTabForms::forms ' + forms[0]);
124 | if (forms[testFormIndex] === undefined){
125 | dump('got an undefined\n');
126 | }
127 | dump('&& and the test form is : '+forms[testFormIndex]+ ' with '+
128 | forms[testFormIndex].elements.length+'elements\n');
129 | for (var formIndex = 0;
130 | formIndex < forms.length;
131 | formIndex++)
132 | {
133 | for (var elementIndex = 0;
134 | elementIndex < forms[formIndex].elements.length;
135 | elementIndex++)
136 | {
137 | var element = forms[formIndex].elements[elementIndex];
138 | dump('checking whether this field ('+formIndex + ',' +elementIndex +')should be loaded with an evil value: ' + (formIndex === testFormIndex && elementIndex === testFieldIndex) + '\n');
139 | if (formIndex !== null &&
140 | formIndex === testFormIndex &&
141 | elementIndex === testFieldIndex &&
142 | testData !== null
143 | )
144 | {
145 | dump('going to force element ' +element.name +' ('+ elementIndex
146 | +') to have value ' + testData+ '\n');
147 | if(element.nodeName.toLowerCase() === 'select') {
148 | var newOption = forms[formIndex].ownerDocument.createElement('option');
149 | newOption.setAttribute('value', testData.string);
150 | newOption.innerHTML = testData.string;
151 | element.options[element.options.length] = newOption;
152 | element.selectedIndex = element.options.length - 1;
153 | }
154 | else {
155 | element.value = testData.string;
156 | }
157 | dump('element[' + elementIndex + '] has value' +
158 | element.value + ' \n');
159 | }
160 | else if (element.nodeName.toLowerCase() == 'submit' ||
161 | element.nodeName.toLowerCase() == 'reset' ||
162 | element.nodeName.toLowerCase() == 'image' ||
163 | element.nodeName.toLowerCase() == 'button')
164 | {
165 | // don't care, this is here just to make sure the elements
166 | // are parallel.
167 | }
168 | else if (element.nodeName.toLowerCase() == 'checkbox' ||
169 | element.nodeName.toLowerCase() == 'radio')
170 | {
171 | element.checked = this.tabForms[formIndex][elementIndex];
172 | }
173 | else {
174 | element.value = this.tabForms[formIndex][elementIndex];
175 | }
176 | }
177 | }
178 | }
179 | ,
180 | getTabData: function(testFormIndex, testFieldIndex, testString){
181 | var rv = new Array();
182 | var formIndex = testFormIndex;
183 | var forms = this.tabForms;
184 | for (var elementIndex = 0;
185 | elementIndex < forms[formIndex].elements.length;
186 | elementIndex++)
187 | {
188 | var element = forms[formIndex].elements[elementIndex];
189 | var fieldInfo = new Object();
190 | fieldInfo.name = element.name;
191 | fieldInfo.data = (elementIndex == testFieldIndex && testString)?testString:element.value;
192 | fieldInfo.tested = (elementIndex == testFieldIndex);
193 | rv.push(fieldInfo);
194 | }
195 | return rv;
196 | }
197 | ,
198 | /**
199 | * This returns the data in a form
200 | */
201 | getFormDataForURL: function(testFormIndex, testFieldIndex,
202 | testData)
203 | {
204 | var formIndex = testFormIndex;
205 | var rv = '';
206 | var forms = this.tabForms;
207 | for (var elementIndex = 0;
208 | elementIndex < forms[testFormIndex].elements.length;
209 | elementIndex++)
210 | {
211 | var element = forms[testFormIndex].elements[elementIndex];
212 | if (rv.length != 0){
213 | rv+='&';
214 | }
215 |
216 | if (elementIndex == testFieldIndex) {
217 | rv += element.name +'='+testData;
218 | }
219 | else if (element.value) {
220 | rv += element.name +'='+element.value;
221 | }
222 | else if (element.checked !== undefined ) {
223 | rv += element + '=' + element.checked?1:0;
224 | }
225 | }
226 | return rv;
227 |
228 | }
229 | };
--------------------------------------------------------------------------------
/content/util.js:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 |
19 | If you have any questions regarding SQL Inject 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 = ']]]]>.
18 |
19 | If you have any questions regarding SQL Inject 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,
40 | "Are you sure you want to close this window?",
41 | "Are you sure you want to close this window? It's useful to " +
42 | "remind you not to use the testing window. Also closing this window will NOT stop the tests.",
43 | prompts.STD_YES_NO_BUTTONS, "", "", "", null, new Object());
44 |
45 | return !rv;
46 |
47 | }
48 |
49 | /**
50 | * This function is called when a test is finished
51 | */
52 | this.finishedTest = function() {
53 | this.numTestsComplete++;
54 | if (this.numTestsComplete > this.maxNumTests) {
55 | Components.utils.reportError('Too many tests have been completed');
56 | }
57 | }
58 |
59 | this.clearNumTests = function() {
60 | this.numTestsComplete = 0;
61 | }
62 |
63 | this.updateUI = function() {
64 |
65 | this.bar.value = this.numTestsComplete / this.maxNumTests * 100
66 | this.span.innerHTML = this.numTestsComplete.toString() + '/' + this.maxNumTests.toString();
67 |
68 | }
69 |
70 | this.startThoroughTesting = function(numVulnerableFields) {
71 | this.bar.value = 100;
72 | this.span.innerHTML = this.maxNumTests.toString() + '/' + this.maxNumTests.toString();
73 |
74 | this.bar = document.getElementById('thoroughBar');
75 | this.span = document.getElementById('thoroughTestCount');
76 |
77 | this.maxNumTests = 2*numVulnerableFields*this.testType.count;
78 | this.numTestsComplete = 0;
79 |
80 | //document.getElementById('heuristicsComplete').style.visibility = 'visible';
81 | }
82 |
83 | function onUnLoad() {
84 | //alert(this.numTestsComplete + ' of ' +this.maxNumTests);
85 | this.bar = null;
86 | this.span = null;
87 | }
88 |
89 | /**
90 | * called when the page loads
91 | */
92 | function onLoad() {
93 | this.clearNumTests();
94 | window.centerWindowOnScreen();
95 | this.maxNumTests = window.arguments[0];
96 | this.testType = window.arguments[1];
97 | this.bar = null;
98 | this.span = null;
99 |
100 | if (this.testType.heuristicTest) {
101 | document.getElementById('heuristicTestingBox').style.visibility = 'visible';
102 | //document.getElementById('heuristicsComplete').style.visibility = 'hidden';
103 | this.bar = document.getElementById('heuristicBar');
104 | this.span = document.getElementById('heuristicTestCount');
105 | }
106 | else {
107 | this.bar = document.getElementById('thoroughBar');
108 | this.span = document.getElementById('thoroughTestCount');
109 | }
110 |
111 | //update UI every 1/5 second
112 | window.setInterval(this.updateUI, 200);
113 | }
114 |
115 | function generatingReport() {
116 | document.getElementById('duringTest').style.visibility = 'collapse';
117 | document.getElementById('generatingReport').style.visibility = 'visible';
118 | }
119 |
--------------------------------------------------------------------------------
/content/whiletestruns.xul:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
60 |
--------------------------------------------------------------------------------
/install.rdf:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 | sqlime@security.compass
6 | SQL Inject Me
7 | 0.4.7
8 | Security Compass
9 | Sam Chapin, sc@samchapin.com
10 | An extension to test for SQL injection vulnerabilities
11 | chrome://sqlime/content/preferences.xul
12 | chrome://sqlime/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/sqlime.dtd:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/locale/en-US/sqlime.properties:
--------------------------------------------------------------------------------
1 | helloMessage=Hello World!
2 | helloMessageTitle=Hello
3 | prefMessage=Int Pref Value: %d
4 | extensions.sqlime.description=An Extension to test for Cross Site Scripting Vulnerabilities
5 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | SQL Inject Me
2 | =============
3 | SQL Inject Me is a part of the Security Compass Exploit-Me series of tools.
4 | SQL Inject Me is designed to aid in the detection of SQL Injection
5 | vulnerabilities. The tool is a Firefox extension that will execute specific
6 | attack strings against forms on your website.
7 |
8 |
9 | Limitations
10 | -----------
11 | SQL Inject Me ships with a default list of error strings which we hope will
12 | help find most SQL Injection errors. However if the application you are testing
13 | has special database related error messages you may wish to add them using the
14 | options window (Tools->SQL Inject Me->Options->SQL Injection Strings).
15 |
16 |
17 | More Information
18 | ----------------
19 | For more information on SQL Inject Me please visit:
20 | http://www.securitycompass.com/exploitme.shtml. If you've got any questions,
21 | comments, or suggestions regarding SQL Inject Me please send them to
22 | tools@securitycompass.com.
23 |
24 |
25 | License
26 | -------
27 | SQL Inject Me is released under the GNU GPLv3 a copy of which should be
28 | included in this distribution.
--------------------------------------------------------------------------------
/skin/logo_sc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SecurityCompass/SQL-Inject-Me/e616319dec89e41dc7f663b63cf68a79b253ba05/skin/logo_sc.png
--------------------------------------------------------------------------------
/skin/overlay.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 | */
19 | *
20 | /* This is just an example. You shouldn't do this. */
21 | #sqlime-hello
22 | {
23 | }
24 | #sqlime-toolbar-button
25 | {
26 | list-style-image: url("chrome://sqlime/skin/toolbar-button.png");
27 | -moz-image-region: rect(0px 24px 24px 0px);
28 | }
29 | #sqlime-toolbar-button:hover
30 | {
31 | -moz-image-region: rect(24px 24px 48px 0px);
32 | }
33 | [iconsize="small"] #sqlime-toolbar-button
34 | {
35 | -moz-image-region: rect( 0px 40px 16px 24px);
36 | }
37 | [iconsize="small"] #sqlime-toolbar-button:hover
38 | {
39 | -moz-image-region: rect(24px 40px 40px 24px);
40 | }
41 |
--------------------------------------------------------------------------------
/skin/preferences.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 | */
19 |
20 |
21 | radio {
22 | list-style-image: url("chrome://browser/skin/preferences/Options.png");
23 | }
24 |
25 | radio[pane=sqligen] {
26 | -moz-image-region: rect(0px, 32px, 32px, 0px);
27 | }
28 |
29 | radio[pane=sqlistrings] {
30 | -moz-image-region: rect(0px, 128px, 32px, 96px);
31 | }
--------------------------------------------------------------------------------
/skin/results.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 | */
19 |
20 | .failed {
21 | color: red;
22 | }
23 |
24 | .passed {
25 | color: green;
26 | }
27 |
28 | .warning {
29 | color: #AAAA00;
30 | }
31 |
32 | p {
33 | margin: 0;
34 | }
35 |
36 | .testfields {
37 | list-style: none;
38 | }
39 |
40 | .title {
41 | color: #405068 !important;
42 | }
43 |
44 | .bar-status{
45 | text-align: right;
46 | width: 10%;
47 | white-space: pre;
48 | }
49 | .bar {
50 | width: 99%;
51 | border: thin solid
52 | }
53 | .percent {
54 | text-align: left;
55 | width: 6em;
56 | }
57 | .bar-passed {
58 |
59 | }
60 | .bar-warning{
61 | }
62 | .bar-failed{
63 | }
64 | li {
65 | list-style: none;
66 | }
67 | .passed {
68 | color: green;
69 | }
70 | .warning {
71 | color: #AAAA00;
72 | }
73 | .failed {
74 | color: red;
75 | }
76 | .title {
77 | color: #405068 !important;
78 | }
79 | fieldset {
80 | margin-bottom: 1em;
81 | }
82 |
83 | ul {
84 | margin: 0;
85 | }
86 | li {
87 | margin-top: .5em;
88 | }
89 |
90 | .errors {
91 | background-color: #ffAAAA;
92 | }
93 | .warn {
94 | background-color: #FFFF33;
95 | }
96 | .pass {
97 | background-color: #66FF66;
98 | }
99 | ul.errors, ul.warn, ul.pass {
100 | margin: 0;
101 | padding: 1em;
102 | }
103 | legend {
104 | font-size:large;
105 | }
--------------------------------------------------------------------------------
/skin/small_logo_sc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SecurityCompass/SQL-Inject-Me/e616319dec89e41dc7f663b63cf68a79b253ba05/skin/small_logo_sc.png
--------------------------------------------------------------------------------
/skin/sqlime_sidebar.css:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2007 Security Compass
3 |
4 | This file is part of SQL Inject Me.
5 |
6 | SQL Inject 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 | SQL Inject 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 SQL Inject Me. If not, see .
18 | */
19 |
20 | #form1_field1_menulist.activated .menulist-editable-input,
21 | #form1_field2_menulist.activated .menulist-editable-input,
22 | .activated .menulist-editable-input
23 | {
24 | background-color: #FFFF11 !important;
25 | }
26 |
27 | #form1_field1_checkbox .checkbox-label-box,
28 | #form1_field2_checkbox .checkbox-label-box,
29 | .nolabel .checkbox-label-box
30 | {
31 | display: none;
32 | }
33 |
34 | .title {
35 | color: #405068 !important;
36 | }
--------------------------------------------------------------------------------
/skin/tiny_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SecurityCompass/SQL-Inject-Me/e616319dec89e41dc7f663b63cf68a79b253ba05/skin/tiny_logo.png
--------------------------------------------------------------------------------
/skin/toolbar-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SecurityCompass/SQL-Inject-Me/e616319dec89e41dc7f663b63cf68a79b253ba05/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 | #generatingReport {
35 | visibility: collapse;
36 | }
--------------------------------------------------------------------------------
/update.rdf:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | 0.2.0
12 |
13 |
14 |
15 |
16 | {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
17 | 2.0.0.9
18 | 2.0.0.*
19 |
20 |
21 |
22 | https://www.mysite.com/foobar2.2.xpi
23 |
24 |
25 |
26 | http://www.mysite.com/updateinfo2.2.xhtml
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------