|
4 | 4 |
|
5 | 5 | import java |
6 | 6 | import semmle.code.java.dataflow.ExternalFlow |
| 7 | +private import semmle.code.java.dataflow.DataFlow |
| 8 | +private import semmle.code.java.dataflow.TaintTracking |
7 | 9 |
|
8 | 10 | /** The class `org.apache.ibatis.jdbc.SqlRunner`. */ |
9 | 11 | class MyBatisSqlRunner extends RefType { |
@@ -104,38 +106,93 @@ class TypeParam extends Interface { |
104 | 106 | } |
105 | 107 |
|
106 | 108 | module ProviderInjection { |
107 | | - private import semmle.code.java.dataflow.DataFlow |
| 109 | + private class MyBatisAbstractSQL extends RefType { |
| 110 | + MyBatisAbstractSQL() { this.hasQualifiedName("org.apache.ibatis.jdbc", "AbstractSQL") } |
| 111 | + } |
| 112 | + |
| 113 | + private class MyBatisProvider extends RefType { |
| 114 | + MyBatisProvider() { |
| 115 | + this.hasQualifiedName("org.apache.ibatis.annotations", |
| 116 | + ["Select", "Delete", "Insert", "Update"] + "Provider") |
| 117 | + } |
| 118 | + } |
| 119 | + |
| 120 | + private class MyBatisAbstractSQLMethodNames extends string { |
| 121 | + MyBatisAbstractSQLMethodNames() { |
| 122 | + this in [ |
| 123 | + "SELECT", "OFFSET_ROWS", "FETCH_FIRST_ROWS_ONLY", "OFFSET", "LIMIT", "ORDER_BY", "HAVING", |
| 124 | + "GROUP_BY", "WHERE", "OUTER_JOIN", "RIGHT_OUTER_JOIN", "LEFT_OUTER_JOIN", "INNER_JOIN", |
| 125 | + "JOIN", "FROM", "DELETE_FROM", "SELECT_DISTINCT", "SELECT", "INTO_VALUES", "INTO_COLUMNS", |
| 126 | + "VALUES", "INSERT_INTO", "SET", "UPDATE" |
| 127 | + ] |
| 128 | + } |
| 129 | + } |
108 | 130 |
|
109 | 131 | class MyBatisInjectionSink extends DataFlow::Node { |
110 | 132 | MyBatisInjectionSink() { |
111 | 133 | exists(Annotation a, Method m, TypeLiteral type, Class c | |
112 | | - a.getType() |
113 | | - .hasQualifiedName("org.apache.ibatis.annotations", |
114 | | - ["Select", "Delete", "Insert", "Update"] + "Provider") and |
| 134 | + a.getType() instanceof MyBatisProvider and |
115 | 135 | type = a.getValue(["type", "value"]) and |
116 | 136 | c.hasMethod(m, type.getTypeName().getType()) and |
117 | | - m.hasName(a.getTarget().getName()) and |
| 137 | + m.hasName(a.getValue("method").(StringLiteral).getValue()) and |
118 | 138 | this.asExpr() = m.getBody().getAStmt().(ReturnStmt).getResult() |
119 | 139 | ) |
120 | 140 | } |
121 | 141 | } |
122 | 142 |
|
123 | | - class MyBatisAbstractSQLStep extends Unit { |
124 | | - predicate step(DataFlow::Node node1, DataFlow::Node node2) { |
| 143 | + class MyBatisAdditionalTaintStep extends TaintTracking::AdditionalTaintStep { |
| 144 | + abstract override predicate step(DataFlow::Node node1, DataFlow::Node node2); |
| 145 | + } |
| 146 | + |
| 147 | + private class MyBatisProviderStep extends MyBatisAdditionalTaintStep { |
| 148 | + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { |
| 149 | + exists( |
| 150 | + MethodAccess ma, Annotation a, Method annotatedMethod, Method providerMethod, |
| 151 | + TypeLiteral type, Class c |
| 152 | + | |
| 153 | + a.getType() instanceof MyBatisProvider and |
| 154 | + annotatedMethod.getAnAnnotation() = a and |
| 155 | + ma.getMethod() = annotatedMethod and |
| 156 | + ma.getAnArgument() = n1.asExpr() and |
| 157 | + type = a.getValue(["type", "value"]) and |
| 158 | + providerMethod.hasName(a.getValue("method").(StringLiteral).getValue()) and |
| 159 | + c.hasMethod(providerMethod, type.getTypeName().getType()) and |
| 160 | + providerMethod.getAParameter() = n2.asParameter() |
| 161 | + ) |
| 162 | + } |
| 163 | + } |
| 164 | + |
| 165 | + private class MyBatisAbstractSQLToStringStep extends MyBatisAdditionalTaintStep { |
| 166 | + override predicate step(DataFlow::Node node1, DataFlow::Node node2) { |
| 167 | + exists(MethodAccess ma | |
| 168 | + ma.getMethod().getDeclaringType().getSourceDeclaration() instanceof MyBatisAbstractSQL and |
| 169 | + ma.getMethod().getName() = "toString" and |
| 170 | + ma.getQualifier() = node1.asExpr() and |
| 171 | + ma = node2.asExpr() |
| 172 | + ) |
| 173 | + } |
| 174 | + } |
| 175 | + |
| 176 | + private class MyBatisAbstractSQLMethodsStep extends MyBatisAdditionalTaintStep { |
| 177 | + override predicate step(DataFlow::Node node1, DataFlow::Node node2) { |
125 | 178 | exists(MethodAccess ma | |
126 | | - ma.getMethod() |
127 | | - .getDeclaringType() |
128 | | - .hasQualifiedName("org.apache.ibatis.jdbc", ["AbstractSQL", "AbstractSQL<SQL>"]) and |
129 | | - ma.getMethod() |
130 | | - .hasName([ |
131 | | - "SELECT", "OFFSET_ROWS", "FETCH_FIRST_ROWS_ONLY", "OFFSET", "LIMIT", "ORDER_BY", |
132 | | - "HAVING", "GROUP_BY", "WHERE", "OUTER_JOIN", "RIGHT_OUTER_JOIN", "LEFT_OUTER_JOIN", |
133 | | - "INNER_JOIN", "JOIN", "FROM", "DELETE_FROM", "SELECT_DISTINCT", "SELECT", |
134 | | - "INTO_VALUES", "INTO_COLUMNS", "VALUES", "INSERT_INTO", "SET", "UPDATE" |
135 | | - ]) and |
| 179 | + ma.getMethod().getDeclaringType().getSourceDeclaration() instanceof MyBatisAbstractSQL and |
| 180 | + ma.getMethod().getName() instanceof MyBatisAbstractSQLMethodNames and |
136 | 181 | ma.getArgument([0, 1]) = node1.asExpr() and |
137 | 182 | ma = node2.asExpr() |
138 | 183 | ) |
139 | 184 | } |
140 | 185 | } |
| 186 | + |
| 187 | + private class MyBatisAbstractSQLAnonymousClassStep extends MyBatisAdditionalTaintStep { |
| 188 | + override predicate step(DataFlow::Node node1, DataFlow::Node node2) { |
| 189 | + exists(MethodAccess ma, ClassInstanceExpr c | |
| 190 | + ma.getMethod().getDeclaringType().getSourceDeclaration() instanceof MyBatisAbstractSQL and |
| 191 | + ma.getMethod().getName() instanceof MyBatisAbstractSQLMethodNames and |
| 192 | + c.getAnonymousClass().getACallable() = ma.getCaller() and |
| 193 | + node1.asExpr() = ma and |
| 194 | + node2.asExpr() = c |
| 195 | + ) |
| 196 | + } |
| 197 | + } |
141 | 198 | } |
0 commit comments