Golang常见漏洞代码
目录
前言
收集遇到了Golang开发过程中的一些常见漏洞代码,方便大家学习和避免。
Sprintf注入
Sprintf注入代码示例
_updatePersonInfo = `
INSERT INTO people (id, name, age, email)
VALUES(%d, '%s', %d, %d, %d)
ON DUPLICATE KEY UPDATE
name=VALUES(name), age=VALUES(age), email=VALUES(email)
`
func (d *Dao) UpdatePersonInfo(ctx context.Context, req *PersonUpdateReq) error {
sql := fmt.Sprintf(_updatePersonInfo, req.ID, req.Name, req.Age, req.Email)
return errors.WithStack(d.DB.Exec(sql).Error)
}
直接采用Sprintf
的方式组装SQL语句,容易受到SQL注入攻击。
修复方案
使用Prepare
和Exec
的方式来执行SQL语句,如下:
const _updatePersonInfo = `
INSERT INTO people (id, name, age, email)
VALUES (?, ?, ?, ?)
ON DUPLICATE KEY UPDATE
name=VALUES(name), age=VALUES(age), email=VALUES(email)
`
type PersonUpdateReq struct {
ID int
Name string
Age int
Email string
}
func (d *Dao) UpdatePersonInfo(ctx context.Context, req *PersonUpdateReq) error {
// Prepare the statement
stmt, err := d.DB.PrepareContext(ctx, _updatePersonInfo)
if err != nil {
return errors.WithStack(err)
}
defer stmt.Close()
// Execute the statement with the provided parameters
_, err = stmt.ExecContext(ctx, req.ID, req.Name, req.Age, req.Email)
if err != nil {
return errors.WithStack(err)
}
return nil
}
DB.Order注入
DB.Order直接封装导致注入的代码示例
func (s *Service) ListPeople(c *gin.Context, p *http.ListPeopleReq) (resp *http.ListPeopleResp, err error) {
resp = new(http.ListPeopleResp)
// Query to get the list of people based on the request parameters
if err = s.d.DB.Order(p.Sort()).Limit(p.Limit()).Offset(p.Offset()).Where("department_id=?", p.DepartmentID).Find(&resp.Records).Error; err != nil {
return
}
// Query to count the total number of people in the specified department
err = s.d.DB.Table("people").Where("department_id=?", p.DepartmentID).Count(&resp.Total).Error
return
}
修复方案
// ListPeopleInfo lists people's information from the database.
func (s *Service) ListPeopleInfo(c *gin.Context, req *ListPeopleInfoRequest) (resp *ListPeopleInfoResponse, err error) {
resp = new(ListPeopleInfoResponse)
// Sanitize and validate the sort parameter
sortColumn, sortOrder := sanitizeSort(req.Sort)
if sortColumn == "" || sortOrder == "" {
return nil, fmt.Errorf("invalid sort parameter")
}
// Ensure limit and offset are valid integers
// omit for brevity
// Perform the query with sanitized inputs
if err = s.d.DB.Order(fmt.Sprintf("%s %s", sortColumn, sortOrder)).Limit(limit).Offset(offset).Where("cluster_id=?", req.ClusterID).Find(&resp.Records).Error; err != nil {
return
}
err = s.d.DB.Table("people").Where("cluster_id=?", req.ClusterID).Count(&resp.Total).Error
return
}
// sanitizeSort sanitizes and validates the sort parameter
func sanitizeSort(sort string) (column, order string) {
// Define allowed columns and sort orders
allowedColumns := map[string]bool{
"id": true, "name": true, "age": true, "email": true, // Add other allowed columns
}
allowedOrders := map[string]bool{
"asc": true, "desc": true,
}
// Split the sort string into column and order
parts := strings.Split(sort, " ")
if len(parts) != 2 {
return "", ""
}
column, order = parts[0], parts[1]
// Validate the column and order
if !allowedColumns[column] || !allowedOrders[order] {
return "", ""
}
return column, order
}