Skip to content
42 changes: 42 additions & 0 deletions .brightsec/tests/get-rest-products-search.test.ts
Original file line number Diff line number Diff line change
@@ -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
});
});
18 changes: 17 additions & 1 deletion routes/delivery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<boolean> {
// Implement your authorization logic here
// For example, check if the user has access to the delivery method
return true // Placeholder implementation
}
5 changes: 4 additions & 1 deletion routes/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down