Browse Source

REPORT-56220 数据连接越权漏洞修复

bugfix/11.0
Henry.Wang 3 years ago
parent
commit
69d6de2bcd
  1. 7
      designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java
  2. 8
      designer-base/src/main/java/com/fr/design/mainframe/authority/DSColumnAuthorityChecker.java
  3. 25
      designer-base/src/main/java/com/fr/design/mainframe/authority/ElementAuthorityChecker.java
  4. 23
      designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java
  5. 121
      designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java
  6. 7
      designer-base/src/main/java/com/fr/design/mainframe/authority/NameDatabaseConnectionAuthorityChecker.java
  7. 7
      designer-base/src/main/java/com/fr/design/mainframe/authority/NameTableDataAuthorityChecker.java

7
designer-base/src/main/java/com/fr/design/mainframe/JTemplate.java

@ -1551,7 +1551,8 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
}
private boolean saveRealFile() throws Exception {
if (new JTemplateAuthorityChecker(this).isAuthority()) {
JTemplateAuthorityChecker jTemplateAuthorityChecker = new JTemplateAuthorityChecker(this);
if (jTemplateAuthorityChecker.isAuthority()) {
FILE editingFILE = this.getEditingFILE();
if (editingFILE == null || editingFILE instanceof MemFILE) {
return false;
@ -1559,8 +1560,10 @@ public abstract class JTemplate<T extends BaseBook, U extends BaseUndoState<?>>
this.getTarget().export(TemplateResourceManager.getResource().saveTemplate(editingFILE));
this.editingFILE = editingFILE;
return true;
} else {
jTemplateAuthorityChecker.showAuthorityFailPromptDialog();
return false;
}
return false;
}
private CallbackSaveWorker saveAs(boolean showLoc) {

8
designer-base/src/main/java/com/fr/design/mainframe/authority/DSColumnAuthorityChecker.java

@ -1,16 +1,18 @@
package com.fr.design.mainframe.authority;
import com.fr.report.cell.cellattr.core.group.DSColumn;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class DSColumnAuthorityChecker extends ElementAuthorityChecker<DSColumn> {
@Override
String checkDatasetName(DSColumn dsColumn, Set<String> authDatasetNames) {
Set<String> getNoAuthDatasetNames(DSColumn dsColumn, Set<String> authDatasetNames) {
if (!authDatasetNames.contains(dsColumn.getDSName())) {
return dsColumn.getDSName();
return new HashSet<>(Arrays.asList(dsColumn.getDSName()));
}
return null;
}
}

25
designer-base/src/main/java/com/fr/design/mainframe/authority/ElementAuthorityChecker.java

@ -7,17 +7,34 @@ import java.util.Set;
public abstract class ElementAuthorityChecker<T> {
//检查是否有越权的数据连接,如果有返回名称,没有返回null
String checkConnectionName(T t, Set<String> authConnectionNames) {
/**
* @Description 获取越权的数据连接
* @param: t 待检查的对象
* @param: authConnectionNames 有权限的数据连接名
* @return 如果有返回名称没有返回null
*/
Set<String> getNoAuthConnectionNames(T t, Set<String> authConnectionNames) {
return null;
}
//检查是否有越权的服务器数据集,如果有返回名称,没有返回null
String checkDatasetName(T t, Set<String> authDatasetNames) {
/**
* @Description 获取越权的服务器数据集
* @param: t 待检查的对象
* @param: authDatasetNames 有权限的服务器数据集名
* @return 如果有返回名称没有返回null
*/
Set<String> getNoAuthDatasetNames(T t, Set<String> authDatasetNames) {
return null;
}
//要检查对象的className
/**
* @Description 要检查对象的className
* @return className
*/
String getCheckClassName() {
ParameterizedTypeImpl parameterizedType = (ParameterizedTypeImpl) this.getClass().getGenericSuperclass();
Type type = parameterizedType.getActualTypeArguments()[0];

23
designer-base/src/main/java/com/fr/design/mainframe/authority/FormulaAuthorityChecker.java

@ -1,26 +1,23 @@
package com.fr.design.mainframe.authority;
import com.fr.base.Formula;
import com.fr.parser.FunctionCall;
import com.fr.parser.StringLiteral;
import com.fr.script.Calculator;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class FormulaAuthorityChecker extends ElementAuthorityChecker<Formula> {
@Override
public String checkConnectionName(Formula formula, Set<String> authConnectionNames) {
public Set<String> getNoAuthConnectionNames(Formula formula, Set<String> authConnectionNames) {
String content = formula.getContent();
try {
FunctionCall functionCall = (FunctionCall) Calculator.createCalculator().parse(content).getConditionalExpression();
StringLiteral stringLiteral = (StringLiteral) functionCall.getArguments()[0];
String connectionName = (String) Calculator.createCalculator().evalValue(stringLiteral);
if (!authConnectionNames.contains(connectionName)) {
return connectionName;
Pattern pattern = Pattern.compile("^=SQL\\(\"(.+?)\",");
Matcher matcher = pattern.matcher(content);
if (matcher.find()) {
if (!authConnectionNames.contains(matcher.group(1))) {
return new HashSet<>(Arrays.asList(matcher.group(1)));
}
} catch (Exception ignore) {
}
return null;
}

121
designer-base/src/main/java/com/fr/design/mainframe/authority/JTemplateAuthorityChecker.java

@ -6,9 +6,13 @@ import com.fr.design.dialog.FineJOptionPane;
import com.fr.design.i18n.Toolkit;
import com.fr.design.mainframe.DesignerContext;
import com.fr.design.mainframe.JTemplate;
import com.fr.design.mod.ModClassFilter;
import com.fr.invoke.ClassHelper;
import com.fr.log.FineLoggerFactory;
import com.fr.rpc.ExceptionHandler;
import com.fr.rpc.RPCInvokerExceptionInfo;
import com.fr.stable.Filter;
import com.fr.workspace.WorkContext;
import com.fr.workspace.server.authority.user.UserAuthority;
@ -42,15 +46,17 @@ public class JTemplateAuthorityChecker {
private void initAuthNames() {
UserAuthority templateAuthority = WorkContext.getCurrent().get(UserAuthority.class);
Map<String, Set<String>> allAuthNames = templateAuthority.getAuthServerDataSetAndConnectionNames();
//有权限的数据连接名称
authConnectionNames = allAuthNames.get(UserAuthority.AUTH_CONNECTION_NAMES);
//有权限的数据集名称(模板数据集和服务器数据集)
authDatasetNames = allAuthNames.get(UserAuthority.AUTH_SERVER_DATASET_NAMES);
Iterator<String> iterator = jTemplate.getTarget().getTableDataNameIterator();
while (iterator.hasNext()) {
String datasetName = iterator.next();
authDatasetNames.add(datasetName);
Map<String, Set<String>> authNamesMap = templateAuthority.getAuthServerDataSetAndConnectionNames();
if (authNamesMap != null) {
//有权限的数据连接名称
authConnectionNames = authNamesMap.get(UserAuthority.AUTH_CONNECTION_NAMES);
//有权限的数据集名称(模板数据集和服务器数据集)
authDatasetNames = authNamesMap.get(UserAuthority.AUTH_SERVER_DATASET_NAMES);
Iterator<String> iterator = jTemplate.getTarget().getTableDataNameIterator();
while (iterator.hasNext()) {
String datasetName = iterator.next();
authDatasetNames.add(datasetName);
}
}
}
@ -69,55 +75,39 @@ public class JTemplateAuthorityChecker {
public boolean isAuthority() {
long s = System.currentTimeMillis();
//遍历模板对象,根据checkerMap.keySet()把感兴趣的对象找出来
Map<String, Collection<Object>> targetObjects = ClassHelper.searchObject(jTemplate.getTarget(), checkerMap.keySet());
Map<String, Collection<Object>> targetObjects = ClassHelper.searchObject(jTemplate.getTarget(), checkerMap.keySet(), ClassFilter.getInstance());
//找到对应的checker,对对象进行检查
for (String name : targetObjects.keySet()) {
ElementAuthorityChecker checker = checkerMap.get(name);
for (Object object : targetObjects.get(name)) {
String authFailName = checker.checkConnectionName(object, authConnectionNames);
if (authFailName != null) {
authFailConnectionNames.add(authFailName);
if (authConnectionNames != null) {
Set<String> noAuthName = checker.getNoAuthConnectionNames(object, authConnectionNames);
if (noAuthName != null) {
authFailConnectionNames.addAll(noAuthName);
}
}
authFailName = checker.checkDatasetName(object, authDatasetNames);
if (authFailName != null) {
authFailDatasetNames.add(authFailName);
if (authDatasetNames != null) {
Set<String> noAuthName = checker.getNoAuthDatasetNames(object, authDatasetNames);
if (noAuthName != null) {
authFailDatasetNames.addAll(noAuthName);
}
}
}
}
FineLoggerFactory.getLogger().info("JTemplateAuthorityChecker check time consume:" + (System.currentTimeMillis() - s));
if (authFailConnectionNames.size() == 0 && authFailDatasetNames.size() == 0) {
return true;
} else {
//如果存在越权的,弹出弹框,并返回false
authorityFailPrompt();
return false;
}
return authFailConnectionNames.size() == 0 && authFailDatasetNames.size() == 0;
}
private void authorityFailPrompt() {
public void showAuthorityFailPromptDialog() {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(Toolkit.i18nText("Fine-Design-Basic_Save_Failure"));
stringBuffer.append("\n");
if (authFailDatasetNames.size() > 0) {
stringBuffer.append(Toolkit.i18nText("Fine-Design_Template_Authority_Check_Current_Operator_Miss"));
stringBuffer.append(authFailDatasetNames.size());
stringBuffer.append(Toolkit.i18nText("Fine-Design_Report_Ge"));
stringBuffer.append(Toolkit.i18nText("Fine-Design_Template_Authority_Check_Server_Dataset_Authority"));
stringBuffer.append("\n");
stringBuffer.append(getNoAuthNameSequence(authFailDatasetNames));
}
if (authFailConnectionNames.size() > 0) {
stringBuffer.append(Toolkit.i18nText("Fine-Design_Template_Authority_Check_Current_Operator_Miss"));
stringBuffer.append(authFailConnectionNames.size());
stringBuffer.append(Toolkit.i18nText("Fine-Design_Report_Ge"));
stringBuffer.append(Toolkit.i18nText("Fine-Design_Template_Authority_Check_Data_Connection_Authority"));
stringBuffer.append("\n");
stringBuffer.append(getNoAuthNameSequence(authFailConnectionNames));
}
stringBuffer.append(getPromptInfo(authFailDatasetNames,
Toolkit.i18nText("Fine-Design_Template_Authority_Check_Server_Dataset_Authority")));
stringBuffer.append(getPromptInfo(authFailConnectionNames,
Toolkit.i18nText("Fine-Design_Template_Authority_Check_Data_Connection_Authority")));
FineJOptionPane.showMessageDialog(
DesignerContext.getDesignerFrame(),
stringBuffer.toString(),
@ -125,6 +115,19 @@ public class JTemplateAuthorityChecker {
WARNING_MESSAGE);
}
private String getPromptInfo(Set<String> authFailNames, String message) {
StringBuffer stringBuffer = new StringBuffer();
if (authFailNames.size() > 0) {
stringBuffer.append(Toolkit.i18nText("Fine-Design_Template_Authority_Check_Current_Operator_Miss"));
stringBuffer.append(authFailNames.size());
stringBuffer.append(Toolkit.i18nText("Fine-Design_Report_Ge"));
stringBuffer.append(message);
stringBuffer.append("\n");
stringBuffer.append(getNoAuthNameSequence(authFailNames));
}
return stringBuffer.toString();
}
private String getNoAuthNameSequence(Set<String> names) {
StringBuffer stringBuffer = new StringBuffer();
int showMaxCount = 3;
@ -143,5 +146,39 @@ public class JTemplateAuthorityChecker {
stringBuffer.append("\n");
return stringBuffer.toString();
}
static class ClassFilter implements Filter<String> {
private static final Set<String> FILTER_SET = new HashSet<>();
private static final Set<String> START_WITH_SET = new HashSet<>();
private static final Filter<String> INSTANCE = new ModClassFilter();
public static Filter<String> getInstance() {
return INSTANCE;
}
static {
FILTER_SET.add("java.awt.image.BufferedImage");
FILTER_SET.add("sun.awt.AppContext");
FILTER_SET.add("com.fr.poly.creator.ECBlockCreator");
FILTER_SET.add("io.netty.channel.nio.SelectedSelectionKeySet");
FILTER_SET.add("com.fr.form.ui.ElementCaseImage");
FILTER_SET.add("this$0");
START_WITH_SET.add("com.fr.design");
}
@Override
public boolean accept(String s) {
if (FILTER_SET.contains(s)) {
return true;
}
for (String start : START_WITH_SET) {
if (s.startsWith(start)) {
return true;
}
}
return false;
}
}
}

7
designer-base/src/main/java/com/fr/design/mainframe/authority/NameDatabaseConnectionAuthorityChecker.java

@ -2,14 +2,17 @@ package com.fr.design.mainframe.authority;
import com.fr.data.impl.NameDatabaseConnection;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
public class NameDatabaseConnectionAuthorityChecker extends ElementAuthorityChecker<NameDatabaseConnection> {
@Override
String checkConnectionName(NameDatabaseConnection nameDatabaseConnection, Set<String> authConnectionNames) {
Set<String> getNoAuthConnectionNames(NameDatabaseConnection nameDatabaseConnection, Set<String> authConnectionNames) {
String name = nameDatabaseConnection.getName();
if (!authConnectionNames.contains(name)) {
return name;
return new HashSet<>(Arrays.asList(name));
}
return null;
}

7
designer-base/src/main/java/com/fr/design/mainframe/authority/NameTableDataAuthorityChecker.java

@ -2,15 +2,16 @@ package com.fr.design.mainframe.authority;
import com.fr.data.impl.NameTableData;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class NameTableDataAuthorityChecker extends ElementAuthorityChecker<NameTableData> {
@Override
String checkDatasetName(NameTableData nameTableData, Set<String> authDatasetNames) {
Set<String> getNoAuthDatasetNames(NameTableData nameTableData, Set<String> authDatasetNames) {
if (!authDatasetNames.contains(nameTableData.getName())) {
return nameTableData.getName();
return new HashSet<>(Arrays.asList(nameTableData.getName()));
}
return null;
}
}

Loading…
Cancel
Save