如题,相对于 PDO 来讲,肯定是 PDO 更好,但按照题目里的说法,是否可行呢?(我使用的是 SQLite )
1
Greenm 2019-02-14 15:14:24 +08:00 1
没搞懂 base64 怎么防注入的,我的理解是你传入后端的时候编码一下,你后端收到数据的时候再解码,然后拼接这个 SQL 语句进行查询,这样除了一些乱码外其他好像没啥作用啊,比如我写这样的语句,1' and 1=1,base64 编码解码后不还是一样的吗,怎么防止注入的?
噢应该可以防止宽字符注入,其他的好像不行。 要不就是我理解错你的意思了。 |
2
CloudMx 2019-02-14 15:15:05 +08:00
有毛用。
|
3
misaka19000 2019-02-14 15:15:29 +08:00
额,不管你怎么编码,最终在转为 SQL 的时候难道不都需要解码回原来的字符?
|
4
est 2019-02-14 15:16:51 +08:00
还不如 md5 一下。保证不可能出现引号。
|
5
ThirdFlame 2019-02-14 15:17:21 +08:00
编码 、解码 不还是原来的输入,所以没有任何防注入能力。
|
6
pimin 2019-02-14 15:18:17 +08:00
当然不可行
|
7
mostkia OP @Greenm 前台拿到的数据是明文字符串,到后台存入数据库前,进行编码后再存入数据库。需要时再取出来,然后直接解码还原。
|
8
ryweer 2019-02-14 15:20:53 +08:00
--tamper base64encode.py 了解一下
|
9
mostkia OP 想不通为什么大家都理解为传输阶段进行编码呢。。我的意思其实是存入数据库前由后台进行编码,存入数据库的就是 base64 内容。
|
10
misaka19000 2019-02-14 15:22:16 +08:00
@mostkia #7 这是可以的,不过这种思路不是和关键词替换是一样的道理吗?前端中用的很多啊。。。
|
11
funcman 2019-02-14 15:24:24 +08:00 via iPhone
没用。
sql 注入利用的核心点在于字符串缺乏反映类型的手段。防注入要从类型校验一直做到逻辑校验才靠谱。 base64 只是种编码,没有任何加密。没有加密的传输很容易随意伪造。 公开的网络交互是很不安全的,所以既要让伪造难以做到,也要能够识破伪造。 |
12
gamexg 2019-02-14 15:28:50 +08:00 3
你如果对所有内容都 base64 后就应该不会有 sql 注入问题。
但是但是,这么搞搜索等功能全挂了。 防注入难道不是应该用参数化查询? |
13
mostkia OP @funcman =_=神奇。。好吧,看来我说的不清楚,大家都有些理解错误。我的意思在明确一下:字符串处理完全在后台存数据时进行,存入到数据库的就是 b64,SQL 增删改查的关键词都是预设的字符串,固定的,前台来的变量则通通都会被编码成 b64 再存储,网络传输阶段都是明文传输的,和传输阶段没有什么关系。
|
14
passerbytiny 2019-02-14 15:31:56 +08:00 1
@mostkia #7 你还是先说下你对 sql 注入的理解把,你现在这需求,跟 sql 注入扯不上一点关系,貌似跟 sql 都没关系。
|
15
yagao0o 2019-02-14 15:32:53 +08:00
有个问题,如果某个字段需要模糊查询怎么办……把也把查询条件 base64 之后查询吗……
|
16
mostkia OP @gamexg 恩,你说的很对,我也考虑过。不过目前我数据库需求,都是完整精确匹配的,可以将输入内容也进行 b64 预处理后再搜索,类似于 MD5 的密码校验吧。复杂的多条件估计是不行的。所以也是处于考虑中是否要这样做。
|
17
mostkia OP @yagao0o 是啊,我也这样考虑了,这个问题比较困难,虽然目前数据库虽然没有模糊匹配的需求,但以后就不确定了,所以也只是探讨一下是否可行。
|
18
opengps 2019-02-14 15:37:56 +08:00
其实全文替换就行了,把一个单引号全文替换为两个单引号(在 sql 两个单引号属于注释输入一个单引号)
|
19
funcman 2019-02-14 15:38:18 +08:00 via iPhone
@mostkia 我后来才看到你说的方式。怎么说呢,更不靠谱。防注入主要防止数据泄漏。数据泄漏之后,除非由强密码加密过,不然就漏光了啊。
一般来讲,为了逻辑操作,使用数据库尽量把序列化的数据拆开成字段。少数无需操作的是直接存序列化的数据。这些是教科书里都会提到各种数据库设计范式,学会拿来用即可。 |
20
gam2046 2019-02-14 15:41:09 +08:00
需要的参数化查询替代字符串拼接 SQL 语句。
只要不使用 SQL 语句的直接拼接,可杜绝绝大部分的注入。 |
21
Greenm 2019-02-14 15:42:10 +08:00
@mostkia #7 如果是这样的话,在将这些字符还原的场景下,会带来一些意想不到安全隐患,考虑如下情况:
比如,你有一些数据需要展示出来,如用户名,地址等消息,我注册的时候随便填的数据,比如 <script>alert(1)</script>,你 base64 放到数据库了,展示的时候解码展示,就会造成 XSS。 为了避免上述问题,你还是需要对用户输入的数据进行过滤和限制,这就让你的 Base64 编码失去了最初的意义。 另外,由于你对入库的数据做了编码转换,这会导致一些数据不直观,数据还需要多做处理,浪费性能。 所以为了达到安全的最佳实践,建议不要自己想出一些方法,这会引起其他意想不到的问题。 总的的说,如果某方法简单有效,那么肯定有人已经想到且运用上了。 |
22
passerbytiny 2019-02-14 15:43:46 +08:00
@mostkia #10 所有值都 b64 转码存储,所有输入的参数值都 b64 转码后再往 sql 上拼,你是这意思吗?
方案倒是可行,但是弊远大于利,随便一项都有一大堆弊端,譬如已经有人提到的模糊查询,譬如该字段是铁定无法用索引优化了,譬如专业的 dba 看不懂你的数据库了 |
23
898601566 2019-02-14 15:44:55 +08:00
我看到有说用 addslashes 的
|
24
Greenm 2019-02-14 15:46:28 +08:00 3
#18 @opengps 这样是完全错误的做法,全局替换非常容易造成一些安全问题,如果我这样写的话 \' 会变成 \'',会将第一个单引号转义,第二个单引号就逃逸出来了,造成 SQL 语句闭合引起注入。
很多问题都是因为一些程序员所谓的“小聪明”导致的,好的坏的程序员都犯过这种错误。 请严格遵守最佳实践。 |
26
shuax 2019-02-14 15:47:52 +08:00
不是 escape 一下就行吗?
|
27
Vegetable 2019-02-14 15:48:54 +08:00
我也不明白,怎么都看不明白呢?
人家说存数据库之前先编码,这样无论什么样的 SQL 语句都一起编码了,当然没了注入的问题 但是这么解决路子太野了吧?不推荐.. |
28
bunnyblueair 2019-02-14 15:54:42 +08:00
@est 难道对 md5 有什么误解
|
29
mostkia OP @Vegetable 没有复杂查询条件我觉得是可以的,但碰到如果有模糊查询就不行了。我目前需求只是偶尔有一些精确匹配搜索,所以问问可行性,没想到那么多人理解错了,哈哈,没关系。实在不行就老老实实的直接做标准过滤吧,反正也就是处理一些用户名、密码、数量、型号、日期什么的,按照它们的类别做好过滤即可,一般也用不上这些特殊字符,保留英文数字,正则判断禁止所有的特殊字符就可以了。
|
31
est 2019-02-14 17:07:38 +08:00
@bunnyblueair 没误解。db 那边再查一下彩虹表就翻译过来原始值了。
|
32
wellR 2019-02-14 18:20:48 +08:00
类似 一表用户表,密码保存的是加密后的值,用户设置的原密码,我们不记录
|
33
daozhihun 2019-02-14 18:54:46 +08:00 via Android
可行,但是建议用参数
|
35
akira 2019-02-14 20:11:17 +08:00
可以。 顺便在写个中间件自动编解码,嗯。。
|
37
lihongjie0209 2019-02-14 20:53:33 +08:00
@mostkia 存 base64 怎么查询
|
38
hxt 2019-02-14 20:56:20 +08:00
防注入不行,不可能所有字段都 base64。不过对长内容可以压缩再 base64 下,比如 php 的 gzcompress 后再 base64 下,存储的长度一般会比原来小。
|
39
caola 2019-02-14 21:01:25 +08:00
PDO 的预处理,已经是在帮你防注入了,也没太必要还做其他的专门处理
|
40
yidinghe 2019-02-14 21:03:52 +08:00 via Android
歪门邪道。不同的语言有不同的处理方法。
|
41
iyaozhen 2019-02-14 21:38:50 +08:00 via Android
666
仔细一想,别说还真行。索引也有,like 查询其实也行 除了存储大小会变大点 |
42
msg7086 2019-02-14 22:44:19 +08:00
可以,但是意义不大。
|
43
madNeal 2019-02-14 22:56:00 +08:00
使用现有的 sql 参数化方法比自己想办法造轮子有效得多
|
44
reself 2019-02-14 23:34:26 +08:00 via Android
你怕是对 SQL 注入的理解有误。
|
45
reself 2019-02-14 23:36:42 +08:00 via Android
抱歉,貌似确实能起到类似转义的作用。
|
46
whoami9894 2019-02-14 23:41:11 +08:00 via Android
如果是数据库所有字段都是 b64 编码内容,那么是可以的
比如拼接 sql 查询时 select * from users where uname = '{param}',b64 可以保证不会闭合掉前面的单引号,但这么麻烦为什么不直接参数化 sql 语句呢 |
47
claysec 2019-02-14 23:44:55 +08:00
楼主是想防止二次 SQL 注入吗。。
|
48
yuikns 2019-02-15 00:08:37 +08:00 via iPhone
其实是可以的。只要没有 like 查询。其实就是利用 b64 字符集没有比较危险的那几个特殊字符。怎么这么多人死活不理解别人的中文呢
但是,现在一个 prepared statement 能解决的问题没必要那么复杂 |
50
just1 2019-02-15 03:30:15 +08:00 via Android
是可以的,楼上很多人怕是对注入有误解
|
51
all4fun 2019-02-15 06:29:30 +08:00
直接参数化比较好吧
|
52
q397064399 2019-02-15 07:20:56 +08:00 via iPhone
一般 orm 都做掉了,自己弄这个 真的是蛋疼
|
53
jalja27 2019-02-15 07:52:41 +08:00 via Android
以我的经验来看,sql 注入的问题有直接的解决方案,就用这个方案。用编码这种间接的,中间多了一层数据转换逻辑,扩展性和其它关联影响是很大的隐患,特别是多人开发的团队中
|
54
reus 2019-02-15 08:25:22 +08:00
我看你是不知道 SQL 可以传参数吧。
|
55
paranoiagu 2019-02-15 08:35:16 +08:00 via Android
数据库存了 base64 后的数据,你查询 like 怎么搞?
查出来的数据都要解码显示,性能行不行? |
56
lzxz1234 2019-02-15 08:44:47 +08:00
内容编码入库是常用的,但依赖这种方式防注入也太低级了
|
57
huahuajun9527 2019-02-15 09:02:05 +08:00
你的意思是查询字符串只允许是 base64 的字符集里的,包含其他的字符就不放进去查询???
|
58
master13 2019-02-15 09:06:04 +08:00
其实在做软件工程的时候,我们经常会遇到一个问题就是:业内通常怎么做。你说的方法也可以,但是不利于后期业务数据分析处理。方法可行,但业内不这么做,肯定是有它的道理。
|
59
firechat 2019-02-15 09:23:20 +08:00
给我的感觉就是放着圆的轮子不用,要造一个方的轮子。
直接用现有的 sql 防注入方案就行了 |
60
xmdbb 2019-02-15 09:23:23 +08:00
可以肯定可以,但是我只想问问,ID 系列的你怎么处理,难不成整个自增 ID 你都用 BASE64 吧?
|
61
xmdbb 2019-02-15 09:25:28 +08:00
还有就是不清楚你业务是怎样,如果涉及计算的,涉及日期对比的,你 BS64 后就只能通过取出来后在计算?
另外如果计算后还要连表查询,那不就变了要跑很多次吗?这样做不就弊大于利了。 其实 PDO 没啥不好吧?如果说不习惯,那就自己封装下成习惯的就可以了。你这简直是杀鸡取卵啊..... |
62
qiyuey 2019-02-15 09:53:34 +08:00
参数化查询,不要去拼接 SQL
|
63
darktutu 2019-02-15 10:00:28 +08:00
我挺心疼楼主的,这下面回复有多少人是题目都没看明白的。这都什么人混迹于此啊?
|
64
AlphaTr 2019-02-15 10:03:46 +08:00
可以是可以,但将 base64encode 换为 escape 工作量是一样的,效果却更好;
|
65
rizon 2019-02-15 10:07:13 +08:00
参数占位符,sql 预编译就可以解决,注入只发生在 sql 编译时。
|
66
CRVV 2019-02-15 10:20:59 +08:00 via Android
|
67
beginor 2019-02-15 10:37:24 +08:00 via Android
进行参数化查询就那么难么?
|
68
missdeer 2019-02-15 10:40:51 +08:00
数据库存 base64 后的文本,之后搜索会麻烦一点吧
|
69
a194259440 2019-02-15 11:35:23 +08:00
@darktutu 所以你拿个方案啊,站着说话不腰疼么
|
70
unco020511 2019-02-15 12:29:42 +08:00
可以肯定可以啊,但是后期很多统计搜索之类的就功能就不好处理了吧
|
71
evilmiracle 2019-02-15 12:55:38 +08:00
预编译啊
|
72
darktutu 2019-02-15 13:11:31 +08:00
@a194259440 你腰已经断了
|
73
mostkia OP 已重写控制程序,目前使用 pdo 预处理解决注入问题,今天一点开就 40 多条回复,没想到那么讨论激烈。其实这个被疯狂吐槽的需求锅不应该由我来背。。。因为之前的数据库控制程序并不是我写的,项目做到一半由我接手的,现在想想的确挺蛋疼的,之前的控制程序直接是标准的 sqlite 接口,当然也有一些基本的字符串过滤,但感觉不太好,但也因为怕出 BUG 实在不想改数据库控制程序这部分,所以才想了一些投机取巧的方法。后来一想长痛不如短痛,索性都重写了,好在业务逻辑也不复杂,已经全部搞定了,感谢大家的意见。
|
74
iwtbauh 2019-02-16 11:36:17 +08:00 via Android
@Greenm #1
@CloudMx #2 @misaka19000 #3 @pimin #6 我以 mysql/mariadb 举例 mysql/mariadb 提供了一个叫 FROM_BASE64 的函数 我在拼接 SQL 的时候,后端把用户的输入都 base64 一下,然后套到这个函数里去,就成了这样 var = base64(${var}) ..... WHERE `id` = FROM_BASE64(${var}) … 所有用户的输入都不可能破坏 sql 语句,并且,存到数据库里 /查询数据库的时候,还是原来的用户输入。 这是我以前用 bash 写个家庭内网自用程序的后端时,因为 bash 没法参数化查询,所做的防注入措施。 可见,base64 防注入十分可行 |
75
misaka19000 2019-02-16 11:53:17 +08:00
@iwtbauh #72 没说不可行啊,只是这个方法太民科了,缺点也很明显
|
76
iwtbauh 2019-02-16 12:38:42 +08:00 via Android
|