aimless-sdk
Version:
Enhanced Runtime Application Self-Protection (RASP) and API Fuzzing Engine with advanced threat detection, behavioral analysis, and intelligent response scoring for Node.js applications
260 lines • 10.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FuzzingEngine = void 0;
const types_1 = require("../types");
const payload_generator_1 = require("./payload-generator");
class FuzzingEngine {
constructor(config = {}, logger) {
this.config = {
enabled: true,
maxPayloads: 100,
timeout: 5000,
authBypassTests: true,
rateLimitTests: true,
graphqlIntrospection: true,
customPayloads: [],
...config
};
this.logger = logger;
this.payloadGenerator = new payload_generator_1.PayloadGenerator();
this.baselineResponses = new Map();
}
async fuzz(target) {
if (!this.config.enabled) {
return {
endpoint: target.url,
method: target.method,
vulnerabilities: [],
testedPayloads: 0,
duration: 0,
timestamp: new Date()
};
}
const startTime = Date.now();
const vulnerabilities = [];
let testedPayloads = 0;
this.logger.info(`Starting fuzzing test for ${target.method} ${target.url}`);
// Fuzz query parameters
if (target.query) {
const queryVulns = await this.fuzzParameters(target, 'query', target.query);
vulnerabilities.push(...queryVulns);
testedPayloads += queryVulns.length;
}
// Fuzz body parameters
if (target.body) {
const bodyVulns = await this.fuzzParameters(target, 'body', target.body);
vulnerabilities.push(...bodyVulns);
testedPayloads += bodyVulns.length;
}
// Fuzz headers
if (target.headers) {
const headerVulns = await this.fuzzHeaders(target);
vulnerabilities.push(...headerVulns);
testedPayloads += headerVulns.length;
}
// Auth bypass tests
if (this.config.authBypassTests) {
const authVulns = await this.testAuthBypass(target);
vulnerabilities.push(...authVulns);
testedPayloads += authVulns.length;
}
// Rate limit tests
if (this.config.rateLimitTests) {
const rateLimitVulns = await this.testRateLimits(target);
vulnerabilities.push(...rateLimitVulns);
testedPayloads += rateLimitVulns.length;
}
// GraphQL introspection
if (this.config.graphqlIntrospection && this.isGraphQL(target)) {
const graphqlVulns = await this.testGraphQLIntrospection(target);
vulnerabilities.push(...graphqlVulns);
testedPayloads += graphqlVulns.length;
}
const duration = Date.now() - startTime;
this.logger.info(`Fuzzing completed: ${testedPayloads} payloads tested, ${vulnerabilities.length} vulnerabilities found`);
return {
endpoint: target.url,
method: target.method,
vulnerabilities,
testedPayloads,
duration,
timestamp: new Date()
};
}
async fuzzParameters(target, location, params) {
const vulnerabilities = [];
for (const [key, value] of Object.entries(params)) {
const mutations = this.payloadGenerator.mutateValue(value);
const testPayloads = mutations.slice(0, this.config.maxPayloads);
for (const payload of testPayloads) {
const result = this.analyzePayload(payload, key, location);
if (result) {
vulnerabilities.push(result);
}
}
}
return vulnerabilities;
}
async fuzzHeaders(target) {
const vulnerabilities = [];
const dangerousHeaders = ['Host', 'X-Forwarded-For', 'X-Real-IP', 'Referer', 'User-Agent'];
for (const header of dangerousHeaders) {
const mutations = this.payloadGenerator.mutateValue('test');
const testPayloads = mutations.slice(0, Math.min(10, this.config.maxPayloads));
for (const payload of testPayloads) {
const result = this.analyzePayload(payload, header, 'header');
if (result) {
vulnerabilities.push(result);
}
}
}
return vulnerabilities;
}
async testAuthBypass(target) {
const vulnerabilities = [];
const authBypassPayloads = this.payloadGenerator.getByType('authBypass');
// Test Authorization header
for (const payload of authBypassPayloads.slice(0, this.config.maxPayloads)) {
vulnerabilities.push({
type: types_1.ThreatType.AUTH_BYPASS_ATTEMPT,
severity: 'high',
description: `Auth bypass test: Testing authorization with payload`,
payload: String(payload),
timestamp: new Date(),
blocked: false,
metadata: { location: 'authorization', target: target.url }
});
}
return vulnerabilities;
}
async testRateLimits(target) {
const vulnerabilities = [];
const burstSize = 100;
this.logger.info(`Testing rate limits with burst of ${burstSize} requests`);
vulnerabilities.push({
type: types_1.ThreatType.RATE_LIMIT_EXCEEDED,
severity: 'medium',
description: `Rate limit test: Simulated ${burstSize} rapid requests`,
timestamp: new Date(),
blocked: false,
metadata: {
target: target.url,
burstSize,
message: 'This is a simulated test - actual requests not sent'
}
});
return vulnerabilities;
}
async testGraphQLIntrospection(target) {
const vulnerabilities = [];
const graphqlPayloads = this.payloadGenerator.generateGraphQLPayloads();
for (const payload of graphqlPayloads) {
vulnerabilities.push({
type: types_1.ThreatType.ANOMALOUS_BEHAVIOR,
severity: 'medium',
description: 'GraphQL introspection query test',
payload,
timestamp: new Date(),
blocked: false,
metadata: {
target: target.url,
type: 'graphql-introspection'
}
});
}
return vulnerabilities;
}
/**
* Analyze response and calculate vulnerability score
*/
analyzeResponse(payload, field, location, response) {
const payloadStr = String(payload);
let score = 0;
let threat = null;
// Response analysis (if available)
if (response) {
const errorKeywords = ['error', 'exception', 'stack trace', 'sql', 'syntax', 'unexpected'];
const hasError = errorKeywords.some(kw => response.body.toLowerCase().includes(kw));
if (hasError)
score += 30;
if (response.status >= 500)
score += 40;
if (response.status === 200 && response.responseTime > 5000)
score += 20; // Potential time-based attack
if (response.headers['x-powered-by'])
score += 10; // Information disclosure
}
// Determine threat type based on payload
if (payloadStr.includes('SELECT') || payloadStr.includes('UNION') || payloadStr.includes('OR 1=1')) {
score += 50;
threat = {
type: types_1.ThreatType.SQL_INJECTION,
severity: score > 70 ? 'critical' : 'high',
description: `SQL injection test payload in ${location}.${field} (score: ${score})`,
payload: payloadStr,
timestamp: new Date(),
blocked: false,
metadata: { field, location, vulnerabilityScore: score, response: response ? { status: response.status } : undefined }
};
}
else if (payloadStr.includes('<script>') || payloadStr.includes('onerror') || payloadStr.includes('javascript:')) {
score += 45;
threat = {
type: types_1.ThreatType.XSS,
severity: score > 70 ? 'critical' : 'high',
description: `XSS test payload in ${location}.${field} (score: ${score})`,
payload: payloadStr,
timestamp: new Date(),
blocked: false,
metadata: { field, location, vulnerabilityScore: score }
};
}
else if (payloadStr.includes('$') && (payloadStr.includes('gt') || payloadStr.includes('ne') || payloadStr.includes('where'))) {
score += 45;
threat = {
type: types_1.ThreatType.NOSQL_INJECTION,
severity: score > 70 ? 'critical' : 'high',
description: `NoSQL injection test payload in ${location}.${field} (score: ${score})`,
payload: payloadStr,
timestamp: new Date(),
blocked: false,
metadata: { field, location, vulnerabilityScore: score }
};
}
else if (payloadStr.includes('../') || payloadStr.includes('..\\') || payloadStr.includes('%2e%2e')) {
score += 40;
threat = {
type: types_1.ThreatType.PATH_TRAVERSAL,
severity: score > 70 ? 'critical' : 'high',
description: `Path traversal test payload in ${location}.${field} (score: ${score})`,
payload: payloadStr,
timestamp: new Date(),
blocked: false,
metadata: { field, location, vulnerabilityScore: score }
};
}
else if (payloadStr.match(/[;&|`]/)) {
score += 50;
threat = {
type: types_1.ThreatType.COMMAND_INJECTION,
severity: score > 70 ? 'critical' : 'high',
description: `Command injection test payload in ${location}.${field} (score: ${score})`,
payload: payloadStr,
timestamp: new Date(),
blocked: false,
metadata: { field, location, vulnerabilityScore: score }
};
}
return { threat, score };
}
analyzePayload(payload, field, location) {
const result = this.analyzeResponse(payload, field, location);
return result.threat;
}
isGraphQL(target) {
return target.url.toLowerCase().includes('graphql') ||
(target.body && typeof target.body === 'object' && 'query' in target.body);
}
}
exports.FuzzingEngine = FuzzingEngine;
//# sourceMappingURL=index.js.map