org.sonar.java.checks.security.SecureXmlTransformerCheck Maven / Gradle / Ivy
/*
* SonarQube Java
* Copyright (C) 2012-2018 SonarSource SA
* mailto:info AT sonarsource DOT com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.java.checks.security;
import java.util.Collections;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.xml.XMLConstants;
import javax.xml.transform.TransformerFactory;
import org.sonar.check.Rule;
import org.sonar.java.checks.methods.AbstractMethodDetection;
import org.sonar.java.matcher.MethodMatcher;
import org.sonar.java.model.LiteralUtils;
import org.sonar.plugins.java.api.tree.Arguments;
import org.sonar.plugins.java.api.tree.BaseTreeVisitor;
import org.sonar.plugins.java.api.tree.MethodInvocationTree;
import org.sonar.plugins.java.api.tree.Tree;
import org.sonar.plugins.java.api.tree.Tree.Kind;
import static org.sonar.java.checks.helpers.ConstantUtils.resolveAsStringConstant;
import static org.sonar.java.matcher.TypeCriteria.subtypeOf;
@Rule(key = "S4435")
public class SecureXmlTransformerCheck extends AbstractMethodDetection {
private static final String TRANSFORMER_FACTORY_CLASS_NAME = TransformerFactory.class.getName();
@Override
protected List getMethodInvocationMatchers() {
return Collections.singletonList(
MethodMatcher.create()
.typeDefinition(subtypeOf(TRANSFORMER_FACTORY_CLASS_NAME))
.name("newInstance")
.withAnyParameters());
}
@Override
protected void onMethodInvocationFound(MethodInvocationTree methodInvocation) {
Tree enclosingMethod = enclosingMethod(methodInvocation);
if (enclosingMethod == null) {
return;
}
MethodBodyVisitor visitor = new MethodBodyVisitor();
enclosingMethod.accept(visitor);
if (!visitor.foundCallsToSecuringMethods()) {
reportIssue(methodInvocation.methodSelect(), "Secure this \"Transformer\" by either disabling external DTDs or enabling secure processing.");
}
}
@CheckForNull
private static Tree enclosingMethod(Tree tree) {
Tree parent = tree.parent();
while (!parent.is(Kind.CLASS, Kind.METHOD)) {
parent = parent.parent();
}
if (parent.is(Kind.CLASS)) {
return null;
}
return parent;
}
private static class MethodBodyVisitor extends BaseTreeVisitor {
private static final MethodMatcher SET_FEATURE =
MethodMatcher.create()
.typeDefinition(subtypeOf(TRANSFORMER_FACTORY_CLASS_NAME))
.name("setFeature")
.parameters("java.lang.String", "boolean");
private static final MethodMatcher SET_ATTRIBUTE =
MethodMatcher.create()
.typeDefinition(subtypeOf(TRANSFORMER_FACTORY_CLASS_NAME))
.name("setAttribute")
.parameters("java.lang.String", "java.lang.Object");
private boolean hasSecureProcessingFeature = false;
private boolean hasSecuredExternalDtd = false;
private boolean hasSecuredExternalStylesheet = false;
private boolean foundCallsToSecuringMethods() {
return hasSecureProcessingFeature || (hasSecuredExternalDtd && hasSecuredExternalStylesheet);
}
@Override
public void visitMethodInvocation(MethodInvocationTree methodInvocation) {
Arguments arguments = methodInvocation.arguments();
if (SET_FEATURE.matches(methodInvocation)
&& XMLConstants.FEATURE_SECURE_PROCESSING.equals(resolveAsStringConstant(arguments.get(0)))
&& LiteralUtils.isTrue(arguments.get(1))) {
hasSecureProcessingFeature = true;
}
if (SET_ATTRIBUTE.matches(methodInvocation)) {
String attributeName = resolveAsStringConstant(arguments.get(0));
String attributeValue = resolveAsStringConstant(arguments.get(1));
if ("".equals(attributeValue)) {
if (XMLConstants.ACCESS_EXTERNAL_DTD.equals(attributeName)) {
hasSecuredExternalDtd = true;
} else if (XMLConstants.ACCESS_EXTERNAL_STYLESHEET.equals(attributeName)) {
hasSecuredExternalStylesheet = true;
}
}
}
super.visitMethodInvocation(methodInvocation);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy