@zhuma4/cli 4.0.0-alpha.1
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/README.md +42 -0
- package/dist/commands/config.d.ts +3 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +18 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +11 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/scan.d.ts +3 -0
- package/dist/commands/scan.d.ts.map +1 -0
- package/dist/commands/scan.js +96 -0
- package/dist/commands/scan.js.map +1 -0
- package/dist/commands/scan_appid.d.ts +20 -0
- package/dist/commands/scan_appid.d.ts.map +1 -0
- package/dist/commands/scan_appid.js +301 -0
- package/dist/commands/scan_appid.js.map +1 -0
- package/dist/commands/scan_manifest.d.ts +13 -0
- package/dist/commands/scan_manifest.d.ts.map +1 -0
- package/dist/commands/scan_manifest.js +103 -0
- package/dist/commands/scan_manifest.js.map +1 -0
- package/dist/engine/api-submit.d.ts +16 -0
- package/dist/engine/api-submit.d.ts.map +1 -0
- package/dist/engine/api-submit.js +66 -0
- package/dist/engine/api-submit.js.map +1 -0
- package/dist/engine/batch_scan.d.ts +36 -0
- package/dist/engine/batch_scan.d.ts.map +1 -0
- package/dist/engine/batch_scan.js +192 -0
- package/dist/engine/batch_scan.js.map +1 -0
- package/dist/engine/config.d.ts +12 -0
- package/dist/engine/config.d.ts.map +1 -0
- package/dist/engine/config.js +27 -0
- package/dist/engine/config.js.map +1 -0
- package/dist/engine/errors.d.ts +36 -0
- package/dist/engine/errors.d.ts.map +1 -0
- package/dist/engine/errors.js +99 -0
- package/dist/engine/errors.js.map +1 -0
- package/dist/engine/filter.d.ts +13 -0
- package/dist/engine/filter.d.ts.map +1 -0
- package/dist/engine/filter.js +64 -0
- package/dist/engine/filter.js.map +1 -0
- package/dist/engine/finding_classifier.d.ts +108 -0
- package/dist/engine/finding_classifier.d.ts.map +1 -0
- package/dist/engine/finding_classifier.js +440 -0
- package/dist/engine/finding_classifier.js.map +1 -0
- package/dist/engine/incremental/engine.d.ts +25 -0
- package/dist/engine/incremental/engine.d.ts.map +1 -0
- package/dist/engine/incremental/engine.js +337 -0
- package/dist/engine/incremental/engine.js.map +1 -0
- package/dist/engine/incremental/git-diff.d.ts +19 -0
- package/dist/engine/incremental/git-diff.d.ts.map +1 -0
- package/dist/engine/incremental/git-diff.js +175 -0
- package/dist/engine/incremental/git-diff.js.map +1 -0
- package/dist/engine/incremental/types.d.ts +33 -0
- package/dist/engine/incremental/types.d.ts.map +1 -0
- package/dist/engine/incremental/types.js +11 -0
- package/dist/engine/incremental/types.js.map +1 -0
- package/dist/engine/manifest_scanner.d.ts +48 -0
- package/dist/engine/manifest_scanner.d.ts.map +1 -0
- package/dist/engine/manifest_scanner.js +599 -0
- package/dist/engine/manifest_scanner.js.map +1 -0
- package/dist/engine/project.d.ts +22 -0
- package/dist/engine/project.d.ts.map +1 -0
- package/dist/engine/project.js +279 -0
- package/dist/engine/project.js.map +1 -0
- package/dist/engine/sarif.d.ts +13 -0
- package/dist/engine/sarif.d.ts.map +1 -0
- package/dist/engine/sarif.js +44 -0
- package/dist/engine/sarif.js.map +1 -0
- package/dist/engine/sca-integration.d.ts +36 -0
- package/dist/engine/sca-integration.d.ts.map +1 -0
- package/dist/engine/sca-integration.js +91 -0
- package/dist/engine/sca-integration.js.map +1 -0
- package/dist/engine/scanner.d.ts +18 -0
- package/dist/engine/scanner.d.ts.map +1 -0
- package/dist/engine/scanner.js +138 -0
- package/dist/engine/scanner.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/report/render.d.ts +23 -0
- package/dist/report/render.d.ts.map +1 -0
- package/dist/report/render.js +335 -0
- package/dist/report/render.js.map +1 -0
- package/package.json +41 -0
- package/rules/android/mobile-cleartext-traffic.yaml +46 -0
- package/rules/android/mobile-component-security.yaml +107 -0
- package/rules/android/mobile-crypto-weakness.yaml +139 -0
- package/rules/android/mobile-cwe-1021-tapjacking.yaml +81 -0
- package/rules/android/mobile-cwe-114-dynamic-dex-loading.yaml +41 -0
- package/rules/android/mobile-cwe-200-clipboard-data-leak.yaml +66 -0
- package/rules/android/mobile-cwe-200-debug-builds.yaml +111 -0
- package/rules/android/mobile-cwe-200-log-sensitive-data.yaml +61 -0
- package/rules/android/mobile-cwe-200-webview-debugging.yaml +56 -0
- package/rules/android/mobile-cwe-200-webview-universal-access.yaml +30 -0
- package/rules/android/mobile-cwe-200-window-flags.yaml +96 -0
- package/rules/android/mobile-cwe-22-content-provider-openfile.yaml +73 -0
- package/rules/android/mobile-cwe-22-path-traversal.yaml +86 -0
- package/rules/android/mobile-cwe-287-biometric-weakness.yaml +102 -0
- package/rules/android/mobile-cwe-295-cert-pinning-missing.yaml +78 -0
- package/rules/android/mobile-cwe-295-webview-ssl-bypass.yaml +104 -0
- package/rules/android/mobile-cwe-312-cleartext-storage.yaml +109 -0
- package/rules/android/mobile-cwe-319-cleartext-communication.yaml +84 -0
- package/rules/android/mobile-cwe-321-hardcoded-crypto-keys.yaml +132 -0
- package/rules/android/mobile-cwe-326-short-rsa.yaml +108 -0
- package/rules/android/mobile-cwe-327-rc4-3des.yaml +107 -0
- package/rules/android/mobile-cwe-329-cbc-padding-oracle.yaml +76 -0
- package/rules/android/mobile-cwe-470-reflection-injection.yaml +39 -0
- package/rules/android/mobile-cwe-489-root-detection-weak.yaml +125 -0
- package/rules/android/mobile-cwe-489-stetho-debug.yaml +107 -0
- package/rules/android/mobile-cwe-502-insecure-deserialization.yaml +76 -0
- package/rules/android/mobile-cwe-552-world-readable-files.yaml +63 -0
- package/rules/android/mobile-cwe-749-webview-java-objects.yaml +78 -0
- package/rules/android/mobile-cwe-749-webview-jsbridge.yaml +57 -0
- package/rules/android/mobile-cwe-749-webview-loadurl-injection.yaml +80 -0
- package/rules/android/mobile-cwe-78-command-injection.yaml +77 -0
- package/rules/android/mobile-cwe-780-rsa-no-oaep.yaml +80 -0
- package/rules/android/mobile-cwe-79-webview-setdata.yaml +78 -0
- package/rules/android/mobile-cwe-79-webview-xss.yaml +65 -0
- package/rules/android/mobile-cwe-798-hardcoded-credentials.yaml +108 -0
- package/rules/android/mobile-cwe-89-sql-injection.yaml +100 -0
- package/rules/android/mobile-cwe-927-implicit-intent.yaml +121 -0
- package/rules/android/mobile-cwe-927-ipc-file-provider.yaml +102 -0
- package/rules/android/mobile-cwe-939-deeplink-validation.yaml +76 -0
- package/rules/android/mobile-sdk-google-firebase-open.yaml +117 -0
- package/rules/android/mobile-sdk-tencent-tpns-config-leak.yaml +131 -0
- package/rules/android/mobile-secrets-storage.yaml +136 -0
- package/rules/android/mobile-webview-security.yaml +88 -0
- package/rules/common/cwe-200-sensitive-data-exposure.yaml +61 -0
- package/rules/common/cwe-22-path-traversal.yaml +47 -0
- package/rules/common/cwe-295-ssl-bypass.yaml +217 -0
- package/rules/common/cwe-295-ssl-verification-disabled.yaml +64 -0
- package/rules/common/cwe-306-missing-authentication.yaml +44 -0
- package/rules/common/cwe-326-weak-key-size.yaml +107 -0
- package/rules/common/cwe-327-weak-crypto.yaml +177 -0
- package/rules/common/cwe-328-weak-hash.yaml +96 -0
- package/rules/common/cwe-329-cbc-mode.yaml +26 -0
- package/rules/common/cwe-352-csrf.yaml +23 -0
- package/rules/common/cwe-434-unrestricted-file-upload.yaml +41 -0
- package/rules/common/cwe-502-insecure-deserialization.yaml +44 -0
- package/rules/common/cwe-601-url-redirect.yaml +110 -0
- package/rules/common/cwe-611-xxe.yaml +70 -0
- package/rules/common/cwe-732-incorrect-permission.yaml +49 -0
- package/rules/common/cwe-770-resource-exhaustion.yaml +44 -0
- package/rules/common/cwe-78-os-command-injection.yaml +43 -0
- package/rules/common/cwe-787-out-of-bounds-write.yaml +37 -0
- package/rules/common/cwe-79-xss.yaml +51 -0
- package/rules/common/cwe-862-missing-authorization.yaml +40 -0
- package/rules/common/cwe-89-sqli.yaml +89 -0
- package/rules/common/cwe-918-ssrf.yaml +45 -0
- package/rules/common/cwe-94-code-injection.yaml +59 -0
- package/rules/common/zm-go-cwe22-path-traversal-fs.yaml +117 -0
- package/rules/common/zm-go-cwe22-path-traversal.yaml +103 -0
- package/rules/common/zm-go-cwe307-brute-force.yaml +129 -0
- package/rules/common/zm-go-cwe326-weak-crypto.yaml +124 -0
- package/rules/common/zm-go-cwe327-weak-cipher.yaml +152 -0
- package/rules/common/zm-go-cwe384-session-fixation.yaml +128 -0
- package/rules/common/zm-go-cwe502-deserialization.yaml +120 -0
- package/rules/common/zm-go-cwe78-command-injection.yaml +95 -0
- package/rules/common/zm-go-cwe79-xss.yaml +104 -0
- package/rules/common/zm-go-cwe798-hardcoded-creds.yaml +153 -0
- package/rules/common/zm-go-cwe89-sqli.yaml +89 -0
- package/rules/common/zm-go-cwe918-ssrf.yaml +117 -0
- package/rules/common/zm-java-cwe117-log-injection.yaml +83 -0
- package/rules/common/zm-java-cwe117-logforging.yaml +153 -0
- package/rules/common/zm-java-cwe200-actuator-exposure.yaml +8 -0
- package/rules/common/zm-java-cwe200-info-disclosure.yaml +91 -0
- package/rules/common/zm-java-cwe22-file-depth.yaml +135 -0
- package/rules/common/zm-java-cwe22-path-traversal-spring.yaml +81 -0
- package/rules/common/zm-java-cwe284-missing-auth-spring.yaml +131 -0
- package/rules/common/zm-java-cwe295-webview-ssl.yaml +123 -0
- package/rules/common/zm-java-cwe327-weakcrypto.yaml +197 -0
- package/rules/common/zm-java-cwe347-jwt.yaml +30 -0
- package/rules/common/zm-java-cwe352-csrf-depth.yaml +107 -0
- package/rules/common/zm-java-cwe352-csrf-disabled.yaml +15 -0
- package/rules/common/zm-java-cwe501-trust-boundary.yaml +124 -0
- package/rules/common/zm-java-cwe502-deserial-depth.yaml +128 -0
- package/rules/common/zm-java-cwe502-fastjson.yaml +137 -0
- package/rules/common/zm-java-cwe502-gadget.yaml +158 -0
- package/rules/common/zm-java-cwe502-jndi-injection.yaml +91 -0
- package/rules/common/zm-java-cwe502-shiro.yaml +108 -0
- package/rules/common/zm-java-cwe601-url-redirect-spring.yaml +85 -0
- package/rules/common/zm-java-cwe611-xxe-enhanced.yaml +80 -0
- package/rules/common/zm-java-cwe611-xxe-transformer.yaml +85 -0
- package/rules/common/zm-java-cwe639-idor.yaml +123 -0
- package/rules/common/zm-java-cwe79-xss-depth.yaml +98 -0
- package/rules/common/zm-java-cwe862-authz-depth.yaml +127 -0
- package/rules/common/zm-java-cwe915-mass-assignment.yaml +16 -0
- package/rules/common/zm-java-cwe917-expression-injection.yaml +120 -0
- package/rules/common/zm-java-cwe918-resttemplate.yaml +67 -0
- package/rules/common/zm-java-cwe918-ssrf-depth.yaml +103 -0
- package/rules/common/zm-java-cwe918-ssrf-resttemplate.yaml +77 -0
- package/rules/common/zm-java-cwe918-webclient.yaml +44 -0
- package/rules/common/zm-java-cwe94-ognl.yaml +66 -0
- package/rules/common/zm-java-cwe94-spel-injection.yaml +85 -0
- package/rules/common/zm-java-cwe94-spel.yaml +112 -0
- package/rules/common/zm-java-cwe94-ssti.yaml +22 -0
- package/rules/common/zm-java-cwe942-cors.yaml +15 -0
- package/rules/common/zm-js-cwe1321-prototype-pollution.yaml +61 -0
- package/rules/common/zm-js-cwe200-info-disclosure.yaml +95 -0
- package/rules/common/zm-js-cwe22-path-traversal-fs.yaml +113 -0
- package/rules/common/zm-js-cwe22-pathtraversal.yaml +111 -0
- package/rules/common/zm-js-cwe307-brute-force.yaml +136 -0
- package/rules/common/zm-js-cwe345-postmessage.yaml +75 -0
- package/rules/common/zm-js-cwe347-jwt-weak.yaml +95 -0
- package/rules/common/zm-js-cwe352-csrf.yaml +52 -0
- package/rules/common/zm-js-cwe384-session-fixation.yaml +132 -0
- package/rules/common/zm-js-cwe502-deserialization.yaml +119 -0
- package/rules/common/zm-js-cwe611-xxe.yaml +108 -0
- package/rules/common/zm-js-cwe639-idor.yaml +122 -0
- package/rules/common/zm-js-cwe693-helmet-missing.yaml +46 -0
- package/rules/common/zm-js-cwe78-exec.yaml +37 -0
- package/rules/common/zm-js-cwe78-spawn.yaml +37 -0
- package/rules/common/zm-js-cwe79-domxss.yaml +84 -0
- package/rules/common/zm-js-cwe79-react-xss.yaml +18 -0
- package/rules/common/zm-js-cwe79-xss-ejs.yaml +70 -0
- package/rules/common/zm-js-cwe89-sqli.yaml +153 -0
- package/rules/common/zm-js-cwe915-mass-assignment.yaml +111 -0
- package/rules/common/zm-js-cwe918-ssrf-fetch.yaml +134 -0
- package/rules/common/zm-js-cwe918-ssrf.yaml +132 -0
- package/rules/common/zm-js-cwe94-template-injection.yaml +130 -0
- package/rules/common/zm-js-cwe942-cors.yaml +49 -0
- package/rules/common/zm-js-cwe943-nosql-injection.yaml +52 -0
- package/rules/common/zm-js-cwe95-eval.yaml +59 -0
- package/rules/common/zm-js-cwe95-function-ctor.yaml +31 -0
- package/rules/common/zm-py-cwe22-path-traversal.yaml +86 -0
- package/rules/common/zm-py-cwe327-weak-crypto.yaml +103 -0
- package/rules/common/zm-py-cwe502-pickle.yaml +92 -0
- package/rules/common/zm-py-cwe611-xxe.yaml +100 -0
- package/rules/common/zm-py-cwe78-command-injection.yaml +121 -0
- package/rules/common/zm-py-cwe79-xss.yaml +123 -0
- package/rules/common/zm-py-cwe798-hardcoded-creds.yaml +86 -0
- package/rules/common/zm-py-cwe89-sqli.yaml +59 -0
- package/rules/common/zm-py-cwe918-ssrf.yaml +123 -0
- package/rules/common/zm-py-cwe94-ssti.yaml +87 -0
- package/rules/common/zm-py-cwe943-nosql-injection.yaml +123 -0
- package/rules/iac/ansible/zm-ansible-cwe269-privilege-escalation.yaml +63 -0
- package/rules/iac/ansible/zm-ansible-cwe78-command-injection.yaml +67 -0
- package/rules/iac/ansible/zm-ansible-cwe798-hardcoded-creds.yaml +93 -0
- package/rules/iac/terraform/zm-tf-cwe200-s3-bucket-public.yaml +100 -0
- package/rules/iac/terraform/zm-tf-cwe284-sg-wide-open.yaml +88 -0
- package/rules/iac/terraform/zm-tf-cwe311-iam-wildcard.yaml +83 -0
- package/rules/iac/terraform/zm-tf-cwe319-rds-public.yaml +72 -0
- package/rules/iac/terraform/zm-tf-cwe798-hardcoded-creds.yaml +102 -0
- package/rules/iac/zm-docker-cwe250-root-user.yaml +50 -0
- package/rules/iac/zm-docker-cwe400-resource-limit.yaml +92 -0
- package/rules/iac/zm-docker-security.yaml +104 -0
- package/rules/iac/zm-k8s-cwe200-service-account.yaml +83 -0
- package/rules/iac/zm-k8s-cwe250-privileged.yaml +56 -0
- package/rules/iac/zm-k8s-security.yaml +79 -0
- package/rules/rules_index.yaml.off +477 -0
- package/rules/semgrep-registry/anonymous-ldap-bind.yaml +34 -0
- package/rules/semgrep-registry/bad-hexa-conversion.yaml +32 -0
- package/rules/semgrep-registry/blowfish-insufficient-key-size.yaml +39 -0
- package/rules/semgrep-registry/cbc-padding-oracle.yaml +38 -0
- package/rules/semgrep-registry/command-injection-formatted-runtime-call.yaml +90 -0
- package/rules/semgrep-registry/command-injection-process-builder.yaml +148 -0
- package/rules/semgrep-registry/cookie-missing-httponly.yaml +38 -0
- package/rules/semgrep-registry/cookie-missing-secure-flag.yaml +38 -0
- package/rules/semgrep-registry/crlf-injection-logs.yaml +86 -0
- package/rules/semgrep-registry/dangerous-groovy-shell.yaml +46 -0
- package/rules/semgrep-registry/el-injection.yaml +137 -0
- package/rules/semgrep-registry/formatted-sql-string.yaml +95 -0
- package/rules/semgrep-registry/http-response-splitting.yaml +44 -0
- package/rules/semgrep-registry/index.txt +1 -0
- package/rules/semgrep-registry/insecure-smtp-connection.yaml +34 -0
- package/rules/semgrep-registry/java-reverse-shell.yaml +43 -0
- package/rules/semgrep-registry/jdbc-sql-formatted-string.yaml +120 -0
- package/rules/semgrep-registry/ldap-entry-poisoning.yaml +41 -0
- package/rules/semgrep-registry/ldap-injection.yaml +82 -0
- package/rules/semgrep-registry/md5-used-as-password.yaml +44 -0
- package/rules/semgrep-registry/object-deserialization.yaml +34 -0
- package/rules/semgrep-registry/ognl-injection.yaml +839 -0
- package/rules/semgrep-registry/overly-permissive-file-permission.yaml +49 -0
- package/rules/semgrep-registry/permissive-cors.yaml +77 -0
- package/rules/semgrep-registry/script-engine-injection.yaml +66 -0
- package/rules/semgrep-registry/tainted-cmd-from-http-request.yaml +74 -0
- package/rules/semgrep-registry/tainted-env-from-http-request.yaml +46 -0
- package/rules/semgrep-registry/tainted-ldapi-from-http-request.yaml +42 -0
- package/rules/semgrep-registry/tainted-session-from-http-request.yaml +70 -0
- package/rules/semgrep-registry/tainted-xpath-from-http-request.yaml +38 -0
- package/rules/semgrep-registry/unsafe-reflection.yaml +39 -0
- package/rules/semgrep-registry/unvalidated-redirect.yaml +127 -0
- package/rules/semgrep-registry/url-rewriting.yaml +82 -0
- package/rules/semgrep-registry/weak-ssl-context.yaml +34 -0
- package/rules/semgrep-registry/xml-decoder.yaml +53 -0
- package/rules/semgrep-registry/xssrequestwrapper-is-insecure.yaml +40 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# CWE-915: Node.js 过度绑定/批量赋值检测规则
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint 2 — JS/TS 规则库
|
|
3
|
+
# 覆盖: Object.assign(req.body, target)、lodash.merge、Mongoose Model(req.body)、Sequelize bulkCreate
|
|
4
|
+
|
|
5
|
+
rules:
|
|
6
|
+
|
|
7
|
+
# ZM-JS-MA-001: Object.assign / lodash.merge 将 req.body 合并到数据库对象
|
|
8
|
+
- id: zm-js-ma-001
|
|
9
|
+
severity: ERROR
|
|
10
|
+
message: |
|
|
11
|
+
Object.assign() 或 lodash.merge() 直接将 req.body / req.query / req.params
|
|
12
|
+
合并或赋值给数据库模型/内部对象,攻击者可注入额外字段(如 role: "admin"、isAdmin: true)
|
|
13
|
+
实现权限提升或数据篡改。
|
|
14
|
+
|
|
15
|
+
修复:
|
|
16
|
+
1. 只提取白名单字段: { username, email } = req.body; Object.assign(dbUser, { username, email })
|
|
17
|
+
2. 使用 pick() 辅助函数从 req.body 提取允许字段
|
|
18
|
+
3. 使用 Mongoose Schema 定义字段白名单
|
|
19
|
+
4. ORM层面设置 strict: 'throw' (Mongoose) 或 fields 白名单 (Sequelize)
|
|
20
|
+
5. 使用 joi / zod Schema 验证并 strip 未知字段
|
|
21
|
+
languages:
|
|
22
|
+
- javascript
|
|
23
|
+
- typescript
|
|
24
|
+
pattern-either:
|
|
25
|
+
- pattern: Object.assign($TARGET, $REQ.body, ...)
|
|
26
|
+
- pattern: Object.assign($TARGET, $REQ.query, ...)
|
|
27
|
+
- pattern: Object.assign($TARGET, $REQ.params, ...)
|
|
28
|
+
- pattern: lodash.merge($TARGET, $REQ.body, ...)
|
|
29
|
+
- pattern: lodash.merge($TARGET, $REQ.query, ...)
|
|
30
|
+
- pattern: lodash.merge($TARGET, $REQ.params, ...)
|
|
31
|
+
- pattern: _.merge($TARGET, $REQ.body, ...)
|
|
32
|
+
- pattern: _.merge($TARGET, $REQ.query, ...)
|
|
33
|
+
- pattern: _.merge($TARGET, $REQ.params, ...)
|
|
34
|
+
- pattern: _.assign($TARGET, $REQ.body, ...)
|
|
35
|
+
- pattern: _.assign($TARGET, $REQ.query, ...)
|
|
36
|
+
- pattern: _.assign($TARGET, $REQ.params, ...)
|
|
37
|
+
- pattern: _.defaults($TARGET, $REQ.body, ...)
|
|
38
|
+
- pattern: _.extend($TARGET, $REQ.body, ...)
|
|
39
|
+
- pattern: $merge($TARGET, $REQ.body, ...)
|
|
40
|
+
metadata:
|
|
41
|
+
cwe: "CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes"
|
|
42
|
+
owasp: "A01:2021 - Broken Access Control"
|
|
43
|
+
category: mass-assignment
|
|
44
|
+
precision: high
|
|
45
|
+
references:
|
|
46
|
+
- "https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html"
|
|
47
|
+
- "https://mongoosejs.com/docs/guide.html#strict"
|
|
48
|
+
|
|
49
|
+
# ZM-JS-MA-002: Mongoose/Sequelize 直接传入 req.body 创建/更新 (无字段过滤)
|
|
50
|
+
- id: zm-js-ma-002
|
|
51
|
+
severity: ERROR
|
|
52
|
+
message: |
|
|
53
|
+
Mongoose Model 构造函数、create()、findByIdAndUpdate() 或 Sequelize Model.create()
|
|
54
|
+
直接传入 req.body / req.query 作为参数,未过滤允许字段,存在过度绑定风险。
|
|
55
|
+
|
|
56
|
+
攻击者可通过注入 protected 字段(如 role、credit、verified)绕过业务限制。
|
|
57
|
+
|
|
58
|
+
修复:
|
|
59
|
+
1. Mongoose: Schema 设置 { strict: true } 或 { strict: 'throw' }
|
|
60
|
+
2. Mongoose 查询: 先 destructure 白名单字段再传入
|
|
61
|
+
3. Sequelize: Model.create() 前使用 fields/attributes 白名单
|
|
62
|
+
4. 统一中间件层做字段过滤
|
|
63
|
+
languages:
|
|
64
|
+
- javascript
|
|
65
|
+
- typescript
|
|
66
|
+
pattern-either:
|
|
67
|
+
- pattern: $MODEL.create($REQ.body, ...)
|
|
68
|
+
- pattern: $MODEL.create($REQ.query, ...)
|
|
69
|
+
- pattern: new $MODEL($REQ.body, ...)
|
|
70
|
+
- pattern: new $MODEL($REQ.query, ...)
|
|
71
|
+
- pattern: $MODEL.insertMany($REQ.body, ...)
|
|
72
|
+
- pattern: $MODEL.findByIdAndUpdate($_, $REQ.body, ...)
|
|
73
|
+
- pattern: $MODEL.findOneAndUpdate($_, $REQ.body, ...)
|
|
74
|
+
- pattern: $MODEL.updateOne($_, $REQ.body, ...)
|
|
75
|
+
- pattern: $MODEL.updateMany($_, $REQ.body, ...)
|
|
76
|
+
- pattern: $MODEL.replaceOne($_, $REQ.body, ...)
|
|
77
|
+
- pattern: $MODEL.bulkWrite($REQ.body, ...)
|
|
78
|
+
metadata:
|
|
79
|
+
cwe: "CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes"
|
|
80
|
+
owasp: "A01:2021 - Broken Access Control"
|
|
81
|
+
category: mass-assignment
|
|
82
|
+
precision: high
|
|
83
|
+
references:
|
|
84
|
+
- "https://mongoosejs.com/docs/guide.html#strict"
|
|
85
|
+
- "https://sequelize.org/docs/v6/core-concepts/model-basics/#data-types"
|
|
86
|
+
|
|
87
|
+
# ZM-JS-MA-003: Sequelize bulkCreate 无 fields 白名单
|
|
88
|
+
- id: zm-js-ma-003
|
|
89
|
+
severity: WARNING
|
|
90
|
+
message: |
|
|
91
|
+
Sequelize Model.bulkCreate() 接收 req.body 且可能未设置 fields 白名单。
|
|
92
|
+
攻击者可批量注入额外字段,影响大量记录。
|
|
93
|
+
|
|
94
|
+
修复:
|
|
95
|
+
1. Model.bulkCreate(data, { fields: ['name', 'email'] }) 显式指定白名单
|
|
96
|
+
2. 在 Controller 层做字段提取: const { name, email } = req.body
|
|
97
|
+
3. 使用 Sequelize beforeBulkCreate hook 做字段验证
|
|
98
|
+
languages:
|
|
99
|
+
- javascript
|
|
100
|
+
- typescript
|
|
101
|
+
pattern-either:
|
|
102
|
+
- pattern: $MODEL.bulkCreate($REQ.body, ...)
|
|
103
|
+
- pattern: $MODEL.bulkCreate($REQ.query, ...)
|
|
104
|
+
- pattern: $MODEL.bulkBuild($REQ.body, ...)
|
|
105
|
+
metadata:
|
|
106
|
+
cwe: "CWE-915: Improperly Controlled Modification of Dynamically-Determined Object Attributes"
|
|
107
|
+
owasp: "A01:2021 - Broken Access Control"
|
|
108
|
+
category: mass-assignment
|
|
109
|
+
precision: medium
|
|
110
|
+
references:
|
|
111
|
+
- "https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#bulkcreate"
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# CWE-918: Node.js SSRF 深度覆盖 — fetch/axios/node-fetch/got 全量sink
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint — JS/TS 规则库
|
|
3
|
+
# 覆盖: fetch() / axios({url:...}) / node-fetch / got / undici 对象式请求
|
|
4
|
+
|
|
5
|
+
rules:
|
|
6
|
+
|
|
7
|
+
# ZM-JS-SSRF-FETCH-001: fetch/axios/node-fetch 直接传入用户输入URL
|
|
8
|
+
- id: zm-js-ssrf-fetch-001
|
|
9
|
+
severity: ERROR
|
|
10
|
+
message: |
|
|
11
|
+
检测到 fetch / axios / node-fetch / got / undici.fetch 等 HTTP 客户端直接使用用户输入作为请求URL,
|
|
12
|
+
存在SSRF(服务端请求伪造)风险。
|
|
13
|
+
攻击者可控制目标URL使服务器发起对内网服务的恶意请求,绕过防火墙访问内部资源
|
|
14
|
+
(如 http://169.254.169.254/latest/meta-data/ 获取云环境元数据)。
|
|
15
|
+
|
|
16
|
+
修复:
|
|
17
|
+
1. 对用户传入的URL做白名单校验,仅允许预设的外部域名
|
|
18
|
+
2. 禁止用户输入直接决定请求目标,使用URL映射表替代
|
|
19
|
+
3. 使用SSRF保护库(如 ssrf-filter / safe-request)
|
|
20
|
+
4. 配置防火墙禁止服务器访问内网地址(169.254.0.0/16, 10.0.0.0/8, 127.0.0.0/8等)
|
|
21
|
+
5. 禁用不必要的HTTP重定向跟踪
|
|
22
|
+
languages:
|
|
23
|
+
- javascript
|
|
24
|
+
- typescript
|
|
25
|
+
pattern-either:
|
|
26
|
+
# fetch()
|
|
27
|
+
- pattern: fetch($REQ.query.$PARAM, ...)
|
|
28
|
+
- pattern: fetch($REQ.params.$PARAM, ...)
|
|
29
|
+
- pattern: fetch($REQ.body.$PARAM, ...)
|
|
30
|
+
# node-fetch
|
|
31
|
+
- pattern: nodeFetch($REQ.query.$PARAM, ...)
|
|
32
|
+
- pattern: nodeFetch($REQ.params.$PARAM, ...)
|
|
33
|
+
- pattern: nodeFetch($REQ.body.$PARAM, ...)
|
|
34
|
+
# axios object-style
|
|
35
|
+
- pattern: |
|
|
36
|
+
axios({url: $REQ.query.$PARAM, ...})
|
|
37
|
+
- pattern: |
|
|
38
|
+
axios({url: $REQ.params.$PARAM, ...})
|
|
39
|
+
- pattern: |
|
|
40
|
+
axios({url: $REQ.body.$PARAM, ...})
|
|
41
|
+
- pattern: |
|
|
42
|
+
$AXIOS({url: $REQ.query.$PARAM, ...})
|
|
43
|
+
- pattern: |
|
|
44
|
+
$AXIOS({url: $REQ.params.$PARAM, ...})
|
|
45
|
+
- pattern: |
|
|
46
|
+
$AXIOS({url: $REQ.body.$PARAM, ...})
|
|
47
|
+
# got object-style
|
|
48
|
+
- pattern: |
|
|
49
|
+
got({url: $REQ.query.$PARAM, ...})
|
|
50
|
+
- pattern: |
|
|
51
|
+
got({url: $REQ.params.$PARAM, ...})
|
|
52
|
+
- pattern: |
|
|
53
|
+
got({url: $REQ.body.$PARAM, ...})
|
|
54
|
+
# undici.fetch
|
|
55
|
+
- pattern: undici.fetch($REQ.query.$PARAM, ...)
|
|
56
|
+
- pattern: undici.fetch($REQ.params.$PARAM, ...)
|
|
57
|
+
- pattern: undici.fetch($REQ.body.$PARAM, ...)
|
|
58
|
+
metadata:
|
|
59
|
+
cwe: "CWE-918: Server-Side Request Forgery (SSRF)"
|
|
60
|
+
owasp: "A10:2021 - Server-Side Request Forgery (SSRF)"
|
|
61
|
+
category: ssrf
|
|
62
|
+
precision: high
|
|
63
|
+
confidence: high
|
|
64
|
+
references:
|
|
65
|
+
- "https://owasp.org/www-community/attacks/Server_Side_Request_Forgery"
|
|
66
|
+
- "https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html"
|
|
67
|
+
|
|
68
|
+
# ZM-JS-SSRF-FETCH-002: 用户输入拼接URL后传入fetch/axios
|
|
69
|
+
- id: zm-js-ssrf-fetch-002
|
|
70
|
+
severity: WARNING
|
|
71
|
+
message: |
|
|
72
|
+
fetch / axios 请求URL由用户输入拼接构造,需确认拼接变量是否可直接控制完整URL。
|
|
73
|
+
若用户可控制协议+域名部分(如 http://evil.com ),存在SSRF风险。
|
|
74
|
+
|
|
75
|
+
修复:
|
|
76
|
+
1. 使用 new URL() 解析目标并验证 hostname 白名单
|
|
77
|
+
2. 使用URL映射表(key->URL)替代直接拼接
|
|
78
|
+
3. 限制协议仅允许 https
|
|
79
|
+
4. 使用SSRF防护库过滤内网IP
|
|
80
|
+
languages:
|
|
81
|
+
- javascript
|
|
82
|
+
- typescript
|
|
83
|
+
pattern-either:
|
|
84
|
+
- pattern: fetch($URL + $INPUT, ...)
|
|
85
|
+
- pattern: nodeFetch($URL + $INPUT, ...)
|
|
86
|
+
- pattern: |
|
|
87
|
+
axios({url: $URL + $INPUT, ...})
|
|
88
|
+
- pattern: got($URL + $INPUT, ...)
|
|
89
|
+
- pattern: undici.fetch($URL + $INPUT, ...)
|
|
90
|
+
metadata:
|
|
91
|
+
cwe: "CWE-918: Server-Side Request Forgery (SSRF)"
|
|
92
|
+
owasp: "A10:2021 - Server-Side Request Forgery (SSRF)"
|
|
93
|
+
category: ssrf
|
|
94
|
+
precision: low
|
|
95
|
+
confidence: medium
|
|
96
|
+
references:
|
|
97
|
+
- "https://owasp.org/www-community/attacks/Server_Side_Request_Forgery"
|
|
98
|
+
|
|
99
|
+
# ZM-JS-SSRF-FETCH-003: got.stream / needle / superagent 对象式URL注入
|
|
100
|
+
- id: zm-js-ssrf-fetch-003
|
|
101
|
+
severity: ERROR
|
|
102
|
+
message: |
|
|
103
|
+
got / superagent / needle 等 HTTP 库的对象式请求中,hostname/href/uri 字段由用户输入控制,
|
|
104
|
+
可导致SSRF攻击。
|
|
105
|
+
|
|
106
|
+
修复:
|
|
107
|
+
1. 白名单限制目标域名
|
|
108
|
+
2. 使用固定的baseURL + 相对路径模式
|
|
109
|
+
3. 禁止用户输入覆盖hostname/href/uri字段
|
|
110
|
+
languages:
|
|
111
|
+
- javascript
|
|
112
|
+
- typescript
|
|
113
|
+
pattern-either:
|
|
114
|
+
- pattern: "got({hostname: $REQ.query.$PARAM})"
|
|
115
|
+
- pattern: "got({hostname: $REQ.params.$PARAM})"
|
|
116
|
+
- pattern: "got({hostname: $REQ.body.$PARAM})"
|
|
117
|
+
- pattern: "got({href: $REQ.query.$PARAM})"
|
|
118
|
+
- pattern: "got({href: $REQ.params.$PARAM})"
|
|
119
|
+
- pattern: "got({uri: $REQ.query.$PARAM})"
|
|
120
|
+
- pattern: "got({uri: $REQ.params.$PARAM})"
|
|
121
|
+
- pattern: superagent($METHOD, $REQ.query.$PARAM)
|
|
122
|
+
- pattern: superagent($METHOD, $REQ.params.$PARAM)
|
|
123
|
+
- pattern: superagent($METHOD, $REQ.body.$PARAM)
|
|
124
|
+
- pattern: needle($METHOD, $REQ.query.$PARAM, ...)
|
|
125
|
+
- pattern: needle($METHOD, $REQ.params.$PARAM, ...)
|
|
126
|
+
- pattern: needle($METHOD, $REQ.body.$PARAM, ...)
|
|
127
|
+
metadata:
|
|
128
|
+
cwe: "CWE-918: Server-Side Request Forgery (SSRF)"
|
|
129
|
+
owasp: "A10:2021 - Server-Side Request Forgery (SSRF)"
|
|
130
|
+
category: ssrf
|
|
131
|
+
precision: high
|
|
132
|
+
confidence: high
|
|
133
|
+
references:
|
|
134
|
+
- "https://owasp.org/www-community/attacks/Server_Side_Request_Forgery"
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# CWE-918: Node.js SSRF 服务端请求伪造检测规则
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint 2 — JS/TS 规则库
|
|
3
|
+
# 覆盖: http/https native、axios、fetch/node-fetch、got、superagent、needle、undici
|
|
4
|
+
|
|
5
|
+
rules:
|
|
6
|
+
|
|
7
|
+
# ZM-JS-SSRF-001: HTTP库直接传入 req.query/params/body 作为URL (高精度)
|
|
8
|
+
- id: zm-js-ssrf-001
|
|
9
|
+
severity: ERROR
|
|
10
|
+
message: |
|
|
11
|
+
HTTP请求库直接将 req.query / req.params / req.body 的值作为URL参数传入,
|
|
12
|
+
存在SSRF(服务端请求伪造)风险。
|
|
13
|
+
|
|
14
|
+
攻击者可控制目标URL使服务器发起对内网服务的恶意请求,绕过防火墙访问内部资源
|
|
15
|
+
(如 http://169.254.169.254/latest/meta-data/ 获取云环境元数据)。
|
|
16
|
+
|
|
17
|
+
修复:
|
|
18
|
+
1. 对用户传入的URL做白名单校验,仅允许预设的外部域名
|
|
19
|
+
2. 禁止用户输入直接决定请求目标,使用URL映射表替代
|
|
20
|
+
3. 使用SSRF保护库(如 ssrf-filter / safe-request)
|
|
21
|
+
4. 配置防火墙禁止服务器访问内网地址(169.254.0.0/16, 10.0.0.0/8, 127.0.0.0/8等)
|
|
22
|
+
5. 禁用不必要的HTTP重定向跟随
|
|
23
|
+
languages:
|
|
24
|
+
- javascript
|
|
25
|
+
- typescript
|
|
26
|
+
pattern-either:
|
|
27
|
+
# Native http/https
|
|
28
|
+
- pattern: http.get($REQ.query.$PARAM, ...)
|
|
29
|
+
- pattern: http.get($REQ.params.$PARAM, ...)
|
|
30
|
+
- pattern: http.get($REQ.body.$PARAM, ...)
|
|
31
|
+
- pattern: http.request($REQ.query.$PARAM, ...)
|
|
32
|
+
- pattern: http.request($REQ.params.$PARAM, ...)
|
|
33
|
+
- pattern: http.request($REQ.body.$PARAM, ...)
|
|
34
|
+
- pattern: https.get($REQ.query.$PARAM, ...)
|
|
35
|
+
- pattern: https.get($REQ.params.$PARAM, ...)
|
|
36
|
+
- pattern: https.get($REQ.body.$PARAM, ...)
|
|
37
|
+
- pattern: https.request($REQ.query.$PARAM, ...)
|
|
38
|
+
- pattern: https.request($REQ.params.$PARAM, ...)
|
|
39
|
+
- pattern: https.request($REQ.body.$PARAM, ...)
|
|
40
|
+
# axios
|
|
41
|
+
- pattern: axios.get($REQ.query.$PARAM, ...)
|
|
42
|
+
- pattern: axios.get($REQ.params.$PARAM, ...)
|
|
43
|
+
- pattern: axios.get($REQ.body.$PARAM, ...)
|
|
44
|
+
- pattern: axios.request($REQ.query.$PARAM, ...)
|
|
45
|
+
- pattern: axios.request($REQ.params.$PARAM, ...)
|
|
46
|
+
- pattern: axios.request($REQ.body.$PARAM, ...)
|
|
47
|
+
- pattern: $AXIOS.get($REQ.query.$PARAM, ...)
|
|
48
|
+
- pattern: $AXIOS.get($REQ.params.$PARAM, ...)
|
|
49
|
+
- pattern: $AXIOS.get($REQ.body.$PARAM, ...)
|
|
50
|
+
- pattern: $AXIOS.request($REQ.query.$PARAM, ...)
|
|
51
|
+
- pattern: $AXIOS.request($REQ.params.$PARAM, ...)
|
|
52
|
+
- pattern: $AXIOS.request($REQ.body.$PARAM, ...)
|
|
53
|
+
- pattern: $AXIOS.post($REQ.query.$PARAM, ...)
|
|
54
|
+
- pattern: $AXIOS.put($REQ.query.$PARAM, ...)
|
|
55
|
+
- pattern: $AXIOS.delete($REQ.query.$PARAM, ...)
|
|
56
|
+
# fetch / node-fetch
|
|
57
|
+
- pattern: fetch($REQ.query.$PARAM, ...)
|
|
58
|
+
- pattern: fetch($REQ.params.$PARAM, ...)
|
|
59
|
+
- pattern: fetch($REQ.body.$PARAM, ...)
|
|
60
|
+
# got
|
|
61
|
+
- pattern: got($REQ.query.$PARAM, ...)
|
|
62
|
+
- pattern: got($REQ.params.$PARAM, ...)
|
|
63
|
+
- pattern: got($REQ.body.$PARAM, ...)
|
|
64
|
+
- pattern: got.get($REQ.query.$PARAM, ...)
|
|
65
|
+
- pattern: got.get($REQ.params.$PARAM, ...)
|
|
66
|
+
- pattern: got.get($REQ.body.$PARAM, ...)
|
|
67
|
+
- pattern: got.post($REQ.query.$PARAM, ...)
|
|
68
|
+
- pattern: got.put($REQ.query.$PARAM, ...)
|
|
69
|
+
# superagent
|
|
70
|
+
- pattern: superagent.get($REQ.query.$PARAM)
|
|
71
|
+
- pattern: superagent.get($REQ.params.$PARAM)
|
|
72
|
+
- pattern: superagent.get($REQ.body.$PARAM)
|
|
73
|
+
- pattern: request.get($REQ.query.$PARAM)
|
|
74
|
+
- pattern: request.get($REQ.params.$PARAM)
|
|
75
|
+
- pattern: request.get($REQ.body.$PARAM)
|
|
76
|
+
# needle
|
|
77
|
+
- pattern: needle.get($REQ.query.$PARAM, ...)
|
|
78
|
+
- pattern: needle.get($REQ.params.$PARAM, ...)
|
|
79
|
+
- pattern: needle.get($REQ.body.$PARAM, ...)
|
|
80
|
+
- pattern: needle.request('get', $REQ.query.$PARAM, ...)
|
|
81
|
+
- pattern: needle.request('get', $REQ.params.$PARAM, ...)
|
|
82
|
+
- pattern: needle.request('get', $REQ.body.$PARAM, ...)
|
|
83
|
+
# undici
|
|
84
|
+
- pattern: undici.request($REQ.query.$PARAM, ...)
|
|
85
|
+
- pattern: undici.request($REQ.params.$PARAM, ...)
|
|
86
|
+
- pattern: undici.request($REQ.body.$PARAM, ...)
|
|
87
|
+
- pattern: undici.fetch($REQ.query.$PARAM, ...)
|
|
88
|
+
- pattern: undici.fetch($REQ.params.$PARAM, ...)
|
|
89
|
+
- pattern: undici.fetch($REQ.body.$PARAM, ...)
|
|
90
|
+
metadata:
|
|
91
|
+
cwe: "CWE-918: Server-Side Request Forgery (SSRF)"
|
|
92
|
+
owasp: "A10:2021 - Server-Side Request Forgery (SSRF)"
|
|
93
|
+
category: ssrf
|
|
94
|
+
precision: high
|
|
95
|
+
references:
|
|
96
|
+
- "https://owasp.org/www-community/attacks/Server_Side_Request_Forgery"
|
|
97
|
+
- "https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html"
|
|
98
|
+
|
|
99
|
+
# ZM-JS-SSRF-002: HTTP库URL字符串拼接 (低精度,需人工确认)
|
|
100
|
+
- id: zm-js-ssrf-002
|
|
101
|
+
severity: WARNING
|
|
102
|
+
message: |
|
|
103
|
+
HTTP请求库使用了字符串拼接或模板字符串构建请求URL,需确认拼接变量是否来自用户输入。
|
|
104
|
+
若变量可控则存在SSRF风险。
|
|
105
|
+
|
|
106
|
+
修复:
|
|
107
|
+
1. 使用 new URL() 解析目标并验证 hostname 白名单
|
|
108
|
+
2. 使用URL映射表(key->URL)替代直接拼接
|
|
109
|
+
3. 使用SSRF防护库过滤内网IP
|
|
110
|
+
languages:
|
|
111
|
+
- javascript
|
|
112
|
+
- typescript
|
|
113
|
+
pattern-either:
|
|
114
|
+
- pattern: http.get($URL + $INPUT, ...)
|
|
115
|
+
- pattern: http.request($URL + $INPUT, ...)
|
|
116
|
+
- pattern: https.get($URL + $INPUT, ...)
|
|
117
|
+
- pattern: https.request($URL + $INPUT, ...)
|
|
118
|
+
- pattern: $AXIOS.get($URL + $INPUT, ...)
|
|
119
|
+
- pattern: $AXIOS.request($URL + $INPUT, ...)
|
|
120
|
+
- pattern: axios.get($URL + $INPUT, ...)
|
|
121
|
+
- pattern: fetch($URL + $INPUT, ...)
|
|
122
|
+
- pattern: got($URL + $INPUT, ...)
|
|
123
|
+
- pattern: got.get($URL + $INPUT, ...)
|
|
124
|
+
- pattern: superagent.get($URL + $INPUT)
|
|
125
|
+
- pattern: needle.get($URL + $INPUT, ...)
|
|
126
|
+
metadata:
|
|
127
|
+
cwe: "CWE-918: Server-Side Request Forgery (SSRF)"
|
|
128
|
+
owasp: "A10:2021 - Server-Side Request Forgery (SSRF)"
|
|
129
|
+
category: ssrf
|
|
130
|
+
precision: low
|
|
131
|
+
references:
|
|
132
|
+
- "https://owasp.org/www-community/attacks/Server_Side_Request_Forgery"
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# CWE-94: Node.js 服务端模板注入 (SSTI) 深度检测
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint — JS/TS 规则库
|
|
3
|
+
# 覆盖: EJS / Vue SSR / Pug / Handlebars / doT 模板引擎 + 用户输入渲染
|
|
4
|
+
|
|
5
|
+
rules:
|
|
6
|
+
|
|
7
|
+
# ZM-JS-SSTI-001: EJS render/renderFile 用户输入直接传入模板数据
|
|
8
|
+
- id: zm-js-ssti-001
|
|
9
|
+
severity: ERROR
|
|
10
|
+
message: |
|
|
11
|
+
检测到 EJS 模板渲染函数(ejs.render / ejs.renderFile)的模板字符串或数据参数由用户输入控制。
|
|
12
|
+
攻击者可注入 <% process.exit() %>/<%= 7*7 %>/<% require('child_process').exec('cmd') %> 等EJS标签,
|
|
13
|
+
导致远程代码执行(RCE)。
|
|
14
|
+
|
|
15
|
+
修复:
|
|
16
|
+
1. 禁止用户输入直接作为模板字符串传入渲染函数
|
|
17
|
+
2. 使用固定的模板文件和严格的白名单变量
|
|
18
|
+
3. 开启EJS delimiter 严格模式,限制标签类型
|
|
19
|
+
4. 使用沙箱环境渲染用户内容(如 vm2/isolated-vm)
|
|
20
|
+
5. 评估是否需要用模板引擎处理用户数据——大多数场景不需要
|
|
21
|
+
languages:
|
|
22
|
+
- javascript
|
|
23
|
+
- typescript
|
|
24
|
+
pattern-either:
|
|
25
|
+
- pattern: ejs.render($REQ.query.$PARAM, ...)
|
|
26
|
+
- pattern: ejs.render($REQ.params.$PARAM, ...)
|
|
27
|
+
- pattern: ejs.render($REQ.body.$PARAM, ...)
|
|
28
|
+
- pattern: ejs.render($REQ.body, ...)
|
|
29
|
+
- pattern: ejs.renderFile($REQ.query.$PARAM, ...)
|
|
30
|
+
- pattern: ejs.renderFile($REQ.params.$PARAM, ...)
|
|
31
|
+
- pattern: ejs.renderFile($REQ.body.$PARAM, ...)
|
|
32
|
+
- pattern: ejs.compile($REQ.query.$PARAM, ...)
|
|
33
|
+
- pattern: ejs.compile($REQ.params.$PARAM, ...)
|
|
34
|
+
- pattern: ejs.compile($REQ.body.$PARAM, ...)
|
|
35
|
+
metadata:
|
|
36
|
+
cwe: "CWE-94: Improper Control of Generation of Code (Code Injection)"
|
|
37
|
+
owasp: "A03:2021 - Injection"
|
|
38
|
+
category: ssti
|
|
39
|
+
precision: high
|
|
40
|
+
confidence: high
|
|
41
|
+
references:
|
|
42
|
+
- "https://ejs.co/#docs"
|
|
43
|
+
- "https://portswigger.net/web-security/server-side-template-injection"
|
|
44
|
+
|
|
45
|
+
# ZM-JS-SSTI-002: Pug / Handlebars / Nunjucks 用户输入模板渲染
|
|
46
|
+
- id: zm-js-ssti-002
|
|
47
|
+
severity: ERROR
|
|
48
|
+
message: |
|
|
49
|
+
检测到 Pug / Handlebars / Nunjucks 模板引擎的 compile/render 函数接收用户可控的模板字符串。
|
|
50
|
+
各引擎支持自定义helper/函数调用,攻击者可注入恶意代码。
|
|
51
|
+
|
|
52
|
+
Pug: #{process.exit()} / each val in process.mainModule.require('child_process')
|
|
53
|
+
Handlebars: {{constructor.constructor('return process')()}}
|
|
54
|
+
Nunjucks: {{range.constructor('return process')().mainModule.require('child_process')}}
|
|
55
|
+
|
|
56
|
+
修复:
|
|
57
|
+
1. 禁止用户输入作为模板内容或模板路径
|
|
58
|
+
2. 禁用危险的 helper/过滤器注册
|
|
59
|
+
3. 对用户数据仅作为模板变量(非模板本身)传入
|
|
60
|
+
4. 使用沙箱环境
|
|
61
|
+
languages:
|
|
62
|
+
- javascript
|
|
63
|
+
- typescript
|
|
64
|
+
pattern-either:
|
|
65
|
+
# Pug
|
|
66
|
+
- pattern: pug.compile($REQ.query.$PARAM, ...)
|
|
67
|
+
- pattern: pug.compile($REQ.params.$PARAM, ...)
|
|
68
|
+
- pattern: pug.compile($REQ.body.$PARAM, ...)
|
|
69
|
+
- pattern: pug.render($REQ.query.$PARAM, ...)
|
|
70
|
+
- pattern: pug.render($REQ.params.$PARAM, ...)
|
|
71
|
+
- pattern: pug.render($REQ.body.$PARAM, ...)
|
|
72
|
+
# Handlebars
|
|
73
|
+
- pattern: Handlebars.compile($REQ.query.$PARAM, ...)
|
|
74
|
+
- pattern: Handlebars.compile($REQ.params.$PARAM, ...)
|
|
75
|
+
- pattern: Handlebars.compile($REQ.body.$PARAM, ...)
|
|
76
|
+
# Nunjucks
|
|
77
|
+
- pattern: nunjucks.renderString($REQ.query.$PARAM, ...)
|
|
78
|
+
- pattern: nunjucks.renderString($REQ.params.$PARAM, ...)
|
|
79
|
+
- pattern: nunjucks.renderString($REQ.body.$PARAM, ...)
|
|
80
|
+
metadata:
|
|
81
|
+
cwe: "CWE-94: Improper Control of Generation of Code (Code Injection)"
|
|
82
|
+
owasp: "A03:2021 - Injection"
|
|
83
|
+
category: ssti
|
|
84
|
+
precision: high
|
|
85
|
+
confidence: high
|
|
86
|
+
references:
|
|
87
|
+
- "https://portswigger.net/web-security/server-side-template-injection"
|
|
88
|
+
|
|
89
|
+
# ZM-JS-SSTI-003: doT.js / lodash.template / mustache 模板注入
|
|
90
|
+
- id: zm-js-ssti-003
|
|
91
|
+
severity: ERROR
|
|
92
|
+
message: |
|
|
93
|
+
检测到 doT.js / lodash.template / mustache 等轻量模板引擎的模板字符串由用户输入控制。
|
|
94
|
+
|
|
95
|
+
lodash.template 底层使用 Function() 构造函数,直接传入用户输入可导致任意代码执行。
|
|
96
|
+
doT.js 的 {{ }} 标签可执行 JavaScript 表达式。
|
|
97
|
+
mustache 虽相对安全(无逻辑标签),但仍可能被利用做信息泄露。
|
|
98
|
+
|
|
99
|
+
修复:
|
|
100
|
+
1. 禁止用户输入作为模板字符串
|
|
101
|
+
2. 使用固定的预定义模板
|
|
102
|
+
3. 如需动态模板,仅允许安全的占位符替换(如简单的 String.replace)
|
|
103
|
+
4. 模板引擎仅用于开发阶段,生产环境避免动态编译
|
|
104
|
+
languages:
|
|
105
|
+
- javascript
|
|
106
|
+
- typescript
|
|
107
|
+
pattern-either:
|
|
108
|
+
- pattern: _.template($REQ.query.$PARAM, ...)
|
|
109
|
+
- pattern: _.template($REQ.params.$PARAM, ...)
|
|
110
|
+
- pattern: _.template($REQ.body.$PARAM, ...)
|
|
111
|
+
- pattern: lodash.template($REQ.query.$PARAM, ...)
|
|
112
|
+
- pattern: lodash.template($REQ.params.$PARAM, ...)
|
|
113
|
+
- pattern: dot.template($REQ.query.$PARAM, ...)
|
|
114
|
+
- pattern: dot.template($REQ.params.$PARAM, ...)
|
|
115
|
+
- pattern: dot.template($REQ.body.$PARAM, ...)
|
|
116
|
+
- pattern: Mustache.render($REQ.query.$PARAM, ...)
|
|
117
|
+
- pattern: Mustache.render($REQ.params.$PARAM, ...)
|
|
118
|
+
- pattern: Mustache.render($REQ.body.$PARAM, ...)
|
|
119
|
+
- pattern: mustache.render($REQ.query.$PARAM, ...)
|
|
120
|
+
- pattern: mustache.render($REQ.params.$PARAM, ...)
|
|
121
|
+
- pattern: mustache.render($REQ.body.$PARAM, ...)
|
|
122
|
+
metadata:
|
|
123
|
+
cwe: "CWE-94: Improper Control of Generation of Code (Code Injection)"
|
|
124
|
+
owasp: "A03:2021 - Injection"
|
|
125
|
+
category: ssti
|
|
126
|
+
precision: high
|
|
127
|
+
confidence: high
|
|
128
|
+
references:
|
|
129
|
+
- "https://lodash.com/docs/#template"
|
|
130
|
+
- "https://portswigger.net/web-security/server-side-template-injection"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# CWE-942: CORS 配置缺陷检测规则
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint 1
|
|
3
|
+
|
|
4
|
+
rules:
|
|
5
|
+
|
|
6
|
+
- id: zm-js-cors-001
|
|
7
|
+
severity: WARNING
|
|
8
|
+
message: |
|
|
9
|
+
CORS 中间件 origin 配置为 '*' 通配符,允许任意域跨域访问 API。
|
|
10
|
+
修复: 1.将origin设为白名单数组或校验函数 2.需要凭证时禁用通配符 3.尽量同域部署
|
|
11
|
+
languages:
|
|
12
|
+
- javascript
|
|
13
|
+
- typescript
|
|
14
|
+
patterns:
|
|
15
|
+
- pattern-either:
|
|
16
|
+
- pattern: 'cors({..., origin: "*", ...})'
|
|
17
|
+
- pattern: "cors({..., origin: '*', ...})"
|
|
18
|
+
- pattern: |
|
|
19
|
+
$APP.use(cors({..., origin: "*", ...}))
|
|
20
|
+
- pattern: |
|
|
21
|
+
$APP.use(cors({..., origin: '*', ...}))
|
|
22
|
+
metadata:
|
|
23
|
+
cwe: "CWE-942"
|
|
24
|
+
precision: very-high
|
|
25
|
+
category: config
|
|
26
|
+
owasp: "A05:2021 - Security Misconfiguration"
|
|
27
|
+
|
|
28
|
+
- id: zm-js-cors-002
|
|
29
|
+
severity: WARNING
|
|
30
|
+
message: |
|
|
31
|
+
手动设置 Access-Control-Allow-Origin 响应头为 '*' 通配符。
|
|
32
|
+
修复: 1.限制origin为受信域名列表 2.如必须使用通配符,确保接口不返回敏感数据
|
|
33
|
+
languages:
|
|
34
|
+
- javascript
|
|
35
|
+
- typescript
|
|
36
|
+
pattern-either:
|
|
37
|
+
- pattern: |
|
|
38
|
+
res.setHeader('Access-Control-Allow-Origin', '*')
|
|
39
|
+
- pattern: |
|
|
40
|
+
res.setHeader("Access-Control-Allow-Origin", "*")
|
|
41
|
+
- pattern: |
|
|
42
|
+
res.header("Access-Control-Allow-Origin", "*")
|
|
43
|
+
- pattern: |
|
|
44
|
+
res.header('Access-Control-Allow-Origin', '*')
|
|
45
|
+
metadata:
|
|
46
|
+
cwe: "CWE-942"
|
|
47
|
+
precision: very-high
|
|
48
|
+
category: config
|
|
49
|
+
owasp: "A05:2021 - Security Misconfiguration"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# CWE-943: Node.js NoSQL 注入检测规则
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint 1 — JS/TS 通用规则库
|
|
3
|
+
|
|
4
|
+
rules:
|
|
5
|
+
|
|
6
|
+
# ZM-JS-NSQLI-001: MongoDB find/findOne 直接传入请求体
|
|
7
|
+
- id: zm-js-nosqli-001
|
|
8
|
+
severity: ERROR
|
|
9
|
+
message: |
|
|
10
|
+
检测到 MongoDB find() / findOne() / updateMany() 直接接收 req.body 或 req.query
|
|
11
|
+
作为查询条件,存在 NoSQL 注入风险。
|
|
12
|
+
|
|
13
|
+
攻击者可通过注入 $gt / $ne / $regex 等 MongoDB 操作符绕过认证逻辑,
|
|
14
|
+
例如: { username: { $gt: "" }, password: { $gt: "" } } 可绕过登录。
|
|
15
|
+
|
|
16
|
+
修复建议:
|
|
17
|
+
1. 使用 mongo-sanitize 或 express-mongo-sanitize 库过滤 $ 和 . 字符
|
|
18
|
+
2. 对用户输入做严格的类型校验(如只允许字符串,拒绝对象)
|
|
19
|
+
3. 使用 joi / zod 等 Schema 验证库,禁止传入嵌套对象
|
|
20
|
+
4. 认证场景使用 bcrypt.compare 而非直接查询
|
|
21
|
+
languages:
|
|
22
|
+
- javascript
|
|
23
|
+
- typescript
|
|
24
|
+
pattern-either:
|
|
25
|
+
- pattern: |
|
|
26
|
+
$COLLECTION.find($REQ.body, ...)
|
|
27
|
+
- pattern: |
|
|
28
|
+
$COLLECTION.findOne($REQ.body, ...)
|
|
29
|
+
- pattern: |
|
|
30
|
+
$COLLECTION.find($REQ.body)
|
|
31
|
+
- pattern: |
|
|
32
|
+
$COLLECTION.findOne($REQ.body)
|
|
33
|
+
- pattern: |
|
|
34
|
+
$COLLECTION.find($REQ.query, ...)
|
|
35
|
+
- pattern: |
|
|
36
|
+
$COLLECTION.findOne($REQ.query, ...)
|
|
37
|
+
- pattern: |
|
|
38
|
+
$COLLECTION.updateMany($REQ.body, ...)
|
|
39
|
+
- pattern: |
|
|
40
|
+
$COLLECTION.updateOne($REQ.body, ...)
|
|
41
|
+
- pattern: |
|
|
42
|
+
$COLLECTION.deleteMany($REQ.body, ...)
|
|
43
|
+
- pattern: |
|
|
44
|
+
$COLLECTION.deleteOne($REQ.body, ...)
|
|
45
|
+
metadata:
|
|
46
|
+
cwe: "CWE-943: Improper Neutralization of Special Elements in Data Query Logic"
|
|
47
|
+
owasp: "A03:2021 - Injection"
|
|
48
|
+
category: sql-injection
|
|
49
|
+
precision: medium
|
|
50
|
+
references:
|
|
51
|
+
- "https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/05.6-Testing_for_NoSQL_Injection"
|
|
52
|
+
- "https://www.mongodb.com/docs/manual/faq/fundamentals/#javascript"
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# CWE-95: eval() 代码注入检测规则
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint 1 — JS/TS 通用规则库
|
|
3
|
+
|
|
4
|
+
rules:
|
|
5
|
+
|
|
6
|
+
# ZM-JS-CI-001: eval() 动态代码执行
|
|
7
|
+
- id: zm-js-ci-001
|
|
8
|
+
severity: ERROR
|
|
9
|
+
message: |
|
|
10
|
+
检测到 eval() 调用,参数为非字面量字符串。
|
|
11
|
+
eval() 会执行传入的任意 JavaScript 代码,攻击者可注入恶意代码导致
|
|
12
|
+
远程代码执行(RCE)。
|
|
13
|
+
|
|
14
|
+
修复建议:
|
|
15
|
+
1. 禁止使用 eval() 处理用户输入
|
|
16
|
+
2. JSON 数据解析使用 JSON.parse() 替代
|
|
17
|
+
3. 动态属性访问使用 obj[key] 替代 eval
|
|
18
|
+
4. 如确实需要动态执行,使用沙箱环境(如 vm2 / isolated-vm)
|
|
19
|
+
languages:
|
|
20
|
+
- javascript
|
|
21
|
+
- typescript
|
|
22
|
+
patterns:
|
|
23
|
+
- pattern: eval(...)
|
|
24
|
+
- pattern-not: eval("...")
|
|
25
|
+
metadata:
|
|
26
|
+
cwe: "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')"
|
|
27
|
+
owasp: "A03:2021 - Injection"
|
|
28
|
+
category: code-injection
|
|
29
|
+
precision: high
|
|
30
|
+
references:
|
|
31
|
+
- "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"
|
|
32
|
+
- "https://owasp.org/www-community/attacks/Code_Injection"
|
|
33
|
+
|
|
34
|
+
# ZM-JS-CI-002: 间接 eval 调用 (通过 globalThis / (0, eval))
|
|
35
|
+
- id: zm-js-ci-002
|
|
36
|
+
severity: ERROR
|
|
37
|
+
message: |
|
|
38
|
+
检测到间接 eval() 调用(如 globalThis.eval / global.eval / (0, eval)),
|
|
39
|
+
可能被用于绕过静态检测工具。
|
|
40
|
+
|
|
41
|
+
修复建议:
|
|
42
|
+
1. 移除所有 eval 调用,包括间接调用形式
|
|
43
|
+
2. 替代方案: Function 构造器(仍有风险)、沙箱执行或重新设计逻辑
|
|
44
|
+
languages:
|
|
45
|
+
- javascript
|
|
46
|
+
- typescript
|
|
47
|
+
pattern-either:
|
|
48
|
+
- pattern: globalThis.eval(...)
|
|
49
|
+
- pattern: global.eval(...)
|
|
50
|
+
- pattern: (0, eval)(...)
|
|
51
|
+
- pattern: (1, eval)(...)
|
|
52
|
+
- pattern: window.eval(...)
|
|
53
|
+
metadata:
|
|
54
|
+
cwe: "CWE-95: Improper Neutralization of Directives in Dynamically Evaluated Code ('Eval Injection')"
|
|
55
|
+
owasp: "A03:2021 - Injection"
|
|
56
|
+
category: code-injection
|
|
57
|
+
precision: high
|
|
58
|
+
references:
|
|
59
|
+
- "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#direct_and_indirect_eval"
|