[
https://issues.apache.org/jira/browse/AVRO-4313?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Ismaël Mejía updated AVRO-4313:
-------------------------------
Description:
When Avro generates Java classes from a schema, the value of the
{{javaAnnotation}} schema property is written *as-is* into the generated source
code. To keep this safe, {{SpecificCompiler}} validates each value with a
regular expression that is supposed to accept only a Java annotation shape: an
identifier optionally followed by a parameter list, e.g.
{code:java}
@Deprecated
@SuppressWarnings("unchecked")
{code}
The validation regex was too permissive. The part that matches a quoted string
(for example {{"unchecked"}}) allowed an *unescaped double-quote inside the
string body*. As a result, a single "string literal" could run past its
intended closing quote and absorb whatever followed it, while the value as a
whole still matched the "valid annotation" shape.
This means a crafted {{javaAnnotation}} value such as:
{code:java}
java.lang.SuppressWarnings("x") static { System.exit(1); }
@java.lang.SuppressWarnings("y")
{code}
passes validation and is emitted verbatim into the generated class — injecting
arbitrary declarations and a static initializer that runs when the class is
loaded.
h3. Impact
Anyone who can influence a schema's {{javaAnnotation}} property can inject
arbitrary Java into the generated (and subsequently compiled) sources.
h3. Fix
Tighten the string-literal grammar so its body may only contain recognized
escape sequences ({{\\ \" \n \t \f \b}}) or characters that are not a quote,
backslash, or line terminator. An unescaped quote now correctly ends the
literal, so injected trailing tokens no longer match and the value is rejected.
Line terminators (CR, LF, NEL, LS, PS) are also excluded so a value cannot
spill onto extra lines. Legitimate annotations
({{SuppressWarnings("unchecked")}}, {{Deprecated(forRemoval = true, since =
"forever")}}, and values with escaped quotes) continue to validate. A
regression test is added.
was:
The {{javaAnnotation}} validator in {{SpecificCompiler}} uses a regular
expression (\{{PATTERN_STRING}}) whose string-literal grammar accepts an
unescaped quote inside the literal body. As a result a single string literal
can extend past its intended closing quote and absorb arbitrary tokens, so a
crafted {{javaAnnotation}} value can full-match the {{IDENTIFIER(STRING)}}
shape while actually containing extra Java declarations. Because the record
template emits annotation values verbatim, such a value would be written
directly into the generated specific-record source.
This tightens the string-literal grammar so the body may only contain
recognized escape sequences or characters that are not a quote, backslash, or
line terminator. Legitimate annotation values (for example
{{{}SuppressWarnings("unchecked"){}}}, {{{}Deprecated(forRemoval = true, since
= "forever"){}}}, and values with escaped quotes) continue to validate. A
regression test is added.
Summary: [java] javaAnnotation values can inject arbitrary Java code
into generated sources (was: [java] Tighten javaAnnotation string-literal
validation in SpecificCompiler)
> [java] javaAnnotation values can inject arbitrary Java code into generated
> sources
> ----------------------------------------------------------------------------------
>
> Key: AVRO-4313
> URL: https://issues.apache.org/jira/browse/AVRO-4313
> Project: Apache Avro
> Issue Type: Bug
> Components: java
> Affects Versions: 1.11.5, 1.12.1
> Reporter: Ismaël Mejía
> Assignee: Ismaël Mejía
> Priority: Major
> Labels: pull-request-available
> Fix For: 1.13.0, 1.12.2
>
> Time Spent: 1h
> Remaining Estimate: 0h
>
> When Avro generates Java classes from a schema, the value of the
> {{javaAnnotation}} schema property is written *as-is* into the generated
> source code. To keep this safe, {{SpecificCompiler}} validates each value
> with a regular expression that is supposed to accept only a Java annotation
> shape: an identifier optionally followed by a parameter list, e.g.
> {code:java}
> @Deprecated
> @SuppressWarnings("unchecked")
> {code}
> The validation regex was too permissive. The part that matches a quoted
> string (for example {{"unchecked"}}) allowed an *unescaped double-quote
> inside the string body*. As a result, a single "string literal" could run
> past its intended closing quote and absorb whatever followed it, while the
> value as a whole still matched the "valid annotation" shape.
> This means a crafted {{javaAnnotation}} value such as:
> {code:java}
> java.lang.SuppressWarnings("x") static { System.exit(1); }
> @java.lang.SuppressWarnings("y")
> {code}
> passes validation and is emitted verbatim into the generated class —
> injecting arbitrary declarations and a static initializer that runs when the
> class is loaded.
> h3. Impact
> Anyone who can influence a schema's {{javaAnnotation}} property can inject
> arbitrary Java into the generated (and subsequently compiled) sources.
> h3. Fix
> Tighten the string-literal grammar so its body may only contain recognized
> escape sequences ({{\\ \" \n \t \f \b}}) or characters that are not a quote,
> backslash, or line terminator. An unescaped quote now correctly ends the
> literal, so injected trailing tokens no longer match and the value is
> rejected. Line terminators (CR, LF, NEL, LS, PS) are also excluded so a value
> cannot spill onto extra lines. Legitimate annotations
> ({{SuppressWarnings("unchecked")}}, {{Deprecated(forRemoval = true, since =
> "forever")}}, and values with escaped quotes) continue to validate. A
> regression test is added.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)