Skip to content

Commit 5c81264

Browse files
Googlercopybara-github
authored andcommitted
Patch Rewards Program submission for apache/struts#781
PiperOrigin-RevId: 704484456
1 parent 0c64b61 commit 5c81264

File tree

1 file changed

+118
-0
lines changed
  • patch-rewards-program/rewarded-patches/apache/struts

1 file changed

+118
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
---
2+
3+
### Improvement category
4+
5+
6+
#### Submission title
7+
8+
Intelligent allowlist based sandbox for OGNL evaluations within the Struts web framework
9+
10+
11+
#### Please select the best-matching category:
12+
13+
Improvement to privilege separation or sandboxing
14+
15+
16+
---
17+
18+
### Patch details
19+
20+
21+
#### Specify project (the scope is limited to the listed projects):
22+
23+
Popular web frameworks and libraries: Angular, Closure, Dart, Django, Dojo Foundation, Ember, GWT, Go, Jinja (Werkzeug, Flask), jQuery, Knockout, Polymer, Struts, Web2py, Wicket
24+
25+
26+
#### Project name
27+
28+
Apache Struts
29+
30+
31+
#### Patch name or short description
32+
33+
Intelligent allowlist based sandbox for OGNL evaluations within the Struts web framework
34+
35+
36+
#### Links to the diffs of the patch
37+
38+
https://github.com/apache/struts/pull/781 https://github.com/apache/struts/pull/791 https://github.com/apache/struts/pull/800 https://github.com/apache/struts/pull/826 https://github.com/apache/struts/pull/831 https://github.com/apache/struts/pull/832
39+
40+
41+
#### Complexity – select the option that best describes the patch's complexity:
42+
43+
High effort or complexity
44+
45+
46+
#### Impact – select the option that best describes the security impact of the patch:
47+
48+
Almost certain to prevent major vulnerabilities in the affected code
49+
50+
51+
#### Tell us more about the patch
52+
53+
Apache Struts has historically been plagued by the most critical vulnerabilities, often remote code executions. This is due to its use of OGNL, a powerful expression language, which enables many of its key features. Due to OGNL’s capabilities, if a bad actor is able to achieve arbitrary expression injection, it is often trivial to escalate to an RCE. Some previous framework design decisions also mean that exploitation paths are often introduced inadvertently by Struts-based web developers not familiar with the Struts framework’s inner workings.
54+
55+
OGNL expression injection based vulnerabilities in Struts have usually been achieved in 2 ways:
56+
1. By leveraging Struts’ parameter deserialization mechanism. This is an intended OGNL expression injection point for users, whereby DTO classes are populated with user/form data. The OGNL expressions used for this purpose are sanitised using a RegEx which limits the OGNL syntax capabilities. However, these expressions still prove dangerous as will be explained later.
57+
2. By exploiting a potential SSTI vulnerability (sometimes known as a double evaluation). In such a scenario, no RegEx based sanitisation takes place as internal OGNL evaluations are intended to leverage all OGNL syntax capabilities.
58+
59+
This patch submission addresses serious security concerns with both the parameter deserializing **intended** OGNL expression injection point, as well as any **unintended** injection points.
60+
61+
Struts already had a class exclusion list mechanism for evaluating OGNL expressions. Whilst this exclusion list contained the most obvious classes that could be used maliciously, it required proactive application-specific maintenance to ensure any sensitive application beans or library classes capable of privileged operations were included on this list. Often it might not be apparent that a certain class could pose a threat as an exploit gadget until an exploit had already occurred.
62+
63+
The most obvious solution here was to introduce a class allow list in place of the exclusion list. However, obtaining a list of all classes needed on such an allow list would prove an equally rigorous endeavour, and the aim here was to have this capability enabled by default for all Struts applications and minimise maintenance burden. Most Struts applications loaded their configuration from an XML file. By having a pre-populated allow list consisting of necessary Struts library classes and then supplementing it with relevant classes while loading a specific application’s XML configuration, the vast majority of classes needed for a fully functional Struts application could be achieved.
64+
65+
For most Struts applications, the only remaining classes that were missing
66+
from the allow list were their form submission DTO classes. Struts has the
67+
concept of Action classes which contains the business logic for serving and
68+
handling web pages, as well as any fields or nested classes to where form
69+
submission parameters can be deserialized. Struts' parameter
70+
deserialization mechanism can be used to set user-controlled data on ANY
71+
public member on the Action class. Given business logic cohabits this
72+
class, it becomes painfully easy to accidentally expose a sensitive
73+
application bean which is then completely open to user mutation.
74+
75+
Struts has never required the explicit declaration of methods/fields
76+
intended for parameter deserialization and thereby clearly separating them
77+
from other methods/fields in the Action class. There was previously an
78+
attempt to introduce such a mechanism
79+
(AnnotationParameterFilterInterceptor) but it was entirely optional, did
80+
not block parameters by default, and its field-based annotation mechanism
81+
was ineffective for many exploitable scenarios (such as a getter returning
82+
an object that doesn't correspond to a field).
83+
84+
Thus, in this patch I additionally introduce a method-based annotation
85+
which is used to explicitly declare parameter deserialization points,
86+
clearly marking the invocation path that OGNL takes. Any user attempt at
87+
setting a parameter value on a member not intended for deserialization will
88+
be discarded. This annotation mechanism synergises with the earlier
89+
introduced allow list. Using the annotations I could detect and load the
90+
final classes needed in the allow list, making it completely
91+
configuration-less for most Struts application developers. Even if OGNL
92+
expression injection via an SSTI is achieved (where most OGNL syntax
93+
capabilities are available to an attacker), there are now a very limited
94+
number of classes that can be invoked, if an access path even exists.
95+
96+
Implementing the overall patch required the use of numerous creative techniques and a deep understanding of the inner workings of both Struts and OGNL. I additionally dealt with complexities related to bean injection, as managed by the pre-release version of Guice bundled with Struts, and rectifying many existing bugs and suboptimal patterns. Please refer to the linked PRs and full diffs for further details.
97+
98+
In recent months, Atlassian’s Confluence Data Center, which is built upon Apache Struts, was subject to multiple Critical and High rated vulnerabilities. These were shown to have been completely preventable by the capabilities introduced in this patch. Specific PoCs and detailed explanations on how this patch would have thwarted these CVEs can be provided upon request.
99+
100+
Critical/High CVEs preventable by this patch:
101+
* CVE-2023-22515
102+
* CVE-2024-21672
103+
* CVE-2024-21673
104+
* CVE-2024-21674
105+
106+
I do believe this patch to be one of the greatest uplifts to Struts’ security posture since its inception. Whilst the Struts framework may be waning in popularity since its peak well over a decade ago, this patch ensures applications built upon Struts can be trusted to experience a much higher level of security. It is already available in test builds and will be officially released in the upcoming Struts 6.4.0 as an opt-in capability, and enabled by default in Struts 7.0.0.
107+
108+
---
109+
110+
### Credit
111+
112+
https://github.com/kusalk
113+
114+
---
115+
116+
### Reward Amount
117+
118+
$10000.00 -- complicated, high-impact improvements that almost certainly prevent major vulnerabilities in the affected code

0 commit comments

Comments
 (0)