Skip to content

Commit 9059110

Browse files
authored
Merge pull request #358 from aschackmull/java/sql-sinks
Approved by yh-semmle
2 parents b880a60 + 263de52 commit 9059110

File tree

5 files changed

+103
-2
lines changed

5 files changed

+103
-2
lines changed

change-notes/1.19/analysis-java.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
| **Query** | **Expected impact** | **Change** |
1313
|----------------------------|------------------------|------------------------------------------------------------------|
1414
| Array index out of bounds (`java/index-out-of-bounds`) | Fewer false positive results | False positives involving arrays with a length evenly divisible by 3 or some greater number and an index being increased with a similar stride length are no longer reported. |
15+
| Query built from user-controlled sources (`java/sql-injection`) | More results | Sql injection sinks from the Spring JDBC, MyBatis, and Hibernate frameworks are now reported. |
16+
| Query built without neutralizing special characters (`java/concatenated-sql-query`) | More results | Sql injection sinks from the Spring JDBC, MyBatis, and Hibernate frameworks are now reported. |
1517
| Unreachable catch clause (`java/unreachable-catch-clause`) | Fewer false positive results | This rule now accounts for calls to generic methods that throw generic exceptions. |
1618
| Useless comparison test (`java/constant-comparison`) | Fewer false positive results | Constant comparisons guarding `java.util.ConcurrentModificationException` are no longer reported, as they are intended to always be false in the absence of API misuse. |
1719

java/ql/src/Security/CWE/CWE-089/SqlInjectionLib.qll

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import semmle.code.java.Expr
44
import semmle.code.java.dataflow.FlowSources
55
import semmle.code.java.frameworks.android.SQLite
66
import semmle.code.java.frameworks.javaee.Persistence
7+
import semmle.code.java.frameworks.SpringJdbc
8+
import semmle.code.java.frameworks.MyBatis
9+
import semmle.code.java.frameworks.Hibernate
710

811
/** A sink for database query language injection vulnerabilities. */
912
abstract class QueryInjectionSink extends DataFlow::ExprNode { }
@@ -13,8 +16,19 @@ class SqlInjectionSink extends QueryInjectionSink {
1316
SqlInjectionSink() {
1417
this.getExpr() instanceof SqlExpr
1518
or
16-
exists(SQLiteRunner s, MethodAccess m | m.getMethod() = s |
17-
m.getArgument(s.sqlIndex()) = this.getExpr()
19+
exists(MethodAccess ma, Method m, int index |
20+
ma.getMethod() = m and
21+
ma.getArgument(index) = this.getExpr()
22+
|
23+
index = m.(SQLiteRunner).sqlIndex()
24+
or
25+
m instanceof BatchUpdateVarargsMethod
26+
or
27+
index = 0 and jdbcSqlMethod(m)
28+
or
29+
index = 0 and mybatisSqlMethod(m)
30+
or
31+
index = 0 and hibernateSqlMethod(m)
1832
)
1933
}
2034
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Provides classes and predicates for working with the Hibernate framework.
3+
*/
4+
5+
import java
6+
7+
/** The interface `org.hibernate.Session`. */
8+
class HibernateSession extends RefType {
9+
HibernateSession() { this.hasQualifiedName("org.hibernate", "Session") }
10+
}
11+
12+
/**
13+
* Holds if `m` is a method on `HibernateSession` taking an SQL string as its
14+
* first argument.
15+
*/
16+
predicate hibernateSqlMethod(Method m) {
17+
m.getDeclaringType() instanceof HibernateSession and
18+
m.getParameterType(0) instanceof TypeString and
19+
(
20+
m.hasName("createQuery") or
21+
m.hasName("createSQLQuery")
22+
)
23+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Provides classes and predicates for working with the MyBatis framework.
3+
*/
4+
5+
import java
6+
7+
/** The class `org.apache.ibatis.jdbc.SqlRunner`. */
8+
class MyBatisSqlRunner extends RefType {
9+
MyBatisSqlRunner() { this.hasQualifiedName("org.apache.ibatis.jdbc", "SqlRunner") }
10+
}
11+
12+
/**
13+
* Holds if `m` is a method on `MyBatisSqlRunner` taking an SQL string as its
14+
* first argument.
15+
*/
16+
predicate mybatisSqlMethod(Method m) {
17+
m.getDeclaringType() instanceof MyBatisSqlRunner and
18+
m.getParameterType(0) instanceof TypeString and
19+
(
20+
m.hasName("delete") or
21+
m.hasName("insert") or
22+
m.hasName("run") or
23+
m.hasName("selectAll") or
24+
m.hasName("selectOne") or
25+
m.hasName("update")
26+
)
27+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Provides classes and predicates for working with the Spring JDBC framework.
3+
*/
4+
5+
import java
6+
7+
/** The class `org.springframework.jdbc.core.JdbcTemplate`. */
8+
class JdbcTemplate extends RefType {
9+
JdbcTemplate() { this.hasQualifiedName("org.springframework.jdbc.core", "JdbcTemplate") }
10+
}
11+
12+
/**
13+
* Holds if `m` is a method on `JdbcTemplate` taking an SQL string as its first
14+
* argument.
15+
*/
16+
predicate jdbcSqlMethod(Method m) {
17+
m.getDeclaringType() instanceof JdbcTemplate and
18+
m.getParameterType(0) instanceof TypeString and
19+
(
20+
m.hasName("batchUpdate") or
21+
m.hasName("execute") or
22+
m.getName().matches("query%") or
23+
m.hasName("update")
24+
)
25+
}
26+
27+
/** The method `JdbcTemplate.batchUpdate(String... sql)` */
28+
class BatchUpdateVarargsMethod extends Method {
29+
BatchUpdateVarargsMethod() {
30+
this.getDeclaringType() instanceof JdbcTemplate and
31+
this.hasName("batchUpdate") and
32+
this.getParameterType(0).(Array).getComponentType() instanceof TypeString and
33+
this.getParameter(0).isVarargs()
34+
}
35+
}

0 commit comments

Comments
 (0)