narvy-cli 1.0.0__py3-none-any.whl
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.
- narvy/__init__.py +3 -0
- narvy/android/__init__.py +0 -0
- narvy/android/source_analyzer.py +268 -0
- narvy/android/split_bundle.py +475 -0
- narvy/android_rule_context.py +196 -0
- narvy/apk_memory_preflight.py +248 -0
- narvy/auth.py +40 -0
- narvy/ci_templates/bitbucket.yml +25 -0
- narvy/ci_templates/github.yml +60 -0
- narvy/ci_templates/gitlab.yml +32 -0
- narvy/cloud/__init__.py +0 -0
- narvy/cloud/aws_scan.py +1188 -0
- narvy/comment_filter.py +134 -0
- narvy/crypto_taint_lite.py +82 -0
- narvy/decompiler.py +337 -0
- narvy/doctor.py +244 -0
- narvy/host/__init__.py +0 -0
- narvy/host/audit.py +157 -0
- narvy/host/host_knowledge.py +982 -0
- narvy/host/lynis_bootstrap.py +400 -0
- narvy/host/lynis_parser.py +358 -0
- narvy/host/narvy_checks.py +789 -0
- narvy/host/report.py +69 -0
- narvy/host/ssh_exec.py +219 -0
- narvy/ios/__init__.py +0 -0
- narvy/ios/binary_analyzer.py +1201 -0
- narvy/ios/plist_checks.py +249 -0
- narvy/ios/source_analyzer.py +301 -0
- narvy/ios/third_party_filter.py +242 -0
- narvy/ios/trust_all_context.py +66 -0
- narvy/main.py +1983 -0
- narvy/native_hardening.py +503 -0
- narvy/reporter.py +151 -0
- narvy/rule_engine.py +57 -0
- narvy/rules/android/config.yml +77 -0
- narvy/rules/android/crypto.yml +34 -0
- narvy/rules/android/secrets.yml +161 -0
- narvy/rules/android/storage.yml +24 -0
- narvy/rules/android/webview.yml +23 -0
- narvy/rules/android.yml +219 -0
- narvy/rules/ios/objc/crypto.yml +56 -0
- narvy/rules/ios/objc/network.yml +67 -0
- narvy/rules/ios/objc/secrets.yml +79 -0
- narvy/rules/ios/objc/storage.yml +45 -0
- narvy/rules/ios/objc/webview.yml +45 -0
- narvy/rules/ios_swift.yml +327 -0
- narvy/rules/web/go.yml +2837 -0
- narvy/rules/web/java.yml +1576 -0
- narvy/rules/web/javascript.yml +3683 -0
- narvy/rules/web/kotlin.yml +413 -0
- narvy/rules/web/local/csharp_narvy/config.yml +61 -0
- narvy/rules/web/local/csharp_narvy/crypto.yml +64 -0
- narvy/rules/web/local/csharp_narvy/deserialization.yml +59 -0
- narvy/rules/web/local/csharp_narvy/injection.yml +122 -0
- narvy/rules/web/local/csharp_narvy/xxe.yml +48 -0
- narvy/rules/web/local/java_narvy/auth_jwt.yml +134 -0
- narvy/rules/web/local/java_narvy/deserialization.yml +108 -0
- narvy/rules/web/local/java_narvy/mybatis.yml +39 -0
- narvy/rules/web/local/java_narvy/snakeyaml.yml +34 -0
- narvy/rules/web/local/java_narvy/spring_authz.yml +32 -0
- narvy/rules/web/local/java_narvy/spring_config.yml +67 -0
- narvy/rules/web/local/java_narvy/spring_hardening.yml +291 -0
- narvy/rules/web/local/java_narvy/sqli.yml +235 -0
- narvy/rules/web/local/java_narvy/xxe.yml +212 -0
- narvy/rules/web/php.yml +1644 -0
- narvy/rules/web/python.yml +3967 -0
- narvy/rules/web/ruby.yml +703 -0
- narvy/rules/web/rust.yml +258 -0
- narvy/rules/web/secrets.yml +1420 -0
- narvy/rules/web/secrets_supplement.yml +383 -0
- narvy/sca/__init__.py +1 -0
- narvy/sca/android_deps.py +349 -0
- narvy/sca/ios_deps.py +578 -0
- narvy/sca/osv_client.py +617 -0
- narvy/sca/web_deps.py +955 -0
- narvy/scope_config.py +195 -0
- narvy/semgrep_engine.py +219 -0
- narvy/stack_protector_evidence.py +96 -0
- narvy/third_party_filter.py +211 -0
- narvy/uploader.py +92 -0
- narvy/weak_prng_context.py +270 -0
- narvy/web/__init__.py +0 -0
- narvy/web/nuclei_binary.py +105 -0
- narvy/web/scan_blocklist.py +96 -0
- narvy/web/scanner.py +842 -0
- narvy/web/source_analyzer.py +714 -0
- narvy/web/ssrf_guard.py +374 -0
- narvy_cli-1.0.0.dist-info/METADATA +165 -0
- narvy_cli-1.0.0.dist-info/RECORD +93 -0
- narvy_cli-1.0.0.dist-info/WHEEL +5 -0
- narvy_cli-1.0.0.dist-info/entry_points.txt +2 -0
- narvy_cli-1.0.0.dist-info/licenses/LICENSE +202 -0
- narvy_cli-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
|
|
3
|
+
# Java/Spring hardening: CSRF disabled, SpEL injection, permissive CORS.
|
|
4
|
+
|
|
5
|
+
- id: narvy.java.spring.csrf-disabled.csrf-disabled
|
|
6
|
+
message: >-
|
|
7
|
+
CSRF protection is explicitly turned off on this
|
|
8
|
+
`HttpSecurity`/`ServerHttpSecurity` chain. Once disabled, any
|
|
9
|
+
state-changing endpoint reachable with a browser-sent cookie can be
|
|
10
|
+
triggered from a page the victim did not intend to submit (CWE-352).
|
|
11
|
+
This is a deliberate choice for pure token-authenticated APIs (no
|
|
12
|
+
cookie-based session, `Authorization: Bearer` on every call) - if that
|
|
13
|
+
is this service, leave a comment explaining why; if any endpoint still
|
|
14
|
+
relies on a session cookie, re-enable CSRF or scope the disable to the
|
|
15
|
+
stateless endpoints only.
|
|
16
|
+
severity: WARNING
|
|
17
|
+
languages: [java]
|
|
18
|
+
metadata:
|
|
19
|
+
category: security
|
|
20
|
+
cwe:
|
|
21
|
+
- "CWE-352: Cross-Site Request Forgery (CSRF)"
|
|
22
|
+
owasp:
|
|
23
|
+
- "A01:2021 - Broken Access Control"
|
|
24
|
+
subcategory: [audit]
|
|
25
|
+
likelihood: LOW
|
|
26
|
+
impact: MEDIUM
|
|
27
|
+
confidence: MEDIUM
|
|
28
|
+
technology: [java, spring]
|
|
29
|
+
patterns:
|
|
30
|
+
- pattern-either:
|
|
31
|
+
- pattern: $HTTP.csrf().disable()
|
|
32
|
+
- pattern: $HTTP.csrf($CSRF -> $CSRF.disable())
|
|
33
|
+
- pattern: $HTTP.csrf(AbstractHttpConfigurer::disable)
|
|
34
|
+
- pattern: $HTTP.csrf(CsrfConfigurer::disable)
|
|
35
|
+
- pattern: $HTTP.csrf(ServerHttpSecurity.CsrfSpec::disable)
|
|
36
|
+
- pattern: $HTTP.csrf(CsrfSpec::disable)
|
|
37
|
+
|
|
38
|
+
- id: narvy.java.spring.spel-injection.tainted-request-parseexpression
|
|
39
|
+
message: >-
|
|
40
|
+
A Spring Expression Language (SpEL) parser evaluates an expression
|
|
41
|
+
string built from an HTTP request parameter, header, or a
|
|
42
|
+
`@RequestParam`/`@PathVariable` handler argument. SpEL is a full
|
|
43
|
+
expression language with reflection and static-method invocation
|
|
44
|
+
(`T(java.lang.Runtime).getRuntime().exec(...)` is valid SpEL) - letting
|
|
45
|
+
the request choose any part of the evaluated expression is remote code
|
|
46
|
+
execution, not just information disclosure (CWE-94). Never evaluate
|
|
47
|
+
request-derived text as SpEL; if the request must select between a
|
|
48
|
+
handful of computations, look them up in a fixed map instead.
|
|
49
|
+
severity: ERROR
|
|
50
|
+
languages: [java]
|
|
51
|
+
metadata:
|
|
52
|
+
category: security
|
|
53
|
+
cwe:
|
|
54
|
+
- "CWE-94: Improper Control of Generation of Code ('Code Injection')"
|
|
55
|
+
owasp:
|
|
56
|
+
- "A03:2021 - Injection"
|
|
57
|
+
subcategory: [vuln]
|
|
58
|
+
likelihood: MEDIUM
|
|
59
|
+
impact: HIGH
|
|
60
|
+
confidence: HIGH
|
|
61
|
+
technology: [java, spring]
|
|
62
|
+
mode: taint
|
|
63
|
+
pattern-sources:
|
|
64
|
+
- patterns:
|
|
65
|
+
- pattern-either:
|
|
66
|
+
- pattern: $REQ.getParameter(...)
|
|
67
|
+
- pattern: $REQ.getHeader(...)
|
|
68
|
+
- patterns:
|
|
69
|
+
- pattern-inside: |
|
|
70
|
+
$RET $METHOD(..., @RequestParam $T $PARAM, ...) {
|
|
71
|
+
...
|
|
72
|
+
}
|
|
73
|
+
- pattern: $PARAM
|
|
74
|
+
- patterns:
|
|
75
|
+
- pattern-inside: |
|
|
76
|
+
$RET $METHOD(..., @RequestParam(...) $T $PARAM, ...) {
|
|
77
|
+
...
|
|
78
|
+
}
|
|
79
|
+
- pattern: $PARAM
|
|
80
|
+
- patterns:
|
|
81
|
+
- pattern-inside: |
|
|
82
|
+
$RET $METHOD(..., @PathVariable $T $PARAM, ...) {
|
|
83
|
+
...
|
|
84
|
+
}
|
|
85
|
+
- pattern: $PARAM
|
|
86
|
+
- patterns:
|
|
87
|
+
- pattern-inside: |
|
|
88
|
+
$RET $METHOD(..., @PathVariable(...) $T $PARAM, ...) {
|
|
89
|
+
...
|
|
90
|
+
}
|
|
91
|
+
- pattern: $PARAM
|
|
92
|
+
pattern-sinks:
|
|
93
|
+
- patterns:
|
|
94
|
+
- pattern: $PARSER.parseExpression($SINK)
|
|
95
|
+
|
|
96
|
+
- id: narvy.java.spring.spel-injection.dynamic-expression-parsed
|
|
97
|
+
message: >-
|
|
98
|
+
A SpEL `ExpressionParser`/`SpelExpressionParser` evaluates a string
|
|
99
|
+
that is not a fixed literal in this call (it comes from a getter, a
|
|
100
|
+
method argument, a loop variable, or a field). SpEL grants full
|
|
101
|
+
reflection and static-method invocation once evaluated, so parsing
|
|
102
|
+
anything other than a compile-time-fixed expression is a code-injection
|
|
103
|
+
risk the moment that string can be influenced by a stored record, a
|
|
104
|
+
config value an admin (not a developer) can edit, or an upstream call
|
|
105
|
+
(CWE-94). Confirm the expression text is fully outside user/operator
|
|
106
|
+
reach, or stop building it dynamically.
|
|
107
|
+
severity: WARNING
|
|
108
|
+
languages: [java]
|
|
109
|
+
metadata:
|
|
110
|
+
category: security
|
|
111
|
+
cwe:
|
|
112
|
+
- "CWE-94: Improper Control of Generation of Code ('Code Injection')"
|
|
113
|
+
owasp:
|
|
114
|
+
- "A03:2021 - Injection"
|
|
115
|
+
subcategory: [audit]
|
|
116
|
+
likelihood: LOW
|
|
117
|
+
impact: HIGH
|
|
118
|
+
confidence: LOW
|
|
119
|
+
technology: [java, spring]
|
|
120
|
+
patterns:
|
|
121
|
+
- pattern-inside: |
|
|
122
|
+
...
|
|
123
|
+
$PARSERTYPE $PARSER = ...;
|
|
124
|
+
...
|
|
125
|
+
- metavariable-regex:
|
|
126
|
+
metavariable: $PARSERTYPE
|
|
127
|
+
regex: ^(SpelExpressionParser|ExpressionParser|TemplateAwareExpressionParser)$
|
|
128
|
+
- pattern: $PARSER.parseExpression($EXPR)
|
|
129
|
+
- pattern-not: $PARSER.parseExpression("...")
|
|
130
|
+
- pattern-not-inside: |
|
|
131
|
+
String $EXPR = "...";
|
|
132
|
+
...
|
|
133
|
+
|
|
134
|
+
- id: narvy.java.spring.spel-injection.dangerous-type-reference
|
|
135
|
+
message: >-
|
|
136
|
+
A hardcoded SpEL expression (parsed directly, or supplied via
|
|
137
|
+
`@Value(...)`) references `java.lang.Runtime` or
|
|
138
|
+
`java.lang.ProcessBuilder` through SpEL's `T(...)` type-reference
|
|
139
|
+
syntax. That is a working remote-code-execution gadget the moment this
|
|
140
|
+
expression string becomes reachable from outside the codebase - a
|
|
141
|
+
config value an operator can edit, a template an admin user can save,
|
|
142
|
+
or debug/test code left behind (CWE-94). Remove the type reference; if
|
|
143
|
+
process execution is genuinely needed, call `ProcessBuilder` directly
|
|
144
|
+
from Java code, not through an evaluated expression string.
|
|
145
|
+
severity: ERROR
|
|
146
|
+
languages: [java]
|
|
147
|
+
metadata:
|
|
148
|
+
category: security
|
|
149
|
+
cwe:
|
|
150
|
+
- "CWE-94: Improper Control of Generation of Code ('Code Injection')"
|
|
151
|
+
owasp:
|
|
152
|
+
- "A03:2021 - Injection"
|
|
153
|
+
subcategory: [vuln]
|
|
154
|
+
likelihood: LOW
|
|
155
|
+
impact: HIGH
|
|
156
|
+
confidence: HIGH
|
|
157
|
+
technology: [java, spring]
|
|
158
|
+
patterns:
|
|
159
|
+
- pattern-either:
|
|
160
|
+
- pattern: $PARSER.parseExpression($S)
|
|
161
|
+
- pattern: '@Value($S)'
|
|
162
|
+
- metavariable-regex:
|
|
163
|
+
metavariable: $S
|
|
164
|
+
regex: .*T\(\s*(java\.lang\.)?(Runtime|ProcessBuilder)\s*\).*
|
|
165
|
+
|
|
166
|
+
- id: narvy.java.spring.permissive-cors.crossorigin-wildcard-annotation
|
|
167
|
+
message: >-
|
|
168
|
+
`@CrossOrigin` allows every origin (`"*"`, or no `origins` value at
|
|
169
|
+
all, which also defaults to allow-all). Any website can now make
|
|
170
|
+
cross-origin requests to this endpoint from a victim's browser and read
|
|
171
|
+
the response, defeating the same-origin policy that protects
|
|
172
|
+
session-cookie-authenticated users from other sites reading their data
|
|
173
|
+
(CWE-942). Name the exact origins that need access instead of `"*"`.
|
|
174
|
+
severity: WARNING
|
|
175
|
+
languages: [java]
|
|
176
|
+
metadata:
|
|
177
|
+
category: security
|
|
178
|
+
cwe:
|
|
179
|
+
- "CWE-942: Permissive Cross-domain Policy with Untrusted Domains"
|
|
180
|
+
owasp:
|
|
181
|
+
- "A05:2021 - Security Misconfiguration"
|
|
182
|
+
subcategory: [audit]
|
|
183
|
+
likelihood: LOW
|
|
184
|
+
impact: MEDIUM
|
|
185
|
+
confidence: MEDIUM
|
|
186
|
+
technology: [java, spring]
|
|
187
|
+
patterns:
|
|
188
|
+
- pattern-either:
|
|
189
|
+
- pattern: '@CrossOrigin(origins = "*")'
|
|
190
|
+
- pattern: '@CrossOrigin(origins = {"*"})'
|
|
191
|
+
- pattern: '@CrossOrigin("*")'
|
|
192
|
+
|
|
193
|
+
- id: narvy.java.spring.permissive-cors.corsconfiguration-wildcard
|
|
194
|
+
message: >-
|
|
195
|
+
A `CorsConfiguration` allows every origin (`"*"`, or the equivalent
|
|
196
|
+
`addAllowedOriginPattern("*")`/wildcard `CorsConfigurationSource`).
|
|
197
|
+
Any website can now make cross-origin requests to this application
|
|
198
|
+
from a victim's browser (CWE-942). Build the allowed-origins list from
|
|
199
|
+
a fixed set of known-good hosts instead of a wildcard.
|
|
200
|
+
severity: WARNING
|
|
201
|
+
languages: [java]
|
|
202
|
+
metadata:
|
|
203
|
+
category: security
|
|
204
|
+
cwe:
|
|
205
|
+
- "CWE-942: Permissive Cross-domain Policy with Untrusted Domains"
|
|
206
|
+
owasp:
|
|
207
|
+
- "A05:2021 - Security Misconfiguration"
|
|
208
|
+
subcategory: [audit]
|
|
209
|
+
likelihood: LOW
|
|
210
|
+
impact: MEDIUM
|
|
211
|
+
confidence: MEDIUM
|
|
212
|
+
technology: [java, spring]
|
|
213
|
+
patterns:
|
|
214
|
+
- pattern-either:
|
|
215
|
+
- pattern: $CFG.setAllowedOrigins(java.util.List.of("*"))
|
|
216
|
+
- pattern: $CFG.setAllowedOrigins(java.util.Arrays.asList("*"))
|
|
217
|
+
- pattern: $CFG.setAllowedOrigins(java.util.Collections.singletonList("*"))
|
|
218
|
+
- pattern: $CFG.addAllowedOrigin("*")
|
|
219
|
+
- pattern: $CFG.setAllowedOriginPatterns(java.util.List.of("*"))
|
|
220
|
+
- pattern: $CFG.addAllowedOriginPattern("*")
|
|
221
|
+
|
|
222
|
+
- id: narvy.java.spring.permissive-cors.corsconfiguration-wildcard-with-credentials
|
|
223
|
+
message: >-
|
|
224
|
+
This `CorsConfiguration` allows every origin AND allows credentials
|
|
225
|
+
(`setAllowCredentials(true)`). Combined, a malicious page on any site
|
|
226
|
+
can send the victim's session cookie/basic-auth header cross-origin and
|
|
227
|
+
read the authenticated response - the exact attack CORS's
|
|
228
|
+
credentialed-request checks exist to block (CWE-942). Most browsers
|
|
229
|
+
reject a literal `"*"` alongside `allowCredentials(true)` today, but a
|
|
230
|
+
reflected-origin implementation (echoing whatever `Origin` header the
|
|
231
|
+
caller sent) has the identical effect and does pass browser checks - if
|
|
232
|
+
this configuration reflects the request origin rather than using a
|
|
233
|
+
fixed allow-list, treat this as exploitable now.
|
|
234
|
+
severity: ERROR
|
|
235
|
+
languages: [java]
|
|
236
|
+
metadata:
|
|
237
|
+
category: security
|
|
238
|
+
cwe:
|
|
239
|
+
- "CWE-942: Permissive Cross-domain Policy with Untrusted Domains"
|
|
240
|
+
owasp:
|
|
241
|
+
- "A05:2021 - Security Misconfiguration"
|
|
242
|
+
subcategory: [vuln]
|
|
243
|
+
likelihood: MEDIUM
|
|
244
|
+
impact: HIGH
|
|
245
|
+
confidence: MEDIUM
|
|
246
|
+
technology: [java, spring]
|
|
247
|
+
patterns:
|
|
248
|
+
- pattern-inside: |
|
|
249
|
+
$CFGTYPE $CFG = ...;
|
|
250
|
+
...
|
|
251
|
+
$CFG.setAllowCredentials(true);
|
|
252
|
+
...
|
|
253
|
+
- pattern-either:
|
|
254
|
+
- pattern: $CFG.setAllowedOrigins(java.util.List.of("*"))
|
|
255
|
+
- pattern: $CFG.setAllowedOrigins(java.util.Arrays.asList("*"))
|
|
256
|
+
- pattern: $CFG.addAllowedOrigin("*")
|
|
257
|
+
- pattern: $CFG.setAllowedOriginPatterns(java.util.List.of("*"))
|
|
258
|
+
- pattern: $CFG.addAllowedOriginPattern("*")
|
|
259
|
+
|
|
260
|
+
- id: narvy.java.spring.permissive-cors.addcorsmapping-wildcard
|
|
261
|
+
message: >-
|
|
262
|
+
A `WebMvcConfigurer.addCorsMapping` registration allows every origin
|
|
263
|
+
(`"*"`, or omits `.allowedOrigins(...)` entirely, which also defaults
|
|
264
|
+
to allow-all). Any website can now make cross-origin requests to the
|
|
265
|
+
mapped paths from a victim's browser (CWE-942). Name the exact origins
|
|
266
|
+
that need access instead of `"*"`.
|
|
267
|
+
severity: WARNING
|
|
268
|
+
languages: [java]
|
|
269
|
+
metadata:
|
|
270
|
+
category: security
|
|
271
|
+
cwe:
|
|
272
|
+
- "CWE-942: Permissive Cross-domain Policy with Untrusted Domains"
|
|
273
|
+
owasp:
|
|
274
|
+
- "A05:2021 - Security Misconfiguration"
|
|
275
|
+
subcategory: [audit]
|
|
276
|
+
likelihood: LOW
|
|
277
|
+
impact: MEDIUM
|
|
278
|
+
confidence: MEDIUM
|
|
279
|
+
technology: [java, spring]
|
|
280
|
+
patterns:
|
|
281
|
+
- pattern-inside: |
|
|
282
|
+
class $CLASS implements WebMvcConfigurer {
|
|
283
|
+
...
|
|
284
|
+
public void addCorsMappings(CorsRegistry $REGISTRY) {
|
|
285
|
+
...
|
|
286
|
+
}
|
|
287
|
+
...
|
|
288
|
+
}
|
|
289
|
+
- pattern-either:
|
|
290
|
+
- pattern: $REGISTRY.addMapping(...).allowedOrigins("*")
|
|
291
|
+
- pattern: $MAPPING.allowedOrigins("*")
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
|
|
3
|
+
# Java SQL injection: JDBC, JPA/Hibernate, Spring JdbcTemplate, MyBatis.
|
|
4
|
+
|
|
5
|
+
- id: narvy.java.sqli.jdbc-statement-concat.jdbc-statement-concat
|
|
6
|
+
message: >-
|
|
7
|
+
A plain JDBC `Statement` executes a query string built with `+`
|
|
8
|
+
concatenation. `Statement` never parameterises, so any tainted value
|
|
9
|
+
reaching the concatenation is a direct SQL injection (CWE-89). Switch to
|
|
10
|
+
`PreparedStatement` with `?` placeholders and `setString`/`setInt`/etc.
|
|
11
|
+
severity: ERROR
|
|
12
|
+
languages: [java]
|
|
13
|
+
metadata:
|
|
14
|
+
category: security
|
|
15
|
+
cwe:
|
|
16
|
+
- "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
|
|
17
|
+
owasp:
|
|
18
|
+
- "A03:2021 - Injection"
|
|
19
|
+
subcategory: [vuln]
|
|
20
|
+
likelihood: HIGH
|
|
21
|
+
impact: HIGH
|
|
22
|
+
confidence: MEDIUM
|
|
23
|
+
technology: [java]
|
|
24
|
+
patterns:
|
|
25
|
+
- pattern-either:
|
|
26
|
+
- pattern: $STMT.executeQuery($A + $B)
|
|
27
|
+
- pattern: $STMT.executeUpdate($A + $B)
|
|
28
|
+
- pattern: $STMT.execute($A + $B)
|
|
29
|
+
- pattern-not: $STMT.executeQuery("..." + "...")
|
|
30
|
+
- pattern-not: $STMT.executeUpdate("..." + "...")
|
|
31
|
+
- pattern-not: $STMT.execute("..." + "...")
|
|
32
|
+
|
|
33
|
+
- id: narvy.java.sqli.jdbc-connection-createquery-concat.jdbc-connection-createquery-concat
|
|
34
|
+
message: >-
|
|
35
|
+
`Connection.prepareStatement(...)` is called with a SQL string built by
|
|
36
|
+
`+` concatenation. Building the query text via concatenation defeats the
|
|
37
|
+
protection `PreparedStatement` exists to provide, because the tainted
|
|
38
|
+
value is already part of the parsed SQL grammar by the time the driver
|
|
39
|
+
sees it (CWE-89). Keep the query text a fixed literal and bind values
|
|
40
|
+
with `?` + `setString`/`setInt`.
|
|
41
|
+
severity: ERROR
|
|
42
|
+
languages: [java]
|
|
43
|
+
metadata:
|
|
44
|
+
category: security
|
|
45
|
+
cwe:
|
|
46
|
+
- "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
|
|
47
|
+
owasp:
|
|
48
|
+
- "A03:2021 - Injection"
|
|
49
|
+
subcategory: [vuln]
|
|
50
|
+
likelihood: HIGH
|
|
51
|
+
impact: HIGH
|
|
52
|
+
confidence: MEDIUM
|
|
53
|
+
technology: [java]
|
|
54
|
+
patterns:
|
|
55
|
+
- pattern-either:
|
|
56
|
+
- pattern: $CONN.prepareStatement($A + $B)
|
|
57
|
+
- pattern: $CONN.prepareStatement($A + $B, ...)
|
|
58
|
+
- pattern-not: $CONN.prepareStatement("..." + "...")
|
|
59
|
+
- pattern-not: $CONN.prepareStatement("..." + "...", ...)
|
|
60
|
+
|
|
61
|
+
- id: narvy.java.sqli.jpa-createquery-concat.jpa-createquery-concat
|
|
62
|
+
message: >-
|
|
63
|
+
A JPA/Hibernate `EntityManager.createQuery(...)` or
|
|
64
|
+
`createNativeQuery(...)` builds JPQL/SQL by string concatenation. Even
|
|
65
|
+
JPQL is subject to injection when the WHERE clause, ORDER BY column, or
|
|
66
|
+
table name is built from tainted data this way (CWE-89). Use a named or
|
|
67
|
+
positional parameter (`:status`, `?1`) and `setParameter(...)` instead
|
|
68
|
+
of splicing the value into the query text.
|
|
69
|
+
severity: ERROR
|
|
70
|
+
languages: [java]
|
|
71
|
+
metadata:
|
|
72
|
+
category: security
|
|
73
|
+
cwe:
|
|
74
|
+
- "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
|
|
75
|
+
owasp:
|
|
76
|
+
- "A03:2021 - Injection"
|
|
77
|
+
subcategory: [vuln]
|
|
78
|
+
likelihood: HIGH
|
|
79
|
+
impact: HIGH
|
|
80
|
+
confidence: MEDIUM
|
|
81
|
+
technology: [java]
|
|
82
|
+
patterns:
|
|
83
|
+
- pattern-either:
|
|
84
|
+
- pattern: $EM.createQuery($A + $B)
|
|
85
|
+
- pattern: $EM.createNativeQuery($A + $B)
|
|
86
|
+
- pattern: $EM.createNativeQuery($A + $B, ...)
|
|
87
|
+
- pattern-not: $EM.createQuery("..." + "...")
|
|
88
|
+
- pattern-not: $EM.createNativeQuery("..." + "...")
|
|
89
|
+
- pattern-not: $EM.createNativeQuery("..." + "...", ...)
|
|
90
|
+
|
|
91
|
+
# Covers the variable-indirection shape (concatenation moved to a local) that the inline rule above misses.
|
|
92
|
+
- id: narvy.java.sqli.jpa-createquery-concat-var.jpa-createquery-concat-var
|
|
93
|
+
message: >-
|
|
94
|
+
The query string handed to `createQuery`/`createNativeQuery` was built
|
|
95
|
+
by string concatenation a few lines earlier and assigned to a local
|
|
96
|
+
variable. Moving the concatenation into a variable does not change
|
|
97
|
+
what reaches the database (CWE-89). Bind the value with
|
|
98
|
+
`setParameter(...)` instead.
|
|
99
|
+
severity: ERROR
|
|
100
|
+
languages: [java]
|
|
101
|
+
metadata:
|
|
102
|
+
category: security
|
|
103
|
+
cwe:
|
|
104
|
+
- "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
|
|
105
|
+
owasp:
|
|
106
|
+
- "A03:2021 - Injection"
|
|
107
|
+
subcategory: [vuln]
|
|
108
|
+
likelihood: HIGH
|
|
109
|
+
impact: HIGH
|
|
110
|
+
confidence: MEDIUM
|
|
111
|
+
technology: [java]
|
|
112
|
+
patterns:
|
|
113
|
+
- pattern-either:
|
|
114
|
+
- pattern: |
|
|
115
|
+
String $Q = $A + $B;
|
|
116
|
+
...
|
|
117
|
+
$EM.createQuery($Q, ...);
|
|
118
|
+
- pattern: |
|
|
119
|
+
String $Q = $A + $B;
|
|
120
|
+
...
|
|
121
|
+
$EM.createNativeQuery($Q, ...);
|
|
122
|
+
- pattern-not: |
|
|
123
|
+
String $Q = "..." + "...";
|
|
124
|
+
...
|
|
125
|
+
$EM.createQuery($Q, ...);
|
|
126
|
+
- pattern-not: |
|
|
127
|
+
String $Q = "..." + "...";
|
|
128
|
+
...
|
|
129
|
+
$EM.createNativeQuery($Q, ...);
|
|
130
|
+
|
|
131
|
+
- id: narvy.java.sqli.jpa-createquery-sprintf-var.jpa-createquery-sprintf-var
|
|
132
|
+
message: >-
|
|
133
|
+
A JPQL/native query string assembled with `String.format(...)` is passed
|
|
134
|
+
to `createQuery`/`createNativeQuery`. `String.format` does not escape
|
|
135
|
+
SQL metacharacters - a tainted format argument is a SQL injection the
|
|
136
|
+
same as direct concatenation would be (CWE-89). Use a bind parameter
|
|
137
|
+
instead of formatting the value into the query text.
|
|
138
|
+
severity: ERROR
|
|
139
|
+
languages: [java]
|
|
140
|
+
metadata:
|
|
141
|
+
category: security
|
|
142
|
+
cwe:
|
|
143
|
+
- "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
|
|
144
|
+
owasp:
|
|
145
|
+
- "A03:2021 - Injection"
|
|
146
|
+
subcategory: [vuln]
|
|
147
|
+
likelihood: MEDIUM
|
|
148
|
+
impact: HIGH
|
|
149
|
+
confidence: HIGH
|
|
150
|
+
technology: [java]
|
|
151
|
+
patterns:
|
|
152
|
+
- pattern-either:
|
|
153
|
+
- pattern: |
|
|
154
|
+
$Q = String.format($FMT, ...);
|
|
155
|
+
...
|
|
156
|
+
$EM.createQuery($Q);
|
|
157
|
+
- pattern: |
|
|
158
|
+
$Q = String.format($FMT, ...);
|
|
159
|
+
...
|
|
160
|
+
$EM.createNativeQuery($Q);
|
|
161
|
+
|
|
162
|
+
- id: narvy.java.sqli.jdbctemplate-concat.jdbctemplate-concat
|
|
163
|
+
message: >-
|
|
164
|
+
Spring `JdbcTemplate` is called with a SQL string built by `+`
|
|
165
|
+
concatenation instead of the `?` placeholder + args form. `JdbcTemplate`
|
|
166
|
+
only protects arguments passed through its own varargs binder; splicing
|
|
167
|
+
a value into the SQL text bypasses that entirely (CWE-89). Use
|
|
168
|
+
`jdbcTemplate.query("... WHERE id = ?", rowMapper, id)`.
|
|
169
|
+
severity: ERROR
|
|
170
|
+
languages: [java]
|
|
171
|
+
metadata:
|
|
172
|
+
category: security
|
|
173
|
+
cwe:
|
|
174
|
+
- "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
|
|
175
|
+
owasp:
|
|
176
|
+
- "A03:2021 - Injection"
|
|
177
|
+
subcategory: [vuln]
|
|
178
|
+
likelihood: HIGH
|
|
179
|
+
impact: HIGH
|
|
180
|
+
confidence: MEDIUM
|
|
181
|
+
technology: [java, spring]
|
|
182
|
+
patterns:
|
|
183
|
+
- pattern-either:
|
|
184
|
+
- pattern: $JT.query($A + $B, ...)
|
|
185
|
+
- pattern: $JT.queryForObject($A + $B, ...)
|
|
186
|
+
- pattern: $JT.queryForList($A + $B, ...)
|
|
187
|
+
- pattern: $JT.update($A + $B, ...)
|
|
188
|
+
- pattern: $JT.execute($A + $B)
|
|
189
|
+
- pattern-not: $JT.query("..." + "...", ...)
|
|
190
|
+
- pattern-not: $JT.queryForObject("..." + "...", ...)
|
|
191
|
+
- pattern-not: $JT.queryForList("..." + "...", ...)
|
|
192
|
+
- pattern-not: $JT.update("..." + "...", ...)
|
|
193
|
+
- pattern-not: $JT.execute("..." + "...")
|
|
194
|
+
|
|
195
|
+
- id: narvy.java.sqli.tainted-request-param-to-statement.tainted-request-param-to-statement
|
|
196
|
+
message: >-
|
|
197
|
+
A value read directly from the HTTP request (`getParameter`,
|
|
198
|
+
`getHeader`, `getQueryString`) reaches a `Statement`/`PreparedStatement`
|
|
199
|
+
SQL sink through a local variable, with no bind-parameter API in the
|
|
200
|
+
call. Even when the sink call itself is a `PreparedStatement`, if the
|
|
201
|
+
tainted value ends up as part of the SQL text (versus a bound `?`
|
|
202
|
+
argument) it is a SQL injection (CWE-89). Bind the value with
|
|
203
|
+
`setString`/`setInt`/etc; never build the SQL string from request data.
|
|
204
|
+
severity: WARNING
|
|
205
|
+
languages: [java]
|
|
206
|
+
metadata:
|
|
207
|
+
category: security
|
|
208
|
+
cwe:
|
|
209
|
+
- "CWE-89: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')"
|
|
210
|
+
owasp:
|
|
211
|
+
- "A03:2021 - Injection"
|
|
212
|
+
subcategory: [vuln]
|
|
213
|
+
likelihood: MEDIUM
|
|
214
|
+
impact: HIGH
|
|
215
|
+
confidence: MEDIUM
|
|
216
|
+
technology: [java]
|
|
217
|
+
mode: taint
|
|
218
|
+
pattern-sources:
|
|
219
|
+
- patterns:
|
|
220
|
+
- pattern-either:
|
|
221
|
+
- pattern: $REQ.getParameter(...)
|
|
222
|
+
- pattern: $REQ.getHeader(...)
|
|
223
|
+
- pattern: $REQ.getQueryString()
|
|
224
|
+
pattern-sinks:
|
|
225
|
+
- patterns:
|
|
226
|
+
- pattern-either:
|
|
227
|
+
- pattern: $STMT.executeQuery("..." + $SINK + "...")
|
|
228
|
+
- pattern: $STMT.executeQuery("..." + $SINK)
|
|
229
|
+
- pattern: $STMT.executeUpdate("..." + $SINK + "...")
|
|
230
|
+
- pattern: $STMT.execute("..." + $SINK + "...")
|
|
231
|
+
pattern-sanitizers:
|
|
232
|
+
- patterns:
|
|
233
|
+
- pattern: Integer.parseInt(...)
|
|
234
|
+
- patterns:
|
|
235
|
+
- pattern: Long.parseLong(...)
|