关于 sql 拼接和 sql 注入的问题

2023-01-12 15:07:48 +08:00
 horou

如图

我使用的是 sql 拼接的方式实现的不同规则的排序,这个 query.order 是请求接口传过来的值,是一个枚举类型

按道理来说是只能传数字类型,传其他类型接口会报 400 错误

这种情况会有 sql 注入 的风险吗?

3551 次点击
所在节点    程序员
33 条回复
rocksolid
2023-01-12 15:15:07 +08:00
数字类型不会有
xuanbg
2023-01-12 15:44:19 +08:00
其实只要检测一下几个特殊符号,拼接 SQL 也不会导致注入。
horou
2023-01-12 17:00:17 +08:00
@rocksolid 好的,谢谢解答
horou
2023-01-12 17:12:22 +08:00
@xuanbg 我拼接都是用的数值类型,这种应该没什么问题吧
xuanbg
2023-01-12 17:17:14 +08:00
@horou 纯数字和字母都是安全的,符号我只允许使用_,'`四个。
horou
2023-01-12 17:29:51 +08:00
@xuanbg 明白了,谢谢
h0099
2023-01-12 17:46:31 +08:00
#5 @xuanbg 允许用户输入'和`意味着他可以逃出您亲自写的'和`包裹
例如执行 sql "SELECT `{用户输入}` FROM table"
这里的用户输入可以是"someFieldExistsInTable`, (SELECT * FROM secretTable), `anotherFieldExistsInTable"
导致实际执行的是"SELECT `someFieldExistsInTable`, (SELECT * FROM secretTable), `anotherFieldExistsInTable` FROM table",于是 secretTable 就也被读出来了

'同理
xuanbg
2023-01-12 18:43:00 +08:00
@h0099 你想多了,前端输入的参数是仅限于被拼接到 order by 子句的。
wtfedc
2023-01-12 18:54:28 +08:00
8 楼没理解 SQL 注入是怎么回事,不管你拼接在哪,都有可能用 union ,或者 ; select 来获取其他表的数据
wtfedc
2023-01-12 19:00:51 +08:00
印象中有些 unicode 字符,在某些情况下,都可以用来突破,比如 0x39 。预防 SQL 注入,不是光过滤特殊字符就够的。
IvanLi127
2023-01-12 19:17:52 +08:00
只是数字的话,应该没事,op 用的是 rust 嘛?
别的比如弱类型语言,就得多一步,转换成数字类型再转成字符串,避免奇怪事情发生。
IvanLi127
2023-01-12 19:19:48 +08:00
@xuanbg 黑名单覆盖不全,不安全的,得上白名单。但就上白名单,还不如用预处理语句省事。
ragnaroks
2023-01-12 19:22:50 +08:00
大多数情况下,不使用字符串拼接风险并不大,逻辑拼接是安全的。

字符串拼接:sql = SELECT id,username FROM table WHERE $arg1 AND $arg2

逻辑拼接:quary = repo.from<TableClass>().select(table=>table.id,table.username).where(table=>table.username==arg1&&table.type===arg2).toList()
h0099
2023-01-12 19:49:45 +08:00
#8 @xuanbg 对于 ORDER BY `{用户输入}`
提供 someExistingField`; SELECT *, otherFieldExistsInSecretTable FROM `secretTable
执行 ORDER BY `someExistingField`; SELECT *, otherFieldExistsInSecretTable FROM `secretTable`
您的 secretTable 又被读出来了
h0099
2023-01-12 19:52:31 +08:00
@ragnaroks 这是使用大多数 orm 附带的 query builder 来构造您要查询的各个 clause 组成,最后由 query builder 来把他们变成 rawsql ,只要您不给 query builder 传入 raw 部分( query builder 通常会把所有是字符串的都作为 prepared statement 的插值参数),如`selectRaw(用户输入)`那就是安全的
h0099
2023-01-12 19:56:22 +08:00
#10 @wtfedc ASCII 0x39 不是`9`吗,纯数字有啥风险?
#12 @IvanLi127 prepared statement 也不是银弹:
https://www.v2ex.com/t/908249#reply15
> phppdo/jdbc/dbdriver 层提供的 prepated statment 不是银弹,无脑 escape 掉用户输入中的所有 sql 语法所使用的特殊字符也不是银弹:phpdelusions.net/pdo/sql_injection_example#escaping

`请不要在每一个回复中都包括外链,这看起来像是在 spamming`
sorcerer
2023-01-12 21:09:49 +08:00
@h0099 看了一下 你第二个例子不也算是 sql 拼接么,单纯的 prepared statement with parameters 有 sql 注入的风险么
h0099
2023-01-12 21:13:14 +08:00
@sorcerer 单纯的没有,但只要遇到有意无意的把用户输入直接拼接进字符串那就需要对用户输入做严格的过滤(如正则)甚至白名单(如只允许已知字段名)
IvanLi127
2023-01-12 21:18:26 +08:00
@h0099 你自己转的地址里不就是说用预处理语句的方法是坚固的么?你再看看?
IvanLi127
2023-01-12 21:20:50 +08:00
@h0099 #16 你要知道,谈字符串就得结合字符串编码,这里面水深的很,你以为你看到的 9 ,天知道转了几手后到数据库执行是他还是不是 9

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/908431

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX