@contrast/common 1.1.5 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +11 -2
- package/lib/index.js +88 -21
- package/lib/index.js.map +1 -1
- package/lib/types.d.ts +29 -17
- package/package.json +2 -2
- package/src/index.ts +110 -18
- package/src/types.ts +49 -19
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CommonRulesResultsMap, HardeningResultsMap, ResultMap, SemanticAnalysisResultsMap, ServerFeaturePreliminaryResultsMap } from './types';
|
|
1
2
|
export * from './constants';
|
|
2
3
|
export * from './types';
|
|
3
4
|
interface TraverseCallback {
|
|
@@ -10,5 +11,13 @@ interface TraverseCallback {
|
|
|
10
11
|
export declare function isString(value: unknown): value is string | String;
|
|
11
12
|
export declare function isNonEmptyObject(value: unknown): value is object;
|
|
12
13
|
export declare function encodeString(str: string): string;
|
|
13
|
-
export declare function
|
|
14
|
-
export declare function
|
|
14
|
+
export declare function traverseKeysAndValues(obj: any, cb: TraverseCallback): void;
|
|
15
|
+
export declare function traverseValues(obj: any, cb: TraverseCallback): void;
|
|
16
|
+
export declare function traverseKeys(obj: any, cb: TraverseCallback): void;
|
|
17
|
+
export declare function callChildComponentMethodsSync(parent: any, method: 'install' | 'uninstall', order?: string[]): void;
|
|
18
|
+
export declare function groupResultsMap(resultsMap: Partial<ResultMap>): {
|
|
19
|
+
commonResultsMap: Partial<CommonRulesResultsMap>;
|
|
20
|
+
hardeningResultsMap: Partial<HardeningResultsMap>;
|
|
21
|
+
semanticResultsMap: Partial<SemanticAnalysisResultsMap>;
|
|
22
|
+
serverFeaturesResultsMap: Partial<ServerFeaturePreliminaryResultsMap>;
|
|
23
|
+
};
|
package/lib/index.js
CHANGED
|
@@ -28,7 +28,8 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
28
28
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
29
29
|
};
|
|
30
30
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
|
-
exports.
|
|
31
|
+
exports.groupResultsMap = exports.callChildComponentMethodsSync = exports.traverseKeys = exports.traverseValues = exports.traverseKeysAndValues = exports.encodeString = exports.isNonEmptyObject = exports.isString = void 0;
|
|
32
|
+
const constants_1 = require("./constants");
|
|
32
33
|
__exportStar(require("./constants"), exports);
|
|
33
34
|
__exportStar(require("./types"), exports);
|
|
34
35
|
/**
|
|
@@ -49,55 +50,121 @@ function encodeString(str) {
|
|
|
49
50
|
return Buffer.from(str).toString('base64');
|
|
50
51
|
}
|
|
51
52
|
exports.encodeString = encodeString;
|
|
52
|
-
function
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
56
|
-
const path = [];
|
|
57
|
-
function traverse(obj) {
|
|
53
|
+
function traverse(obj, cb, path, traverseValues, traverseKeys) {
|
|
54
|
+
let shouldKeepTraversing = true;
|
|
55
|
+
function _traverse(obj, cb, path, traverseValues, traverseKeys) {
|
|
58
56
|
const isArray = Array.isArray(obj);
|
|
59
57
|
for (const k in obj) {
|
|
58
|
+
if (!shouldKeepTraversing)
|
|
59
|
+
return;
|
|
60
60
|
if (isArray) {
|
|
61
61
|
const _k = Number(k);
|
|
62
62
|
// if it is an array, store each index in path but don't call the
|
|
63
63
|
// callback on the index itself as they are just numeric strings.
|
|
64
64
|
path.push(_k);
|
|
65
65
|
if (typeof obj[_k] === 'object' && obj[_k] !== null) {
|
|
66
|
-
|
|
66
|
+
_traverse(obj[_k], cb, path, traverseValues, traverseKeys);
|
|
67
67
|
}
|
|
68
|
-
else if (typeof obj[_k] === 'string' &&
|
|
69
|
-
cb(path, 'Value', obj[_k], obj)
|
|
68
|
+
else if (typeof obj[_k] === 'string' && obj[_k]) {
|
|
69
|
+
if (traverseValues && cb(path, 'Value', obj[_k], obj)) {
|
|
70
|
+
return shouldKeepTraversing = false;
|
|
71
|
+
}
|
|
70
72
|
}
|
|
71
73
|
path.pop();
|
|
72
74
|
}
|
|
73
75
|
else if (typeof obj[k] === 'object' && obj[k] !== null) {
|
|
74
|
-
cb(path, 'Key', k, obj)
|
|
76
|
+
if (traverseKeys && cb(path, 'Key', k, obj)) {
|
|
77
|
+
return shouldKeepTraversing = false;
|
|
78
|
+
}
|
|
75
79
|
path.push(k);
|
|
76
|
-
|
|
80
|
+
_traverse(obj[k], cb, path, traverseValues, traverseKeys);
|
|
77
81
|
path.pop();
|
|
78
82
|
}
|
|
79
83
|
else {
|
|
80
|
-
cb(path, 'Key', k, obj)
|
|
84
|
+
if (traverseKeys && cb(path, 'Key', k, obj)) {
|
|
85
|
+
return shouldKeepTraversing = false;
|
|
86
|
+
}
|
|
81
87
|
// only callback if the value is a non-empty string
|
|
82
|
-
if (typeof obj[k] === 'string' &&
|
|
88
|
+
if (typeof obj[k] === 'string' && obj[k]) {
|
|
83
89
|
path.push(k);
|
|
84
|
-
cb(path, 'Value', obj[k], obj)
|
|
90
|
+
if (traverseValues && cb(path, 'Value', obj[k], obj)) {
|
|
91
|
+
return shouldKeepTraversing = false;
|
|
92
|
+
}
|
|
85
93
|
path.pop();
|
|
86
94
|
}
|
|
87
95
|
}
|
|
88
96
|
}
|
|
89
97
|
}
|
|
90
|
-
|
|
98
|
+
_traverse(obj, cb, path, traverseValues, traverseKeys);
|
|
91
99
|
}
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
function traverseKeysAndValues(obj, cb) {
|
|
101
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
traverse(obj, cb, [], true, true);
|
|
105
|
+
}
|
|
106
|
+
exports.traverseKeysAndValues = traverseKeysAndValues;
|
|
107
|
+
function traverseValues(obj, cb) {
|
|
108
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
traverse(obj, cb, [], true, false);
|
|
112
|
+
}
|
|
113
|
+
exports.traverseValues = traverseValues;
|
|
114
|
+
function traverseKeys(obj, cb) {
|
|
115
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
traverse(obj, cb, [], false, true);
|
|
119
|
+
}
|
|
120
|
+
exports.traverseKeys = traverseKeys;
|
|
121
|
+
function callChildComponentMethodsSync(parent, method, order) {
|
|
94
122
|
const keys = order || Object.keys(parent);
|
|
95
123
|
for (const key of keys) {
|
|
96
124
|
const component = parent[key];
|
|
97
|
-
if (typeof component
|
|
98
|
-
component
|
|
125
|
+
if (typeof component[method] === 'function') {
|
|
126
|
+
component[method]();
|
|
99
127
|
}
|
|
100
128
|
}
|
|
101
129
|
}
|
|
102
|
-
exports.
|
|
130
|
+
exports.callChildComponentMethodsSync = callChildComponentMethodsSync;
|
|
131
|
+
function groupResultsMap(resultsMap) {
|
|
132
|
+
const result = {
|
|
133
|
+
commonResultsMap: {},
|
|
134
|
+
hardeningResultsMap: {},
|
|
135
|
+
semanticResultsMap: {},
|
|
136
|
+
serverFeaturesResultsMap: {},
|
|
137
|
+
};
|
|
138
|
+
Object.keys(resultsMap).reduce((acc, rule) => {
|
|
139
|
+
switch (rule) {
|
|
140
|
+
case constants_1.Rule.SQL_INJECTION:
|
|
141
|
+
case constants_1.Rule.CMD_INJECTION:
|
|
142
|
+
case constants_1.Rule.PATH_TRAVERSAL:
|
|
143
|
+
case constants_1.Rule.REFLECTED_XSS:
|
|
144
|
+
case constants_1.Rule.SSJS_INJECTION:
|
|
145
|
+
case constants_1.Rule.NOSQL_INJECTION_MONGO:
|
|
146
|
+
case constants_1.Rule.UNSAFE_FILE_UPLOAD:
|
|
147
|
+
case constants_1.Rule.BOT_BLOCKER:
|
|
148
|
+
case constants_1.Rule.NOSQL_INJECTION:
|
|
149
|
+
acc.commonResultsMap[rule] = resultsMap[rule];
|
|
150
|
+
break;
|
|
151
|
+
case constants_1.Rule.CMD_INJECTION_SEMANTIC_DANGEROUS_PATHS:
|
|
152
|
+
case constants_1.Rule.CMD_INJECTION_SEMANTIC_CHAINED_COMMANDS:
|
|
153
|
+
case constants_1.Rule.XXE:
|
|
154
|
+
case constants_1.Rule.CMD_INJECTION_COMMAND_BACKDOORS:
|
|
155
|
+
case constants_1.Rule.PATH_TRAVERSAL_SEMANTIC_FILE_SECURITY_BYPASS:
|
|
156
|
+
acc.semanticResultsMap[rule] = resultsMap[rule];
|
|
157
|
+
break;
|
|
158
|
+
case constants_1.Rule.VIRTUAL_PATCH:
|
|
159
|
+
case constants_1.Rule.IP_DENYLIST:
|
|
160
|
+
acc.serverFeaturesResultsMap[rule] = resultsMap[rule];
|
|
161
|
+
break;
|
|
162
|
+
case constants_1.Rule.UNTRUSTED_DESERIALIZATION:
|
|
163
|
+
acc.hardeningResultsMap[rule] = resultsMap[rule];
|
|
164
|
+
}
|
|
165
|
+
return acc;
|
|
166
|
+
}, result);
|
|
167
|
+
return result;
|
|
168
|
+
}
|
|
169
|
+
exports.groupResultsMap = groupResultsMap;
|
|
103
170
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;GAaG;;;;;;;;;;;;;;;;;AAEH,8CAA4B;AAC5B,0CAAwB;AAMxB;;;GAGG;AACH,wDAAwD;AACxD,SAAgB,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,YAAY,MAAM,CAAC;AAC9D,CAAC;AAFD,4BAEC;AAED,SAAgB,gBAAgB,CAAC,KAAc;IAC7C,OAAO,CAAC,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;AAC/E,CAAC;AAFD,4CAEC;AAED,sBAAsB;AACtB,SAAgB,YAAY,CAAC,GAAW;IACtC,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAFD,oCAEC;AAED,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/lib/types.d.ts
CHANGED
|
@@ -21,10 +21,13 @@ export interface AppInfo {
|
|
|
21
21
|
serverEnvironment: string;
|
|
22
22
|
version: string;
|
|
23
23
|
}
|
|
24
|
-
export declare type
|
|
24
|
+
export declare type CommonRules = Rule.SQL_INJECTION | Rule.CMD_INJECTION | Rule.PATH_TRAVERSAL | Rule.REFLECTED_XSS | Rule.SSJS_INJECTION | Rule.NOSQL_INJECTION_MONGO | Rule.UNSAFE_FILE_UPLOAD | Rule.NOSQL_INJECTION | Rule.BOT_BLOCKER;
|
|
25
|
+
export declare type SemanticAnalysisRules = Rule.CMD_INJECTION_SEMANTIC_DANGEROUS_PATHS | Rule.CMD_INJECTION_SEMANTIC_CHAINED_COMMANDS | Rule.XXE | Rule.CMD_INJECTION_COMMAND_BACKDOORS | Rule.PATH_TRAVERSAL_SEMANTIC_FILE_SECURITY_BYPASS;
|
|
26
|
+
export declare type ServerFeaturePreliminaryRules = Rule.VIRTUAL_PATCH | Rule.IP_DENYLIST;
|
|
27
|
+
export declare type HardeningRules = Rule.UNTRUSTED_DESERIALIZATION;
|
|
25
28
|
export interface Result {
|
|
26
29
|
blocked: boolean;
|
|
27
|
-
|
|
30
|
+
exploitMetadata?: any[] | any;
|
|
28
31
|
idsList?: string[];
|
|
29
32
|
inputType: string;
|
|
30
33
|
key?: string;
|
|
@@ -34,20 +37,22 @@ export interface Result {
|
|
|
34
37
|
ruleId: Rule;
|
|
35
38
|
score: number;
|
|
36
39
|
value: string;
|
|
40
|
+
sinkContext?: any;
|
|
37
41
|
}
|
|
38
42
|
export interface SemanticAnalysisResult extends Result {
|
|
39
|
-
|
|
43
|
+
ruleId: SemanticAnalysisRules;
|
|
44
|
+
exploitMetadata: {
|
|
40
45
|
command?: string;
|
|
41
46
|
prolog?: string;
|
|
42
47
|
xml?: string;
|
|
43
|
-
};
|
|
48
|
+
}[];
|
|
44
49
|
sinkContext?: any;
|
|
45
50
|
}
|
|
46
51
|
export interface HardeningResult extends Result {
|
|
47
|
-
|
|
52
|
+
exploitMetadata: {
|
|
48
53
|
command?: boolean;
|
|
49
54
|
deserializer?: string;
|
|
50
|
-
};
|
|
55
|
+
}[];
|
|
51
56
|
sinkContext?: any;
|
|
52
57
|
}
|
|
53
58
|
export interface ServerFeaturePreliminaryResult {
|
|
@@ -56,7 +61,7 @@ export interface ServerFeaturePreliminaryResult {
|
|
|
56
61
|
ip?: string;
|
|
57
62
|
}
|
|
58
63
|
export interface ServerFeatureResult extends Result {
|
|
59
|
-
|
|
64
|
+
exploitMetadata?: ServerFeaturePreliminaryResult[];
|
|
60
65
|
}
|
|
61
66
|
export interface ReqData {
|
|
62
67
|
method: string;
|
|
@@ -67,22 +72,29 @@ export interface ReqData {
|
|
|
67
72
|
ip: string;
|
|
68
73
|
httpVersion: string;
|
|
69
74
|
}
|
|
70
|
-
export
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
75
|
+
export declare type CommonRulesResultsMap = {
|
|
76
|
+
[rule in CommonRules]: Result[];
|
|
77
|
+
};
|
|
78
|
+
export declare type SemanticAnalysisResultsMap = {
|
|
79
|
+
[rule in SemanticAnalysisRules]: SemanticAnalysisResult[];
|
|
80
|
+
};
|
|
81
|
+
export declare type ServerFeaturePreliminaryResultsMap = {
|
|
82
|
+
[rule in ServerFeaturePreliminaryRules]: ServerFeaturePreliminaryResult[];
|
|
83
|
+
};
|
|
84
|
+
export declare type HardeningResultsMap = {
|
|
85
|
+
[rule in HardeningRules]: HardeningResult[];
|
|
86
|
+
};
|
|
87
|
+
export declare type ResultMap = CommonRulesResultsMap & SemanticAnalysisResultsMap & ServerFeaturePreliminaryResultsMap & HardeningResultsMap;
|
|
79
88
|
export interface ProtectMessage {
|
|
80
89
|
reqData: ReqData;
|
|
81
90
|
block: (mode: string, ruleId: string) => void;
|
|
82
91
|
policy: Partial<Record<Rule, ProtectRuleMode>>;
|
|
83
92
|
exclusions: any[];
|
|
84
93
|
virtualPatches: any[];
|
|
85
|
-
|
|
94
|
+
trackRequest: boolean;
|
|
95
|
+
securityException?: [mode: ProtectRuleMode, ruleId: string];
|
|
96
|
+
bodyType?: 'json' | 'urlencoded';
|
|
97
|
+
resultsMap: Partial<ResultMap>;
|
|
86
98
|
parsedBody: any;
|
|
87
99
|
parsedCookies: any;
|
|
88
100
|
parsedParams: any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contrast/common",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Shared constants and utilities for all Contrast Agent modules",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Contrast Security <nodejs@contrastsecurity.com> (https://www.contrastsecurity.com)",
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
"build": "tsc --build src/",
|
|
15
15
|
"test": "../scripts/test.sh"
|
|
16
16
|
}
|
|
17
|
-
}
|
|
17
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
* way not consistent with the End User License Agreement.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
+
import { Rule } from './constants';
|
|
17
|
+
import { CommonRulesResultsMap, HardeningResultsMap, ResultMap, SemanticAnalysisResultsMap, ServerFeaturePreliminaryResultsMap } from './types';
|
|
18
|
+
|
|
16
19
|
export * from './constants';
|
|
17
20
|
export * from './types';
|
|
18
21
|
|
|
@@ -38,51 +41,140 @@ export function encodeString(str: string): string {
|
|
|
38
41
|
return Buffer.from(str).toString('base64');
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
function traverse(
|
|
45
|
+
obj: any,
|
|
46
|
+
cb: TraverseCallback,
|
|
47
|
+
path: any[],
|
|
48
|
+
traverseValues: boolean,
|
|
49
|
+
traverseKeys: boolean
|
|
50
|
+
) {
|
|
51
|
+
let shouldKeepTraversing = true;
|
|
52
|
+
|
|
53
|
+
function _traverse(
|
|
54
|
+
obj: any,
|
|
55
|
+
cb: TraverseCallback,
|
|
56
|
+
path: any[],
|
|
57
|
+
traverseValues: boolean,
|
|
58
|
+
traverseKeys: boolean
|
|
59
|
+
) {
|
|
47
60
|
const isArray = Array.isArray(obj);
|
|
61
|
+
|
|
48
62
|
for (const k in obj) {
|
|
63
|
+
if (!shouldKeepTraversing) return;
|
|
64
|
+
|
|
49
65
|
if (isArray) {
|
|
50
66
|
const _k = Number(k);
|
|
51
67
|
// if it is an array, store each index in path but don't call the
|
|
52
68
|
// callback on the index itself as they are just numeric strings.
|
|
53
69
|
path.push(_k);
|
|
54
70
|
if (typeof obj[_k] === 'object' && obj[_k] !== null) {
|
|
55
|
-
|
|
56
|
-
} else if (typeof obj[_k] === 'string' &&
|
|
57
|
-
cb(path, 'Value', obj[_k], obj)
|
|
71
|
+
_traverse(obj[_k], cb, path, traverseValues, traverseKeys);
|
|
72
|
+
} else if (typeof obj[_k] === 'string' && obj[_k]) {
|
|
73
|
+
if (traverseValues && cb(path, 'Value', obj[_k], obj)) {
|
|
74
|
+
return shouldKeepTraversing = false;
|
|
75
|
+
}
|
|
58
76
|
}
|
|
59
77
|
path.pop();
|
|
60
78
|
} else if (typeof obj[k] === 'object' && obj[k] !== null) {
|
|
61
|
-
cb(path, 'Key', k, obj)
|
|
79
|
+
if (traverseKeys && cb(path, 'Key', k, obj)) {
|
|
80
|
+
return shouldKeepTraversing = false;
|
|
81
|
+
}
|
|
62
82
|
path.push(k);
|
|
63
|
-
|
|
83
|
+
_traverse(obj[k], cb, path, traverseValues, traverseKeys);
|
|
64
84
|
path.pop();
|
|
65
85
|
} else {
|
|
66
|
-
cb(path, 'Key', k, obj)
|
|
86
|
+
if (traverseKeys && cb(path, 'Key', k, obj)) {
|
|
87
|
+
return shouldKeepTraversing = false;
|
|
88
|
+
}
|
|
67
89
|
// only callback if the value is a non-empty string
|
|
68
|
-
if (typeof obj[k] === 'string' &&
|
|
90
|
+
if (typeof obj[k] === 'string' && obj[k]) {
|
|
69
91
|
path.push(k);
|
|
70
|
-
cb(path, 'Value', obj[k], obj)
|
|
92
|
+
if (traverseValues && cb(path, 'Value', obj[k], obj)) {
|
|
93
|
+
return shouldKeepTraversing = false;
|
|
94
|
+
}
|
|
71
95
|
path.pop();
|
|
72
96
|
}
|
|
73
97
|
}
|
|
74
98
|
}
|
|
75
99
|
}
|
|
76
100
|
|
|
77
|
-
|
|
101
|
+
_traverse(obj, cb, path, traverseValues, traverseKeys);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function traverseKeysAndValues(obj: any, cb: TraverseCallback) {
|
|
105
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
traverse(obj, cb, [], true, true);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function traverseValues(obj: any, cb: TraverseCallback) {
|
|
112
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
traverse(obj, cb, [], true, false);
|
|
78
116
|
}
|
|
79
117
|
|
|
80
|
-
export function
|
|
118
|
+
export function traverseKeys(obj: any, cb: TraverseCallback) {
|
|
119
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
traverse(obj, cb, [], false, true);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function callChildComponentMethodsSync(parent: any, method: 'install' | 'uninstall', order?: string[]) {
|
|
81
126
|
const keys = order || Object.keys(parent);
|
|
82
127
|
for (const key of keys) {
|
|
83
128
|
const component: any = parent[key];
|
|
84
|
-
if (typeof component
|
|
85
|
-
component
|
|
129
|
+
if (typeof component[method] === 'function') {
|
|
130
|
+
component[method]();
|
|
86
131
|
}
|
|
87
132
|
}
|
|
88
133
|
}
|
|
134
|
+
|
|
135
|
+
export function groupResultsMap (resultsMap: Partial<ResultMap>) {
|
|
136
|
+
const result: {
|
|
137
|
+
commonResultsMap: Partial<CommonRulesResultsMap>;
|
|
138
|
+
hardeningResultsMap: Partial<HardeningResultsMap>;
|
|
139
|
+
semanticResultsMap: Partial<SemanticAnalysisResultsMap>;
|
|
140
|
+
serverFeaturesResultsMap: Partial<ServerFeaturePreliminaryResultsMap>;
|
|
141
|
+
} = {
|
|
142
|
+
commonResultsMap: {},
|
|
143
|
+
hardeningResultsMap: {},
|
|
144
|
+
semanticResultsMap: {},
|
|
145
|
+
serverFeaturesResultsMap: {},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
Object.keys(resultsMap).reduce((acc, rule) => {
|
|
149
|
+
switch (rule) {
|
|
150
|
+
case Rule.SQL_INJECTION:
|
|
151
|
+
case Rule.CMD_INJECTION:
|
|
152
|
+
case Rule.PATH_TRAVERSAL:
|
|
153
|
+
case Rule.REFLECTED_XSS:
|
|
154
|
+
case Rule.SSJS_INJECTION:
|
|
155
|
+
case Rule.NOSQL_INJECTION_MONGO:
|
|
156
|
+
case Rule.UNSAFE_FILE_UPLOAD:
|
|
157
|
+
case Rule.BOT_BLOCKER:
|
|
158
|
+
case Rule.NOSQL_INJECTION:
|
|
159
|
+
acc.commonResultsMap[rule] = resultsMap[rule];
|
|
160
|
+
break;
|
|
161
|
+
case Rule.CMD_INJECTION_SEMANTIC_DANGEROUS_PATHS:
|
|
162
|
+
case Rule.CMD_INJECTION_SEMANTIC_CHAINED_COMMANDS:
|
|
163
|
+
case Rule.XXE:
|
|
164
|
+
case Rule.CMD_INJECTION_COMMAND_BACKDOORS:
|
|
165
|
+
case Rule.PATH_TRAVERSAL_SEMANTIC_FILE_SECURITY_BYPASS:
|
|
166
|
+
acc.semanticResultsMap[rule] = resultsMap[rule];
|
|
167
|
+
break;
|
|
168
|
+
case Rule.VIRTUAL_PATCH:
|
|
169
|
+
case Rule.IP_DENYLIST:
|
|
170
|
+
acc.serverFeaturesResultsMap[rule] = resultsMap[rule];
|
|
171
|
+
break;
|
|
172
|
+
case Rule.UNTRUSTED_DESERIALIZATION:
|
|
173
|
+
acc.hardeningResultsMap[rule] = resultsMap[rule];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return acc;
|
|
177
|
+
}, result);
|
|
178
|
+
|
|
179
|
+
return result;
|
|
180
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -37,14 +37,31 @@ export interface AppInfo {
|
|
|
37
37
|
version: string;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
export type CommonRules =
|
|
41
|
+
Rule.SQL_INJECTION |
|
|
42
|
+
Rule.CMD_INJECTION |
|
|
43
|
+
Rule.PATH_TRAVERSAL |
|
|
44
|
+
Rule.REFLECTED_XSS |
|
|
45
|
+
Rule.SSJS_INJECTION |
|
|
46
|
+
Rule.NOSQL_INJECTION_MONGO |
|
|
47
|
+
Rule.UNSAFE_FILE_UPLOAD |
|
|
48
|
+
Rule.NOSQL_INJECTION |
|
|
49
|
+
Rule.BOT_BLOCKER;
|
|
50
|
+
|
|
40
51
|
export type SemanticAnalysisRules =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
Rule.CMD_INJECTION_SEMANTIC_DANGEROUS_PATHS |
|
|
53
|
+
Rule.CMD_INJECTION_SEMANTIC_CHAINED_COMMANDS |
|
|
54
|
+
Rule.XXE |
|
|
55
|
+
Rule.CMD_INJECTION_COMMAND_BACKDOORS |
|
|
56
|
+
Rule.PATH_TRAVERSAL_SEMANTIC_FILE_SECURITY_BYPASS;
|
|
57
|
+
|
|
58
|
+
export type ServerFeaturePreliminaryRules = Rule.VIRTUAL_PATCH | Rule.IP_DENYLIST;
|
|
59
|
+
|
|
60
|
+
export type HardeningRules = Rule.UNTRUSTED_DESERIALIZATION;
|
|
44
61
|
|
|
45
62
|
export interface Result {
|
|
46
63
|
blocked: boolean;
|
|
47
|
-
|
|
64
|
+
exploitMetadata?: any[] | any; // TODO
|
|
48
65
|
idsList?: string[];
|
|
49
66
|
inputType: string; // TODO
|
|
50
67
|
key?: string;
|
|
@@ -54,22 +71,24 @@ export interface Result {
|
|
|
54
71
|
ruleId: Rule;
|
|
55
72
|
score: number;
|
|
56
73
|
value: string;
|
|
74
|
+
sinkContext?: any;
|
|
57
75
|
}
|
|
58
76
|
|
|
59
77
|
export interface SemanticAnalysisResult extends Result {
|
|
60
|
-
|
|
78
|
+
ruleId: SemanticAnalysisRules;
|
|
79
|
+
exploitMetadata: {
|
|
61
80
|
command?: string;
|
|
62
81
|
prolog?: string;
|
|
63
82
|
xml?: string;
|
|
64
|
-
};
|
|
83
|
+
}[];
|
|
65
84
|
sinkContext?: any;
|
|
66
85
|
}
|
|
67
86
|
|
|
68
87
|
export interface HardeningResult extends Result {
|
|
69
|
-
|
|
88
|
+
exploitMetadata: {
|
|
70
89
|
command?: boolean;
|
|
71
90
|
deserializer?: string;
|
|
72
|
-
};
|
|
91
|
+
}[];
|
|
73
92
|
sinkContext?: any;
|
|
74
93
|
}
|
|
75
94
|
|
|
@@ -80,7 +99,7 @@ export interface ServerFeaturePreliminaryResult {
|
|
|
80
99
|
}
|
|
81
100
|
|
|
82
101
|
export interface ServerFeatureResult extends Result {
|
|
83
|
-
|
|
102
|
+
exploitMetadata?: ServerFeaturePreliminaryResult[];
|
|
84
103
|
}
|
|
85
104
|
|
|
86
105
|
export interface ReqData {
|
|
@@ -93,15 +112,23 @@ export interface ReqData {
|
|
|
93
112
|
httpVersion: string;
|
|
94
113
|
}
|
|
95
114
|
|
|
96
|
-
export
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
115
|
+
export type CommonRulesResultsMap = {
|
|
116
|
+
[rule in CommonRules]: Result[];
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export type SemanticAnalysisResultsMap = {
|
|
120
|
+
[rule in SemanticAnalysisRules]: SemanticAnalysisResult[];
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export type ServerFeaturePreliminaryResultsMap = {
|
|
124
|
+
[rule in ServerFeaturePreliminaryRules]: ServerFeaturePreliminaryResult[]
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export type HardeningResultsMap = {
|
|
128
|
+
[rule in HardeningRules]:HardeningResult[];
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export type ResultMap = CommonRulesResultsMap & SemanticAnalysisResultsMap & ServerFeaturePreliminaryResultsMap & HardeningResultsMap;
|
|
105
132
|
|
|
106
133
|
export interface ProtectMessage {
|
|
107
134
|
reqData: ReqData;
|
|
@@ -109,7 +136,10 @@ export interface ProtectMessage {
|
|
|
109
136
|
policy: Partial<Record<Rule, ProtectRuleMode>>;
|
|
110
137
|
exclusions: any[]; // TODO
|
|
111
138
|
virtualPatches: any[]; // TODO
|
|
112
|
-
|
|
139
|
+
trackRequest: boolean;
|
|
140
|
+
securityException?: [mode: ProtectRuleMode, ruleId: string];
|
|
141
|
+
bodyType?: 'json' | 'urlencoded';
|
|
142
|
+
resultsMap: Partial<ResultMap>
|
|
113
143
|
parsedBody: any;
|
|
114
144
|
parsedCookies: any;
|
|
115
145
|
parsedParams: any;
|