版权声明:本文为博主原创文章,未经博主允许不得转载。
Struts2存在远程代码执行的严重漏洞,需要把Struts2的版本升级到2.3.32后,出现部分问题。
漏洞描述:
- 漏洞编号:S2-045,CVE-2017-5638
- 漏洞名称:基于Jakarta plugin插件的Struts远程代码执行漏洞
- 官方评级:高危
当把ognl-3.0.6的jar包升级ognl-3.0.19时,会出现部分变量(变量名称为单个小写字母开头紧跟大写字母的变量)无法注入问题,即变量对应的set和get方法无法找到。
经查源码发现,在ognl包中,类OgnlRuntime.java对其方法getDeclaredMethods做了部分修改,修改代码如下:
其中capitalizeBeanPropertyName方法的代码实现如下:
private static String capitalizeBeanPropertyName(String propertyName) {
if (propertyName.length() == 1) {
return propertyName.toUpperCase();
}
// don't capitalize getters/setters
if (propertyName.startsWith(GET_PREFIX) && propertyName.endsWith("()")) {
if (Character.isUpperCase(propertyName.substring(3,4).charAt(0))) {
return propertyName;
}
}
if (propertyName.startsWith(SET_PREFIX) && propertyName.endsWith(")")) {
if (Character.isUpperCase(propertyName.substring(3,4).charAt(0))) {
return propertyName;
}
}
if (propertyName.startsWith(IS_PREFIX) && propertyName.endsWith("()")) {
if (Character.isUpperCase(propertyName.substring(2,3).charAt(0))) {
return propertyName;
}
}
char first = propertyName.charAt(0);
char second = propertyName.charAt(1);
if (Character.isLowerCase(first) && Character.isUpperCase(second)) {
return propertyName;
} else {
char[] chars = propertyName.toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
return new String(chars);
}
}
而原先ognl-3.0.6包下的实现为
String baseName = Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1);
可以发现无法注入问题由于capitalizeBeanPropertyName方法对变量名称为单个小写字母开头紧跟大写字母的变量没有做首字母转换为大写引起。
修复此问题,有两种方法。
第一种方法:可以将capitalizeBeanPropertyName方法进行修改,修改后的代码如下:
private static String capitalizeBeanPropertyName(String propertyName) {
if (propertyName.length() == 1) {
return propertyName.toUpperCase();
}
// don't capitalize getters/setters
if (propertyName.startsWith(GET_PREFIX) && propertyName.endsWith("()")) {
if (Character.isUpperCase(propertyName.substring(3,4).charAt(0))) {
return propertyName;
}
}
if (propertyName.startsWith(SET_PREFIX) && propertyName.endsWith(")")) {
if (Character.isUpperCase(propertyName.substring(3,4).charAt(0))) {
return propertyName;
}
}
if (propertyName.startsWith(IS_PREFIX) && propertyName.endsWith("()")) {
if (Character.isUpperCase(propertyName.substring(2,3).charAt(0))) {
return propertyName;
}
}
// char first = propertyName.charAt(0);
// char second = propertyName.charAt(1);
// if (Character.isLowerCase(first) && Character.isUpperCase(second)) {
// return propertyName;
// } else {
char[] chars = propertyName.toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
return new String(chars);
// }
}
第二种方法:修改变量名称为java标准规范写法,特别注意不要使用单个小写字母开头紧跟大写字母的变量,对应的set和get方法都得跟着改变。
另附ognl-3.0.6和ognl-3.0.19以及修改后的类OgnlRuntime.java的资源路径: