@contrast/protect 1.2.2 → 1.3.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/cli-rewriter.js +15 -0
- package/lib/error-handlers/constants.js +15 -0
- package/lib/error-handlers/index.js +17 -0
- package/lib/error-handlers/install/express4.js +90 -0
- package/lib/error-handlers/install/fastify3.js +15 -0
- package/lib/error-handlers/install/koa2.js +15 -0
- package/lib/esm-loader.mjs +15 -0
- package/lib/index.d.ts +145 -19
- package/lib/index.js +15 -0
- package/lib/input-analysis/constants.js +20 -0
- package/lib/input-analysis/handlers.js +33 -10
- package/lib/input-analysis/index.js +36 -3
- package/lib/input-analysis/install/body-parser1.js +130 -0
- package/lib/input-analysis/install/cookie-parser1.js +82 -0
- package/lib/input-analysis/install/express4.js +108 -0
- package/lib/input-analysis/install/fastify3.js +47 -19
- package/lib/input-analysis/install/formidable1.js +73 -0
- package/lib/input-analysis/install/http.js +18 -1
- package/lib/input-analysis/install/koa-body5.js +68 -0
- package/lib/input-analysis/install/koa-bodyparser4.js +68 -0
- package/lib/input-analysis/install/koa2.js +26 -25
- package/lib/input-analysis/install/multer1.js +89 -0
- package/lib/input-analysis/install/qs6.js +61 -0
- package/lib/input-analysis/install/universal-cookie4.js +56 -0
- package/lib/input-tracing/constants.js +15 -0
- package/lib/input-tracing/handlers/index.js +154 -59
- package/lib/input-tracing/index.js +17 -0
- package/lib/input-tracing/install/child-process.js +16 -1
- package/lib/input-tracing/install/fs.js +17 -2
- package/lib/input-tracing/install/mongodb.js +233 -0
- package/lib/input-tracing/install/mysql.js +18 -2
- package/lib/input-tracing/install/postgres.js +15 -0
- package/lib/input-tracing/install/sequelize.js +15 -0
- package/lib/input-tracing/install/sqlite3.js +15 -0
- package/lib/make-response-blocker.js +15 -0
- package/lib/make-source-context.js +18 -0
- package/lib/security-exception.js +15 -0
- package/lib/throw-security-exception.js +17 -6
- package/lib/utils.js +14 -18
- package/package.json +8 -8
- package/lib/input-analysis/install/co-body.js +0 -51
- package/lib/input-analysis/install/cookie-parser.js +0 -48
- package/lib/input-analysis/install/formidable.js +0 -53
- package/lib/input-analysis/install/multer.js +0 -52
- package/lib/input-analysis/install/qs.js +0 -40
- package/lib/input-analysis/install/universal-cookie.js +0 -34
- package/lib/input-tracing/handlers/nosql-injection-mongo.js +0 -48
package/lib/cli-rewriter.js
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
/*
|
|
4
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
5
|
+
* Contact: support@contrastsecurity.com
|
|
6
|
+
* License: Commercial
|
|
7
|
+
|
|
8
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
9
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
10
|
+
* made available through public repositories, use of this Software is subject to
|
|
11
|
+
* the applicable End User Licensing Agreement found at
|
|
12
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
13
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
14
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
15
|
+
* way not consistent with the End User License Agreement.
|
|
16
|
+
*/
|
|
17
|
+
|
|
3
18
|
'use strict';
|
|
4
19
|
|
|
5
20
|
const { cliRewriter } = require('@contrast/core')();
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
1
16
|
'use strict';
|
|
2
17
|
|
|
3
18
|
module.exports = {
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
1
16
|
'use strict';
|
|
2
17
|
|
|
3
18
|
module.exports = function(core) {
|
|
@@ -5,10 +20,12 @@ module.exports = function(core) {
|
|
|
5
20
|
|
|
6
21
|
require('./install/fastify3')(core);
|
|
7
22
|
require('./install/koa2')(core);
|
|
23
|
+
require('./install/express4')(core);
|
|
8
24
|
|
|
9
25
|
errorHandlers.install = function() {
|
|
10
26
|
errorHandlers.fastify3ErrorHandler.install();
|
|
11
27
|
errorHandlers.koa2ErrorHandler.install();
|
|
28
|
+
errorHandlers.express4ErrorHandler.install();
|
|
12
29
|
};
|
|
13
30
|
|
|
14
31
|
return errorHandlers;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
const SecurityException = require('../../security-exception');
|
|
19
|
+
const { patchType } = require('../constants');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
module.exports = function(core) {
|
|
23
|
+
const {
|
|
24
|
+
logger,
|
|
25
|
+
depHooks,
|
|
26
|
+
patcher,
|
|
27
|
+
scopes: { sources },
|
|
28
|
+
protect,
|
|
29
|
+
} = core;
|
|
30
|
+
|
|
31
|
+
const express4ErrorHandler = protect.errorHandlers.express4ErrorHandler = {};
|
|
32
|
+
|
|
33
|
+
express4ErrorHandler.install = function () {
|
|
34
|
+
depHooks.resolve({ name: 'finalhandler' }, (finalhandler) =>
|
|
35
|
+
patcher.patch(finalhandler, {
|
|
36
|
+
name: 'finalHandler',
|
|
37
|
+
patchType,
|
|
38
|
+
post(data) {
|
|
39
|
+
data.result = patcher.patch(data.result, {
|
|
40
|
+
name: 'finalHandler.returnedFunction',
|
|
41
|
+
patchType,
|
|
42
|
+
around(org, data) {
|
|
43
|
+
const [err] = data.args;
|
|
44
|
+
const sourceContext = sources.getStore()?.protect;
|
|
45
|
+
const isSecurityException = SecurityException.isSecurityException(err);
|
|
46
|
+
|
|
47
|
+
if (isSecurityException && sourceContext) {
|
|
48
|
+
const blockInfo = sourceContext.findings.securityException;
|
|
49
|
+
|
|
50
|
+
sourceContext.block(...blockInfo);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!sourceContext && isSecurityException) {
|
|
55
|
+
logger.info('source context not found; unable to handle response');
|
|
56
|
+
}
|
|
57
|
+
org();
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
},
|
|
61
|
+
})
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
depHooks.resolve({ name: 'express', version: '>=4.0.0', file: 'lib/router/layer.js' }, (Layer) => {
|
|
65
|
+
patcher.patch(Layer.prototype, 'handle_error', {
|
|
66
|
+
name: 'Layer.prototype.handle_error',
|
|
67
|
+
patchType,
|
|
68
|
+
around(org, data) {
|
|
69
|
+
const [err] = data.args;
|
|
70
|
+
const sourceContext = sources.getStore()?.protect;
|
|
71
|
+
const isSecurityException = SecurityException.isSecurityException(err);
|
|
72
|
+
|
|
73
|
+
if (isSecurityException && sourceContext) {
|
|
74
|
+
const blockInfo = sourceContext.findings.securityException;
|
|
75
|
+
|
|
76
|
+
sourceContext.block(...blockInfo);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (!sourceContext && isSecurityException) {
|
|
81
|
+
logger.info('source context not found; unable to handle response');
|
|
82
|
+
}
|
|
83
|
+
org();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return express4ErrorHandler;
|
|
90
|
+
};
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
1
16
|
'use strict';
|
|
2
17
|
|
|
3
18
|
const { isSecurityException } = require('../../security-exception');
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
1
16
|
'use strict';
|
|
2
17
|
|
|
3
18
|
const SecurityException = require('../../security-exception');
|
package/lib/esm-loader.mjs
CHANGED
|
@@ -1,2 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
1
16
|
import esmHooks from '@contrast/esm-hooks';
|
|
2
17
|
export const { getSource, transformSource, load } = esmHooks();
|
package/lib/index.d.ts
CHANGED
|
@@ -1,29 +1,157 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
4
|
+
* Contact: support@contrastsecurity.com
|
|
5
|
+
* License: Commercial
|
|
6
|
+
|
|
7
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
8
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
9
|
+
* made available through public repositories, use of this Software is subject to
|
|
10
|
+
* the applicable End User Licensing Agreement found at
|
|
11
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
12
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
13
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
14
|
+
* way not consistent with the End User License Agreement.
|
|
15
|
+
*/
|
|
16
|
+
|
|
1
17
|
import { Core } from '@contrast/core';
|
|
18
|
+
import { Logger } from '@contrast/logger';
|
|
19
|
+
import { Sources } from '@contrast/scopes';
|
|
20
|
+
import RequireHook from '@contrast/require-hook';
|
|
21
|
+
import { RulesConfig, Rule, Messages, Result } from '@contrast/common';
|
|
22
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
23
|
+
import { Config } from '@contrast/config';
|
|
24
|
+
import { ProtectMessage } from '@contrast/common';
|
|
25
|
+
import * as http from 'node:http';
|
|
26
|
+
import * as https from 'node:https';
|
|
27
|
+
|
|
28
|
+
type Http = typeof http;
|
|
29
|
+
type Https = typeof https;
|
|
30
|
+
|
|
31
|
+
export type Block = (mode: string, ruleId: string) => void;
|
|
32
|
+
export class HttpInstrumentation {
|
|
33
|
+
messages: Messages;
|
|
34
|
+
scope: Sources;
|
|
35
|
+
config: Config;
|
|
36
|
+
logger: Logger;
|
|
37
|
+
depHooks: RequireHook;
|
|
38
|
+
protect: ProtectMessage;
|
|
39
|
+
makeSourceContext: Protect['makeSourceContext'];
|
|
40
|
+
maxBodySize: number;
|
|
41
|
+
installed: boolean;
|
|
42
|
+
|
|
43
|
+
constructor(core: Core);
|
|
44
|
+
|
|
45
|
+
install(): void;
|
|
46
|
+
uninstall(): void; //NYI
|
|
47
|
+
hookHttp(): void;
|
|
48
|
+
hookHttps(): void;
|
|
49
|
+
hookServer(xport: Http | Https): void;
|
|
50
|
+
initiateRequestHandling(fnContext: { instance: any, method: any, args: any }): void; //TODO
|
|
51
|
+
removeCookies(headers: string[]): string[];
|
|
52
|
+
}
|
|
53
|
+
export interface ReqData {
|
|
54
|
+
method: string;
|
|
55
|
+
headers: string[];
|
|
56
|
+
uriPath: string;
|
|
57
|
+
queries: string;
|
|
58
|
+
contentType?: string;
|
|
59
|
+
standardUrlParsing: boolean;
|
|
60
|
+
ip: string;
|
|
61
|
+
httpVersion: string,
|
|
62
|
+
headers2: { [key: string]: Array<string> };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface Findings {
|
|
66
|
+
trackRequest: boolean;
|
|
67
|
+
securityException?: [mode: string, ruleId: string];
|
|
68
|
+
bodyType?: 'json' | 'urlencoded';
|
|
69
|
+
resultsMap: Record<Rule, Result[]>
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface ProtectRequestStore {
|
|
73
|
+
reqData: ReqData;
|
|
74
|
+
block: Block;
|
|
75
|
+
rules: {
|
|
76
|
+
agentLibRules: RulesConfig;
|
|
77
|
+
agentLibRulesMask: number;
|
|
78
|
+
agentRules: RulesConfig;
|
|
79
|
+
};
|
|
80
|
+
exclusions: any[]; // TODO
|
|
81
|
+
virtualPatches: any[]; // TODO
|
|
82
|
+
findings: Findings;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export interface ConnectInputs {
|
|
86
|
+
headers: string[],
|
|
87
|
+
uriPath: string,
|
|
88
|
+
method: string,
|
|
89
|
+
queries?: string
|
|
90
|
+
}
|
|
2
91
|
|
|
3
|
-
// TODO
|
|
4
92
|
export interface Protect {
|
|
5
|
-
makeResponseBlocker: () =>
|
|
6
|
-
makeSourceContext: () =>
|
|
93
|
+
makeResponseBlocker: (res: ServerResponse) => Block,
|
|
94
|
+
makeSourceContext: (req: IncomingMessage, res: ServerResponse) => ProtectRequestStore,
|
|
95
|
+
throwSecurityException: (sourceContext: ProtectRequestStore) => void,
|
|
7
96
|
inputAnalysis: {
|
|
8
|
-
handleConnect: () =>
|
|
9
|
-
handleRequestEnd: () => void,
|
|
10
|
-
|
|
11
|
-
handleQueryParams: () => void,
|
|
12
|
-
handleUrlParams: () => void,
|
|
13
|
-
handleCookies: () => void,
|
|
14
|
-
|
|
15
|
-
|
|
97
|
+
handleConnect: (sourceContext: ProtectRequestStore, connectInputs: ConnectInputs) => undefined | [string, string],
|
|
98
|
+
handleRequestEnd: (sourceContext: ProtectRequestStore) => void, //NYI
|
|
99
|
+
handleParsedBody: (sourceContext: ProtectRequestStore, parsedBody: { [key: string]: any }) => void,
|
|
100
|
+
handleQueryParams: (sourceContext: ProtectRequestStore, queryParams: { [key: string]: any }) => void,
|
|
101
|
+
handleUrlParams: (sourceContext: ProtectRequestStore, urlParams: { [key: string]: any }) => void,
|
|
102
|
+
handleCookies: (sourceContext: ProtectRequestStore, cookies: { [key: string]: any }) => void,
|
|
103
|
+
handleFileuploadName: (sourceContext: ProtectRequestStore, name: string) => void, //NYI
|
|
104
|
+
librariesInstrumentation: {
|
|
105
|
+
bodyParser: { install: () => void },
|
|
106
|
+
coBody: { install: () => void },
|
|
107
|
+
cookieParser: { install: () => void },
|
|
108
|
+
formidable: { install: () => void },
|
|
109
|
+
multer: { install: () => void },
|
|
110
|
+
qs: { install: () => void },
|
|
111
|
+
universalCookie: { install: () => void },
|
|
112
|
+
},
|
|
113
|
+
expressInstrumentation: { install: () => void },
|
|
114
|
+
fastifyInstrumentation: { install: () => void },
|
|
115
|
+
koaInstrumentation: { install: () => void },
|
|
116
|
+
httpInstrumentation: HttpInstrumentation,
|
|
16
117
|
install: () => void,
|
|
17
118
|
},
|
|
18
119
|
inputTracing: {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
120
|
+
handlePathTraversal: (sourceContext: ProtectRequestStore, sinkContext: { name: string, value: string, stack: { [key: string]: any }[] }) => void,
|
|
121
|
+
handleCommandInjection: (sourceContext: ProtectRequestStore, sinkContext: { name: string, value: string, stack: { [key: string]: any }[] }) => void,
|
|
122
|
+
handleSqlInjection: (sourceContext: ProtectRequestStore, sinkContext: { name: string, value: string, stack: { [key: string]: any }[] }) => void,
|
|
123
|
+
nosqlInjectionMongo: (sourceContext: ProtectRequestStore, sinkContext: { name: string, value: any, stack: { [key: string]: any }[] }) => void,
|
|
124
|
+
ssjsInjection: () => void, //NYI
|
|
125
|
+
fsInstrumentation: {
|
|
126
|
+
getValues: (indices: number[], args: any) => string[],
|
|
127
|
+
install: () => void
|
|
128
|
+
},
|
|
129
|
+
cpInstrumentation: { install: () => void },
|
|
130
|
+
mysqlInstrumentation: {
|
|
131
|
+
getValueFromArgs: ([value]: any[]) => string | undefined,
|
|
132
|
+
install: () => void
|
|
133
|
+
},
|
|
134
|
+
postgresInstrumentation: {
|
|
135
|
+
getQueryFromArgs: ([value]: any[]) => string | undefined,
|
|
136
|
+
install: () => void
|
|
137
|
+
},
|
|
138
|
+
mongodbInstrumentation: { install: () => void },
|
|
139
|
+
sqlite3Instrumentation: { install: () => void },
|
|
140
|
+
sequelizeInstrumentation: {
|
|
141
|
+
getQueryFromArgs: ([value]: any[]) => string | undefined,
|
|
142
|
+
install: () => void
|
|
143
|
+
}
|
|
24
144
|
install: () => void
|
|
25
145
|
}
|
|
26
146
|
errorHandlers: {
|
|
147
|
+
fastify3ErrorHandler: {
|
|
148
|
+
_userHandler: null | ((...args: any[]) => any),
|
|
149
|
+
defaultErrorHandler: (error: Error, request: IncomingMessage, reply: ServerResponse) => void,
|
|
150
|
+
handler: (err: Error, request: IncomingMessage, reply: ServerResponse) => void,
|
|
151
|
+
install: () => void
|
|
152
|
+
}
|
|
153
|
+
koa2ErrorHandler: { install: () => void },
|
|
154
|
+
express4ErrorHandler: { install: () => void },
|
|
27
155
|
install: () => void,
|
|
28
156
|
},
|
|
29
157
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -31,6 +159,4 @@ export interface Protect {
|
|
|
31
159
|
version: string,
|
|
32
160
|
}
|
|
33
161
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
export default init;
|
|
162
|
+
export default function(core: Core): ProtectMessage;
|
package/lib/index.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
1
16
|
'use strict';
|
|
2
17
|
|
|
3
18
|
const agentLib = require('@contrast/agent-lib');
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
'use strict';
|
|
17
|
+
|
|
18
|
+
module.exports = {
|
|
19
|
+
patchType: 'protect-input-analysis',
|
|
20
|
+
};
|
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
1
16
|
'use strict';
|
|
2
17
|
|
|
3
18
|
const { simpleTraverse } = require('../utils');
|
|
@@ -144,7 +159,11 @@ module.exports = function(core) {
|
|
|
144
159
|
logger.debug({ queryParams }, 'handleQueryParams() called with non-object');
|
|
145
160
|
return;
|
|
146
161
|
}
|
|
147
|
-
commonObjectAnalyzer(sourceContext, queryParams, parameterInputTypes);
|
|
162
|
+
const block = commonObjectAnalyzer(sourceContext, queryParams, parameterInputTypes);
|
|
163
|
+
|
|
164
|
+
if (block) {
|
|
165
|
+
core.protect.throwSecurityException(sourceContext);
|
|
166
|
+
}
|
|
148
167
|
};
|
|
149
168
|
|
|
150
169
|
/**
|
|
@@ -199,10 +218,11 @@ module.exports = function(core) {
|
|
|
199
218
|
securityException: undefined,
|
|
200
219
|
resultsList,
|
|
201
220
|
};
|
|
221
|
+
|
|
202
222
|
const block = mergeFindings(rules.agentLibRules, sourceContext.findings, urlParamsFindings);
|
|
203
223
|
|
|
204
224
|
if (block) {
|
|
205
|
-
|
|
225
|
+
core.protect.throwSecurityException(sourceContext);
|
|
206
226
|
}
|
|
207
227
|
};
|
|
208
228
|
|
|
@@ -225,7 +245,7 @@ module.exports = function(core) {
|
|
|
225
245
|
const block = mergeFindings(rules.agentLibRules, sourceContext.findings, cookieFindings);
|
|
226
246
|
|
|
227
247
|
if (block) {
|
|
228
|
-
|
|
248
|
+
core.protect.throwSecurityException(sourceContext);
|
|
229
249
|
}
|
|
230
250
|
};
|
|
231
251
|
|
|
@@ -253,8 +273,13 @@ module.exports = function(core) {
|
|
|
253
273
|
bodyType = 'urlencoded';
|
|
254
274
|
inputTypes = parameterInputTypes;
|
|
255
275
|
}
|
|
256
|
-
commonObjectAnalyzer(sourceContext, parsedBody, inputTypes);
|
|
276
|
+
const block = commonObjectAnalyzer(sourceContext, parsedBody, inputTypes);
|
|
277
|
+
|
|
257
278
|
sourceContext.findings.bodyType = bodyType;
|
|
279
|
+
|
|
280
|
+
if (block) {
|
|
281
|
+
core.protect.throwSecurityException(sourceContext);
|
|
282
|
+
}
|
|
258
283
|
};
|
|
259
284
|
|
|
260
285
|
// was MULTIPART_NAME but maybe we should just call it what it is. it's kind
|
|
@@ -277,7 +302,7 @@ module.exports = function(core) {
|
|
|
277
302
|
* @param {Object} inputTypes is either jsonInputTypes or parameterInputTypes,
|
|
278
303
|
* both are defined above. They specify the input types to be used when evaluating
|
|
279
304
|
* the object.
|
|
280
|
-
* @returns undefined
|
|
305
|
+
* @returns {Array | undefined} returns an array with block info if vulnerability was found.
|
|
281
306
|
*/
|
|
282
307
|
function commonObjectAnalyzer(sourceContext, object, inputTypes) {
|
|
283
308
|
const { rules, rules: { agentLibRulesMask: mask } } = sourceContext;
|
|
@@ -333,7 +358,8 @@ module.exports = function(core) {
|
|
|
333
358
|
// mimic it here (where scoreAtom() was used). the actual object/string
|
|
334
359
|
// to match is stored as `inputToCheck`.
|
|
335
360
|
const inputType = typeof inputToCheck;
|
|
336
|
-
|
|
361
|
+
// query types up to Where, inclusive, accept either string or object values. Where and above accept only string values
|
|
362
|
+
if (mongoQueryType <= Where || inputType === 'string') {
|
|
337
363
|
// the query-type/input-type combination is valid. add a synthesized item.
|
|
338
364
|
const item = { ruleId: 'nosql-injection-mongo', score: 10, mongoContext: { inputToCheck } };
|
|
339
365
|
items.push(item);
|
|
@@ -370,10 +396,7 @@ module.exports = function(core) {
|
|
|
370
396
|
resultsList,
|
|
371
397
|
};
|
|
372
398
|
|
|
373
|
-
|
|
374
|
-
if (block) {
|
|
375
|
-
sourceContext.block(...block);
|
|
376
|
-
}
|
|
399
|
+
return mergeFindings(rules.agentLibRules, sourceContext.findings, findings);
|
|
377
400
|
}
|
|
378
401
|
};
|
|
379
402
|
|
|
@@ -1,17 +1,50 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright: 2022 Contrast Security, Inc
|
|
3
|
+
* Contact: support@contrastsecurity.com
|
|
4
|
+
* License: Commercial
|
|
5
|
+
|
|
6
|
+
* NOTICE: This Software and the patented inventions embodied within may only be
|
|
7
|
+
* used as part of Contrast Security’s commercial offerings. Even though it is
|
|
8
|
+
* made available through public repositories, use of this Software is subject to
|
|
9
|
+
* the applicable End User Licensing Agreement found at
|
|
10
|
+
* https://www.contrastsecurity.com/enduser-terms-0317a or as otherwise agreed
|
|
11
|
+
* between Contrast Security and the End User. The Software may not be reverse
|
|
12
|
+
* engineered, modified, repackaged, sold, redistributed or otherwise used in a
|
|
13
|
+
* way not consistent with the End User License Agreement.
|
|
14
|
+
*/
|
|
15
|
+
|
|
1
16
|
'use strict';
|
|
2
17
|
|
|
3
18
|
module.exports = function(core) {
|
|
4
19
|
const inputAnalysis = core.protect.inputAnalysis = {};
|
|
5
20
|
|
|
21
|
+
// inputAnalysis handlers
|
|
6
22
|
require('./handlers')(core);
|
|
23
|
+
|
|
24
|
+
// http(s) modules instrumentation
|
|
7
25
|
require('./install/http')(core);
|
|
26
|
+
|
|
27
|
+
// common libraries instrumentation
|
|
28
|
+
require('./install/body-parser1')(core);
|
|
29
|
+
require('./install/cookie-parser1')(core);
|
|
30
|
+
require('./install/formidable1')(core);
|
|
31
|
+
require('./install/koa-body5')(core);
|
|
32
|
+
require('./install/koa-bodyparser4')(core);
|
|
33
|
+
require('./install/multer1')(core);
|
|
34
|
+
require('./install/qs6')(core);
|
|
35
|
+
require('./install/universal-cookie4')(core);
|
|
36
|
+
|
|
37
|
+
// framework specific instrumentation
|
|
8
38
|
require('./install/fastify3')(core);
|
|
9
39
|
require('./install/koa2')(core);
|
|
40
|
+
require('./install/express4')(core);
|
|
10
41
|
|
|
11
42
|
inputAnalysis.install = function() {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
43
|
+
Object.values(inputAnalysis)
|
|
44
|
+
.filter((property) => property.install)
|
|
45
|
+
.forEach((library) => {
|
|
46
|
+
library.install();
|
|
47
|
+
});
|
|
15
48
|
};
|
|
16
49
|
|
|
17
50
|
return inputAnalysis;
|