diff --git a/tests/integration.js b/tests/integration.js index 368839f..38952d1 100644 --- a/tests/integration.js +++ b/tests/integration.js @@ -560,6 +560,83 @@ async function cleanup() { log(got429, 'rate-limiter: POST /add → 429 после 30 запросов'); } + // ───────────────────────────────────────────────────────────────────────────── + // 18. IDOR — user пытается добавить запись в чужую компанию через company_id + // ───────────────────────────────────────────────────────────────────────────── + console.log('\n── 18. IDOR: подделка company_id ──'); + + { + // user2 (WZ02001) пытается добавить запись в компанию user (WZ01325) + const { MOCK_USERS } = require('../src/config'); + const userClient = MOCK_USERS.find(u => u.id === 'test')?.clientId; + const uRes = await pool.query( + `SELECT id FROM companies WHERE client_id = $1 LIMIT 1`, [userClient] + ); + const userCompId = uRes.rows[0]?.id; + + if (userCompId && user2Agent) { + const countBefore = (await pool.query( + `SELECT COUNT(*)::int AS c FROM whitelist_entries WHERE company_id = $1 AND deleted_at IS NULL`, + [userCompId] + )).rows[0].c; + + const csrf = await getCsrfFromIndex(user2Agent); + // user2 подделывает company_id = чужой компании + const res = await user2Agent.post('/add').type('form') + .send({ value: '5.6.7.8', comment: 'IDOR test', company_id: userCompId, _csrf: csrf }); + + const countAfter = (await pool.query( + `SELECT COUNT(*)::int AS c FROM whitelist_entries WHERE company_id = $1 AND deleted_at IS NULL`, + [userCompId] + )).rows[0].c; + + log(countBefore === countAfter, + 'IDOR: user2 не смог добавить в компанию user через company_id', + `before=${countBefore} after=${countAfter}`); + + // Чистим на случай если баг сработал + await pool.query( + `UPDATE whitelist_entries SET deleted_at = NOW(), deleted_by = 'test-cleanup' + WHERE value_cidr = '5.6.7.8/32' AND deleted_at IS NULL` + ); + } else { + log(false, 'IDOR: нет userCompId или user2Agent'); + } + } + + // ───────────────────────────────────────────────────────────────────────────── + // 19. /admin страница — user не может зайти + // ───────────────────────────────────────────────────────────────────────────── + console.log('\n── 19. /admin — только для admin ──'); + + { + const res = await userAgent.get('/admin'); + log(res.status === 302 || res.status === 403, + 'user: GET /admin → redirect или 403', `status=${res.status}`); + } + + { + const res = await adminAgent.get('/admin'); + log(res.status === 200, 'admin: GET /admin → 200', `status=${res.status}`); + } + + // ───────────────────────────────────────────────────────────────────────────── + // 20. /audit — только для admin, user видит только свои + // ───────────────────────────────────────────────────────────────────────────── + console.log('\n── 20. /audit ──'); + + { + const res = await userAgent.get('/audit'); + // /audit только для admin — user получает 403 + log(res.status === 403 || res.status === 302, + 'user: GET /audit → 403 (нет доступа)', `status=${res.status}`); + } + + { + const res = await adminAgent.get('/audit'); + log(res.status === 200, 'admin: GET /audit → 200', `status=${res.status}`); + } + // ───────────────────────────────────────────────────────────────────────────── // Cleanup // ─────────────────────────────────────────────────────────────────────────────