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