V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
vvhhaaattt
V2EX  ›  Go 编程语言

fmt.Sprintf 方法的%q 是否可以防止 mysql 注入?

  •  
  •   vvhhaaattt · 2022-07-07 21:56:09 +08:00 via Android · 2611 次点击
    这是一个创建于 861 天前的主题,其中的信息可能已经有所发展或是发生改变。
    sql 防止注入最安全的方法,就我知道的是参数化查询
    让 mysql 将 sql 解析跟数据传递分开,不过这种一般会多一次与 mysql 的交互。
    我知道 go mysql driver 有参数可在 driver 层做相关过滤,但似乎对部分编码不是很友好?
    %s 进行 sql 拼接很容易被注入没什么疑问。
    %q 会将字符串 进行一定的安全处理,之前有看到用%q 开拼接 sql 的,是否安全?个人感觉有风险,但想不出什么情况下会被注入。
    有哪位研究过的么?之前很少看到用%q 的
    11 条回复    2022-07-08 23:02:24 +08:00
    junmoxiao
        1
    junmoxiao  
       2022-07-07 22:07:11 +08:00
    一样存在 sql 注入的问题
    lianyue
        2
    lianyue  
       2022-07-07 22:13:40 +08:00
    现在基本没有使用 sql 拼接的了再差 也是传参数
    基本上 都在用 orm 了

    统一 utf8 编码
    尽量避免字符串直接拼接
    百分之九十九的 语句都可以用 orm go 有 gorm
    需要手动写的 就 使用 传参 语句 和 值分离

    我能接受最差的写法
    ```
    where := []string{}
    args := []string{}
    if url.query.uid != "" {
    args = append(args, url.query.uid)
    where = append(where, "uid = ?")
    }

    query := "SELECT * FROM users"
    if len(where) != 0 {
    query += " WHERE " + strings.Join(where, " AND ")
    }
    db.Query(query, args...)

    ```
    vvhhaaattt
        3
    vvhhaaattt  
    OP
       2022-07-07 22:20:59 +08:00 via Android
    @junmoxiao
    @lianyue
    感谢回复,我自己写肯定不会拼接。
    重点是标题,%q 下 mysql 注入案例?
    linauror
        4
    linauror  
       2022-07-07 22:26:36 +08:00
    测试了一下,这个转义看起来还是很安全的,不知道是不是有些案例没测试到
    lianyue
        5
    lianyue  
       2022-07-07 22:34:42 +08:00
    vvhhaaattt
        6
    vvhhaaattt  
    OP
       2022-07-07 22:42:09 +08:00 via Android
    @lianyue 输出被成对的双引号包裹了,对 mysql sql ,双引号内单个单引号是否会截断字符串?单纯这样感觉 sql 报错,但还不至于注入?用来 dos 倒是有点用的感觉
    linauror
        7
    linauror  
       2022-07-07 22:53:39 +08:00
    @vvhhaaattt 双引号可以包含单引号,不会被截断,只会被当成单引号字符串,也不会报错,这种看起来不会造成注入
    dzdh
        8
    dzdh  
       2022-07-08 09:24:52 +08:00
    @lianyue #5
    怎么通过外部输入造出这种数据呢?比如 通过 http\rpc 传进来的参数
    nothingistrue
        9
    nothingistrue  
       2022-07-08 10:22:03 +08:00
    %q 是给字符串加 双 引号,也就 Mysql 你能这样用了,Oracle 下面 SQL 报错( SQL 规范上是要求单引号定义字符串)。这只是误打误撞防止了 sql 注入,但本质上是瞎几把拼 SQL 。
    CRVV
        10
    CRVV  
       2022-07-08 10:28:46 +08:00
    注入应该不会,但是你的字符串可能会变成错的。
    比如 fmt.Printf("%q", "\x0b\x1b") -> "\v\x1b"
    "\v\x1b" 在 MySQL 里面会变成 “vx1b"
    lesismal
        11
    lesismal  
       2022-07-08 23:02:24 +08:00
    标准库应该是默认对 query string 做了 Prepare 的,所以预期 Sprintf 拼接,还是不如都使用 place holder 来避免比较好。
    我新搞的 sqlw 就没像 sqlx 那样去支持一些 query 配合 Named() 的解析,保持最简单、最实用的东西,其他那些华而不实的花哨,能少整就少整
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2670 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 15:47 · PVG 23:47 · LAX 07:47 · JFK 10:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.