diff --git a/vendor/wheels/model/properties.cfc b/vendor/wheels/model/properties.cfc index 66d813d66..27aea2053 100644 --- a/vendor/wheels/model/properties.cfc +++ b/vendor/wheels/model/properties.cfc @@ -750,8 +750,11 @@ component { local.val = Replace(local.val, ";", "", "all"); // Strip dangerous SQL keywords that could be used for injection. // Word-boundary matching prevents false positives in normal values. - local.val = REReplaceNoCase(local.val, "\b(UNION|EXEC|EXECUTE|BENCHMARK|SLEEP)\b", "", "all"); + local.val = REReplaceNoCase(local.val, "\b(UNION|EXEC|EXECUTE|BENCHMARK|SLEEP|WAITFOR|DELAY)\b", "", "all"); local.val = REReplaceNoCase(local.val, "\bxp_\w*", "", "all"); + local.val = REReplaceNoCase(local.val, "\bINTO\s+OUTFILE\b", "", "all"); + local.val = REReplaceNoCase(local.val, "\bLOAD_FILE\s*\(", "(", "all"); + local.val = REReplaceNoCase(local.val, "\bCHAR\s*\(", "(", "all"); local.sanitized[local.key] = $escapeSqlValue(local.val); } else { local.sanitized[local.key] = local.val; diff --git a/vendor/wheels/tests/specs/model/scopeHandlerSanitizationSpec.cfc b/vendor/wheels/tests/specs/model/scopeHandlerSanitizationSpec.cfc index 8c34ac4be..08041684d 100644 --- a/vendor/wheels/tests/specs/model/scopeHandlerSanitizationSpec.cfc +++ b/vendor/wheels/tests/specs/model/scopeHandlerSanitizationSpec.cfc @@ -179,6 +179,46 @@ component extends="wheels.WheelsTest" { expect(result["1"]).toBe("executor"); }); + it("strips WAITFOR and DELAY keywords from time-based injection", () => { + var m = application.wo.model("author"); + var result = m.$sanitizeScopeHandlerArgs({"1": "WAITFOR DELAY ''00:00:05''"}); + + expect(result["1"]).notToInclude("WAITFOR"); + expect(result["1"]).notToInclude("DELAY"); + }); + + it("strips INTO OUTFILE from file-write injection", () => { + var m = application.wo.model("author"); + var result = m.$sanitizeScopeHandlerArgs({"1": "test'' INTO OUTFILE ''/tmp/dump"}); + + expect(result["1"]).notToInclude("INTO OUTFILE"); + }); + + it("strips LOAD_FILE function from file-read injection", () => { + var m = application.wo.model("author"); + var result = m.$sanitizeScopeHandlerArgs({"1": "LOAD_FILE(''/etc/passwd'')"}); + + expect(result["1"]).notToInclude("LOAD_FILE"); + }); + + it("strips CHAR function from encoding bypass injection", () => { + var m = application.wo.model("author"); + var result = m.$sanitizeScopeHandlerArgs({"1": "CHAR(0x41)"}); + + expect(result["1"]).notToInclude("CHAR("); + }); + + it("does not strip DELAY or WAITFOR as partial word matches", () => { + var m = application.wo.model("author"); + var result = m.$sanitizeScopeHandlerArgs({"1": "delayed"}); + + expect(result["1"]).toBe("delayed"); + + var result2 = m.$sanitizeScopeHandlerArgs({"1": "waitforward"}); + + expect(result2["1"]).toBe("waitforward"); + }); + }); }