@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,136 @@
|
|
|
1
|
+
# CWE-307: Node.js 暴力破解防护缺失检测
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint — JS/TS 规则库
|
|
3
|
+
# 覆盖: 登录接口无限速、express-rate-limit未配置、验证码缺失
|
|
4
|
+
|
|
5
|
+
rules:
|
|
6
|
+
|
|
7
|
+
# ZM-JS-BF-001: 登录接口未使用 rate limiter
|
|
8
|
+
- id: zm-js-bf-001
|
|
9
|
+
severity: HIGH
|
|
10
|
+
message: |
|
|
11
|
+
检测到登录路由未使用 express-rate-limit 或其他限速中间件。
|
|
12
|
+
攻击者可对登录接口发起暴力破解攻击,尝试大量用户名/密码组合。
|
|
13
|
+
|
|
14
|
+
修复:
|
|
15
|
+
1. 对登录接口使用 express-rate-limit:
|
|
16
|
+
const loginLimiter = rateLimit({
|
|
17
|
+
windowMs: 15 * 60 * 1000, // 15分钟
|
|
18
|
+
max: 5, // 最多5次尝试
|
|
19
|
+
message: 'Too many login attempts'
|
|
20
|
+
})
|
|
21
|
+
app.post('/login', loginLimiter, handler)
|
|
22
|
+
2. 基于用户名/IP的渐进式延迟(每次失败增加等待时间)
|
|
23
|
+
3. 实现账户锁定策略(连续N次失败锁定M分钟)
|
|
24
|
+
4. 添加 CAPTCHA 验证码
|
|
25
|
+
5. 使用 helmet 等安全头中间件
|
|
26
|
+
languages:
|
|
27
|
+
- javascript
|
|
28
|
+
- typescript
|
|
29
|
+
patterns:
|
|
30
|
+
- pattern-either:
|
|
31
|
+
- pattern: |
|
|
32
|
+
$APP.post('/login', $HANDLER)
|
|
33
|
+
- pattern: |
|
|
34
|
+
$APP.post('/login', $MIDDLEWARE, $HANDLER)
|
|
35
|
+
- pattern: |
|
|
36
|
+
$ROUTER.post('/login', $HANDLER)
|
|
37
|
+
- pattern: |
|
|
38
|
+
$ROUTER.post('/login', $MIDDLEWARE, $HANDLER)
|
|
39
|
+
- pattern: |
|
|
40
|
+
$APP.post('/signin', $HANDLER)
|
|
41
|
+
- pattern: |
|
|
42
|
+
$ROUTER.post('/signin', $HANDLER)
|
|
43
|
+
- pattern: |
|
|
44
|
+
$APP.post('/auth/login', $HANDLER)
|
|
45
|
+
- pattern: |
|
|
46
|
+
$ROUTER.post('/auth/login', $HANDLER)
|
|
47
|
+
- pattern-not: |
|
|
48
|
+
$APP.post('/login', rateLimit(...), $X)
|
|
49
|
+
- pattern-not: |
|
|
50
|
+
$ROUTER.post('/login', rateLimit(...), $X)
|
|
51
|
+
- pattern-not: |
|
|
52
|
+
$APP.post('/login', $LIMIT, $X)
|
|
53
|
+
metadata:
|
|
54
|
+
cwe: "CWE-307: Improper Restriction of Excessive Authentication Attempts"
|
|
55
|
+
owasp: "A07:2021 - Identification and Authentication Failures"
|
|
56
|
+
category: brute-force
|
|
57
|
+
precision: medium
|
|
58
|
+
confidence: medium
|
|
59
|
+
references:
|
|
60
|
+
- "https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html"
|
|
61
|
+
|
|
62
|
+
# ZM-JS-BF-002: bcrypt / argon2 cost factor 过低
|
|
63
|
+
- id: zm-js-bf-002
|
|
64
|
+
severity: WARNING
|
|
65
|
+
message: |
|
|
66
|
+
检测到密码哈希函数(bcrypt/argon2)的 cost/saltRounds 参数过低。
|
|
67
|
+
cost 过低使哈希计算速度过快,攻击者可高效进行离线暴力破解。
|
|
68
|
+
|
|
69
|
+
bcrypt saltRounds < 10: 过弱,建议 >= 12
|
|
70
|
+
argon2 timeCost < 3: 过弱,建议 >= 3
|
|
71
|
+
|
|
72
|
+
修复:
|
|
73
|
+
1. bcrypt: saltRounds >= 12 (生产环境)
|
|
74
|
+
2. argon2: timeCost >= 3, memoryCost >= 65536
|
|
75
|
+
3. 定期评估并上调 cost(随硬件性能提升)
|
|
76
|
+
languages:
|
|
77
|
+
- javascript
|
|
78
|
+
- typescript
|
|
79
|
+
pattern-either:
|
|
80
|
+
- pattern: bcrypt.hash($PASS, 1)
|
|
81
|
+
- pattern: bcrypt.hash($PASS, 2)
|
|
82
|
+
- pattern: bcrypt.hash($PASS, 3)
|
|
83
|
+
- pattern: bcrypt.hash($PASS, 4)
|
|
84
|
+
- pattern: bcrypt.hash($PASS, 5)
|
|
85
|
+
- pattern: bcrypt.hash($PASS, 6)
|
|
86
|
+
- pattern: bcrypt.hash($PASS, 7)
|
|
87
|
+
- pattern: bcrypt.hash($PASS, 8)
|
|
88
|
+
- pattern: bcrypt.hash($PASS, 9)
|
|
89
|
+
- pattern: bcrypt.hashSync($PASS, $LOW_COST)
|
|
90
|
+
- pattern: bcrypt.genSalt(1)
|
|
91
|
+
- pattern: bcrypt.genSalt(2)
|
|
92
|
+
- pattern: bcrypt.genSalt(3)
|
|
93
|
+
- pattern: bcrypt.genSalt(4)
|
|
94
|
+
- pattern: bcrypt.genSalt(5)
|
|
95
|
+
- pattern: bcrypt.genSalt(6)
|
|
96
|
+
- pattern: bcrypt.genSalt(7)
|
|
97
|
+
- pattern: bcrypt.genSalt(8)
|
|
98
|
+
- pattern: bcrypt.genSalt(9)
|
|
99
|
+
metadata:
|
|
100
|
+
cwe: "CWE-307: Improper Restriction of Excessive Authentication Attempts"
|
|
101
|
+
owasp: "A07:2021 - Identification and Authentication Failures"
|
|
102
|
+
category: brute-force
|
|
103
|
+
precision: very-high
|
|
104
|
+
confidence: high
|
|
105
|
+
references:
|
|
106
|
+
- "https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html"
|
|
107
|
+
|
|
108
|
+
# ZM-JS-BF-003: rate-limit 配置过于宽松
|
|
109
|
+
- id: zm-js-bf-003
|
|
110
|
+
severity: WARNING
|
|
111
|
+
message: |
|
|
112
|
+
检测到 express-rate-limit 配置的 max 值过高或 windowMs 过短。
|
|
113
|
+
过于宽松的限速无法有效阻止暴力破解攻击。
|
|
114
|
+
|
|
115
|
+
登录接口建议配置:
|
|
116
|
+
- max: 5-10 次 / 15分钟
|
|
117
|
+
- 全局/API: max: 100 次 / 15分钟
|
|
118
|
+
|
|
119
|
+
修复:
|
|
120
|
+
1. 登录接口 max <= 10, windowMs >= 15 * 60 * 1000
|
|
121
|
+
2. 敏感操作(密码重置)使用更严格的限制
|
|
122
|
+
3. 使用 Redis/Memcached 做分布式环境限流
|
|
123
|
+
languages:
|
|
124
|
+
- javascript
|
|
125
|
+
- typescript
|
|
126
|
+
pattern-either:
|
|
127
|
+
- pattern: |
|
|
128
|
+
rateLimit({max: $HIGH})
|
|
129
|
+
metadata:
|
|
130
|
+
cwe: "CWE-307: Improper Restriction of Excessive Authentication Attempts"
|
|
131
|
+
owasp: "A07:2021 - Identification and Authentication Failures"
|
|
132
|
+
category: brute-force
|
|
133
|
+
precision: low
|
|
134
|
+
confidence: low
|
|
135
|
+
references:
|
|
136
|
+
- "https://express-rate-limit.mintlify.app/overview"
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# CWE-345: postMessage 无 origin 验证检测规则
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint 1 — JS/TS 通用规则库
|
|
3
|
+
|
|
4
|
+
rules:
|
|
5
|
+
|
|
6
|
+
# ZM-JS-POSTMSG-001: postMessage 监听器未校验 origin
|
|
7
|
+
- id: zm-js-postmsg-001
|
|
8
|
+
severity: WARNING
|
|
9
|
+
message: |
|
|
10
|
+
检测到 window.addEventListener('message', ...) 或 window.onmessage
|
|
11
|
+
事件监听器,但未对 event.origin 进行校验。
|
|
12
|
+
攻击者可通过任意域的页面发送恶意消息,导致数据泄露或跨域操作。
|
|
13
|
+
|
|
14
|
+
修复建议:
|
|
15
|
+
1. 在校验 event.origin 白名单后再处理消息:
|
|
16
|
+
if (event.origin !== 'https://trusted.com') return;
|
|
17
|
+
2. 同时校验 event.source 来源窗口
|
|
18
|
+
3. 在 postMessage 发送时指定精确的 targetOrigin,避免使用 '*'
|
|
19
|
+
4. 对接收的消息数据进行结构校验
|
|
20
|
+
languages:
|
|
21
|
+
- javascript
|
|
22
|
+
- typescript
|
|
23
|
+
patterns:
|
|
24
|
+
- pattern-either:
|
|
25
|
+
- pattern: |
|
|
26
|
+
window.addEventListener('message', $CALLBACK)
|
|
27
|
+
- pattern: |
|
|
28
|
+
window.addEventListener("message", $CALLBACK)
|
|
29
|
+
- pattern: |
|
|
30
|
+
globalThis.addEventListener('message', $CALLBACK)
|
|
31
|
+
- pattern: |
|
|
32
|
+
window.onmessage = $CALLBACK
|
|
33
|
+
- pattern-not-inside: |
|
|
34
|
+
...
|
|
35
|
+
event.origin === ...
|
|
36
|
+
...
|
|
37
|
+
- pattern-not-inside: |
|
|
38
|
+
...
|
|
39
|
+
event.origin !== ...
|
|
40
|
+
...
|
|
41
|
+
metadata:
|
|
42
|
+
cwe: "CWE-345: Insufficient Verification of Data Authenticity"
|
|
43
|
+
owasp: "A08:2021 - Software and Data Integrity Failures"
|
|
44
|
+
category: xss
|
|
45
|
+
precision: medium
|
|
46
|
+
references:
|
|
47
|
+
- "https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage"
|
|
48
|
+
- "https://owasp.org/www-community/attacks/HTML5_Security_Cheat_Sheet#postmessage"
|
|
49
|
+
|
|
50
|
+
# ZM-JS-POSTMSG-002: postMessage 使用通配符 targetOrigin
|
|
51
|
+
- id: zm-js-postmsg-002
|
|
52
|
+
severity: WARNING
|
|
53
|
+
message: |
|
|
54
|
+
检测到 postMessage 调用使用了通配符 '*' 作为 targetOrigin。
|
|
55
|
+
这将导致消息可被任意域的页面接收,存在信息泄露风险。
|
|
56
|
+
|
|
57
|
+
修复建议:
|
|
58
|
+
1. 将 targetOrigin 设置为精确的目标 origin: $WINDOW.postMessage(data, 'https://trusted.com')
|
|
59
|
+
2. 如果确实需要发给多个域,校验接收方 origin 白名单后再发送
|
|
60
|
+
3. 避免在消息中携带敏感数据
|
|
61
|
+
languages:
|
|
62
|
+
- javascript
|
|
63
|
+
- typescript
|
|
64
|
+
pattern-either:
|
|
65
|
+
- pattern: $WINDOW.postMessage($DATA, '*')
|
|
66
|
+
- pattern: $WINDOW.postMessage($DATA, "*")
|
|
67
|
+
- pattern: $FRAME.contentWindow.postMessage($DATA, '*')
|
|
68
|
+
- pattern: $FRAME.contentWindow.postMessage($DATA, "*")
|
|
69
|
+
metadata:
|
|
70
|
+
cwe: "CWE-345: Insufficient Verification of Data Authenticity"
|
|
71
|
+
owasp: "A08:2021 - Software and Data Integrity Failures"
|
|
72
|
+
category: xss
|
|
73
|
+
precision: very-high
|
|
74
|
+
references:
|
|
75
|
+
- "https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#security_concerns"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# CWE-347: JWT 弱签名检测规则
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint 1 — JS/TS 通用规则库
|
|
3
|
+
|
|
4
|
+
rules:
|
|
5
|
+
|
|
6
|
+
# ZM-JS-JWT-001: JWT secret 硬编码
|
|
7
|
+
- id: zm-js-jwt-001
|
|
8
|
+
severity: ERROR
|
|
9
|
+
message: |
|
|
10
|
+
检测到 jwt.sign() 使用硬编码字符串作为签名密钥(secret)。
|
|
11
|
+
硬编码密钥泄露后攻击者可伪造任意 JWT Token,冒充任意用户身份。
|
|
12
|
+
|
|
13
|
+
修复建议:
|
|
14
|
+
1. 使用环境变量存储密钥: process.env.JWT_SECRET
|
|
15
|
+
2. 密钥长度至少 256 位(HMAC-SHA256),使用 crypto.randomBytes(32).toString('hex') 生成
|
|
16
|
+
3. 使用非对称算法 RS256/ES256 替代对称 HMAC 算法
|
|
17
|
+
4. 密钥定期轮换
|
|
18
|
+
languages:
|
|
19
|
+
- javascript
|
|
20
|
+
- typescript
|
|
21
|
+
pattern-either:
|
|
22
|
+
- pattern: |
|
|
23
|
+
jwt.sign($PAYLOAD, '...', ...)
|
|
24
|
+
- pattern: |
|
|
25
|
+
jwt.sign($PAYLOAD, "...", ...)
|
|
26
|
+
- pattern: |
|
|
27
|
+
jsonwebtoken.sign($PAYLOAD, '...', ...)
|
|
28
|
+
- pattern: |
|
|
29
|
+
jsonwebtoken.sign($PAYLOAD, "...", ...)
|
|
30
|
+
metadata:
|
|
31
|
+
cwe: "CWE-347: Improper Verification of Cryptographic Signature"
|
|
32
|
+
owasp: "A02:2021 - Cryptographic Failures"
|
|
33
|
+
category: crypto
|
|
34
|
+
precision: very-high
|
|
35
|
+
references:
|
|
36
|
+
- "https://www.npmjs.com/package/jsonwebtoken"
|
|
37
|
+
- "https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/"
|
|
38
|
+
|
|
39
|
+
# ZM-JS-JWT-002: JWT algorithm 设置为 none
|
|
40
|
+
- id: zm-js-jwt-002
|
|
41
|
+
severity: ERROR
|
|
42
|
+
message: |
|
|
43
|
+
检测到 JWT 配置中 algorithm 设置为 'none'。
|
|
44
|
+
这意味着 Token 不进行签名验证,攻击者可伪造任意 Token。
|
|
45
|
+
|
|
46
|
+
修复建议:
|
|
47
|
+
1. 移除 algorithm: 'none' 配置
|
|
48
|
+
2. 使用安全的签名算法: HS256 / RS256 / ES256
|
|
49
|
+
3. jwt.verify 时显式指定 algorithms 参数,禁止接受 'none'
|
|
50
|
+
languages:
|
|
51
|
+
- javascript
|
|
52
|
+
- typescript
|
|
53
|
+
pattern-either:
|
|
54
|
+
- pattern: |
|
|
55
|
+
jwt.sign(..., {..., algorithm: 'none', ...})
|
|
56
|
+
- pattern: |
|
|
57
|
+
jwt.sign(..., {..., algorithm: "none", ...})
|
|
58
|
+
- pattern: |
|
|
59
|
+
jwt.verify(..., {..., algorithms: ['none', ...], ...})
|
|
60
|
+
- pattern: |
|
|
61
|
+
jwt.verify(..., {..., algorithms: ["none", ...], ...})
|
|
62
|
+
metadata:
|
|
63
|
+
cwe: "CWE-347: Improper Verification of Cryptographic Signature"
|
|
64
|
+
owasp: "A02:2021 - Cryptographic Failures"
|
|
65
|
+
category: crypto
|
|
66
|
+
precision: very-high
|
|
67
|
+
references:
|
|
68
|
+
- "https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/"
|
|
69
|
+
|
|
70
|
+
# ZM-JS-JWT-003: jwt.verify 未指定 algorithms
|
|
71
|
+
- id: zm-js-jwt-003
|
|
72
|
+
severity: WARNING
|
|
73
|
+
message: |
|
|
74
|
+
检测到 jwt.verify() 调用未显式指定 algorithms 参数。
|
|
75
|
+
某些旧版本 JWT 库默认接受 'none' 算法,可能导致 Token 伪造攻击。
|
|
76
|
+
|
|
77
|
+
修复建议:
|
|
78
|
+
1. 显式指定 algorithms: ['HS256'] 或 ['RS256']
|
|
79
|
+
2. 升级 jsonwebtoken 至最新版本
|
|
80
|
+
3. 禁止在 algorithms 列表中出现 'none'
|
|
81
|
+
languages:
|
|
82
|
+
- javascript
|
|
83
|
+
- typescript
|
|
84
|
+
pattern-either:
|
|
85
|
+
- pattern: jwt.verify($TOKEN, $SECRET)
|
|
86
|
+
- pattern: jwt.verify($TOKEN, $SECRET, $CALLBACK)
|
|
87
|
+
- pattern: jsonwebtoken.verify($TOKEN, $SECRET)
|
|
88
|
+
- pattern: jsonwebtoken.verify($TOKEN, $SECRET, $CALLBACK)
|
|
89
|
+
metadata:
|
|
90
|
+
cwe: "CWE-347: Improper Verification of Cryptographic Signature"
|
|
91
|
+
owasp: "A02:2021 - Cryptographic Failures"
|
|
92
|
+
category: crypto
|
|
93
|
+
precision: medium
|
|
94
|
+
references:
|
|
95
|
+
- "https://auth0.com/blog/critical-vulnerabilities-in-json-web-token-libraries/"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# CWE-352: Express CSRF 保护缺失检测规则
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint 1 — JS/TS 通用规则库
|
|
3
|
+
|
|
4
|
+
rules:
|
|
5
|
+
|
|
6
|
+
# ZM-JS-CSRF-001: Express 应用未使用 CSRF 中间件
|
|
7
|
+
- id: zm-js-csrf-001
|
|
8
|
+
severity: WARNING
|
|
9
|
+
message: |
|
|
10
|
+
检测到 Express 应用中未发现 csurf / lusca / csrf 等 CSRF 保护中间件的使用。
|
|
11
|
+
缺少 CSRF 保护使应用面临跨站请求伪造攻击风险,攻击者可诱导用户执行
|
|
12
|
+
未授权的状态变更操作。
|
|
13
|
+
|
|
14
|
+
修复建议:
|
|
15
|
+
1. 安装并使用 csurf 中间件: app.use(csurf({ cookie: true }))
|
|
16
|
+
2. 或使用 lusca: app.use(lusca.csrf())
|
|
17
|
+
3. REST API 使用 Authorization Header (Bearer Token) 而非 Cookie 认证
|
|
18
|
+
4. 验证 Origin / Referer 请求头
|
|
19
|
+
languages:
|
|
20
|
+
- javascript
|
|
21
|
+
- typescript
|
|
22
|
+
patterns:
|
|
23
|
+
- pattern-either:
|
|
24
|
+
- pattern: |
|
|
25
|
+
const $APP = express();
|
|
26
|
+
...
|
|
27
|
+
- pattern: |
|
|
28
|
+
const $APP = express();
|
|
29
|
+
...
|
|
30
|
+
$APP.use(...);
|
|
31
|
+
...
|
|
32
|
+
- pattern-not-inside: |
|
|
33
|
+
...
|
|
34
|
+
$APP.use(csurf(...));
|
|
35
|
+
...
|
|
36
|
+
- pattern-not-inside: |
|
|
37
|
+
...
|
|
38
|
+
$APP.use(lusca.csrf(...));
|
|
39
|
+
...
|
|
40
|
+
- pattern-not-inside: |
|
|
41
|
+
...
|
|
42
|
+
$APP.use(csrf(...));
|
|
43
|
+
...
|
|
44
|
+
metadata:
|
|
45
|
+
cwe: "CWE-352: Cross-Site Request Forgery (CSRF)"
|
|
46
|
+
owasp: "A01:2021 - Broken Access Control"
|
|
47
|
+
category: csrf
|
|
48
|
+
precision: low
|
|
49
|
+
references:
|
|
50
|
+
- "https://owasp.org/www-community/attacks/csrf"
|
|
51
|
+
- "https://www.npmjs.com/package/csurf"
|
|
52
|
+
- "https://www.npmjs.com/package/lusca"
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# CWE-384: Node.js 会话固定 (Session Fixation) 检测
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint — JS/TS 规则库
|
|
3
|
+
# 覆盖: express-session未regenerate、cookie未设secure/httpOnly、sameSite未设Strict
|
|
4
|
+
|
|
5
|
+
rules:
|
|
6
|
+
|
|
7
|
+
# ZM-JS-SF-001: express-session 未调用 regenerate (登录后未更换会话ID)
|
|
8
|
+
- id: zm-js-sf-001
|
|
9
|
+
severity: HIGH
|
|
10
|
+
message: |
|
|
11
|
+
检测到登录成功逻辑中未调用 req.session.regenerate() 更换会话ID。
|
|
12
|
+
攻击者可通过固定会话攻击(Session Fixation)劫持已验证用户的会话:
|
|
13
|
+
1. 攻击者获取一个有效的session ID
|
|
14
|
+
2. 诱骗受害者使用此session ID登录
|
|
15
|
+
3. 攻击者使用同一session ID冒充受害者
|
|
16
|
+
|
|
17
|
+
修复:
|
|
18
|
+
1. 登录成功后调用 req.session.regenerate(function(err) { ... })
|
|
19
|
+
2. 或在 passport.authenticate 后使用 passport.logIn + regenerate
|
|
20
|
+
3. 确保 regenerate 在 session 数据设置之前执行
|
|
21
|
+
languages:
|
|
22
|
+
- javascript
|
|
23
|
+
- typescript
|
|
24
|
+
patterns:
|
|
25
|
+
- pattern-either:
|
|
26
|
+
- pattern: |
|
|
27
|
+
$APP.post('/login', function($REQ, $RES) {
|
|
28
|
+
...
|
|
29
|
+
$REQ.session.$USER = $DATA;
|
|
30
|
+
...
|
|
31
|
+
})
|
|
32
|
+
- pattern: |
|
|
33
|
+
$APP.post('/login', ($REQ, $RES) => {
|
|
34
|
+
...
|
|
35
|
+
$REQ.session.$USER = $DATA;
|
|
36
|
+
...
|
|
37
|
+
})
|
|
38
|
+
- pattern: |
|
|
39
|
+
$ROUTER.post('/login', function($REQ, $RES) {
|
|
40
|
+
...
|
|
41
|
+
$REQ.session.$USER = $DATA;
|
|
42
|
+
...
|
|
43
|
+
})
|
|
44
|
+
- pattern-not: |
|
|
45
|
+
$REQ.session.regenerate(...)
|
|
46
|
+
metadata:
|
|
47
|
+
cwe: "CWE-384: Session Fixation"
|
|
48
|
+
owasp: "A07:2021 - Identification and Authentication Failures"
|
|
49
|
+
category: session
|
|
50
|
+
precision: medium
|
|
51
|
+
confidence: high
|
|
52
|
+
references:
|
|
53
|
+
- "https://owasp.org/www-community/attacks/Session_fixation"
|
|
54
|
+
- "https://expressjs.com/en/resources/middleware/session.html"
|
|
55
|
+
|
|
56
|
+
# ZM-JS-SF-002: Cookie 安全属性缺失 (secure / httpOnly / sameSite)
|
|
57
|
+
- id: zm-js-sf-002
|
|
58
|
+
severity: HIGH
|
|
59
|
+
message: |
|
|
60
|
+
检测到 session / cookie 配置中缺少关键安全属性。
|
|
61
|
+
|
|
62
|
+
- secure: false 或缺失 → Cookie可被中间人通过HTTP明文传输窃取
|
|
63
|
+
- httpOnly: false 或缺失 → JavaScript可读取Cookie,XSS可窃取会话
|
|
64
|
+
- sameSite 未设 Strict/Lax → 跨站请求携带Cookie,易受CSRF
|
|
65
|
+
|
|
66
|
+
修复:
|
|
67
|
+
1. 生产环境强制 secure: true (HTTPS)
|
|
68
|
+
2. 始终设置 httpOnly: true
|
|
69
|
+
3. sameSite: 'strict' 或至少 'lax'
|
|
70
|
+
4. 设置合理的 maxAge / expires
|
|
71
|
+
languages:
|
|
72
|
+
- javascript
|
|
73
|
+
- typescript
|
|
74
|
+
pattern-either:
|
|
75
|
+
# express-session 漏设 secure
|
|
76
|
+
- pattern: |
|
|
77
|
+
app.use(session({cookie: {secure: false}}))
|
|
78
|
+
# express-session 漏设 httpOnly
|
|
79
|
+
- pattern: |
|
|
80
|
+
app.use(session({cookie: {httpOnly: false}}))
|
|
81
|
+
# res.cookie 漏设 sameSite
|
|
82
|
+
- pattern: |
|
|
83
|
+
$RES.cookie($NAME, $VAL, {sameSite: false})
|
|
84
|
+
# res.cookie 漏设 secure
|
|
85
|
+
- pattern: |
|
|
86
|
+
$RES.cookie($NAME, $VAL, {secure: false})
|
|
87
|
+
# res.cookie 漏设 httpOnly
|
|
88
|
+
- pattern: |
|
|
89
|
+
$RES.cookie($NAME, $VAL, {httpOnly: false})
|
|
90
|
+
metadata:
|
|
91
|
+
cwe: "CWE-384: Session Fixation"
|
|
92
|
+
owasp: "A07:2021 - Identification and Authentication Failures"
|
|
93
|
+
category: session
|
|
94
|
+
precision: medium
|
|
95
|
+
confidence: high
|
|
96
|
+
references:
|
|
97
|
+
- "https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Security"
|
|
98
|
+
|
|
99
|
+
# ZM-JS-SF-003: express-session 配置缺少关键安全选项
|
|
100
|
+
- id: zm-js-sf-003
|
|
101
|
+
severity: WARNING
|
|
102
|
+
message: |
|
|
103
|
+
检测到 express-session 配置中可能缺少 cookie.secure、cookie.httpOnly 或 cookie.sameSite 选项。
|
|
104
|
+
|
|
105
|
+
缺失配置示例:
|
|
106
|
+
app.use(session({
|
|
107
|
+
secret: 'keyboard cat',
|
|
108
|
+
resave: false,
|
|
109
|
+
saveUninitialized: true,
|
|
110
|
+
cookie: {} // ← 缺少安全属性
|
|
111
|
+
}))
|
|
112
|
+
|
|
113
|
+
修复:
|
|
114
|
+
1. cookie.secure: true (生产环境)
|
|
115
|
+
2. cookie.httpOnly: true
|
|
116
|
+
3. cookie.sameSite: 'strict'
|
|
117
|
+
4. saveUninitialized: false (避免空会话创建)
|
|
118
|
+
5. name: 自定义session名称(隐藏默认connect.sid)
|
|
119
|
+
languages:
|
|
120
|
+
- javascript
|
|
121
|
+
- typescript
|
|
122
|
+
patterns:
|
|
123
|
+
- pattern: |
|
|
124
|
+
app.use(session({...}))
|
|
125
|
+
metadata:
|
|
126
|
+
cwe: "CWE-384: Session Fixation"
|
|
127
|
+
owasp: "A07:2021 - Identification and Authentication Failures"
|
|
128
|
+
category: session
|
|
129
|
+
precision: low
|
|
130
|
+
confidence: medium
|
|
131
|
+
references:
|
|
132
|
+
- "https://expressjs.com/en/resources/middleware/session.html"
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# CWE-502: Node.js 不安全反序列化检测规则
|
|
2
|
+
# 逐码 ZhuMa V4.1 Sprint 2 — JS/TS 规则库
|
|
3
|
+
# 覆盖: node-serialize、serialize-javascript、js-yaml.load、JSON.parse prototype injection
|
|
4
|
+
|
|
5
|
+
rules:
|
|
6
|
+
|
|
7
|
+
# ZM-JS-DSER-001: node-serialize / serialize-javascript / js-yaml.load 不安全反序列化
|
|
8
|
+
- id: zm-js-dser-001
|
|
9
|
+
severity: ERROR
|
|
10
|
+
message: |
|
|
11
|
+
检测到使用 node-serialize.unserialize() / serialize-javascript(eval) / js-yaml.load()
|
|
12
|
+
进行不安全反序列化,可能导致远程代码执行(RCE)。
|
|
13
|
+
|
|
14
|
+
node-serialize.unserialize() 支持IIFE,攻击者可注入恶意函数体执行任意代码。
|
|
15
|
+
js-yaml.load() 默认使用 !!js/undefined 等危险类型,可触发代码执行。
|
|
16
|
+
serialize-javascript 需配合 eval 使用,存在RCE风险。
|
|
17
|
+
|
|
18
|
+
修复:
|
|
19
|
+
1. node-serialize => 使用 JSON.parse() 替代,或 v8.deserialize() + v8.serialize()
|
|
20
|
+
2. js-yaml.load(input) => js-yaml.load(input, { schema: yaml.FAILSAFE_SCHEMA }) 或 yaml.safeLoad()
|
|
21
|
+
3. serialize-javascript => 禁止配合 eval() 使用
|
|
22
|
+
4. 对所有反序列化输入做完整性校验(HMAC/Signature)
|
|
23
|
+
languages:
|
|
24
|
+
- javascript
|
|
25
|
+
- typescript
|
|
26
|
+
pattern-either:
|
|
27
|
+
- pattern: nodeSerialize.unserialize(...)
|
|
28
|
+
- pattern: $NS.unserialize(...)
|
|
29
|
+
- pattern: $SJ.serialize(...)
|
|
30
|
+
- pattern: eval(serializeJavascript(...))
|
|
31
|
+
- pattern: eval(serialize(...))
|
|
32
|
+
- pattern: jsYaml.load(...)
|
|
33
|
+
- pattern: yaml.load(...)
|
|
34
|
+
- pattern: $YAML.load(...)
|
|
35
|
+
metadata:
|
|
36
|
+
cwe: "CWE-502: Deserialization of Untrusted Data"
|
|
37
|
+
owasp: "A08:2021 - Software and Data Integrity Failures"
|
|
38
|
+
category: deserialization
|
|
39
|
+
precision: medium
|
|
40
|
+
references:
|
|
41
|
+
- "https://github.com/luin/serialize#security-issue"
|
|
42
|
+
- "https://github.com/nodeca/js-yaml#security"
|
|
43
|
+
- "https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html"
|
|
44
|
+
|
|
45
|
+
# ZM-JS-DSER-002: js-yaml.load 无 safeLoad / schema 参数
|
|
46
|
+
- id: zm-js-dser-002
|
|
47
|
+
severity: WARNING
|
|
48
|
+
message: |
|
|
49
|
+
js-yaml.load() 未指定 { schema: FAULT_SAFE_SCHEMA } 安全选项。
|
|
50
|
+
默认schema支持 !!js/undefined / !!js/regexp 等危险类型,可能导致原型污染或RCE。
|
|
51
|
+
|
|
52
|
+
修复:
|
|
53
|
+
1. js-yaml.safeLoad(input) 替代 js-yaml.load(input)
|
|
54
|
+
2. 或 yaml.load(input, { schema: yaml.FAILSAFE_SCHEMA })
|
|
55
|
+
3. 升级 js-yaml 到最新版本(>=4.1.0)
|
|
56
|
+
languages:
|
|
57
|
+
- javascript
|
|
58
|
+
- typescript
|
|
59
|
+
patterns:
|
|
60
|
+
- pattern-either:
|
|
61
|
+
- pattern: $YAML.load(...)
|
|
62
|
+
- pattern-not: $YAML.load(..., ...)
|
|
63
|
+
metadata:
|
|
64
|
+
cwe: "CWE-502: Deserialization of Untrusted Data"
|
|
65
|
+
owasp: "A08:2021 - Software and Data Integrity Failures"
|
|
66
|
+
category: deserialization
|
|
67
|
+
precision: low
|
|
68
|
+
references:
|
|
69
|
+
- "https://github.com/nodeca/js-yaml#safe-load"
|
|
70
|
+
|
|
71
|
+
# ZM-JS-DSER-003: JSON.parse 后直接访问嵌套属性(可能的prototype injection)
|
|
72
|
+
- id: zm-js-dser-003
|
|
73
|
+
severity: WARNING
|
|
74
|
+
message: |
|
|
75
|
+
JSON.parse(userInput) 后对结果对象进行属性赋值或 __proto__ 路径访问。
|
|
76
|
+
JSON.parse 本身安全,但若不验证输入直接合并到其他对象中,攻击者可利用
|
|
77
|
+
{"__proto__": {"isAdmin": true}} 进行原型污染。
|
|
78
|
+
|
|
79
|
+
修复:
|
|
80
|
+
1. 检查并过滤 __proto__ / constructor / prototype 键名
|
|
81
|
+
2. 使用 Object.create(null) 创建目标对象
|
|
82
|
+
3. 使用 Map 替代普通对象存储数据
|
|
83
|
+
4. 使用 joi / zod Schema 验证输入结构,禁止额外属性
|
|
84
|
+
languages:
|
|
85
|
+
- javascript
|
|
86
|
+
- typescript
|
|
87
|
+
patterns:
|
|
88
|
+
- pattern-either:
|
|
89
|
+
- pattern: |
|
|
90
|
+
$PARSED = JSON.parse($REQ.body, ...)
|
|
91
|
+
...
|
|
92
|
+
$OBJ[$PARSED] = $VAL
|
|
93
|
+
- pattern: |
|
|
94
|
+
$PARSED = JSON.parse($REQ.query, ...)
|
|
95
|
+
...
|
|
96
|
+
$OBJ[$PARSED] = $VAL
|
|
97
|
+
- pattern: |
|
|
98
|
+
$PARSED = JSON.parse($REQ.params, ...)
|
|
99
|
+
...
|
|
100
|
+
$OBJ[$PARSED] = $VAL
|
|
101
|
+
- pattern: |
|
|
102
|
+
$PARSED = JSON.parse($REQ.body, ...)
|
|
103
|
+
...
|
|
104
|
+
Object.assign($TARGET, $PARSED)
|
|
105
|
+
- pattern: |
|
|
106
|
+
$PARSED = JSON.parse($REQ.body, ...)
|
|
107
|
+
...
|
|
108
|
+
lodash.merge($TARGET, $PARSED)
|
|
109
|
+
- pattern: |
|
|
110
|
+
$PARSED = JSON.parse($REQ.body, ...)
|
|
111
|
+
...
|
|
112
|
+
_.merge($TARGET, $PARSED)
|
|
113
|
+
metadata:
|
|
114
|
+
cwe: "CWE-502: Deserialization of Untrusted Data"
|
|
115
|
+
owasp: "A08:2021 - Software and Data Integrity Failures"
|
|
116
|
+
category: deserialization
|
|
117
|
+
precision: low
|
|
118
|
+
references:
|
|
119
|
+
- "https://www.npmjs.com/advisories/1065"
|