diff --git a/.brightsec/tests/get-addpage.test.ts b/.brightsec/tests/get-addpage.test.ts new file mode 100644 index 00000000..63811459 --- /dev/null +++ b/.brightsec/tests/get-addpage.test.ts @@ -0,0 +1,33 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /AddPage', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['xss', 'excessive_data_exposure'], + attackParamLocations: [AttackParamLocation.QUERY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/AddPage?filename=example.html&content=%3Chtml%3E%3Cbody%3EHello%20World%3C/body%3E%3C/html%3E` + }); +}); diff --git a/.brightsec/tests/get-emailcheck.test.ts b/.brightsec/tests/get-emailcheck.test.ts new file mode 100644 index 00000000..26df1642 --- /dev/null +++ b/.brightsec/tests/get-emailcheck.test.ts @@ -0,0 +1,33 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /EmailCheck', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'excessive_data_exposure', 'full_path_disclosure'], + attackParamLocations: [AttackParamLocation.QUERY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/EmailCheck?email=example@example.com` + }); +}); diff --git a/.brightsec/tests/get-install.test.ts b/.brightsec/tests/get-install.test.ts new file mode 100644 index 00000000..285b3e28 --- /dev/null +++ b/.brightsec/tests/get-install.test.ts @@ -0,0 +1,33 @@ +import { test, before, after } from 'node:test'; +import { SecRunner } from '@sectester/runner'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /install', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'open_database', 'excessive_data_exposure', 'csrf', 'xss', 'full_path_disclosure'], + attackParamLocations: [AttackParamLocation.QUERY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/install?dburl=jdbc:mysql://localhost:3306/&jdbcdriver=com.mysql.jdbc.Driver&dbuser=root&dbpass=password&dbname=javavulnerablelab&siteTitle=Java+Vulnerable+Lab&adminuser=admin&adminpass=adminpass&setup=1` + }); +}); diff --git a/.brightsec/tests/get-login-validator.test.ts b/.brightsec/tests/get-login-validator.test.ts new file mode 100644 index 00000000..72b47542 --- /dev/null +++ b/.brightsec/tests/get-login-validator.test.ts @@ -0,0 +1,33 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /LoginValidator', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'xss', 'unvalidated_redirect', 'excessive_data_exposure', 'csrf', 'secret_tokens'], + attackParamLocations: [AttackParamLocation.QUERY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/LoginValidator?username=sampleUser&password=samplePass` + }); +}); diff --git a/.brightsec/tests/get-open.test.ts b/.brightsec/tests/get-open.test.ts new file mode 100644 index 00000000..ec7118fe --- /dev/null +++ b/.brightsec/tests/get-open.test.ts @@ -0,0 +1,34 @@ +import { test, before, after } from 'node:test'; +import { SecRunner } from '@sectester/runner'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /Open', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['unvalidated_redirect', 'xss'], + attackParamLocations: [AttackParamLocation.QUERY], + skipStaticParams: false + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/Open?url=http://example.com` + }); +}); diff --git a/.brightsec/tests/get-register.test.ts b/.brightsec/tests/get-register.test.ts new file mode 100644 index 00000000..5e2b0339 --- /dev/null +++ b/.brightsec/tests/get-register.test.ts @@ -0,0 +1,33 @@ +import { test, before, after } from 'node:test'; +import { SecRunner } from '@sectester/runner'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /register', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'xss', 'csrf', 'excessive_data_exposure', 'unvalidated_redirect'], + attackParamLocations: [AttackParamLocation.QUERY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/register` + }); +}); diff --git a/.brightsec/tests/get-usernamecheck.test.ts b/.brightsec/tests/get-usernamecheck.test.ts new file mode 100644 index 00000000..85929c43 --- /dev/null +++ b/.brightsec/tests/get-usernamecheck.test.ts @@ -0,0 +1,33 @@ +import { test, before, after } from 'node:test'; +import { SecRunner } from '@sectester/runner'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /UsernameCheck', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'excessive_data_exposure', 'full_path_disclosure'], + attackParamLocations: [AttackParamLocation.QUERY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/UsernameCheck?username=sampleUser` + }); +}); diff --git a/.brightsec/tests/get-vulnerability-send-message.test.ts b/.brightsec/tests/get-vulnerability-send-message.test.ts new file mode 100644 index 00000000..69ae7820 --- /dev/null +++ b/.brightsec/tests/get-vulnerability-send-message.test.ts @@ -0,0 +1,35 @@ +import { test, before, after } from 'node:test'; +import { SecRunner } from '@sectester/runner'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /vulnerability/SendMessage', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['xss', 'email_injection', 'excessive_data_exposure', 'sqli', 'csrf'], + attackParamLocations: [ + AttackParamLocation.QUERY + ] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/vulnerability/SendMessage?recipient=exampleRecipient&subject=exampleSubject&msg=exampleMessage&sender=exampleSender&send=true` + }); +}); diff --git a/.brightsec/tests/get-xpathquery.test.ts b/.brightsec/tests/get-xpathquery.test.ts new file mode 100644 index 00000000..edc7b4dc --- /dev/null +++ b/.brightsec/tests/get-xpathquery.test.ts @@ -0,0 +1,40 @@ +import { test, before, after } from 'node:test'; +import { SecRunner } from '@sectester/runner'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /XPathQuery', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['xpathi', 'excessive_data_exposure', 'unvalidated_redirect', 'full_path_disclosure'], + attackParamLocations: [AttackParamLocation.QUERY, AttackParamLocation.HEADER] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/XPathQuery`, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + query: { + username: 'sampleUser', + password: 'samplePass' + } + }); +}); diff --git a/.brightsec/tests/get-xxe.test.ts b/.brightsec/tests/get-xxe.test.ts new file mode 100644 index 00000000..f1ce77ac --- /dev/null +++ b/.brightsec/tests/get-xxe.test.ts @@ -0,0 +1,33 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('GET /xxe', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['xxe'], + attackParamLocations: [AttackParamLocation.PATH] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/xxe` + }); +}); diff --git a/.brightsec/tests/post-addpage.test.ts b/.brightsec/tests/post-addpage.test.ts new file mode 100644 index 00000000..bd78351d --- /dev/null +++ b/.brightsec/tests/post-addpage.test.ts @@ -0,0 +1,37 @@ +import { test, before, after } from 'node:test'; +import { SecRunner } from '@sectester/runner'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /AddPage', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['file_upload', 'stored_xss', 'lfi', 'osi', 'excessive_data_exposure'], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/AddPage`, + body: 'filename=example.html&content=Hello World', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }); +}); diff --git a/.brightsec/tests/post-emailcheck.test.ts b/.brightsec/tests/post-emailcheck.test.ts new file mode 100644 index 00000000..1938d637 --- /dev/null +++ b/.brightsec/tests/post-emailcheck.test.ts @@ -0,0 +1,39 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /EmailCheck', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'excessive_data_exposure', 'xss', 'csrf', 'open_database'], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/EmailCheck`, + headers: { + 'Content-Type': 'application/json' + }, + body: { + email: 'example@example.com' + } + }); +}); diff --git a/.brightsec/tests/post-install.test.ts b/.brightsec/tests/post-install.test.ts new file mode 100644 index 00000000..05944ff7 --- /dev/null +++ b/.brightsec/tests/post-install.test.ts @@ -0,0 +1,44 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /install', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'csrf', 'open_database', 'excessive_data_exposure', 'xss', 'full_path_disclosure'], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/install`, + body: { + dburl: 'jdbc:mysql://localhost:3306/', + jdbcdriver: 'com.mysql.jdbc.Driver', + dbuser: 'root', + dbpass: 'password', + dbname: 'javavulnerablelab', + siteTitle: 'Java Vulnerable Lab', + adminuser: 'admin', + adminpass: 'adminpass', + setup: '1' + } + }); +}); diff --git a/.brightsec/tests/post-login-validator.test.ts b/.brightsec/tests/post-login-validator.test.ts new file mode 100644 index 00000000..ee130202 --- /dev/null +++ b/.brightsec/tests/post-login-validator.test.ts @@ -0,0 +1,37 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /LoginValidator', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'csrf', 'xss', 'unvalidated_redirect', 'excessive_data_exposure'], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/LoginValidator`, + body: 'username=sampleUser&password=samplePass', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }); +}); diff --git a/.brightsec/tests/post-open.test.ts b/.brightsec/tests/post-open.test.ts new file mode 100644 index 00000000..0d559336 --- /dev/null +++ b/.brightsec/tests/post-open.test.ts @@ -0,0 +1,33 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /Open', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['unvalidated_redirect', 'csrf'], + attackParamLocations: [AttackParamLocation.QUERY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/Open?url=http://example.com` + }); +}); diff --git a/.brightsec/tests/post-register.test.ts b/.brightsec/tests/post-register.test.ts new file mode 100644 index 00000000..6707cfd7 --- /dev/null +++ b/.brightsec/tests/post-register.test.ts @@ -0,0 +1,37 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /register', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'csrf', 'xss', 'excessive_data_exposure', 'secret_tokens'], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/register`, + body: 'username=sampleUser&password=samplePass&email=sample%40email.com&About=Sample+about+text&secret=sampleSecret', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + } + }); +}); diff --git a/.brightsec/tests/post-username-check.test.ts b/.brightsec/tests/post-username-check.test.ts new file mode 100644 index 00000000..11ebba2e --- /dev/null +++ b/.brightsec/tests/post-username-check.test.ts @@ -0,0 +1,37 @@ +import { test, before, after } from 'node:test'; +import { SecRunner } from '@sectester/runner'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /UsernameCheck', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli', 'excessive_data_exposure', 'full_path_disclosure'], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/UsernameCheck`, + headers: { + 'Content-Type': 'application/json' + }, + body: 'username=sampleUser' + }); +}); diff --git a/.brightsec/tests/post-vulnerability-send-message.test.ts b/.brightsec/tests/post-vulnerability-send-message.test.ts new file mode 100644 index 00000000..c6f31fcc --- /dev/null +++ b/.brightsec/tests/post-vulnerability-send-message.test.ts @@ -0,0 +1,34 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /vulnerability/SendMessage', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['csrf', 'excessive_data_exposure', 'xss'], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/vulnerability/SendMessage`, + body: 'recipient=exampleRecipient&subject=exampleSubject&msg=exampleMessage&sender=exampleSender&send=true' + }); +}); diff --git a/.brightsec/tests/post-xpathquery.test.ts b/.brightsec/tests/post-xpathquery.test.ts new file mode 100644 index 00000000..c7c46106 --- /dev/null +++ b/.brightsec/tests/post-xpathquery.test.ts @@ -0,0 +1,37 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /XPathQuery', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['xpathi', 'excessive_data_exposure', 'csrf', 'full_path_disclosure'], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/XPathQuery`, + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + body: 'username=sampleUser&password=samplePass' + }); +}); diff --git a/.brightsec/tests/post-xxe.test.ts b/.brightsec/tests/post-xxe.test.ts new file mode 100644 index 00000000..f1e640a3 --- /dev/null +++ b/.brightsec/tests/post-xxe.test.ts @@ -0,0 +1,37 @@ +import { test, before, after } from 'node:test'; +import { Severity, AttackParamLocation, HttpMethod } from '@sectester/scan'; +import { SecRunner } from '@sectester/runner'; + +let runner!: SecRunner; + +before(async () => { + runner = new SecRunner({ + hostname: process.env.BRIGHT_HOSTNAME!, + projectId: process.env.BRIGHT_PROJECT_ID! + }); + + await runner.init(); +}); + +after(() => runner.clear()); + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +test('POST /xxe', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['xxe'], + attackParamLocations: [AttackParamLocation.BODY] + }) + .threshold(Severity.CRITICAL) + .timeout(timeout) + .run({ + method: HttpMethod.POST, + url: `${baseUrl}/xxe`, + headers: { + 'Content-Type': 'application/xml' + }, + body: 'Example' + }); +}); diff --git a/.github/workflows/bright.yml b/.github/workflows/bright.yml new file mode 100644 index 00000000..388abc37 --- /dev/null +++ b/.github/workflows/bright.yml @@ -0,0 +1,55 @@ +name: Security Tests + +on: + pull_request: + branches: + - '*' + +permissions: + checks: write + contents: read + +jobs: + security-tests: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '22' + + - name: Install SecTester dependencies + run: npm install --save-dev @sectester/core @sectester/repeater @sectester/scan @sectester/runner + + - name: Start application using Docker Compose + run: docker compose up --wait + env: + MYSQL_ROOT_PASSWORD: root + + - name: Verify application readiness + run: | + until nc -zv 127.0.0.1 8080; do + echo "Waiting for application to be ready..." + sleep 5 + done + + - name: Run security tests + run: | + node --experimental-transform-types \ + --experimental-strip-types \ + --experimental-detect-module \ + --disable-warning=MODULE_TYPELESS_PACKAGE_JSON \ + --disable-warning=ExperimentalWarning \ + --test-force-exit \ + --test .brightsec/tests/*.test.ts \ + --test-concurrency=4 + env: + BRIGHT_HOSTNAME: ${{ vars.BRIGHT_HOSTNAME }} + BRIGHT_PROJECT_ID: ${{ vars.BRIGHT_PROJECT_ID }} + BRIGHT_TOKEN: ${{ secrets.BRIGHT_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + BRIGHT_TARGET_URL: 'http://127.0.0.1:8080' \ No newline at end of file