Skip to content

Commit f4c2e65

Browse files
authored
Merge pull request #15812 from atorralba/atorralba/go/squirrel-sinks
Go: Add SQLi sinks for Squirrel
2 parents 66d2a84 + e78e71c commit f4c2e65

File tree

6 files changed

+388
-20
lines changed

6 files changed

+388
-20
lines changed

go/ql/lib/semmle/go/frameworks/SQL.qll

+19-9
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,28 @@ module SQL {
8181
"github.com/lann/squirrel"
8282
], "")
8383
|
84-
// first argument to `squirrel.Expr`
85-
fn.hasQualifiedName(sq, "Expr")
84+
fn.hasQualifiedName(sq, ["Delete", "Expr", "Insert", "Select", "Update"])
8685
or
87-
// first argument to the `Prefix`, `Suffix` or `Where` method of one of the `*Builder` classes
88-
exists(string builder | builder.matches("%Builder") |
89-
fn.(Method).hasQualifiedName(sq, builder, "Prefix") or
90-
fn.(Method).hasQualifiedName(sq, builder, "Suffix") or
91-
fn.(Method).hasQualifiedName(sq, builder, "Where")
86+
exists(Method m, string builder | m = fn |
87+
builder = ["DeleteBuilder", "InsertBuilder", "SelectBuilder", "UpdateBuilder"] and
88+
m.hasQualifiedName(sq, builder,
89+
["Columns", "From", "Options", "OrderBy", "Prefix", "Suffix", "Where"])
90+
or
91+
builder = "InsertBuilder" and
92+
m.hasQualifiedName(sq, builder, ["Replace", "Into"])
93+
or
94+
builder = "SelectBuilder" and
95+
m.hasQualifiedName(sq, builder,
96+
["CrossJoin", "GroupBy", "InnerJoin", "LeftJoin", "RightJoin"])
97+
or
98+
builder = "UpdateBuilder" and
99+
m.hasQualifiedName(sq, builder, ["Set", "Table"])
92100
)
93101
) and
94-
this = fn.getACall().getArgument(0) and
95-
this.getType().getUnderlyingType() instanceof StringType
102+
this = fn.getACall().getArgument(0)
103+
|
104+
this.getType().getUnderlyingType() instanceof StringType or
105+
this.getType().getUnderlyingType().(SliceType).getElementType() instanceof StringType
96106
)
97107
}
98108
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The query `go/sql-injection` now recognizes more sinks in the package `github.com/Masterminds/squirrel`.

go/ql/test/library-tests/semmle/go/frameworks/SQL/go.mod

+10-4
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,21 @@ module semmle.go.frameworks.SQL
33
go 1.13
44

55
require (
6-
github.com/Masterminds/squirrel v1.1.0
6+
github.com/Masterminds/squirrel v1.5.4
77
github.com/go-pg/pg v8.0.6+incompatible
88
github.com/go-pg/pg/v9 v9.1.3
99
github.com/go-sql-driver/mysql v1.6.0 // indirect
1010
github.com/go-xorm/xorm v0.7.9
1111
github.com/kr/text v0.2.0 // indirect
1212
github.com/lib/pq v1.10.2 // indirect
13-
github.com/uptrace/bun v1.1.14
14-
github.com/uptrace/bun/dialect/sqlitedialect v1.1.14
15-
github.com/uptrace/bun/driver/sqliteshim v1.1.14
13+
github.com/mattn/go-isatty v0.0.19 // indirect
14+
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
15+
github.com/stretchr/testify v1.8.1 // indirect
16+
golang.org/x/tools v0.9.1 // indirect
17+
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
18+
lukechampine.com/uint128 v1.3.0 // indirect
19+
modernc.org/libc v1.22.6 // indirect
20+
modernc.org/sqlite v1.22.1 // indirect
21+
modernc.org/token v1.1.0 // indirect
1622
xorm.io/xorm v1.1.0
1723
)

go/ql/test/library-tests/semmle/go/frameworks/SQL/main.go

+38-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package main
22

3-
//go:generate depstubber -vendor github.com/Masterminds/squirrel "" Select,Expr
3+
//go:generate depstubber -vendor github.com/Masterminds/squirrel DeleteBuilder,InsertBuilder,SelectBuilder,UpdateBuilder Delete,Expr,Insert,Select,Update
44

55
import (
66
"context"
@@ -43,9 +43,43 @@ func test(db *sql.DB, ctx context.Context) {
4343
}
4444

4545
func squirrelTest(querypart string) {
46-
squirrel.Select("*").From("users").Where(squirrel.Expr(querypart)) // $ querystring=querypart
47-
squirrel.Select("*").From("users").Where(querypart) // $ querystring=querypart
48-
squirrel.Select("*").From("users").Suffix(querypart) // $ querystring=querypart
46+
squirrel.Expr(querypart) // $ querystring=querypart
47+
deleteBuilder := squirrel.Delete(querypart) // $ querystring=querypart
48+
deleteBuilder.From(querypart) // $ querystring=querypart
49+
deleteBuilder.OrderBy(querypart) // $ querystring=[]type{args}
50+
deleteBuilder.Prefix(querypart) // $ querystring=querypart
51+
deleteBuilder.Suffix(querypart) // $ querystring=querypart
52+
deleteBuilder.Where(querypart) // $ querystring=querypart
53+
54+
insertBuilder := squirrel.Insert(querypart) // $ querystring=querypart
55+
insertBuilder.Columns(querypart) // $ querystring=[]type{args}
56+
insertBuilder.Options(querypart) // $ querystring=[]type{args}
57+
insertBuilder.Prefix(querypart) // $ querystring=querypart
58+
insertBuilder.Suffix(querypart) // $ querystring=querypart
59+
insertBuilder.Into(querypart) // $ querystring=querypart
60+
61+
selectBuilder := squirrel.Select(querypart) // $ querystring=[]type{args}
62+
selectBuilder.Columns(querypart) // $ querystring=[]type{args}
63+
selectBuilder.From(querypart) // $ querystring=querypart
64+
selectBuilder.Options(querypart) // $ querystring=[]type{args}
65+
selectBuilder.OrderBy(querypart) // $ querystring=[]type{args}
66+
selectBuilder.Prefix(querypart) // $ querystring=querypart
67+
selectBuilder.Suffix(querypart) // $ querystring=querypart
68+
selectBuilder.Where(querypart) // $ querystring=querypart
69+
selectBuilder.CrossJoin(querypart) // $ querystring=querypart
70+
selectBuilder.GroupBy(querypart) // $ querystring=[]type{args}
71+
selectBuilder.InnerJoin(querypart) // $ querystring=querypart
72+
selectBuilder.LeftJoin(querypart) // $ querystring=querypart
73+
selectBuilder.RightJoin(querypart) // $ querystring=querypart
74+
75+
updateBuilder := squirrel.Update(querypart) // $ querystring=querypart
76+
updateBuilder.From(querypart) // $ querystring=querypart
77+
updateBuilder.OrderBy(querypart) // $ querystring=[]type{args}
78+
updateBuilder.Prefix(querypart) // $ querystring=querypart
79+
updateBuilder.Suffix(querypart) // $ querystring=querypart
80+
updateBuilder.Where(querypart) // $ querystring=querypart
81+
updateBuilder.Set(querypart, "") // $ querystring=querypart
82+
updateBuilder.Table(querypart) // $ querystring=querypart
4983
}
5084

5185
func test2(tx *sql.Tx, query string, ctx context.Context) {

0 commit comments

Comments
 (0)