基于 HTTPS 对外提供 API,十万个为什么,求 web 安全高手指教 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
phx13ye
V2EX    程序员

基于 HTTPS 对外提供 API,十万个为什么,求 web 安全高手指教

  •  
  •   phx13ye
    Alwayswithme 2020-01-15 22:05:23 +08:00 via Android 5178 次点击
    这是一个创建于 2098 天前的主题,其中的信息可能已经有所发展或是发生改变。
    对接过各种第三方,他们的 HTTPS 接口有时会要求
    1 对数据计算签名,有 https 还有必要吗?
    2 每次请求带上时间戳和 nonce,这个应该是防重放?
    3 OAuth2 那一套 token 机制
    4 稀奇古怪的数据加解密方式,主要是银行和支付公司

    搞得我每次调试时都很郁闷

    HTTPS 不是已经很完善了吗,上面四种哪些是瞎搞呢,应该做设计怎么做既可以简单实现,方便自己和他人调试,又足够安全呢?
    第 1 条附言    2020-01-16 16:11:03 +08:00
    content-type 是 json 的话,怎样生成和传输签名大家有没有好的实践????

    我目前的想法是,对整个 body digest,然后把签名的 base64 存到请求首部

    但是 json 序列反序列化一般是框架处理,就要 hack 框架,好像不是很好

    对于请求,body 一般只能读取一次,读取时要先缓存一份,然后和请求首部比对

    对于响应,业务代码只返回对象,需要在序列化成 body 时拦截并设置响应首部,或者这一步省去,只判断请求,毕竟响应带签名,客户端收到也不一定会校验
    24 条回复    2020-01-16 18:23:14 +08:00
    Maboroshii
        1
    Maboroshii  
       2020-01-15 22:11:31 +08:00 via Android   1
    1 https 是加密,是让第三方看不见原文。签名是保证数据来源可靠。
    2 时间戳可以认为是防重放,nonce 更多的是保证签名不一致,防止签名被简单破解。
    3 token 是验证身份
    4 是更多一层的数据保护。
    yankebupt
        2
    yankebupt  
       2020-01-15 22:19:27 +08:00   1
    据说有限量的测试专用 api,可以找他们要,测试专用的,除了限量很低什么防范措施都没有那种
    比如语音音箱 *滴平台 就这样……
    blless
        3
    blless  
       2020-01-15 22:25:09 +08:00 via Android   1
    1、签名是防篡改,签名算法不可逆,中间人想要篡改信息需要签名算法跟盐
    2、时间戳跟 nonce 除了防重放本身也可以加强签名
    3、4 就是 1 楼说的
    phx13ye
        4
    phx13ye  
    OP
       2020-01-15 22:26:07 +08:00 via Android
    @yankebupt 倒也不算是为了绕过验证,只是明明已经用了 https 并且有一些还要设置 ip 白名单才能请求,我在想哪些步骤是没必要做的
    jugelizi
        5
    jugelizi  
       2020-01-15 22:28:29 +08:00
    所以你真的研究了 https ?
    also24
        6
    also24  
       2020-01-15 22:33:39 +08:00   22
    单向的 https 只能保证你请求的银行真的是银行,但银行无法确定你是你。

    加了 token 才能让银行知道你是你,但是银行不知道你带的东西是你自己带的,还是别人塞进你包里的。

    加上 nonce 和签名,才能让银行知道这些东西全都是你带的,别人没有夹带,但是银行不知道这个你,是否是用 1 年前的你克隆出来的。

    加上时间戳,银行才能确定面前的你确实是当前时间点真实存在你,东西也是你带的东西。

    最后,稀奇古怪的加密又是什么呢?
    答:你带的东西是一个保险箱~
    leloext
        7
    leloext  
       2020-01-15 22:37:52 +08:00   1
    仅说下看法。
    https 仅仅是防止了第三方对信息的截取(除去中间人攻击),业务逻辑还应该在服务端验证,客户端返回的信息都不可信,需要各种验证,这个验证并不是 https 能保证的。
    also24
        8
    also24  
       2020-01-15 22:41:02 +08:00
    @leloext #7
    https 是有双向认证机制的,可以保证双向通信可信,只是大家一般都没在用而已
    blless
        9
    blless  
       2020-01-15 22:48:58 +08:00 via Android
    1、签名是防篡改,签名算法不可逆,中间人想要篡改信息需要签名算法跟盐
    2、时间戳跟 nonce 除了防重放本身也可以加强签名
    3、4 就是 1 楼说的
    leloext
        10
    leloext  
       2020-01-15 22:49:04 +08:00
    @also24 有一说一,我真还没用过双向认证,我做的业务来说都是在 http 上面包一层 tls,确保传输的安全性,后端的各种验证一个都少不了。
    blless
        11
    blless  
       2020-01-15 22:50:02 +08:00 via Android
    ……点进来怎么又发了一遍
    Xbluer
        12
    Xbluer  
       2020-01-15 22:58:04 +08:00
    4、稀奇古怪的加解密方式,指的是国密算法?当然也可能是不专业的 Base64“加密"。
    eminemcola
        13
    eminemcola  
       2020-01-15 23:05:04 +08:00   1
    @blless #11 一次成功的重放(狗头
    phx13ye
        14
    phx13ye  
    OP
       2020-01-15 23:10:21 +08:00 via Android
    @also24

    所以一个都不能少吗?

    加解密,大概是这样他们把需要处理的内容数据用私钥加密,放在 body 某个地方,比如 xml 的一个字段,然后我用公钥解出来。我响应内容也是这样,公钥加密后发出去
    phx13ye
        15
    phx13ye  
    OP
       2020-01-15 23:14:35 +08:00 via Android
    @Xbluer 什么叫国密,一般是非对称或者 hmac sha 之类的哈,我应该没混淆加密,哈希,编码之类的概念
    also24
        16
    also24  
       2020-01-15 23:17:07 +08:00   1
    @phx13ye #14
    看你要的是 『尽可能安全』,还是 『尽可能省事』。
    鉴权认证、防监听、防篡改、防重放 都是事实需求啊。


    另外我倒数第二句不是疑问句,是设问句,答案就在最后一行啊。

    从实际角度来说,这样做也确实存在一定的意义,因为 https 的流量卸载很有可能在负载均衡那一步就进行了,如果没有这个二次加密,那么数据在负载均衡那一步就是 『裸』的了,而多了这一层加密,可以让数据在到达业务代码部分时才被解谜。
    Xbluer
        17
    Xbluer  
       2020-01-15 23:21:03 +08:00
    Kontinue
        18
    Kontinue  
       2020-01-16 08:18:56 +08:00   1
    之前博客中的总结。
    -------
    这边还想提一下 HTTPS。之前看到一则知乎上的提问:[使用了 https 后,还有必要对数据进行签名来确保数据没有被篡改吗?]( https://www.zhihu.com/question/52392988)

    总结一下就是:

    API 签名保证的是应用的数据安全和防篡改,并且可以作为业务的参数校验和处理重放攻击。

    HTTPS 保证的是运输层的加密传输,但是无法防御重放攻击。

    换句话说,HTTPS 保证通过中间人攻击抓到的报文是密文,无法或者说很难破解。但仍然可以将报文重发,形成 DDOS。同时,如果不签名,只用 HTTP 简单认证,通过抓包,直接可以获取到 Authorization,就可以随意发起请求了。因此最安全的方法就是结合 HTTPS 和 API 签名。
    SmiteChow
        19
    SmiteChow  
       2020-01-16 09:23:13 +08:00
    #6 通俗易懂 赞
    LeeSeoung
        20
    LeeSeoung  
       2020-01-16 11:10:28 +08:00
    简单来说,这些措施都是有必要的,但也只是增大破解难度而已,不能 100%防御。
    unco020511
        21
    unco020511  
       2020-01-16 11:30:11 +08:00
    都有必要啊,签名是防篡改的,一般 :签名=不可逆算法(参数列表+时间戳+密钥)
    phx13ye
        22
    phx13ye  
    OP
       2020-01-16 16:27:44 +08:00
    @also24

    要的是 『尽可能安全』
    HTTPS 的服务端收到请求,加上这些验证,还有什么遗漏吗?
    响应时,有什么措施是必须采纳的呢?
    also24
        23
    also24  
       2020-01-16 16:57:29 +08:00   1
    @phx13ye #22
    遗漏有很多种可能吧,我这二把刀应该保证不了没有遗漏。
    这东西应该只涉及到你期望覆盖的面的大小,没有尽头。

    比如说 客户端是否要对 https 证书进行强验证(不止验证证书有效性,还要验证证书是否一致)。
    比如说 时间戳+签名 需要有时间差冗余,避免时间不一致导致出错,而冗余就带来了短时间内重放的风险,此时又需要缓存若干个请求信息来防止短时间内的重放。
    比如说 你的 token 机制是否足够安全,是否有吊销机制( JWT 出来挨打)。

    每个措施,一般都是对应某个场景给出的,其实还是确认场景的问题。



    另外回应你附言中的问题:

    content-type 是 json 的话,签名可以放进 header,也可以给 json 再罩一层 “非签名” 区域。
    即:参与签名运算的只是某个子字段,而另一个子字段存储签名信息即可。

    但是这里需要注意:
    JSON 的 k-v 是无序的,且 JSON 序列化的格式是可以自定义的,当你期望对一个 JSON 求签名( hash )的时候,请务必协调好两端的 JSON 序列化格式及顺序。
    如果觉得麻烦,也可以选择将需要传递的 JSON 对象,先序列化之后,存于某个 JSON String 字段。


    > 对于请求,body 一般只能读取一次,读取时要先缓存一份,然后和请求首部比对
    这段话我没有理解是什么意思,为什么只能读取一次。
    可以考虑设置类似 “API 网关” 的概念,所有请求先经过网关的核验之后再传入业务代码。
    phx13ye
        24
    phx13ye  
    OP
       2020-01-16 18:23:14 +08:00
    @also24 感谢大佬

    防重放准备这样做
    1.验证签名防篡改
    2.判断服务器时间是否比请求 timestamp
    3.判断 nonce 是否 redis set 中

    是考虑 json 的字段可以嵌套和 k-v 无序,才将整个 body hash

    请求可以读取多次,只是很多时候 web 框架只让读取一次,可以缓存一份替代,在 java-spring 里是 ContentCachingRequestWrapper,在 go-gin 里是 ioutil.NopCloser
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     925 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 21:37 PVG 05:37 LAX 14:37 JFK 17:37
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86