API 接口已经有 HTTPS 的前提下,为什么还需要签名机制?

2021-04-12 19:48:35 +08:00
 dzdh

注意场景:

综合以上三点。为什么在 Https 的保护下,还要额外做签名验证?

主要疑问,如 stripe 的退款接口

curl https://api.stripe.com/v1/refunds -u "$密钥:" -d charge=$charge_id

就可以发起一笔订单的退款或者扣款。按照某些论述的话,没有签名的 Stripe 岂不是非常危险?

13121 次点击
所在节点    SSL
248 条回复
no1xsyzy
2021-04-14 00:17:19 +08:00
@dzdh 主要是“关闭验证”太简单了。
curl -k
wget --no-check-certificate
requests.get(..., verify=False)
NODE_TLS_REJECT_UNAUTHORIZED=0 (任意一个被引入的 js 文件中的并不显而易见的环境变量就可以破坏整个体系,太恐怖了
签名密钥泄漏可以被发现继而解除密钥权限;但关闭验证…… 不看对面代码一百年不会被发现,看了代码也不一定能发现,各种语言各种工具采用了各种各样不同的名称,又很少添加任何“危险警示标志”( Sigh

考虑犯蠢准确地说不是技术问题,是风险管控问题。
至于遗留 / 习惯,是人脑的系统性偏差,这你得问造物主怎么想的( https://www.solidot.org/story?sid=67470
chinvo
2021-04-14 00:17:28 +08:00
总之, api 安全 的 设计思路 就是

降低风险
失效可靠

比如站里曾经讨论过把 Google 的 oauth 密钥放在 app 端 还是 自己实现个 oauth 然后把相应密钥放在 app. 其实结论就是, 必须要暴露安全相关的敏感信息的话, 应当选择暴露泄露或失效后损失小的. (相比换 Google 的密钥, 换自己的更容易, 同时也能避免第三方系统被恶意用户直接操作)
jim9606
2021-04-14 00:18:14 +08:00
@dzdh #124
1. 有些企业网络的网管系统可能会干这种反人类的事,不过现在越来越少了,因为手机操作系统通常明确无法兼容这种环境。
2. 通常 CDN 会解密 TLS 流量,再通过预先设置的专用客户端证书 /无客户端证书的 TLS 连接回源至源站,这个过程会导致源站获取不到客户端连接状态,但不排除有 CDN 服务商支持将客户端证书信息嵌入 HTTP 头的方法,肯定不是所有服务商都支持这个。Stripe 和 Paypal 用啥我也不知道。
3.没有 RTC 时钟又没有正确执行时间同步的设备可能会出这个问题。
4. 这个得根据具体分析。
5. 如果你的客户端有廉价设备(例如单片机驱动的收付款 POS ),出于节省硬件资源会选择不实现复杂的 TLS,或者支持的套件和扩展大幅缩减的 TLS,然后服务器还得小心选择合适的套件集以避免部分设备连不上的问题。

Server 到 Server 通常不用考虑问题 1 、3 、5,我也没说 TLS 双向认证一定不能用,自行评估这些缺陷能不能接受即可。
dzdh
2021-04-14 00:19:02 +08:00
@chinvo #160

是的。但是『客户端证书』非必要场景,非极端条件其实不用考虑。
而且『应用』只需要拿到客户端 PEM 后自行处理不同路径验证,不必在 webserver 层处理。
3dwelcome
2021-04-14 00:19:24 +08:00
@dzdh "客户端环境都木马了,你的签名 KEY 还有何安全可谈?"
木马一般都是定向功能,比如能盗取 HTTPS 数据流并解密,又不一定能成功偷到商户 KEY 。

前几天有个类似安全贴子,讨论数据库被脱裤,数据加密还有什么意义?
回帖都表示,黑客只靠一个漏洞,要同时盗取数据和对应的解密 KEY 是有一定难度的。能黑进数据库,往往不代表能同时获取 KEY 。

用于 URL 签名的商户 KEY 也是同理。
dzdh
2021-04-14 00:21:19 +08:00
@jim9606 #163

明白
dzdh
2021-04-14 00:23:45 +08:00
@3dwelcome #165

> 木马一般都是定向功能,比如能盗取 HTTPS 数据流并解密,又不一定能成功偷到商户 KEY 。

木马一般都是定向功能,比如能成功偷到商户 KEY,又不一定能盗取 HTTPS 数据流并解密

> 前几天有个类似安全贴子,讨论数据库被.......

对啊?别说加密了,还搞开发干啥。管你什么 KEY 你数据库里总有吧?
palfortime
2021-04-14 00:24:09 +08:00
我站楼主,双向证书的 https 就可以解决楼上很多人说的认证问题。现在很多第三方支付的接口用 rsa 的就是要先登管理平台上传商户证书的。
今天才和安全怼过这个问题,搞到最终的方案就是在 https 上套多一层业务自己实现的“tls”。安全还称 app 上加盐 hash 能够防串改,称 app 上的加盐 hash 是签名。公开的盐都不知道是谁的名。
dzdh
2021-04-14 00:27:50 +08:00
@no1xsyzy #161

@chinvo #162

已经脱离『纯技术』了。真的要考虑客户端的话,我个人人为没有『任何』方案可以保证安全,我甚至认为无论你有什么方案客户端环境都是『绝对不安全』的
chinvo
2021-04-14 00:27:58 +08:00
@dzdh
确实, 要求 mutual tls 的场景不多

但是你说的第二条, "不必在 webserver 层处理" 并不能实现, 用 nginx 也好, 用语言自带的 http server 也罢, 要想要求客户端发送自己的证书信息, 必须在站级启用 client tls authentication, 这样就会直接影响同站下的所有路径.

当然我是支持"不用或少用 mutual tls authentication"的, 同时我也认为"签名"在现在的环境下不是保护接口安全"不二法门".

签名其实和一个短期有效的 token 没有本质上的区别, 只是可以在客户端自行生成.

当然, 签名的方式, 相对于 oauth2 之类的解决方案, 进一步降低了密钥泄露的可能性, 毕竟 oauth2 在获取 token 之前需要通过网络发送 client secret 给授权服务器.

api 安全, 需要必要的"冗余设计"来实现"失效可靠".
3dwelcome
2021-04-14 00:31:26 +08:00
@dzdh "对啊?别说加密了,还搞开发干啥。管你什么 KEY 你数据库里总有吧?"
保存 key 可以靠操作系统的权限来隔离,windows/mac 搞了那么多年的 keychain,总比存数据库要安全一点了。
linux 系统 root 提权很难很难; windows 系统上,你 chrome 保存的网站密码文件泄露后,换台 PC 没有对应解密 key,神仙也解不出来。
chinvo
2021-04-14 00:33:10 +08:00
因前述"mutual tls 是站级设置, 不够灵活", 我会避免使用 tls client cert 认证.

通常情况下我选择使用 HTTPS + OAuth2. 如果有对外的资金等高安全需求的 API, 我选择增加额外的验证逻辑, 比如 Signing HTTP Messages (RFC Draft HttpBIS message signatures https://tools.ietf.org/html/draft-ietf-httpbis-message-signatures-00).
dzdh
2021-04-14 00:34:18 +08:00
@chinvo #170

是的。我纠正一下我的说法:服务层只需要拿到解析后的验证参数,如 nginx 的话: http_s|c_xx 等 Header 头。至于客户端证书的验证交由 Nginx 来处理至于路径我毫不关心,我只要知道我必须得要。

补充:像这种场景个人人为通常都是独立 API 域名吧?或者是 OpenAPI 网关,由网关(即是 WS 又是鉴权应用)来决定这个路径给不给验证信息。内网,到此步骤已经『完成并结束了对『安全』』的『需求』,再往后已经是各种服务协作,已经『没必要』再顾及 HTTPS 自身安全了。
dzdh
2021-04-14 00:36:13 +08:00
@3dwelcome #171

> linux 系统 root 提权很难很难; windows 系统上,你 chrome 保存的...

像你说的,木马对吧?你总要把 Key 读出来吧?我读内存行吗?进程 HOOK 可以吗?
nikan999
2021-04-14 00:37:10 +08:00
@palfortime
我举个防篡改的例子
如果用户发了消息 "转账给张三",当局域网有设备获取到这条明文消息,进行修改变成“转账给李四”,如果没有 hash 的话, 用户并不知道自己的消息被篡改,服务也不知道这条消息是被篡改的。如果有了 hash,那么进行计算可以知道这条消息被篡改了。
dzdh
2021-04-14 00:38:49 +08:00
@nikan999 #175

HTTPS 数据包可以被改了?
3dwelcome
2021-04-14 00:39:52 +08:00
@chinvo "我选择增加额外的验证逻辑, 比如 Signing HTTP Messages"

我去看了一眼,RFC 里完全解释了 TLS 不可全信。(for example, if the application is hosted behind a TLS-terminating gateway or if the client is behind a TLS Inspection appliance)

楼主就是死不承认有 TLS 解密网关的存在。都 2020 年了,http 签名还是浮上了水面,强烈支持啊!
0o0O0o0O0o
2021-04-14 00:41:30 +08:00
提供一个视角:在我这种**过不少客户端的看来,原则就是客户端不可信任,对于客户端来说,ssl pinning 和 sign 都是客户端范畴,都是用来提高**成本,而前者通常很简单,后者可以配合保护和奇技淫巧变得相当相当难。

所以如果可以信任运行环境、没有什么反爬对抗的压力,那楼主提到的这类 api 的签名“无意义”我觉得没问题,防重放之类的逻辑当然是要放到服务端。
dzdh
2021-04-14 00:41:55 +08:00
@3dwelcome #177

好的,我承认解密网关存在。我不用。然后呢?参看 173 楼。

HTTP 的签名机制完全没有存在的必要
chinvo
2021-04-14 00:42:06 +08:00
@dzdh 既然是网关的话, 完全可以解密后重新加密, 和 https cdn 是一样的逻辑.

虽然可以通过要求 Digest 头来验证 body 的 hash, 但是 Header 毕竟也可以一起改.

当然这属于极端情况了. 服务器的网关如果都不能被信任, 那么这个环境就太恶劣了.

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

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

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

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

© 2021 V2EX