forked from ServiceNowDevProgram/code-snippets
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSQLInjectionChecker.js
More file actions
304 lines (269 loc) · 13 KB
/
SQLInjectionChecker.js
File metadata and controls
304 lines (269 loc) · 13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
/**
* SQLInjectionValidator
*
* Script Include for detecting potential SQL injection attempts in user-provided strings.
*
* Purpose:
* Validates user input against a comprehensive list of SQL injection patterns including
* keywords, operators, comment syntax, and common attack vectors.
*
* Usage:
* var validator = new SQLInjectionValidator();
* var isSafe = validator.isSafeFromSQLInjection(userInput);
*
* Performance Considerations:
* - Uses efficient string methods (toLowerCase, includes) for keyword detection
* - Regex patterns are pre-compiled for performance
* - Early exit on first match to minimize processing
* - Suitable for high-volume input validation
*
* Security Note:
* This function provides pattern-based detection and should be used as ONE LAYER
* of defense. Always use parameterized queries and prepared statements in your
* database interactions as the PRIMARY defense against SQL injection.
*
* @class SQLInjectionValidator
*/
var SQLInjectionValidator = Class.create();
SQLInjectionValidator.prototype = {
/**
* Checks if a string appears safe from SQL injection attempts
*
* @param {string} inputString - The user-provided string to validate
* @returns {boolean} true if string appears safe, false if suspicious patterns detected
*/
isSafeFromSQLInjection: function(inputString) {
// Input validation: ensure we have a string
if (typeof inputString !== 'string') {
gs.debug('SQLInjectionValidator: Input is not a string, converting to string');
inputString = String(inputString);
}
// Empty strings are considered safe
if (inputString.length === 0) {
return true;
}
// Convert to lowercase for case-insensitive comparison
var lowerInput = inputString.toLowerCase();
// ========== CHECK 1: SQL Keywords ==========
// Detects common SQL commands that could indicate injection attempts
var sqlKeywords = [
'select', 'insert', 'update', 'delete', 'drop', 'create', 'alter',
'truncate', 'exec', 'execute', 'union', 'declare', 'cast', 'convert'
];
for (var i = 0; i < sqlKeywords.length; i++) {
// Use word boundary regex to avoid false positives (e.g., "selected" vs "select")
var keywordRegex = new RegExp('\\b' + sqlKeywords[i] + '\\b', 'i');
if (keywordRegex.test(inputString)) {
gs.debug('SQLInjectionValidator: Detected SQL keyword: ' + sqlKeywords[i]);
return false;
}
}
// ========== CHECK 2: SQL Clauses ==========
// Detects FROM, WHERE, ORDER BY, GROUP BY, HAVING clauses
var sqlClauses = [
'from', 'where', 'order by', 'group by', 'having', 'join', 'inner join',
'left join', 'right join', 'cross join', 'on'
];
for (var j = 0; j < sqlClauses.length; j++) {
var clauseRegex = new RegExp('\\b' + sqlClauses[j] + '\\b', 'i');
if (clauseRegex.test(inputString)) {
gs.debug('SQLInjectionValidator: Detected SQL clause: ' + sqlClauses[j]);
return false;
}
}
// ========== CHECK 3: Comment Patterns ==========
// Detects SQL comment syntax: --, /* */, ;
var commentPatterns = [
/--\s/, // SQL line comment: -- followed by space
/\/\*/, // SQL block comment start: /*
/\*\//, // SQL block comment end: */
/;\s*$/, // Semicolon at end (statement terminator)
/;\s*select/i, // Semicolon followed by select
/;\s*insert/i, // Semicolon followed by insert
/;\s*update/i, // Semicolon followed by update
/;\s*delete/i // Semicolon followed by delete
];
for (var k = 0; k < commentPatterns.length; k++) {
if (commentPatterns[k].test(inputString)) {
gs.debug('SQLInjectionValidator: Detected comment pattern');
return false;
}
}
// ========== CHECK 4: Boolean-based Injection Patterns ==========
// Detects common boolean-based SQL injection: OR 1=1, AND 1=1, etc.
var booleanPatterns = [
/or\s+1\s*=\s*1/i, // OR 1=1
/and\s+1\s*=\s*1/i, // AND 1=1
/or\s+'1'\s*=\s*'1'/i, // OR '1'='1'
/and\s+'1'\s*=\s*'1'/i, // AND '1'='1'
/or\s+true/i, // OR TRUE
/and\s+true/i, // AND TRUE
/or\s+1/i, // OR 1 (generic)
/and\s+1/i, // AND 1 (generic)
/or\s+''/i, // OR ''
/and\s+''/i // AND ''
];
for (var l = 0; l < booleanPatterns.length; l++) {
if (booleanPatterns[l].test(inputString)) {
gs.debug('SQLInjectionValidator: Detected boolean-based injection pattern');
return false;
}
}
// ========== CHECK 5: Comparison Operators with Suspicious Values ==========
// Detects patterns like: = 1, != 0, <> 0, > 0, < 1
var comparisonPatterns = [
/=\s*1\s*$/i, // Ends with = 1
/!=\s*0/i, // != 0
/<>\s*0/i, // <> 0
/>\s*0/i, // > 0
/<\s*1/i // < 1
];
for (var m = 0; m < comparisonPatterns.length; m++) {
if (comparisonPatterns[m].test(inputString)) {
gs.debug('SQLInjectionValidator: Detected suspicious comparison pattern');
return false;
}
}
// ========== CHECK 6: SQL Functions ==========
// Detects SQL functions commonly used in injection: CHAR, ASCII, SUBSTRING, WAITFOR, SLEEP, BENCHMARK
var sqlFunctions = [
'char(', 'ascii(', 'substring(', 'waitfor(', 'sleep(', 'benchmark(',
'concat(', 'length(', 'mid(', 'instr(', 'load_file(', 'into outfile'
];
for (var n = 0; n < sqlFunctions.length; n++) {
if (lowerInput.includes(sqlFunctions[n])) {
gs.debug('SQLInjectionValidator: Detected SQL function: ' + sqlFunctions[n]);
return false;
}
}
// ========== CHECK 7: System Variables and Commands ==========
// Detects: @@VERSION, xp_cmdshell, sp_executesql, etc.
var systemPatterns = [
/@@version/i, // SQL Server version
/@@servername/i, // SQL Server name
/xp_cmdshell/i, // SQL Server command shell
/sp_executesql/i, // SQL Server execute SQL
/information_schema/i, // Database schema enumeration
/mysql\.user/i, // MySQL user table
/pg_catalog/i // PostgreSQL catalog
];
for (var o = 0; o < systemPatterns.length; o++) {
if (systemPatterns[o].test(inputString)) {
gs.debug('SQLInjectionValidator: Detected system variable or command');
return false;
}
}
// ========== CHECK 8: Quote Escaping and Concatenation ==========
// Detects: '', "", \', \", ||, +, CONCAT
var escapePatterns = [
/''/, // Double single quote (escape)
/""/, // Double double quote (escape)
/\\'/ , // Backslash single quote
/\\"/, // Backslash double quote
/\|\|/, // Oracle/PostgreSQL concatenation
/\+\\s*'/i // SQL Server concatenation
];
for (var p = 0; p < escapePatterns.length; p++) {
if (escapePatterns[p].test(inputString)) {
gs.debug('SQLInjectionValidator: Detected quote escaping or concatenation pattern');
return false;
}
}
// ========== CHECK 9: UNION-based Injection ==========
// Detects UNION SELECT patterns
var unionPatterns = [
/union\s+select/i, // UNION SELECT
/union\s+all\s+select/i, // UNION ALL SELECT
/union\s+distinct\s+select/i // UNION DISTINCT SELECT
];
for (var q = 0; q < unionPatterns.length; q++) {
if (unionPatterns[q].test(inputString)) {
gs.debug('SQLInjectionValidator: Detected UNION-based injection pattern');
return false;
}
}
// ========== CHECK 10: Time-based Blind Injection ==========
// Detects: SLEEP, BENCHMARK, WAITFOR DELAY, pg_sleep
var timeBasedPatterns = [
/sleep\s*\(/i, // SLEEP function
/benchmark\s*\(/i, // BENCHMARK function
/waitfor\s+delay/i, // WAITFOR DELAY
/pg_sleep\s*\(/i // PostgreSQL sleep
];
for (var r = 0; r < timeBasedPatterns.length; r++) {
if (timeBasedPatterns[r].test(inputString)) {
gs.debug('SQLInjectionValidator: Detected time-based blind injection pattern');
return false;
}
}
// ========== CHECK 11: Stacked Queries ==========
// Detects multiple statements separated by semicolons
var stackedQueryPattern = /;\s*[a-z]/i;
if (stackedQueryPattern.test(inputString)) {
gs.debug('SQLInjectionValidator: Detected stacked query pattern');
return false;
}
// ========== CHECK 12: Hex Encoding ==========
// Detects: 0x (hex encoding used to bypass filters)
var hexPattern = /0x[0-9a-f]+/i;
if (hexPattern.test(inputString)) {
gs.debug('SQLInjectionValidator: Detected hex encoding pattern');
return false;
}
// ========== CHECK 13: Comment-based Injection ==========
// Detects: #, --, /*, */ patterns
var commentInjectionPatterns = [
/#/, // MySQL comment
/--/, // SQL comment
/\/\*/, // Block comment start
/\*\// // Block comment end
];
for (var s = 0; s < commentInjectionPatterns.length; s++) {
if (commentInjectionPatterns[s].test(inputString)) {
gs.debug('SQLInjectionValidator: Detected comment-based injection pattern');
return false;
}
}
// ========== CHECK 14: Wildcard Patterns ==========
// Detects: %, _ (SQL wildcards that could be used in LIKE injection)
// Note: This is a loose check - legitimate data may contain these
// Only flag if combined with suspicious patterns
var wildcardPattern = /[%_]\s*(or|and|union|select)/i;
if (wildcardPattern.test(inputString)) {
gs.debug('SQLInjectionValidator: Detected wildcard with SQL keyword pattern');
return false;
}
// ========== CHECK 15: Parentheses Nesting ==========
// Detects excessive parentheses which could indicate subquery injection
var openParens = (inputString.match(/\(/g) || []).length;
var closeParens = (inputString.match(/\)/g) || []).length;
// Flag if more than 3 levels of nesting or mismatched parentheses
if (openParens > 5 || closeParens > 5 || openParens !== closeParens) {
gs.debug('SQLInjectionValidator: Detected excessive or mismatched parentheses');
return false;
}
// ========== CHECK 16: Case Sensitivity Bypass ==========
// Detects: sElEcT, UnIoN, etc. (mixed case SQL keywords)
var mixedCasePattern = /[a-z]{2,}\s+[a-z]{2,}/i;
if (mixedCasePattern.test(inputString)) {
// Check if it matches known SQL keywords in mixed case
var mixedCaseKeywords = [
/s[eE][lL][eE][cC][tT]/,
/u[nN][iI][oO][nN]/,
/[iI][nN][sS][eE][rR][tT]/,
/[uU][pP][dD][aA][tT][eE]/,
/[dD][eE][lL][eE][tT][eE]/
];
for (var t = 0; t < mixedCaseKeywords.length; t++) {
if (mixedCaseKeywords[t].test(inputString)) {
gs.debug('SQLInjectionValidator: Detected mixed-case SQL keyword');
return false;
}
}
}
// ========== All checks passed ==========
gs.debug('SQLInjectionValidator: Input passed all SQL injection checks');
return true;
},
type: 'SQLInjectionValidator'
};