@aikidosec/firewall
Version:
Zen by Aikido is an embedded Web Application Firewall that autonomously protects Node.js apps against common and critical attacks
113 lines (112 loc) • 4.85 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkIfRequestIsBlocked = checkIfRequestIsBlocked;
const Context_1 = require("../../agent/Context");
const escapeHTML_1 = require("../../helpers/escapeHTML");
const ipAllowedToAccessRoute_1 = require("./ipAllowedToAccessRoute");
const checkedBlocks = Symbol("__zen_checked_blocks__");
/**
* Inspects the IP address and user agent of the request:
* - Whether the IP address is blocked by an IP blocklist (e.g. Geo restrictions)
* - Whether the IP address is allowed to access the current route (e.g. Admin panel)
* - Whether the user agent is blocked by a user agent blocklist
*/
function checkIfRequestIsBlocked(
// This flag is used to determine whether the request has already been checked
// We use a Symbol so that we don't accidentally overwrite any other properties on the response object
// and that we're the only ones that can access it
res, agent) {
if (res.headersSent) {
// The headers have already been sent, so we can't block the request
// This might happen if the server has multiple listeners
return false;
}
const context = (0, Context_1.getContext)();
if (!context) {
return false;
}
if (res[checkedBlocks]) {
return false;
}
// We don't need to check again if the request has already been checked
// Also ensures that the statistics are only counted once
res[checkedBlocks] = true;
if (!(0, ipAllowedToAccessRoute_1.ipAllowedToAccessRoute)(context, agent)) {
res.statusCode = 403;
res.setHeader("Content-Type", "text/plain");
let message = "Your IP address is not allowed to access this resource.";
if (context.remoteAddress) {
message += ` (Your IP: ${(0, escapeHTML_1.escapeHTML)(context.remoteAddress)})`;
}
res.end(message);
return true;
}
const isBypassedIP = context.remoteAddress &&
agent.getConfig().isBypassedIP(context.remoteAddress);
if (isBypassedIP) {
return false;
}
if (context.remoteAddress &&
!agent.getConfig().isAllowedIPAddress(context.remoteAddress).allowed) {
res.statusCode = 403;
res.setHeader("Content-Type", "text/plain");
let message = "Your IP address is not allowed to access this resource.";
if (context.remoteAddress) {
message += ` (Your IP: ${(0, escapeHTML_1.escapeHTML)(context.remoteAddress)})`;
}
res.end(message);
return true;
}
const result = context.remoteAddress
? agent.getConfig().isIPAddressBlocked(context.remoteAddress)
: { blocked: false };
if (context.remoteAddress) {
// Let's see if the IP occurs on one or more monitored lists and collect those keys
const monitoredKeys = agent
.getConfig()
.getMatchingMonitoredIPListKeys(context.remoteAddress);
agent.getInspectionStatistics().onIPAddressMatches(monitoredKeys);
if (result.blocked) {
// Let's see if the IP occurs on one or more blocked lists and collect those keys
const blockedKeys = agent
.getConfig()
.getMatchingBlockedIPListKeys(context.remoteAddress);
agent.getInspectionStatistics().onIPAddressMatches(blockedKeys);
}
}
if (result.blocked) {
res.statusCode = 403;
res.setHeader("Content-Type", "text/plain");
let message = `Your IP address is blocked due to ${(0, escapeHTML_1.escapeHTML)(result.reason)}.`;
if (context.remoteAddress) {
message += ` (Your IP: ${(0, escapeHTML_1.escapeHTML)(context.remoteAddress)})`;
}
res.end(message);
return true;
}
const userAgent = context.headers && typeof context.headers["user-agent"] === "string"
? context.headers["user-agent"]
: undefined;
const isUserAgentBlocked = userAgent
? agent.getConfig().isUserAgentBlocked(userAgent)
: { blocked: false };
if (userAgent) {
const isMonitoredUserAgent = agent
.getConfig()
.isMonitoredUserAgent(userAgent);
if (isUserAgentBlocked.blocked || isMonitoredUserAgent) {
// Find all the matching user agent keys when it's a blocked or monitored user agent
const userAgentKeys = agent
.getConfig()
.getMatchingUserAgentKeys(userAgent);
agent.getInspectionStatistics().onUserAgentMatches(userAgentKeys);
}
}
if (isUserAgentBlocked.blocked) {
res.statusCode = 403;
res.setHeader("Content-Type", "text/plain");
res.end("You are not allowed to access this resource because you have been identified as a bot.");
return true;
}
return false;
}