diff --git a/.brightsec/tests/get-rest-products-search.test.ts b/.brightsec/tests/get-rest-products-search.test.ts new file mode 100644 index 00000000000..fd7c8a29f33 --- /dev/null +++ b/.brightsec/tests/get-rest-products-search.test.ts @@ -0,0 +1,42 @@ +import { test, before, after } from 'node:test'; +import { SecRunner } from '@sectester/runner'; +import { AttackParamLocation, HttpMethod } from '@sectester/scan'; + +const timeout = 40 * 60 * 1000; +const baseUrl = process.env.BRIGHT_TARGET_URL!; + +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()); + +test('GET /rest/products/search?q=:query', { signal: AbortSignal.timeout(timeout) }, async () => { + await runner + .createScan({ + tests: ['sqli'], + attackParamLocations: [AttackParamLocation.QUERY], + starMetadata: { + code_source: "tssbox/juice-shop:master", + databases: ["SQLite"], + user_roles: { + roles: ["customer", "deluxe", "accounting", "admin"] + } + }, + poolSize: +process.env.SECTESTER_SCAN_POOL_SIZE || undefined + }) + .setFailFast(false) + .timeout(timeout) + .run({ + method: HttpMethod.GET, + url: `${baseUrl}/rest/products/search?q=apple`, + auth: process.env.BRIGHT_AUTH_ID + }); +}); diff --git a/routes/delivery.ts b/routes/delivery.ts index c2e23ed870f..bc6c7db9291 100644 --- a/routes/delivery.ts +++ b/routes/delivery.ts @@ -31,8 +31,18 @@ export function getDeliveryMethods () { export function getDeliveryMethod () { return async (req: Request, res: Response, next: NextFunction) => { + const userId = req.user?.id // Assuming req.user is populated with authenticated user info + if (!userId) { + return res.status(401).json({ status: 'error', message: 'Unauthorized' }) + } + const method = await DeliveryModel.findOne({ where: { id: req.params.id } }) if (method != null) { + // Add authorization check here + if (!await isUserAuthorizedForDeliveryMethod(userId, method.id)) { + return res.status(403).json({ status: 'error', message: 'Forbidden' }) + } + const sendMethod = { id: method.id, name: method.name, @@ -42,7 +52,13 @@ export function getDeliveryMethod () { } res.status(200).json({ status: 'success', data: sendMethod }) } else { - res.status(400).json({ status: 'error' }) + res.status(404).json({ status: 'error', message: 'Not Found' }) } } } + +async function isUserAuthorizedForDeliveryMethod (userId: number, deliveryMethodId: number): Promise { + // Implement your authorization logic here + // For example, check if the user has access to the delivery method + return true // Placeholder implementation +} diff --git a/routes/search.ts b/routes/search.ts index 07d0fcddaee..3517d796bfb 100644 --- a/routes/search.ts +++ b/routes/search.ts @@ -20,7 +20,10 @@ export function searchProducts () { return (req: Request, res: Response, next: NextFunction) => { let criteria: any = req.query.q === 'undefined' ? '' : req.query.q ?? '' criteria = (criteria.length <= 200) ? criteria : criteria.substring(0, 200) - models.sequelize.query(`SELECT * FROM Products WHERE ((name LIKE '%${criteria}%' OR description LIKE '%${criteria}%') AND deletedAt IS NULL) ORDER BY name`) // vuln-code-snippet vuln-line unionSqlInjectionChallenge dbSchemaChallenge + models.sequelize.query('SELECT * FROM Products WHERE ((name LIKE :criteria OR description LIKE :criteria) AND deletedAt IS NULL) ORDER BY name', { + replacements: { criteria: `%${criteria}%` }, + type: models.sequelize.QueryTypes.SELECT + }) .then(([products]: any) => { const dataString = JSON.stringify(products) if (challengeUtils.notSolved(challenges.unionSqlInjectionChallenge)) { // vuln-code-snippet hide-start