V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
dayeye2006199
V2EX  ›  信息安全

为什么使用 https 调用 API 仍然推荐需要使用 key 来签名

  •  
  •   dayeye2006199 · 70 天前 · 5036 次点击
    这是一个创建于 70 天前的主题,其中的信息可能已经有所发展或是发生改变。
    例如如下的 API -- https://open.shipout.com/portal/documentation/introduction.html#%E9%89%B4%E6%9D%83

    仍然使用了获取的 key 来签名 http 头文件。我的理解是 https 已经保证了通信过程中内容的不可篡改性,这种情况下,手动签名主要是为了解决什么问题呢?

    我是安全小白。
    第 1 条附言  ·  70 天前
    看了一些国外的厂商 API 调用,似乎这个自签名的操作并不常见

    Shopify token 塞在头文件里面 - https://shopify.dev/api/admin-rest#authentication
    Github token 塞在头文件里面或者用户名+账号 - https://docs.github.com/en/rest/overview/other-authentication-methods
    Strip 用户名+账号 - https://stripe.com/docs/api/authentication
    64 条回复    2022-08-14 23:14:12 +08:00
    yin1999
        1
    yin1999  
       70 天前 via Android   ❤️ 2
    不了解这个产品,就举个例子吧,有时需要在客户端调用这些 API ,但鉴权的 key 不能下发给客户端(比如网盘服务,需要由客户端向对象存储服务上传图片),可以由服务端生成签名后的 URL ,下发给客户端,客户端直接根据 URL 发送请求,即完成了一次 API 调用,但又不会泄漏 key 。
    ZE3kr
        2
    ZE3kr  
       70 天前 via iPhone
    除了一楼说的,也不排除一些开发者配置有问题导致不验证证书的情况,以及某些操作系统过于陈旧证书缺失导致开发者为了省事不验证证书。但不管怎样不验证证书都是非常不专业的做法。也有可能是历史遗留问题,该系统曾今是 HTTP 的,后来升级 HTTPS 了但接口没变

    微信支付的 Native API 也这样搞…实际上用了 HTTPS 就不需要再一次加密了。估计是为了兼容 HTTP 系统吧
    https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_5.shtml
    moen
        3
    moen  
       70 天前
    HTTPS 防的是传输过程中不会被监听,但是不防中间人攻击

    假如中间人能获取到发送者的公钥,那中间人就能解密并篡改请求,所以要用额外的私钥签名防止内容被篡改;但只有签名也不行,因为中间人可以选择不解密原文重发,所以还要加上时间戳并参与签名防止重放攻击
    ZE3kr
        4
    ZE3kr  
       70 天前 via iPhone   ❤️ 2
    HTTPS 当然可以防御中间人攻击 https://datatracker.ietf.org/doc/html/rfc2818#section-3.1
    phpfpm
        5
    phpfpm  
       70 天前   ❤️ 6
    我觉得这是几个维度的事情

    ssl 解决的是你们之间的通信是不是安全,和业务无关

    Authentication ( AuthN )解决的是和你通信的是谁,毕竟不是想和每一个人打交道
    Authorization ( AuthZ )解决的是确定对方身份之后,他能做什么
    Daiwf
        6
    Daiwf  
       69 天前
    https 有单向认证和双向认证的 我们一般用的是单向认证不需要本地证书。只是证明网站是官方的。双向认证需要你自己有服务端证书同一个 root 签发的证书。这样就可以认证你。当然你讲的这种方案。是业务层的认证。又是另一个维度。
    zed1018
        7
    zed1018  
       69 天前   ❤️ 5
    因为国内的好多乐色项目,把 https 当成 zz 任务来完成,自签证书还不双向验证,不 pin ssl/HSTS 。所以只能多做一些脱裤子放屁的事情来显得自己的安全防护做到位了。
    0o0O0o0O0o
        8
    0o0O0o0O0o  
       69 天前 via iPhone
    好像隔一段时间就能看到类似问题

    /t/770172
    oneisall8955
        9
    oneisall8955  
       69 天前 via Android
    shopify 的 webhook 请求需要校验签名呢
    wanguorui123
        10
    wanguorui123  
       69 天前
    Pro 和 Pro Max 的区别
    dzdh
        11
    dzdh  
       69 天前
    好多回帖。就没人说说为啥列举的几个 server-side 的 api 他就是不用签名呢
    aguesuka
        12
    aguesuka  
       69 天前
    虽然但是, 这个签名的功能和 https 没啥关系. appKey 是用户名, securetKey 是密码. 一般我们要登录拿到 session, 这个接口可以跳过登录.
    aguesuka
        13
    aguesuka  
       69 天前
    github 用的是 Basic Authentication, 这个相当于密码明文传输, 而且每次携带密文. 尽管 https 下是安全的, 如果校验时间戳可以一定程度地防重攻击.
    lululau
        14
    lululau  
       69 天前   ❤️ 1
    签名可以作为一种认证 (authentication) 的手段,除此之外,在 https 里又嵌一层签名的根本就不懂什么是签名什么是 https ,这种设计其实见得很多,很多金融相关的科技企业的产品都是瞎用加密技术的
    aguesuka
        15
    aguesuka  
       69 天前
    不用 Basic Authentication 还是有意义的, 如果是服务器的 https 密钥泄露, 那么中间人最多只能看到明文. 如果是用户的密钥泄漏, 那只有当前用户受到影响. 相当于提高了鲁棒性.
    seth19960929
        16
    seth19960929  
       69 天前
    都没说到点上. https 你被别人捉包了, 别人只是无法伪造数据, 可以无限请求.
    比如说获取订单数据, 我现在获取 有 5 个订单, 一个小时后用户下单了, 我继续请求, 可以拿到 6 个订单了.

    你用 sign, 你没发现 sign 参数基本都加了 ts 参数吗, 我服务端判断 ts 参数不在请求时间范围(比如说 5s 内的)直接不处理你的请求.
    还有一些加了参数, 比如说你查询接口, 查询 手机, 你捉包之后可以随意查.
    但是加 sign 参数, 我手机混入 sign, 你查电脑, sign 就会不一致.
    zed1018
        17
    zed1018  
       69 天前
    @seth19960929 那五秒内呢
    ZE3kr
        18
    ZE3kr  
       69 天前 via iPhone
    @seth19960929 HTTPS 不可被重放攻击,不存在你说的无限请求
    seth19960929
        19
    seth19960929  
       69 天前   ❤️ 2
    @zed1018 5 s 内的通过业务代码解决. 这是一个类似中间件的解决方案

    @ZE3kr https://help.aliyun.com/document_detail/50041.html

    API 重放攻击( Replay Attacks )又称重播攻击、回放攻击,这种攻击会不断恶意或欺诈性地重复一个有效的 API 请求。攻击者利用网络监听或者其他方式盗取 API 请求,进行一定的处理后,再把它重新发给认证服务器,是黑客常用的攻击方式之一。

    HTTPS 数据加密是否可以防止重放攻击?
    否,加密可以有效防止明文数据被监听,但是却防止不了重放攻击。
    ZE3kr
        20
    ZE3kr  
       69 天前 via iPhone
    seth19960929
        21
    seth19960929  
       69 天前
    @zed1018 看了一下 5 内的常见解决方案, 上个 redis 或者用 bitmap, 缓存时间 >= 允许容错的时间.
    seth19960929
        22
    seth19960929  
       69 天前
    @ZE3kr 感觉应该是理解上的问题, 让我问问阿里云
    ZE3kr
        23
    ZE3kr  
       69 天前 via iPhone
    @seth19960929 我查了下并不是所有版本 TLS 都可以防止重放。以及中间人可以干扰 HTTPS 连接导致客户端那边发多个 HTTP 内容相同但数据包不同的重试请求实现“重放”。不过不论哪种重放本来也需要业务上作处理,因为网络不稳定时客户端就可能重试请求
    momocraft
        24
    momocraft  
       69 天前   ❤️ 1
    要求 payload 里放一份自己发明的 json HMAC 的 大多是中国特产
    我怀疑是刻舟求剑跟某几个大厂学的
    libook
        25
    libook  
       69 天前
    识别请求发起方的身份。比如我是一个攻击者,因为这个域的 CA 公钥是公开的,那么我完全可以发起一个跟合法用户一样加密的 HTTPS 请求。如果加上签名了,相当于服务器会对客户端的合法性进行验证,也就是说攻击者只要没法造出合法的签名,服务器就可以认定为非法请求。

    你给出的 API 文档里说,你要在 map 序列化后拼接分配给你的 SK ,这个 SK 只有你和服务器知道,别人不知道,那么服务器就可以拿分配给你的 SK 做和你一样的操作就能得出相同的 MD5 ,就能证明请求是你发的,而不是其他人发的。

    对于 HTTPS 来说,header 也是会被加密传输的,所以其实不是特别有必要将你的参数序列化一起签名。假设你签名不需要带着参数,一旦某一次的签名泄漏了,攻击者就可以拿着这个签名带着任何他想要的参数去发请求,服务器会误认为是你发的,所以带着参数一起签名可以在你签名泄漏过一次的时候,至少不会被别人伪造不同参数的请求。

    签名的时候拼了时间戳,可以确保当签名泄漏一次后,在一定时间之外,攻击者无法使用相同参数来发起攻击。
    dzdh
        26
    dzdh  
       69 天前
    @seth19960929 #16

    这场景都是 C->S 。那 S-S 呢。

    C->S 自己实现一套 Sign 的意义呢。浏览器端 JS 公开的,sign 的 salt 哪里来呢。安卓端 Hook 之后一览无遗。图个啥呢。
    rekulas
        27
    rekulas  
       69 天前
    @ZE3kr 只能通过升级客户端和系统提高中间人攻击操作难度,但没法防御
    ychost
        28
    ychost  
       69 天前
    AK/SK 和 Https 不冲突
    seth19960929
        29
    seth19960929  
       69 天前
    @dzdh S->S 更需要啊
    意义就是可以屏蔽大部分直接裸露的接口.
    你看爬虫入门都是爬 xxx 家的接口, 就因为他们家的接口不用任何校验.
    那你看看抖音的接口能直接捉吗(web)
    andyskaura
        30
    andyskaura  
       69 天前
    就好比寄快递:
    ssl:保证快递运输安全,不会被掉包偷盗。
    key:快递员要求验证身份证,确保是本人收件。
    jiulang
        31
    jiulang  
       69 天前   ❤️ 1
    只有 https:直接放屁;
    https+这个签名:先脱个裤子,再放个屁
    jiulang
        32
    jiulang  
       69 天前   ❤️ 3
    喜欢脱裤子放屁的人说:我脱了裤子再放,自我感觉卫生;
    直接放屁的人说:方便还没啥问题,卫生不卫生看屁本身;
    dzdh
        33
    dzdh  
       69 天前
    @ychost
    @andyskaura

    的确不冲突。但是。是否 [必须] 要 md5/sha*/hmac* + salt 。直接在 https 基础上 basic auth 行不行呢?
    dzdh
        34
    dzdh  
       69 天前
    @jiulang #32
    精辟!
    dzdh
        35
    dzdh  
       69 天前
    @seth19960929 #29
    太能了。客户端抓个包而已。

    https://zhuanlan.zhihu.com/p/355450670
    https://blog.csdn.net/qq_44862120/article/details/107467725
    https://www.cnblogs.com/cherish-hao/p/12815603.html

    ios 越狱后照抓不误。函数 hook 完每一步干了啥都清清楚楚。S-S 服务端,没必要,可以客户端证书。C->S 端,更更没必要。
    andyskaura
        36
    andyskaura  
       69 天前
    @dzdh 虽然 key 有那么一丁点保证安全的能力,但我更多的是把 key 理解为一个业务需求。
    dzdh
        37
    dzdh  
       69 天前
    seth19960929
        38
    seth19960929  
       69 天前
    @dzdh 直接裸露的难度是几, 捉包的难度是几, 反编译找到 key 的难度是几.
    seth19960929
        39
    seth19960929  
       69 天前
    按你这么这么说, 希望各个大厂 app 都不要加所谓保护机制了, 直接调就行了. 你去和他们说才管用.
    dzdh
        40
    dzdh  
       69 天前
    https://v2ex.com/help/api

    包括 v2 的 api 也是 有个固定的 token 就行。我保护好我的 token 即可,泄露了就重新生成。Server-Server 的模式。

    sign 私以为适合的是类似 S3 的私有文件开放给他人下载场景用,三方用户无需任何配置可直接凭 URL 访问资源。
    dzdh
        41
    dzdh  
       69 天前
    @seth19960929 #38/39

    抬杠。

    难不难?难。 能不能?能。所以因为这个就 必须、一定、绝对 要前端签名吗?而且一直说的是 S-S 。
    seth19960929
        42
    seth19960929  
       69 天前
    @dzdh S -> S 就不需要吗? 服务器被入侵了, 你的请求就不被捉了吗
    seth19960929
        43
    seth19960929  
       69 天前
    直接用 appid + secretkey 和裸奔有什么区别
    vantis
        44
    vantis  
       69 天前
    自签名还有一个功能 是证明调用方自己是合法的调用方
    wanacry
        45
    wanacry  
       69 天前 via iPhone
    之前也对接过这种 api ,一直都是照葫芦画瓢,也不懂哈哈
    eason1874
        46
    eason1874  
       69 天前
    参数签名可以确保,一旦请求泄露了,别人也构造不了新请求

    在 HTTPS 可靠的情况,这个签名没意义,在 HTTPS 不一定可靠的情况就很有意义。比如内网有流量审计、代理上网的时候
    dzdh
        47
    dzdh  
       69 天前
    @seth19960929

    #42
    服务器都被入侵了你告诉我有什么手段还能是安全的?就算你硬件加密也屁用没有啊?
    #43
    那 stripe\google\facebook\paypal 就都不安全呗?


    @vantis #44
    不是光 https 就没别的了。https+ http basic auth 一样能证明啊
    datoujiejie221
        48
    datoujiejie221  
       69 天前 via iPhone
    签名不是为了防监听的 是防止身份伪造的
    这种方法在 openapi 很常见 比如云云对接时 a 厂商申请了好几个 appkey 那么 a 厂商是不是可以猜出规律来去暴力破解其他厂商的 key 呢 但是有了签名的保障 a 厂商很难猜出其他厂商的 key 和 secret 的
    对于反编译的问题,最好还是服务器云云对接 openapi
    dzdh
        49
    dzdh  
       69 天前
    @datoujiejie221

    我有个疑问。用 hmac/md*/sha*(rsa 除外啊)我不是也可以无限尝试嘛? 因为你采用的哈希算法和排列方式是公开的呀。

    无非是

    https://xx?key=$RANDOM 无限



    https://xx?{hmac(key1value1,key2value2,$RANDOM_SALT} 的问题吗?



    如果是 rsasign ,那是不是一样可以客户端证书呢?
    datoujiejie221
        50
    datoujiejie221  
       69 天前 via iPhone
    @dzdh 所以 secret 生成的时候一定要足够随机
    key 不能太随机主要还要考虑数据库索引性能
    所以你看国内一些平台 key 或 appid 比较简单 但是 secret 很复杂
    密码复杂了 暴力破解成本也很高呀
    rsa 这种用在 jwt 这种场景是很很合适的
    datoujiejie221
        51
    datoujiejie221  
       69 天前 via iPhone
    @dzdh rsasign 是签名方式 证书是连接建立握手的 只能说证书验证过程中用到了 rsa
    dzdh
        52
    dzdh  
       69 天前
    @datoujiejie221

    不。我说的是 [客户端证书] 。必须是指定 CA 签发(私有)的证书,并且能被正确解析的从证书中解析出 COMMONNAME 当作 UID 使用的。

    不是用于 HTTPS 连接的权威 CA 证书。

    rsasign 指的是使用私有 RSA Private Key 对指定字符串生成的 sign 如( php: openssl_sign ($data, $private_key, $sign ))
    dorothyREN
        53
    dorothyREN  
       69 天前
    @dzdh #40 你怎么知道已经泄漏了呢
    dzdh
        54
    dzdh  
       69 天前
    @dorothyREN #53 那签名怎么知道 secretkey 没泄漏呢
    datoujiejie221
        55
    datoujiejie221  
       69 天前 via iPhone
    @dzdh 是的呀 那他也是连接建立的时候才验证呀 验证过了才会协商密钥 客户端证书又不是每次请求都验证
    sivacohan
        56
    sivacohan  
       69 天前
    @seth19960929 在 19 楼说的大体是对的。

    我认为楼主的问题是不明白为什么要有一个 sign 。
    这个东西在没有 HTTPS 的时代,起到了一个防篡改的作用。

    在有 HTTPS 的时代,HTTPS 保证了传输过程的安全性。但是客户端的安全性仍然存在风险,比如我可以打开 chrome 的 console ,然后复制出这个请求来进行重放。

    这个 sign 不是 AAA ( authentication authorization and accounting )的范畴。
    这个 sign 如果直接是通过 请求参数的 map + key 生成的,那就是保证数据可靠性,避免篡改。
    这个 sign 如果是 请求参数 + salt ( timestamp ) + key 生成的,就除了数据可靠性之外,增加了一个防重放攻击的能力。
    Chenhe
        57
    Chenhe  
       68 天前 via Android
    简单说。https 一般是验证服务器的身份。而这些 api 还需要验证客户端的身份。
    siweipancc
        58
    siweipancc  
       68 天前 via iPhone
    ……op 有什么服务是无偿提供的吗,我想用
    siweipancc
        59
    siweipancc  
       68 天前 via iPhone
    @siweipancc 回个点子上的吧,这是保护买资源客户,甚至预防客户的熟人作案(这边发生过,然后还改造了一版)
    EminemW
        60
    EminemW  
       68 天前
    不就是用来校验用户是否合法的,很难理解吗
    IvanLi127
        61
    IvanLi127  
       67 天前
    @EminemW 这里讨论有没有必要增加校验的复杂度,很难理解吗?
    vantis
        62
    vantis  
       66 天前
    @dzdh 和服务器有啥关系……
    HTTPS 是公开的证书 任何人都可以建立加密通信 但客户服务器怎么证明自己是自己呢?除非网站有一个客户服务器自己的证书并且对签名验签通过
    这个就是签名的作用
    签名的密钥是在之前记录进去的 只有你通过私有的密钥签名 服务器用你之前录入的公钥验签了 才能保证请求确实来自对应的客户服务器

    以上和客户服务器被入侵是两个话题 如果你服务器被入侵了 是你自己持有的私钥泄漏了 这个服务器当然不知道访问者是攻击者的
    dzdh
        63
    dzdh  
       66 天前
    @vantis #62

    首先回的是哪一楼啊

    HTTPS 的证书是公开的,没错,在 TLS 握手阶段会发送给浏览器也没错。

    然后呢?我 HTTPS 的基础之上,不使用 [签名] ,而使用 basic auth 就不能证明自己了吗?
    byte10
        64
    byte10  
       50 天前
    @datoujiejie221 我是好奇为啥大家聊偏了,就是一个鉴权的方案而已,不用签名,也可以换别的。。服了这些评论区。。。
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1378 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 51ms · UTC 00:28 · PVG 08:28 · LAX 17:28 · JFK 20:28
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.