/** * @kind path-problem */ import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.dataflow.TaintTracking import codeql.dataflow.DataFlow class AllControllerMethod extends Method{ AllControllerMethod(){ exists(RefType rt | rt.getName().indexOf("Controller")>0 and this = rt.getACallable()) } } class MyBatisMapperXmlFile extends XmlFile{ //一个MyBaits Mapper XML MyBatisMapperXmlFile(){ count(XmlElement e | e = this.getAChild()) = 1 and this.getAChild().getName() = "mapper" } } class MyBatisMapperXmlElement extends XmlElement{ MyBatisMapperXmlElement(){this.getFile() instanceof MyBatisMapperXmlFile} string getValue(){result = this.getAChild*().allCharactersString().trim()} string getId(){result = this.getAttribute("id").getValue()} } class MyBatisMapperVulMethod extends Method{ MyBatisMapperVulMethod(){ exists(MyBatisMapperXmlElement mmxe| mmxe.getValue().indexOf("${")>0 and this.hasName(mmxe.getId()) and this.getDeclaringType().getASubtype*().getQualifiedName() = mmxe.getFile().getAChild().getAttribute("namespace").getValue() ) } } class MyTaintTrackingConfiguration extends TaintTracking::Configuration{ MyTaintTrackingConfiguration(){this = "MyTaintTrackingConfiguration"} override predicate isSource(DataFlow::Node source){ exists(Method method | method instanceof AllControllerMethod and source.asParameter() = method.getAParameter()) } override predicate isSink(DataFlow::Node sink){ exists(MethodCall call, MyBatisMapperXmlElement mmxe, string unsafeExpression | call.getMethod() instanceof MyBatisMapperVulMethod and unsafeExpression = mmxe.getValue().regexpFind("(\\$)\\{[^\\}]*\\}" ,_,_) and (sink.asExpr().toString() = unsafeExpression.substring(2,unsafeExpression.length()-1) or sink.asExpr().toString() = unsafeExpression.substring(2,unsafeExpression.length()-1).splitAt(".")) and sink.asExpr() = call.getAnArgument() ) } override predicate isAdditionalTaintStep(DataFlow::Node src, DataFlow::Node sink){ exists(MethodCall ma | ma.getMethod().getDeclaringType() instanceof TypeObject and ma.getMethod().getName() = "toString" and ma.getQualifier() = src.asExpr() and ma = sink.asExpr() ) } override predicate isSanitizer(DataFlow::Node node){ node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType or node.getType() instanceof NumberType } } from MyTaintTrackingConfiguration config, DataFlow::Node source, DataFlow::Node sink where config.hasFlowPath(source,sink) select source,sink,"sqlinject!"