Skip to main content
Glama

security.test_idor

Test web applications for IDOR vulnerabilities by checking access control on object references to identify security weaknesses.

Instructions

Test for IDOR (Insecure Direct Object Reference) vulnerabilities

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesTarget URL with ID parameter
idParamNoID parameter nameid
testIdsNoIDs to test (e.g., [1, 2, 3])

Implementation Reference

  • The handler function executes IDOR tests by sending GET requests to the target URL with varying ID values, establishes a baseline response, detects differences indicating potential unauthorized access, logs findings via saveFinding, saves test results, and returns formatted output.
    async ({ url, idParam = 'id', testIds = [1, 2, 3, 999, 1000] }: any): Promise<ToolResult> => { try { const results: any[] = []; let baselineResponse: AxiosResponse | null = null; for (const testId of testIds) { try { const response = await axios.get(url, { params: { [idParam]: testId }, validateStatus: () => true, timeout: 15000, }); if (!baselineResponse) { baselineResponse = response; } const isDifferent = response.status !== baselineResponse.status || response.data !== baselineResponse.data; const result = { id: testId, status: response.status, length: typeof response.data === 'string' ? response.data.length : JSON.stringify(response.data).length, isDifferent, accessible: response.status === 200, }; if (isDifferent && response.status === 200) { await saveFinding({ target: url, type: 'IDOR', severity: 'high', description: `Potential IDOR - different response for ID: ${testId}`, payload: `${idParam}=${testId}`, response: typeof response.data === 'string' ? response.data.substring(0, 1000) : JSON.stringify(response.data).substring(0, 1000), timestamp: new Date(), score: 7, }); } results.push(result); } catch (error: any) { results.push({ id: testId, error: error.message, }); } } const idorScore = results.some((r: any) => r.vulnerable) ? 8 : 4; await saveTestResult(url, 'idor_test', true, { results }, undefined, idorScore, JSON.stringify(testIds), JSON.stringify(results)); return formatToolResult(true, { results, summary: { totalTests: testIds.length, accessible: results.filter((r) => r.accessible).length, potentialVulns: results.filter((r) => r.isDifferent && r.accessible).length, }, }); } catch (error: any) { await saveTestResult(url, 'idor_test', false, null, error.message, 0, JSON.stringify(testIds), undefined); return formatToolResult(false, null, error.message); } }
  • Input schema defining parameters for the IDOR test: required 'url', optional 'idParam' (default 'id'), and 'testIds' array of numbers.
    inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Target URL with ID parameter' }, idParam: { type: 'string', description: 'ID parameter name', default: 'id' }, testIds: { type: 'array', items: { type: 'number' }, description: 'IDs to test (e.g., [1, 2, 3])', }, }, required: ['url'], },
  • Registers the 'security.test_idor' tool on the MCP server within the registerSecurityTools function, which is called from src/index.ts.
    'security.test_idor', { description: 'Test for IDOR (Insecure Direct Object Reference) vulnerabilities', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Target URL with ID parameter' }, idParam: { type: 'string', description: 'ID parameter name', default: 'id' }, testIds: { type: 'array', items: { type: 'number' }, description: 'IDs to test (e.g., [1, 2, 3])', }, }, required: ['url'], }, }, async ({ url, idParam = 'id', testIds = [1, 2, 3, 999, 1000] }: any): Promise<ToolResult> => { try { const results: any[] = []; let baselineResponse: AxiosResponse | null = null; for (const testId of testIds) { try { const response = await axios.get(url, { params: { [idParam]: testId }, validateStatus: () => true, timeout: 15000, }); if (!baselineResponse) { baselineResponse = response; } const isDifferent = response.status !== baselineResponse.status || response.data !== baselineResponse.data; const result = { id: testId, status: response.status, length: typeof response.data === 'string' ? response.data.length : JSON.stringify(response.data).length, isDifferent, accessible: response.status === 200, }; if (isDifferent && response.status === 200) { await saveFinding({ target: url, type: 'IDOR', severity: 'high', description: `Potential IDOR - different response for ID: ${testId}`, payload: `${idParam}=${testId}`, response: typeof response.data === 'string' ? response.data.substring(0, 1000) : JSON.stringify(response.data).substring(0, 1000), timestamp: new Date(), score: 7, }); } results.push(result); } catch (error: any) { results.push({ id: testId, error: error.message, }); } } const idorScore = results.some((r: any) => r.vulnerable) ? 8 : 4; await saveTestResult(url, 'idor_test', true, { results }, undefined, idorScore, JSON.stringify(testIds), JSON.stringify(results)); return formatToolResult(true, { results, summary: { totalTests: testIds.length, accessible: results.filter((r) => r.accessible).length, potentialVulns: results.filter((r) => r.isDifferent && r.accessible).length, }, }); } catch (error: any) { await saveTestResult(url, 'idor_test', false, null, error.message, 0, JSON.stringify(testIds), undefined); return formatToolResult(false, null, error.message); } } );

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/telmon95/VulneraMCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server