1 SQL注入
1.1 WHERE 注入
我們可以使用佔位符來進行參數綁定解決。
// Where add conditions
//
// See the [docs] for details on the various formats that where clauses can take. By default, where clauses chain with AND.
//
// // Find the first user with name jinzhu
// db.Where("name = ?", "jinzhu").First(&user)
// // Find the first user with name jinzhu and age 20
// db.Where(&User{Name: "jinzhu", Age: 20}).First(&user)
// // Find the first user with name jinzhu and age not equal to 20
// db.Where("name = ?", "jinzhu").Where("age <> ?", "20").First(&user)
//
// [docs]: https://gorm.io/docs/query.html#Conditions
func (db *DB) Where(query interface{}, args ...interface{}) (tx *DB) {
tx = db.getInstance()
if conds := tx.Statement.BuildCondition(query, args...); len(conds) > 0 {
tx.Statement.AddClause(clause.Where{Exprs: conds})
}
return
}
有兩種方法:一種是直接用佔位符
tx.Where(fmt.Sprintf(" (%s = ?) ", columnName), value)
第二種是用表達式:
expr := gorm.Expr(fmt.Sprintf(" (%s = ?) ", columnName), value)
tx.Where(expr.SQL, expr.Vars)
1.2 order by SQL注入
// Order specify order when retrieving records from database
//
// db.Order("name DESC")
// db.Order(clause.OrderByColumn{Column: clause.Column{Name: "name"}, Desc: true})
func (db *DB) Order(value interface{}) (tx *DB) {
tx = db.getInstance()
switch v := value.(type) {
case clause.OrderByColumn:
tx.Statement.AddClause(clause.OrderBy{
Columns: []clause.OrderByColumn{v},
})
case string:
if v != "" {
tx.Statement.AddClause(clause.OrderBy{
Columns: []clause.OrderByColumn{{
Column: clause.Column{Name: v, Raw: true},
}},
})
}
}
return
}
上面是 Order 方法,可以看到它有兩種使用方式,一種是直接的字符串,也是容易SQL注入的;另一種是使用 clause.OrderByColumn 結構體:
package clause
type OrderByColumn struct {
Column Column
Desc bool
Reorder bool
}
// Column quote with name
type Column struct {
Table string
Name string
Alias string
Raw bool
}
我們可以使用以下方法:
...
isRaw := strings.ContainsAny(orderByItem.Field, "=><(){},;.")
tx.Order(clause.OrderByColumn{Column: clause.Column{Name: orderByItem.Field, Raw: isRaw}, Desc: orderByItem.Direction == "desc"})