Skip to content

Commit

Permalink
Merge branch 'main' into patch-perf
Browse files Browse the repository at this point in the history
  • Loading branch information
hansott authored Mar 6, 2024
2 parents b46edd0 + 94aeb2a commit 40ae51d
Show file tree
Hide file tree
Showing 18 changed files with 80 additions and 106 deletions.
4 changes: 2 additions & 2 deletions end2end/tests/express-mongodb.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const t = require("tap");
const { spawn } = require("node:child_process");
const { resolve } = require("node:path");
const { spawn } = require("child_process");
const { resolve } = require("path");
const timeout = require("../timeout");

const pathToApp = resolve(
Expand Down
4 changes: 2 additions & 2 deletions end2end/tests/express-mongoose.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const t = require("tap");
const { spawn } = require("node:child_process");
const { resolve } = require("node:path");
const { spawn } = require("child_process");
const { resolve } = require("path");
const timeout = require("../timeout");

const pathToApp = resolve(
Expand Down
4 changes: 2 additions & 2 deletions end2end/tests/express-mysql.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const t = require("tap");
const { spawn } = require("node:child_process");
const { resolve } = require("node:path");
const { spawn } = require("child_process");
const { resolve } = require("path");
const timeout = require("../timeout");

const pathToApp = resolve(
Expand Down
4 changes: 2 additions & 2 deletions end2end/tests/express-mysql2.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const t = require("tap");
const { spawn } = require("node:child_process");
const { resolve } = require("node:path");
const { spawn } = require("child_process");
const { resolve } = require("path");
const timeout = require("../timeout");

const pathToApp = resolve(
Expand Down
4 changes: 2 additions & 2 deletions end2end/tests/express-postgres.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const t = require("tap");
const { spawn } = require("node:child_process");
const { resolve } = require("node:path");
const { spawn } = require("child_process");
const { resolve } = require("path");
const timeout = require("../timeout");

const pathToApp = resolve(
Expand Down
2 changes: 1 addition & 1 deletion library/src/agent/Agent.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { hostname, platform, release } from "node:os";
import { hostname, platform, release } from "os";
import * as t from "tap";
import { ip } from "../helpers/ipAddress";
import { MongoDB } from "../sinks/MongoDB";
Expand Down
2 changes: 1 addition & 1 deletion library/src/agent/Agent.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable max-lines-per-function */
import { hostname, platform, release } from "node:os";
import { hostname, platform, release } from "os";
import { convertRequestBodyToString } from "../helpers/convertRequestBodyToString";
import { getAgentVersion } from "../helpers/getAgentVersion";
import { ip } from "../helpers/ipAddress";
Expand Down
2 changes: 1 addition & 1 deletion library/src/agent/Context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AsyncLocalStorage } from "node:async_hooks";
import { AsyncLocalStorage } from "async_hooks";
import type { ParsedQs } from "qs";

export type Context = {
Expand Down
4 changes: 2 additions & 2 deletions library/src/agent/api/APIFetch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { request as requestHttp } from "node:http";
import { request as requestHttps } from "node:https";
import { request as requestHttp } from "http";
import { request as requestHttps } from "https";
import { API } from "./API";
import { Token } from "./Token";
import { Event } from "./Event";
Expand Down
2 changes: 1 addition & 1 deletion library/src/agent/applyHooks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable max-lines-per-function */
import { join } from "node:path";
import { join } from "path";
import { wrap } from "shimmer";
import { getPackageVersion } from "../helpers/getPackageVersion";
import { satisfiesVersion } from "../helpers/satisfiesVersion";
Expand Down
2 changes: 1 addition & 1 deletion library/src/sources/Express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { NextFunction, Request, Response } from "express";
import { runWithContext } from "../agent/Context";
import { Hooks } from "../agent/hooks/Hooks";
import { Wrapper } from "../agent/Wrapper";
import { METHODS } from "node:http";
import { METHODS } from "http";

type Middleware = (req: Request, resp: Response, next: NextFunction) => void;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isDeepStrictEqual } from "node:util";
import { isDeepStrictEqual } from "util";
import { Context } from "../../agent/Context";
import { Source } from "../../agent/Source";
import { buildPathToPayload, PathPart } from "../../helpers/attackPath";
Expand Down
3 changes: 3 additions & 0 deletions library/src/vulnerabilities/sql-injection/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ export const SQL_OPERATORS = [
"^",
">",
"<",
"#",
"::",
];

export const SQL_DANGEROUS_IN_STRING = [
Expand All @@ -96,6 +98,7 @@ export const SQL_DANGEROUS_IN_STRING = [
"`",
"/*", // Start of comment
"--", // Start of comment
"#", // Start of comment
];

export const SQL_STRING_CHARS = ['"', "'"];
147 changes: 59 additions & 88 deletions library/src/vulnerabilities/sql-injection/detectSQLInjection.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { basename, join } from "path";
import * as t from "tap";
import * as fs from "fs";
import { readFileSync } from "fs";
import * as path from "path";
import { dangerousCharsInInput } from "./dangerousCharsInInput";
import {
Expand Down Expand Up @@ -41,7 +42,6 @@ const GOOD_SQL_COMMANDS = [
"Roses are red ORis isAND",
// Check for some general statements
`[email protected]`,
`roses are red violets are blue#`,
// Test some special characters
"[email protected]",
// Test SQL Function (that should not be blocked)
Expand Down Expand Up @@ -85,78 +85,11 @@ t.test("Test detectSQLInjection() function", async () => {
}
});

// BEGIN TESTS WITH EXPLOITS FROM : https://github.com/payloadbox/sql-injection-payload-list/tree/master

const AUTH_BYPASS = fs
.readFileSync(
path.join(
__dirname,
"./../../../testing/sql-injection-payloads/Auth_Bypass.txt"
),
"utf-8"
)
.split(/\r?\n/);

t.test("Test the detectSQLInjection() with Auth_Bypass.txt", async () => {
for (const sql of AUTH_BYPASS) {
isSqlInjection(sql, sql);
}
});

const POSTGRES_TXT = fs
.readFileSync(
path.join(
__dirname,
"./../../../testing/sql-injection-payloads/postgres.txt"
),
"utf-8"
)
.split(/\r?\n/);

t.test("Test the detectSQLInjection() with postgres.txt", async () => {
for (const sql of POSTGRES_TXT) {
isSqlInjection(sql, sql);
}
});

const MYSQL_TXT = fs
.readFileSync(
path.join(__dirname, "./../../../testing/sql-injection-payloads/mysql.txt"),
"utf-8"
)
.split(/\r?\n/);

t.test(
"Test the detectSQLInjection() with postgres-enumeration.txt",
async () => {
for (const sql of MYSQL_TXT) {
isSqlInjection(sql, sql);
}
}
);

const MSSQL_AND_DB2 = fs
.readFileSync(
path.join(
__dirname,
"./../../../testing/sql-injection-payloads/mssql_and_db2.txt"
),
"utf-8"
)
.split(/\r?\n/);

t.test("Test the detectSQLInjection() with mssql_and_db2.txt", async () => {
for (const sql of MSSQL_AND_DB2) {
isSqlInjection(sql, sql);
}
});

// 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 () => {
// Keep in mind t.ok means that it IS in fact a SQL Injection
isSqlInjection("foobar()", "foobar()");
isSqlInjection("foobar(1234567)", "foobar(1234567)");
isSqlInjection("foobar ()", "foobar ()");
Expand All @@ -170,56 +103,94 @@ t.test(
isSqlInjection("1foobar()", "1foobar()");
isSqlInjection("1foo_bar()", "1foo_bar()");
isSqlInjection("1foo-bar()", "1foo-bar()");
isSqlInjection("#foobar()", "#foobar()");

isNotSqlInjection("foobar)", "foobar)");
isNotSqlInjection("foobar )", "foobar )");
isNotSqlInjection("#foobar()", "#foobar()");
isNotSqlInjection("$foobar()", "$foobar()");
}
);

t.test("Test the queryContainsUserInput() function", async () => {
t.ok(queryContainsUserInput("SELECT * FROM 'Jonas';", "Jonas"));
t.ok(queryContainsUserInput("Hi I'm MJoNaSs", "jonas"));
t.ok(queryContainsUserInput("Hiya, 123^&*( is a real string", "123^&*("));
t.notOk(queryContainsUserInput("Roses are red", "violet"));
t.same(queryContainsUserInput("SELECT * FROM 'Jonas';", "Jonas"), true);
t.same(queryContainsUserInput("Hi I'm MJoNaSs", "jonas"), true);
t.same(
queryContainsUserInput("Hiya, 123^&*( is a real string", "123^&*("),
true
);
t.same(queryContainsUserInput("Roses are red", "violet"), false);
});

t.test(
"Test the userInputOccurrencesSafelyEncapsulated() function",
async () => {
t.ok(
t.same(
userInputOccurrencesSafelyEncapsulated(
` Hello Hello 'UNION'and also "UNION" `,
"UNION"
)
),
true
);
t.same(userInputOccurrencesSafelyEncapsulated(`"UNION"`, "UNION"), true);
t.same(userInputOccurrencesSafelyEncapsulated(` 'UNION' `, "UNION"), true);
t.same(
userInputOccurrencesSafelyEncapsulated(`"UNION"'UNION'`, "UNION"),
true
);
t.ok(userInputOccurrencesSafelyEncapsulated(`"UNION"`, "UNION"));
t.ok(userInputOccurrencesSafelyEncapsulated(` 'UNION' `, "UNION"));
t.ok(userInputOccurrencesSafelyEncapsulated(`"UNION"'UNION'`, "UNION"));

t.notOk(
userInputOccurrencesSafelyEncapsulated(`'UNION'"UNION"UNION`, "UNION")
t.same(
userInputOccurrencesSafelyEncapsulated(`'UNION'"UNION"UNION`, "UNION"),
false
);
t.notOk(
userInputOccurrencesSafelyEncapsulated(`'UNION'UNION"UNION"`, "UNION")
t.same(
userInputOccurrencesSafelyEncapsulated(`'UNION'UNION"UNION"`, "UNION"),
false
);
t.notOk(userInputOccurrencesSafelyEncapsulated("UNION", "UNION"));
t.same(userInputOccurrencesSafelyEncapsulated("UNION", "UNION"), false);
}
);

t.test("Test the dangerousCharsInInput() function", async () => {
t.ok(dangerousCharsInInput("This is not ok--"));
});

t.test("Test the postgres bitwise operator #", async () => {
isSqlInjection("10 # 12", "10 # 12");
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.ok(detectSQLInjection(sql, input), sql);
t.same(detectSQLInjection(sql, input), true, sql);
}

function isNotSqlInjection(sql: string, input: string) {
t.notOk(detectSQLInjection(sql, input), sql);
t.same(detectSQLInjection(sql, input), false, sql);
}

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"),
join(__dirname, "payloads", "mssql_and_db2.txt"),
];

for (const file of files) {
const contents = readFileSync(file, "utf-8");
const lines = contents.split(/\r?\n/);
for (const sql of lines) {
t.test(
`It flags ${sql} from ${basename(file)} as SQL injection`,
async () => {
t.same(detectSQLInjection(sql, sql), true, sql);
}
);
}
}

0 comments on commit 40ae51d

Please sign in to comment.