Skip to content

Commit 192443f

Browse files
authored
Merge pull request #602 from AikidoSec/beta
Beta
2 parents 608413f + 3f61e1c commit 192443f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1597
-138
lines changed

end2end/server/src/handlers/lists.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ const {
22
getBlockedIPAddresses,
33
getBlockedUserAgents,
44
getAllowedIPAddresses,
5+
getMonitoredUserAgents,
6+
getMonitoredIPAddresses,
7+
getUserAgentDetails,
58
} = require("../zen/config");
69

710
module.exports = function lists(req, res) {
@@ -12,6 +15,9 @@ module.exports = function lists(req, res) {
1215
const blockedIps = getBlockedIPAddresses(req.app);
1316
const blockedUserAgents = getBlockedUserAgents(req.app);
1417
const allowedIps = getAllowedIPAddresses(req.app);
18+
const monitoredUserAgents = getMonitoredUserAgents(req.app);
19+
const monitoredIps = getMonitoredIPAddresses(req.app);
20+
const userAgentDetails = getUserAgentDetails(req.app);
1521

1622
res.json({
1723
success: true,
@@ -20,22 +26,37 @@ module.exports = function lists(req, res) {
2026
blockedIps.length > 0
2127
? [
2228
{
29+
key: "geoip/Belgium;BE",
2330
source: "geoip",
2431
description: "geo restrictions",
2532
ips: blockedIps,
2633
},
2734
]
2835
: [],
2936
blockedUserAgents: blockedUserAgents,
37+
monitoredUserAgents: monitoredUserAgents,
38+
userAgentDetails: userAgentDetails,
3039
allowedIPAddresses:
3140
allowedIps.length > 0
3241
? [
3342
{
43+
key: "geoip/Belgium;BE",
3444
source: "geoip",
3545
description: "geo restrictions",
3646
ips: allowedIps,
3747
},
3848
]
3949
: [],
50+
monitoredIPAddresses:
51+
monitoredIps.length > 0
52+
? monitoredIps
53+
: [
54+
{
55+
key: "geoip/Belgium;BE",
56+
source: "geoip",
57+
description: "geo restrictions",
58+
ips: monitoredIps,
59+
},
60+
],
4061
});
4162
};

end2end/server/src/handlers/updateLists.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ const {
22
updateBlockedIPAddresses,
33
updateBlockedUserAgents,
44
updateAllowedIPAddresses,
5+
updateMonitoredUserAgents,
6+
updateMonitoredIPAddresses,
7+
updateUserAgentDetails,
58
} = require("../zen/config");
69

710
module.exports = function updateIPLists(req, res) {
@@ -46,5 +49,26 @@ module.exports = function updateIPLists(req, res) {
4649
updateAllowedIPAddresses(req.app, req.body.allowedIPAddresses);
4750
}
4851

52+
if (
53+
req.body.monitoredUserAgents &&
54+
typeof req.body.monitoredUserAgents === "string"
55+
) {
56+
updateMonitoredUserAgents(req.app, req.body.monitoredUserAgents);
57+
}
58+
59+
if (
60+
req.body.monitoredIPAddresses &&
61+
Array.isArray(req.body.monitoredIPAddresses)
62+
) {
63+
updateMonitoredIPAddresses(req.app, req.body.monitoredIPAddresses);
64+
}
65+
66+
if (
67+
req.body.userAgentDetails &&
68+
Array.isArray(req.body.userAgentDetails)
69+
) {
70+
updateUserAgentDetails(req.app, req.body.userAgentDetails);
71+
}
72+
4973
res.json({ success: true });
5074
};

end2end/server/src/zen/config.js

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ function updateAppConfig(app, newConfig) {
4040
const blockedIPAddresses = [];
4141
const blockedUserAgents = [];
4242
const allowedIPAddresses = [];
43+
const monitoredUserAgents = [];
44+
const monitoredIPAddresses = [];
45+
const userAgentDetails = [];
4346

4447
function updateBlockedIPAddresses(app, ips) {
4548
let entry = blockedIPAddresses.find((ip) => ip.serviceId === app.serviceId);
@@ -90,7 +93,7 @@ function getAllowedIPAddresses(app) {
9093
}
9194

9295
function updateBlockedUserAgents(app, uas) {
93-
let entry = blockedUserAgents.find((e) => e.serviceId === e.serviceId);
96+
let entry = blockedUserAgents.find((e) => e.serviceId === app.serviceId);
9497

9598
if (entry) {
9699
entry.userAgents = uas;
@@ -104,7 +107,7 @@ function updateBlockedUserAgents(app, uas) {
104107
}
105108

106109
function getBlockedUserAgents(app) {
107-
const entry = blockedUserAgents.find((e) => e.serviceId === e.serviceId);
110+
const entry = blockedUserAgents.find((e) => e.serviceId === app.serviceId);
108111

109112
if (entry) {
110113
return entry.userAgents;
@@ -113,6 +116,78 @@ function getBlockedUserAgents(app) {
113116
return "";
114117
}
115118

119+
function updateMonitoredUserAgents(app, uas) {
120+
let entry = monitoredUserAgents.find((e) => e.serviceId === app.serviceId);
121+
122+
if (entry) {
123+
entry.userAgents = uas;
124+
} else {
125+
entry = { serviceId: app.serviceId, userAgents: uas };
126+
monitoredUserAgents.push(entry);
127+
}
128+
129+
// Bump lastUpdatedAt
130+
updateAppConfig(app, {});
131+
}
132+
133+
function getMonitoredUserAgents(app) {
134+
const entry = monitoredUserAgents.find((e) => e.serviceId === app.serviceId);
135+
136+
if (entry) {
137+
return entry.userAgents;
138+
}
139+
140+
return "";
141+
}
142+
143+
function updateMonitoredIPAddresses(app, ips) {
144+
let entry = monitoredIPAddresses.find((e) => e.serviceId === app.serviceId);
145+
146+
if (entry) {
147+
entry.ipAddresses = ips;
148+
} else {
149+
entry = { serviceId: app.serviceId, ipAddresses: ips };
150+
monitoredIPAddresses.push(entry);
151+
}
152+
153+
// Bump lastUpdatedAt
154+
updateAppConfig(app, {});
155+
}
156+
157+
function getMonitoredIPAddresses(app) {
158+
const entry = monitoredIPAddresses.find((e) => e.serviceId === app.serviceId);
159+
160+
if (entry) {
161+
return entry.ipAddresses;
162+
}
163+
164+
return [];
165+
}
166+
167+
function updateUserAgentDetails(app, uas) {
168+
let entry = userAgentDetails.find((e) => e.serviceId === app.serviceId);
169+
170+
if (entry) {
171+
entry.userAgents = uas;
172+
} else {
173+
entry = { serviceId: app.serviceId, userAgents: uas };
174+
userAgentDetails.push(entry);
175+
}
176+
177+
// Bump lastUpdatedAt
178+
updateAppConfig(app, {});
179+
}
180+
181+
function getUserAgentDetails(app) {
182+
const entry = userAgentDetails.find((e) => e.serviceId === app.serviceId);
183+
184+
if (entry) {
185+
return entry.userAgents;
186+
}
187+
188+
return [];
189+
}
190+
116191
module.exports = {
117192
getAppConfig,
118193
updateAppConfig,
@@ -122,4 +197,10 @@ module.exports = {
122197
getBlockedUserAgents,
123198
getAllowedIPAddresses,
124199
updateAllowedIPAddresses,
200+
updateMonitoredUserAgents,
201+
getMonitoredUserAgents,
202+
updateMonitoredIPAddresses,
203+
getMonitoredIPAddresses,
204+
updateUserAgentDetails,
205+
getUserAgentDetails,
125206
};
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
const t = require("tap");
2+
const { spawn } = require("child_process");
3+
const { resolve } = require("path");
4+
const timeout = require("../timeout");
5+
6+
const pathToApp = resolve(__dirname, "../../sample-apps/hono-xml", "app.js");
7+
const testServerUrl = "http://localhost:5874";
8+
9+
let token;
10+
t.beforeEach(async () => {
11+
const response = await fetch(`${testServerUrl}/api/runtime/apps`, {
12+
method: "POST",
13+
});
14+
const body = await response.json();
15+
token = body.token;
16+
17+
const lists = await fetch(`${testServerUrl}/api/runtime/firewall/lists`, {
18+
method: "POST",
19+
headers: {
20+
"Content-Type": "application/json",
21+
Authorization: token,
22+
},
23+
body: JSON.stringify({
24+
blockedIPAddresses: [],
25+
monitoredIPAddresses: ["1.3.2.0/24", "e98c:a7ba:2329:8c69::/64"],
26+
monitoredUserAgents: "monitored-bot",
27+
userAgentDetails: [
28+
{
29+
key: "monitored-bot",
30+
pattern: "monitored-bot",
31+
},
32+
],
33+
}),
34+
});
35+
t.same(lists.status, 200);
36+
});
37+
38+
t.test("it does not block monitored IPs", (t) => {
39+
const server = spawn(`node`, [pathToApp, "4005"], {
40+
env: {
41+
...process.env,
42+
AIKIDO_DEBUG: "true",
43+
AIKIDO_BLOCKING: "true",
44+
AIKIDO_TOKEN: token,
45+
AIKIDO_ENDPOINT: testServerUrl,
46+
},
47+
});
48+
49+
server.on("close", () => {
50+
t.end();
51+
});
52+
53+
server.on("error", (err) => {
54+
t.fail(err);
55+
});
56+
57+
let stdout = "";
58+
server.stdout.on("data", (data) => {
59+
stdout += data.toString();
60+
});
61+
62+
let stderr = "";
63+
server.stderr.on("data", (data) => {
64+
stderr += data.toString();
65+
});
66+
67+
// Wait for the server to start
68+
timeout(2000)
69+
.then(async () => {
70+
// Test IPv4 monitoring
71+
const resp1 = await fetch("http://127.0.0.1:4005/add", {
72+
method: "POST",
73+
body: "<cat><name>Njuska</name></cat>",
74+
headers: {
75+
"Content-Type": "application/xml",
76+
"X-Forwarded-For": "1.3.2.4",
77+
},
78+
signal: AbortSignal.timeout(5000),
79+
});
80+
t.same(resp1.status, 200);
81+
t.same(await resp1.text(), JSON.stringify({ success: true }));
82+
83+
// Test IPv6 monitoring
84+
const resp2 = await fetch("http://127.0.0.1:4005/add", {
85+
method: "POST",
86+
body: "<cat><name>Harry</name></cat>",
87+
headers: {
88+
"Content-Type": "application/xml",
89+
"X-Forwarded-For": "e98c:a7ba:2329:8c69:a13a:8aff:a932:13f2",
90+
},
91+
signal: AbortSignal.timeout(5000),
92+
});
93+
t.same(resp2.status, 200);
94+
t.same(await resp2.text(), JSON.stringify({ success: true }));
95+
})
96+
.catch((error) => {
97+
t.fail(error);
98+
})
99+
.finally(() => {
100+
server.kill();
101+
});
102+
});
103+
104+
t.test("it does not block monitored user agents", (t) => {
105+
const server = spawn(`node`, [pathToApp, "4006"], {
106+
env: {
107+
...process.env,
108+
AIKIDO_DEBUG: "true",
109+
AIKIDO_BLOCKING: "true",
110+
AIKIDO_TOKEN: token,
111+
AIKIDO_ENDPOINT: testServerUrl,
112+
},
113+
});
114+
115+
server.on("close", () => {
116+
t.end();
117+
});
118+
119+
server.on("error", (err) => {
120+
t.fail(err);
121+
});
122+
123+
let stdout = "";
124+
server.stdout.on("data", (data) => {
125+
stdout += data.toString();
126+
});
127+
128+
let stderr = "";
129+
server.stderr.on("data", (data) => {
130+
stderr += data.toString();
131+
});
132+
133+
// Wait for the server to start
134+
timeout(2000)
135+
.then(async () => {
136+
// Test monitored user agent
137+
const resp1 = await fetch("http://127.0.0.1:4006/", {
138+
headers: {
139+
"User-Agent": "monitored-bot",
140+
},
141+
signal: AbortSignal.timeout(5000),
142+
});
143+
t.same(resp1.status, 200);
144+
})
145+
.catch((error) => {
146+
t.fail(error);
147+
})
148+
.finally(() => {
149+
server.kill();
150+
});
151+
});

0 commit comments

Comments
 (0)