From f2e7353ff5214e2fff5d47a91a51a2579f88eb81 Mon Sep 17 00:00:00 2001 From: Hans Ott Date: Thu, 7 Mar 2024 18:32:07 +0100 Subject: [PATCH] Split tests --- .../detectSQLInjection.mysql.test.ts | 40 ++ .../detectSQLInjection.postgres.test.ts | 42 ++ .../sql-injection/detectSQLInjection.test.ts | 125 ++---- .../dialect/SQLDialectPostgres.ts | 371 +----------------- .../sql-injection/payloads/README.md | 1 + .../userInputContainsSQLSyntax.ts | 7 +- 6 files changed, 119 insertions(+), 467 deletions(-) create mode 100644 library/src/vulnerabilities/sql-injection/detectSQLInjection.mysql.test.ts create mode 100644 library/src/vulnerabilities/sql-injection/detectSQLInjection.postgres.test.ts create mode 100644 library/src/vulnerabilities/sql-injection/payloads/README.md diff --git a/library/src/vulnerabilities/sql-injection/detectSQLInjection.mysql.test.ts b/library/src/vulnerabilities/sql-injection/detectSQLInjection.mysql.test.ts new file mode 100644 index 000000000..f0c6606cb --- /dev/null +++ b/library/src/vulnerabilities/sql-injection/detectSQLInjection.mysql.test.ts @@ -0,0 +1,40 @@ +import { basename, join } from "path"; +import * as t from "tap"; +import { readFileSync } from "fs"; +import { detectSQLInjection } from "./detectSQLInjection"; +import { SQLDialectMySQL } from "./dialect/SQLDialectMySQL"; + +t.test("It flags MySQL bitwise operator as SQL injection", async () => { + isSqlInjection("SELECT 10 ^ 12", "10 ^ 12"); +}); + +const files = [ + join(__dirname, "payloads", "Auth_Bypass.txt"), + join(__dirname, "payloads", "mysql.txt"), +]; + +for (const file of files) { + const contents = readFileSync(file, "utf-8"); + const lines = contents.split(/\r?\n/); + for (const sql of lines) { + const source = `${sql} (${basename(file)})`; + t.test( + `It flags ${sql} from ${basename(file)} as SQL injection`, + async () => { + t.same( + detectSQLInjection(sql, sql, new SQLDialectMySQL()), + true, + source + ); + } + ); + } +} + +function isSqlInjection(sql: string, input: string) { + t.same(detectSQLInjection(sql, input, new SQLDialectMySQL()), true, sql); +} + +function isNotSqlInjection(sql: string, input: string) { + t.same(detectSQLInjection(sql, input, new SQLDialectMySQL()), false, sql); +} diff --git a/library/src/vulnerabilities/sql-injection/detectSQLInjection.postgres.test.ts b/library/src/vulnerabilities/sql-injection/detectSQLInjection.postgres.test.ts new file mode 100644 index 000000000..2d3e71d78 --- /dev/null +++ b/library/src/vulnerabilities/sql-injection/detectSQLInjection.postgres.test.ts @@ -0,0 +1,42 @@ +import { basename, join } from "path"; +import * as t from "tap"; +import { readFileSync } from "fs"; +import { dangerousCharsInInput } from "./dangerousCharsInInput"; +import { detectSQLInjection } from "./detectSQLInjection"; +import { SQLDialectPostgres } from "./dialect/SQLDialectPostgres"; + +t.test("It flags postgres bitwise operator as SQL injection", async () => { + isSqlInjection("SELECT 10 # 12", "10 # 12"); +}); + +t.test("It flags postgres type cast operator as SQL injection", async () => { + isSqlInjection("SELECT abc::date", "abc::date"); +}); + +const files = [join(__dirname, "payloads", "postgres.txt")]; + +for (const file of files) { + const contents = readFileSync(file, "utf-8"); + const lines = contents.split(/\r?\n/); + for (const sql of lines) { + const source = `${sql} (${basename(file)})`; + t.test( + `It flags ${sql} from ${basename(file)} as SQL injection`, + async () => { + t.same( + detectSQLInjection(sql, sql, new SQLDialectPostgres()), + true, + source + ); + } + ); + } +} + +function isSqlInjection(sql: string, input: string) { + t.same(detectSQLInjection(sql, input, new SQLDialectPostgres()), true, sql); +} + +function isNotSqlInjection(sql: string, input: string) { + t.same(detectSQLInjection(sql, input, new SQLDialectPostgres()), false, sql); +} diff --git a/library/src/vulnerabilities/sql-injection/detectSQLInjection.test.ts b/library/src/vulnerabilities/sql-injection/detectSQLInjection.test.ts index e895d79f0..b85edbafe 100644 --- a/library/src/vulnerabilities/sql-injection/detectSQLInjection.test.ts +++ b/library/src/vulnerabilities/sql-injection/detectSQLInjection.test.ts @@ -4,10 +4,10 @@ import { readFileSync } from "fs"; import { dangerousCharsInInput } from "./dangerousCharsInInput"; import { detectSQLInjection, - userInputOccurrencesSafelyEncapsulated, queryContainsUserInput, } from "./detectSQLInjection"; import { SQLDialectMySQL } from "./dialect/SQLDialectMySQL"; +import { SQLDialectPostgres } from "./dialect/SQLDialectPostgres"; const BAD_SQL_COMMANDS = [ // Check for SQL Commands like : INSERT or DROP @@ -40,10 +40,6 @@ const GOOD_SQL_COMMANDS = [ "Roses are reddelete are blue", "Roses are red WHEREis blue", "Roses are red ORis isAND", - // Check for some general statements - `abcdefghijklmnop@hotmail.com`, - // Test some special characters - "steve@yahoo.com", // Test SQL Function (that should not be blocked) "I was benchmark ing", "We were delay ed", @@ -54,9 +50,9 @@ const GOOD_SQL_COMMANDS = [ ]; const IS_NOT_INJECTION = [ - [`'UNION 123' UNION "UNION 123"`, "UNION 123"], // String encapsulation - [`'union' is not "UNION"`, "UNION!"], // String not present in SQL - [`"UNION;"`, "UNION;"], // String encapsulation + [`'UNION 123' UNION 'UNION 123'`, "UNION 123"], // String encapsulation + [`'union' is not 'UNION'`, "UNION!"], // String not present in SQL + [`'UNION;'`, "UNION;"], // String encapsulation ["SELECT * FROM table", "*"], ]; @@ -85,8 +81,6 @@ t.test("Test detectSQLInjection() function", async () => { } }); -// END TESTS WITH EXPLOITS FROM : https://github.com/payloadbox/sql-injection-payload-list/tree/master - t.test( "Test the detectSQLInjection() function to see if it detects SQL Functions", async () => { @@ -121,99 +115,37 @@ t.test("Test the queryContainsUserInput() function", async () => { t.same(queryContainsUserInput("Roses are red", "violet"), false); }); -t.test( - "Test the userInputOccurrencesSafelyEncapsulated() function", - async () => { - t.same( - userInputOccurrencesSafelyEncapsulated( - ` Hello Hello 'UNION'and also "UNION" `, - "UNION", - new SQLDialectMySQL() - ), - true - ); - t.same( - userInputOccurrencesSafelyEncapsulated( - `"UNION"`, - "UNION", - new SQLDialectMySQL() - ), - true - ); - t.same( - userInputOccurrencesSafelyEncapsulated( - ` 'UNION' `, - "UNION", - new SQLDialectMySQL() - ), - true - ); - t.same( - userInputOccurrencesSafelyEncapsulated( - `"UNION"'UNION'`, - "UNION", - new SQLDialectMySQL() - ), - true - ); - - t.same( - userInputOccurrencesSafelyEncapsulated( - `'UNION'"UNION"UNION`, - "UNION", - new SQLDialectMySQL() - ), - false - ); - t.same( - userInputOccurrencesSafelyEncapsulated( - `'UNION'UNION"UNION"`, - "UNION", - new SQLDialectMySQL() - ), - false - ); - t.same( - userInputOccurrencesSafelyEncapsulated( - "UNION", - "UNION", - new SQLDialectMySQL() - ), - false - ); - } -); - t.test("Test the dangerousCharsInInput() function", async () => { t.ok(dangerousCharsInInput("This is not ok--")); }); -t.test("It flags postgres bitwise operator as SQL injection", async () => { - isSqlInjection("SELECT 10 # 12", "10 # 12"); -}); - -t.test("It flags MySQL bitwise operator as SQL injection", async () => { - isSqlInjection("SELECT 10 ^ 12", "10 ^ 12"); -}); - -t.test("It flags postgres type cast operator as SQL injection", async () => { - isSqlInjection("SELECT abc::date", "abc::date"); -}); - function isSqlInjection(sql: string, input: string) { - t.same(detectSQLInjection(sql, input, new SQLDialectMySQL()), true, sql); + t.same( + detectSQLInjection(sql, input, new SQLDialectMySQL()), + true, + sql + " (MySQL)" + ); + t.same( + detectSQLInjection(sql, input, new SQLDialectPostgres()), + true, + sql + " (Postgres)" + ); } function isNotSqlInjection(sql: string, input: string) { - t.same(detectSQLInjection(sql, input, new SQLDialectMySQL()), false, sql); + t.same( + detectSQLInjection(sql, input, new SQLDialectMySQL()), + false, + sql + " (MySQL)" + ); + t.same( + detectSQLInjection(sql, input, new SQLDialectPostgres()), + false, + sql + " (Postgres)" + ); } -const files = [ - // Taken from https://github.com/payloadbox/sql-injection-payload-list/tree/master - join(__dirname, "payloads", "Auth_Bypass.txt"), - join(__dirname, "payloads", "postgres.txt"), - join(__dirname, "payloads", "mysql.txt"), -]; +const files = [join(__dirname, "payloads", "Auth_Bypass.txt")]; for (const file of files) { const contents = readFileSync(file, "utf-8"); @@ -226,7 +158,12 @@ for (const file of files) { t.same( detectSQLInjection(sql, sql, new SQLDialectMySQL()), true, - source + source + " (MySQL)" + ); + t.same( + detectSQLInjection(sql, sql, new SQLDialectPostgres()), + true, + source + " (Postgres)" ); } ); diff --git a/library/src/vulnerabilities/sql-injection/dialect/SQLDialectPostgres.ts b/library/src/vulnerabilities/sql-injection/dialect/SQLDialectPostgres.ts index 8f09e350f..febe8772b 100644 --- a/library/src/vulnerabilities/sql-injection/dialect/SQLDialectPostgres.ts +++ b/library/src/vulnerabilities/sql-injection/dialect/SQLDialectPostgres.ts @@ -211,28 +211,23 @@ export class SQLDialectPostgres implements SQLDialect { "#>>", "~~", "@?", + "::", ]; } // https://www.postgresql.org/docs/current/sql-keywords-appendix.html getKeywords(): string[] { return [ - "A", "ABORT", - "ABS", "ABSENT", "ABSOLUTE", "ACCESS", - "ACCORDING", - "ACOS", "ACTION", - "ADA", "ADD", "ADMIN", "AFTER", "AGGREGATE", "ALL", - "ALLOCATE", "ALSO", "ALTER", "ALWAYS", @@ -240,234 +235,124 @@ export class SQLDialectPostgres implements SQLDialect { "ANALYZE", "AND", "ANY", - "ANY_VALUE", - "ARE", "ARRAY", - "ARRAY_AGG", - "ARRAY_MAX_CARDINALITY", "AS", "ASC", "ASENSITIVE", - "ASIN", "ASSERTION", "ASSIGNMENT", "ASYMMETRIC", "AT", - "ATAN", "ATOMIC", "ATTACH", "ATTRIBUTE", - "ATTRIBUTES", "AUTHORIZATION", - "AVG", "BACKWARD", - "BASE64", "BEFORE", "BEGIN", - "BEGIN_FRAME", - "BEGIN_PARTITION", - "BERNOULLI", "BETWEEN", "BIGINT", "BINARY", "BIT", - "BIT_LENGTH", - "BLOB", - "BLOCKED", - "BOM", "BOOLEAN", "BOTH", "BREADTH", - "BTRIM", "BY", - "C", "CACHE", "CALL", "CALLED", - "CARDINALITY", "CASCADE", "CASCADED", "CASE", "CAST", "CATALOG", - "CATALOG_NAME", - "CEIL", - "CEILING", "CHAIN", - "CHAINING", "CHAR", "CHARACTER", "CHARACTERISTICS", - "CHARACTERS", - "CHARACTER_LENGTH", - "CHARACTER_SET_CATALOG", - "CHARACTER_SET_NAME", - "CHARACTER_SET_SCHEMA", - "CHAR_LENGTH", "CHECK", "CHECKPOINT", "CLASS", - "CLASSIFIER", - "CLASS_ORIGIN", - "CLOB", "CLOSE", "CLUSTER", "COALESCE", - "COBOL", "COLLATE", "COLLATION", - "COLLATION_CATALOG", - "COLLATION_NAME", - "COLLATION_SCHEMA", - "COLLECT", "COLUMN", "COLUMNS", - "COLUMN_NAME", - "COMMAND_FUNCTION", - "COMMAND_FUNCTION_CODE", "COMMENT", "COMMENTS", "COMMIT", "COMMITTED", "COMPRESSION", "CONCURRENTLY", - "CONDITION", - "CONDITIONAL", - "CONDITION_NUMBER", "CONFIGURATION", "CONFLICT", - "CONNECT", "CONNECTION", - "CONNECTION_NAME", "CONSTRAINT", "CONSTRAINTS", - "CONSTRAINT_CATALOG", - "CONSTRAINT_NAME", - "CONSTRAINT_SCHEMA", - "CONSTRUCTOR", - "CONTAINS", "CONTENT", "CONTINUE", - "CONTROL", "CONVERSION", - "CONVERT", - "COPARTITION", "COPY", - "CORR", - "CORRESPONDING", - "COS", - "COSH", "COST", - "COUNT", - "COVAR_POP", - "COVAR_SAMP", "CREATE", "CROSS", "CSV", "CUBE", - "CUME_DIST", "CURRENT", "CURRENT_CATALOG", "CURRENT_DATE", - "CURRENT_DEFAULT_TRANSFORM_GROUP", - "CURRENT_PATH", "CURRENT_ROLE", - "CURRENT_ROW", "CURRENT_SCHEMA", "CURRENT_TIME", "CURRENT_TIMESTAMP", - "CURRENT_TRANSFORM_GROUP_FOR_TYPE", "CURRENT_USER", "CURSOR", - "CURSOR_NAME", "CYCLE", "DATA", "DATABASE", - "DATALINK", - "DATE", - "DATETIME_INTERVAL_CODE", - "DATETIME_INTERVAL_PRECISION", "DAY", - "DB", "DEALLOCATE", "DEC", - "DECFLOAT", "DECIMAL", "DECLARE", "DEFAULT", "DEFAULTS", "DEFERRABLE", "DEFERRED", - "DEFINE", - "DEFINED", "DEFINER", - "DEGREE", "DELETE", "DELIMITER", "DELIMITERS", - "DENSE_RANK", "DEPENDS", "DEPTH", - "DEREF", - "DERIVED", "DESC", - "DESCRIBE", - "DESCRIPTOR", "DETACH", - "DETERMINISTIC", - "DIAGNOSTICS", "DICTIONARY", "DISABLE", "DISCARD", - "DISCONNECT", - "DISPATCH", "DISTINCT", - "DLNEWCOPY", - "DLPREVIOUSCOPY", - "DLURLCOMPLETE", - "DLURLCOMPLETEONLY", - "DLURLCOMPLETEWRITE", - "DLURLPATH", - "DLURLPATHONLY", - "DLURLPATHWRITE", - "DLURLSCHEME", - "DLURLSERVER", - "DLVALUE", "DO", "DOCUMENT", "DOMAIN", "DOUBLE", "DROP", - "DYNAMIC", - "DYNAMIC_FUNCTION", - "DYNAMIC_FUNCTION_CODE", "EACH", - "ELEMENT", "ELSE", - "EMPTY", "ENABLE", "ENCODING", "ENCRYPTED", "END", - "END-EXEC", - "END_FRAME", - "END_PARTITION", - "ENFORCED", "ENUM", - "EQUALS", - "ERROR", "ESCAPE", "EVENT", - "EVERY", "EXCEPT", - "EXCEPTION", "EXCLUDE", "EXCLUDING", "EXCLUSIVE", - "EXEC", "EXECUTE", "EXISTS", - "EXP", "EXPLAIN", "EXPRESSION", "EXTENSION", @@ -476,41 +361,23 @@ export class SQLDialectPostgres implements SQLDialect { "FALSE", "FAMILY", "FETCH", - "FILE", "FILTER", - "FINAL", "FINALIZE", - "FINISH", "FIRST", - "FIRST_VALUE", - "FLAG", "FLOAT", - "FLOOR", "FOLLOWING", "FOR", "FORCE", "FOREIGN", "FORMAT", - "FORTRAN", "FORWARD", - "FOUND", - "FRAME_ROW", - "FREE", "FREEZE", "FROM", - "FS", - "FULFILL", "FULL", "FUNCTION", "FUNCTIONS", - "FUSION", - "G", - "GENERAL", "GENERATED", - "GET", "GLOBAL", - "GO", - "GOTO", "GRANT", "GRANTED", "GREATEST", @@ -520,19 +387,13 @@ export class SQLDialectPostgres implements SQLDialect { "HANDLER", "HAVING", "HEADER", - "HEX", - "HIERARCHY", "HOLD", "HOUR", - "ID", "IDENTITY", "IF", - "IGNORE", "ILIKE", "IMMEDIATE", - "IMMEDIATELY", "IMMUTABLE", - "IMPLEMENTATION", "IMPLICIT", "IMPORT", "IN", @@ -542,10 +403,8 @@ export class SQLDialectPostgres implements SQLDialect { "INDENT", "INDEX", "INDEXES", - "INDICATOR", "INHERIT", "INHERITS", - "INITIAL", "INITIALLY", "INLINE", "INNER", @@ -553,14 +412,10 @@ export class SQLDialectPostgres implements SQLDialect { "INPUT", "INSENSITIVE", "INSERT", - "INSTANCE", - "INSTANTIABLE", "INSTEAD", "INT", "INTEGER", - "INTEGRITY", "INTERSECT", - "INTERSECTION", "INTERVAL", "INTO", "INVOKER", @@ -571,103 +426,54 @@ export class SQLDialectPostgres implements SQLDialect { "JSON", "JSON_ARRAY", "JSON_ARRAYAGG", - "JSON_EXISTS", "JSON_OBJECT", "JSON_OBJECTAGG", - "JSON_QUERY", - "JSON_SCALAR", - "JSON_SERIALIZE", - "JSON_TABLE", - "JSON_TABLE_PRIMITIVE", - "JSON_VALUE", - "K", - "KEEP", "KEY", "KEYS", - "KEY_MEMBER", - "KEY_TYPE", "LABEL", - "LAG", "LANGUAGE", "LARGE", "LAST", - "LAST_VALUE", "LATERAL", - "LEAD", "LEADING", "LEAKPROOF", "LEAST", "LEFT", - "LENGTH", "LEVEL", - "LIBRARY", "LIKE", - "LIKE_REGEX", "LIMIT", - "LINK", - "LISTAGG", "LISTEN", - "LN", "LOAD", "LOCAL", "LOCALTIME", "LOCALTIMESTAMP", "LOCATION", - "LOCATOR", "LOCK", "LOCKED", - "LOG", - "LOG10", "LOGGED", - "LOWER", - "LPAD", - "LTRIM", - "M", - "MAP", "MAPPING", "MATCH", "MATCHED", - "MATCHES", - "MATCH_NUMBER", - "MATCH_RECOGNIZE", "MATERIALIZED", - "MAX", "MAXVALUE", - "MEASURES", - "MEMBER", "MERGE", - "MESSAGE_LENGTH", - "MESSAGE_OCTET_LENGTH", - "MESSAGE_TEXT", "METHOD", - "MIN", "MINUTE", "MINVALUE", - "MOD", "MODE", - "MODIFIES", - "MODULE", "MONTH", - "MORE", "MOVE", - "MULTISET", - "MUMPS", "NAME", "NAMES", - "NAMESPACE", "NATIONAL", "NATURAL", "NCHAR", - "NCLOB", - "NESTED", - "NESTING", "NEW", "NEXT", "NFC", "NFD", "NFKC", "NFKD", - "NIL", "NO", "NONE", "NORMALIZE", @@ -677,130 +483,68 @@ export class SQLDialectPostgres implements SQLDialect { "NOTIFY", "NOTNULL", "NOWAIT", - "NTH_VALUE", - "NTILE", "NULL", - "NULLABLE", "NULLIF", "NULLS", - "NULL_ORDERING", - "NUMBER", "NUMERIC", "OBJECT", - "OCCURRENCE", - "OCCURRENCES_REGEX", - "OCTETS", - "OCTET_LENGTH", "OF", "OFF", "OFFSET", "OIDS", "OLD", - "OMIT", "ON", - "ONE", "ONLY", - "OPEN", "OPERATOR", "OPTION", "OPTIONS", "OR", "ORDER", - "ORDERING", "ORDINALITY", "OTHERS", "OUT", "OUTER", - "OUTPUT", "OVER", - "OVERFLOW", "OVERLAPS", "OVERLAY", "OVERRIDING", "OWNED", "OWNER", - "P", - "PAD", "PARALLEL", "PARAMETER", - "PARAMETER_MODE", - "PARAMETER_NAME", - "PARAMETER_ORDINAL_POSITION", - "PARAMETER_SPECIFIC_CATALOG", - "PARAMETER_SPECIFIC_NAME", - "PARAMETER_SPECIFIC_SCHEMA", "PARSER", "PARTIAL", "PARTITION", - "PASCAL", - "PASS", "PASSING", - "PASSTHROUGH", "PASSWORD", - "PAST", - "PATH", - "PATTERN", - "PER", - "PERCENT", - "PERCENTILE_CONT", - "PERCENTILE_DISC", - "PERCENT_RANK", - "PERIOD", - "PERMISSION", - "PERMUTE", - "PIPE", "PLACING", - "PLAN", "PLANS", - "PLI", "POLICY", - "PORTION", "POSITION", - "POSITION_REGEX", - "POWER", - "PRECEDES", "PRECEDING", "PRECISION", "PREPARE", "PREPARED", "PRESERVE", - "PREV", "PRIMARY", "PRIOR", - "PRIVATE", "PRIVILEGES", "PROCEDURAL", "PROCEDURE", "PROCEDURES", "PROGRAM", - "PRUNE", - "PTF", - "PUBLIC", "PUBLICATION", "QUOTE", - "QUOTES", "RANGE", - "RANK", "READ", - "READS", "REAL", "REASSIGN", "RECHECK", - "RECOVERY", "RECURSIVE", "REF", "REFERENCES", "REFERENCING", "REFRESH", - "REGR_AVGX", - "REGR_AVGY", - "REGR_COUNT", - "REGR_INTERCEPT", - "REGR_R2", - "REGR_SLOPE", - "REGR_SXX", - "REGR_SXY", - "REGR_SYY", "REINDEX", "RELATIVE", "RELEASE", @@ -808,18 +552,10 @@ export class SQLDialectPostgres implements SQLDialect { "REPEATABLE", "REPLACE", "REPLICA", - "REQUIRING", "RESET", - "RESPECT", "RESTART", - "RESTORE", "RESTRICT", - "RESULT", "RETURN", - "RETURNED_CARDINALITY", - "RETURNED_LENGTH", - "RETURNED_OCTET_LENGTH", - "RETURNED_SQLSTATE", "RETURNING", "RETURNS", "REVOKE", @@ -829,43 +565,22 @@ export class SQLDialectPostgres implements SQLDialect { "ROLLUP", "ROUTINE", "ROUTINES", - "ROUTINE_CATALOG", - "ROUTINE_NAME", - "ROUTINE_SCHEMA", "ROW", "ROWS", - "ROW_COUNT", - "ROW_NUMBER", - "RPAD", - "RTRIM", "RULE", - "RUNNING", "SAVEPOINT", "SCALAR", - "SCALE", "SCHEMA", "SCHEMAS", - "SCHEMA_NAME", - "SCOPE", - "SCOPE_CATALOG", - "SCOPE_NAME", - "SCOPE_SCHEMA", "SCROLL", "SEARCH", "SECOND", - "SECTION", "SECURITY", - "SEEK", "SELECT", - "SELECTIVE", - "SELF", - "SEMANTICS", - "SENSITIVE", "SEQUENCE", "SEQUENCES", "SERIALIZABLE", "SERVER", - "SERVER_NAME", "SESSION", "SESSION_USER", "SET", @@ -875,97 +590,48 @@ export class SQLDialectPostgres implements SQLDialect { "SHOW", "SIMILAR", "SIMPLE", - "SIN", - "SINH", - "SIZE", "SKIP", "SMALLINT", "SNAPSHOT", "SOME", - "SORT_DIRECTION", - "SOURCE", - "SPACE", - "SPECIFIC", - "SPECIFICTYPE", - "SPECIFIC_NAME", "SQL", - "SQLCODE", - "SQLERROR", - "SQLEXCEPTION", - "SQLSTATE", - "SQLWARNING", - "SQRT", "STABLE", "STANDALONE", "START", - "STATE", "STATEMENT", - "STATIC", "STATISTICS", - "STDDEV_POP", - "STDDEV_SAMP", "STDIN", "STDOUT", "STORAGE", "STORED", "STRICT", - "STRING", "STRIP", - "STRUCTURE", - "STYLE", - "SUBCLASS_ORIGIN", - "SUBMULTISET", "SUBSCRIPTION", - "SUBSET", "SUBSTRING", - "SUBSTRING_REGEX", - "SUCCEEDS", - "SUM", "SUPPORT", "SYMMETRIC", "SYSID", "SYSTEM", - "SYSTEM_TIME", "SYSTEM_USER", - "T", "TABLE", "TABLES", "TABLESAMPLE", "TABLESPACE", - "TABLE_NAME", - "TAN", - "TANH", "TEMP", "TEMPLATE", "TEMPORARY", "TEXT", "THEN", - "THROUGH", "TIES", "TIME", "TIMESTAMP", - "TIMEZONE_HOUR", - "TIMEZONE_MINUTE", "TO", - "TOKEN", - "TOP_LEVEL_COUNT", "TRAILING", "TRANSACTION", - "TRANSACTIONS_COMMITTED", - "TRANSACTIONS_ROLLED_BACK", - "TRANSACTION_ACTIVE", "TRANSFORM", - "TRANSFORMS", - "TRANSLATE", - "TRANSLATE_REGEX", - "TRANSLATION", "TREAT", "TRIGGER", - "TRIGGER_CATALOG", - "TRIGGER_NAME", - "TRIGGER_SCHEMA", "TRIM", - "TRIM_ARRAY", "TRUE", "TRUNCATE", "TRUSTED", @@ -974,57 +640,33 @@ export class SQLDialectPostgres implements SQLDialect { "UESCAPE", "UNBOUNDED", "UNCOMMITTED", - "UNCONDITIONAL", - "UNDER", "UNENCRYPTED", "UNION", "UNIQUE", "UNKNOWN", - "UNLINK", "UNLISTEN", "UNLOGGED", - "UNMATCHED", - "UNNAMED", - "UNNEST", "UNTIL", - "UNTYPED", "UPDATE", - "UPPER", - "URI", - "USAGE", "USER", - "USER_DEFINED_TYPE_CATALOG", - "USER_DEFINED_TYPE_CODE", - "USER_DEFINED_TYPE_NAME", - "USER_DEFINED_TYPE_SCHEMA", "USING", - "UTF16", - "UTF32", - "UTF8", "VACUUM", "VALID", "VALIDATE", "VALIDATOR", "VALUE", "VALUES", - "VALUE_OF", - "VARBINARY", "VARCHAR", "VARIADIC", "VARYING", - "VAR_POP", - "VAR_SAMP", "VERBOSE", "VERSION", - "VERSIONING", "VIEW", "VIEWS", "VOLATILE", "WHEN", - "WHENEVER", "WHERE", "WHITESPACE", - "WIDTH_BUCKET", "WINDOW", "WITH", "WITHIN", @@ -1033,28 +675,17 @@ export class SQLDialectPostgres implements SQLDialect { "WRAPPER", "WRITE", "XML", - "XMLAGG", "XMLATTRIBUTES", - "XMLBINARY", - "XMLCAST", - "XMLCOMMENT", "XMLCONCAT", - "XMLDECLARATION", - "XMLDOCUMENT", "XMLELEMENT", "XMLEXISTS", "XMLFOREST", - "XMLITERATE", "XMLNAMESPACES", "XMLPARSE", "XMLPI", - "XMLQUERY", "XMLROOT", - "XMLSCHEMA", "XMLSERIALIZE", "XMLTABLE", - "XMLTEXT", - "XMLVALIDATE", "YEAR", "YES", "ZONE", diff --git a/library/src/vulnerabilities/sql-injection/payloads/README.md b/library/src/vulnerabilities/sql-injection/payloads/README.md new file mode 100644 index 000000000..ead5bde13 --- /dev/null +++ b/library/src/vulnerabilities/sql-injection/payloads/README.md @@ -0,0 +1 @@ +These files come from https://github.com/payloadbox/sql-injection-payload-list/tree/master. diff --git a/library/src/vulnerabilities/sql-injection/userInputContainsSQLSyntax.ts b/library/src/vulnerabilities/sql-injection/userInputContainsSQLSyntax.ts index 308ecc61b..72caf2b64 100644 --- a/library/src/vulnerabilities/sql-injection/userInputContainsSQLSyntax.ts +++ b/library/src/vulnerabilities/sql-injection/userInputContainsSQLSyntax.ts @@ -1,12 +1,13 @@ import { escapeStringRegexp } from "../../helpers/escapeStringRegexp"; import { SQLDialect } from "./dialect/SQLDialect"; +import { SQLDialectPostgres } from "./dialect/SQLDialectPostgres"; function compileSqlRegex(dialect: SQLDialect): RegExp { const operators = dialect.getOperators(); const keywords = dialect.getKeywords(); const matchSqlKeywords = "(?