V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
haython
V2EX  ›  程序员

微信小程序,有什么办法可以防止别人破解我的接口?

  •  2
     
  •   haython · 200 天前 · 6145 次点击
    这是一个创建于 200 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前有 2 种想法,一种是每次请求弄个加密的签名,不过我记得好像是可以拿到小程序的源码,前端的东西,肯定会被人拿到加密算法;第二种是小程序云开发,走微信自己的协议,转发一下请求,这种就是太麻烦,绕一圈,求教各位大佬还有别的招术吗?

    第 1 条附言  ·  199 天前
    预防的场景是这样,小程序有些功能是需要看广告才能领取的奖励,但是小程序的源码被人下载到了,直接绕过了看广告,直接调用了领取奖励接口,怎么能确保领取奖励接口一定是在我的小程序里调用的?
    第 2 条附言  ·  199 天前
    感谢 @lizuoqiang @banlink 提供的解决方案,目前可以使用 wx.getUserCryptoManager ,改动最少,且安全性有一定保证
    第 3 条附言  ·  192 天前
    84 条回复    2023-10-12 10:41:09 +08:00
    zhcode
        1
    zhcode  
       200 天前
    加密算法写到 wasm 里面
    worldqiuzhi
        2
    worldqiuzhi  
       200 天前
    你限制接口登录才能访问不就行了吗。一个微信账号才能刷一次 成本就很高了
    haython
        3
    haython  
    OP
       200 天前
    @worldqiuzhi 不行,因为我肯定是登录之后,才刷接口,就像签到一样
    haython
        4
    haython  
    OP
       200 天前
    @zhcode 不确定能不能行,如果别人不破解 wasm ,直接复制了我的 wasm,直接调用加密方法就行了吧
    iOCZ
        5
    iOCZ  
       200 天前   ❤️ 1
    这么有价值?
    cat
        6
    cat  
       200 天前   ❤️ 1
    1. 是的,可以拿到小程序源码,上个月刚拿了一个
    2. 没有绝对的“防止”,只有提高破解者的成本,比如自签名就是一种,一般破解者对普通程序 也就抓个包什么的,搞不到就算了,如果你的程序价值特别高,你要考虑其它方式给用户使用,而不是放在小程序,或者从账户层面做限制
    me1onsoda
        7
    me1onsoda  
       200 天前
    @cat 怎么拿
    4ark
        8
    4ark  
       200 天前 via iPhone   ❤️ 1
    每个请求都带上一个 wx.login 拿到的 code ,后端检验,虽然也有解决方案,但已经能挡下一大批脚本小子了
    jadelike
        9
    jadelike  
       200 天前
    jwt 里加时间戳啊,加密的时间戳,时间戳不对就 return error
    Ashore
        10
    Ashore  
       200 天前
    @me1onsoda 有专门的解压工具的。。
    sentinelK
        11
    sentinelK  
       200 天前   ❤️ 1
    关键要看这个“破解”的概念是什么。

    1 、如果是接口仅限小程序调用,走云函数是最可行的。

    2 、如果是对调用次数有限制,对提交信息逻辑有要求,完全可以从 openID 的控制入手。频次异常、操作逻辑异常直接把他 openID 封了。(微信小程序的 openID 逻辑是服务器端控制的,前端只提交 wx.login 获得的 code )

    3 、如果是对提交的信息可信度有要求,那其实搞 IT 的应该都知道,web 提交的信息零信任。

    总体来讲,就是把异常调用接口的成本提高,高过其收益。自然就不会有人恶意调用接口了。
    haython
        12
    haython  
    OP
       200 天前
    @iOCZ 你说这话,说明你没有价值呀
    haython
        13
    haython  
    OP
       200 天前
    @jadelike jwt 肯定不行的,因为这太容易绕过去了
    jianyang
        14
    jianyang  
       200 天前
    小程序约等于前端
    要么你就付费混淆随便整个写个加密就行了
    要么你就用类似 GRPC 的通讯协议、在前端有点偏冷门、逆向这玩意得靠经验猜
    tool2d
        15
    tool2d  
       200 天前
    还是服务器限制每一个 IP 的访问次数比较好,客户端限制比较有限。
    jadelike
        16
    jadelike  
       200 天前
    @haython jwt 你别明文啊,用非对称加密不行么,私钥在你自己手上你怕啥
    lambdaq
        17
    lambdaq  
       200 天前
    @haython wasm 里面的算法根据 userid 动态生成。
    AndyChina
        18
    AndyChina  
       200 天前
    @4ark 方法靠谱, 否则只能使用微信云函数, 或者加上用户请求次数限制也行
    haython
        19
    haython  
    OP
       200 天前
    @jadelike 我怀疑你没懂我要做什么,jwt 不管是加密还是不加密,肯定要下发给用户的,前端拿到直接再提交就行,根本不需要解密,我是要阻止有人在我的小程序之外恶意调用我的接口
    haython
        20
    haython  
    OP
       200 天前
    @lambdaq 这种情况下,我的理解是 wasm 就是一个类库,userid 还是要传递参数进去,别人按照我的方式同样调用就行了
    lambdaq
        21
    lambdaq  
       200 天前
    @haython 同样的方式只能破解单一 userid 的接口 。。。

    除非你的接口不跟 userid 相关,否则很容易发现单一用户的异常
    jadelike
        22
    jadelike  
       200 天前
    @haython ‘jwt 不管是加密还是不加密,肯定要下发给用户的,前端拿到直接再提交就行,根本不需要解密,我是要阻止有人在我的小程序之外恶意调用我的接口’
    我怀疑你没看懂我说了什么,五分钟,一分钟,甚至你可以做一个特殊的 flag 让一串请求只能请一次,他是可以拿到,但你也可以判断这个请求是否被重放了,是否是一个小时前就应该来的请求
    haython
        23
    haython  
    OP
       200 天前
    @jadelike 我拿到了小程序源码,你一个 jwt 能阻挡我模拟你的请求吗
    agostop
        24
    agostop  
       200 天前 via Android
    小兄弟,你是不是在找“防重放攻击”?顺着这个关键字搜搜吧
    maocat
        25
    maocat  
       200 天前 via iPhone
    #14 @jianyang 之前我们前端搞过 grpc web ,妈的,自己人调试东西麻烦度上升了一个量级
    ByZHkc3
        26
    ByZHkc3  
       199 天前
    @4ark @haython 我也是用这个来做验证,再套上个 AES,可以增加破解难度。如果你有朋友有公司资质的小程序开发账号,可以弄个私有化插件,可以完全杜绝 95%以上的脚本小子
    summerLast
        27
    summerLast  
       199 天前
    代码混淆+ 增加无用的代码呢?
    xiaoriri666
        28
    xiaoriri666  
       199 天前   ❤️ 1
    核心功能直接调用云函数,90%没法破解,如果要破解只能走微信协议,或者 hook
    bestkayle
        29
    bestkayle  
       199 天前
    为什么说云开发太麻烦,我感觉除了贵和不能掌控在自己手里,还是很方便的啊。
    ahhhhhh888
        30
    ahhhhhh888  
       199 天前   ❤️ 1
    提供两个思路:
    1 、在云函数中通过算法生成一个 code ,小程序每次请求服务端时都需要携带上这个 code ,服务端通过和云函数配套的算法进行解密,非法的 code 一律拒绝,这样可以可以防止在小程序外部调用 API 。
    2 、在网关、应用 AOP 层面限制用户每秒的访问频率,防止爆刷。
    ahhhhhh888
        31
    ahhhhhh888  
       199 天前
    @ahhhhhh888 #30 code 中加上时间戳
    haython
        32
    haython  
    OP
       199 天前
    @agostop 不是防重放攻击
    hantianyang
        33
    hantianyang  
       199 天前
    我已经拿小程序源码了,我直接用源码恶意调用接口,怎么防止恶意调用接口,是这个意思吗
    layzh
        34
    layzh  
       199 天前   ❤️ 1
    貌似你们都没懂意思 他核心问题就是 服务端没法知道广告视频是不是真的播放了. 所以领取接口根本不是重放.他要防止的是 广告视频没播放 直接就走接口领取了奖励
    haython
        35
    haython  
    OP
       199 天前
    @hantianyang 对,怎么确保是在我的小程序发起的调用,而不是别人模拟的请求
    jiayouzl
        36
    jiayouzl  
       199 天前
    @jadelike 哈哈哈哈,你真是个人才!
    jiayouzl
        37
    jiayouzl  
       199 天前
    如果接口流量不大,就限制同请求次数,如果接口流量本身就大,那就时间戳加密,用自己的一套时间戳.
    lyc8503
        38
    lyc8503  
       199 天前   ❤️ 2
    客户端执行的代码,除非依赖可信计算环境,否则不可能完全做到防止别人模拟

    退而求其次的方法是,写个 js 签名算法,再加密混淆 js 后发布,提高别人逆向分析的成本

    加密 js 的免费或收费方案 Google 即可,有很多
    zero3412
        39
    zero3412  
       199 天前
    小程序就是 HTML ,抓个包就把接口都暴出来了,可以考虑 RSA 非对称加密,有必要的话,OPENID 加个令牌桶
    thinkershare
        40
    thinkershare  
       199 天前   ❤️ 1
    @haython 你要的是可信环境,而目前除了专门的硬件,手机这种东西,包括微信的客户端都不是可信环境,因此要做到你想要的功能是不现实的。只能提高破解者的门槛,如果利益足够,最终肯定还是防不住的,过度加强会导致成本上升,正常用户体验也会受限。电脑上播放的 DRM 加密视频就是一个典型的例子。
    XiLingHost
        41
    XiLingHost  
       199 天前
    如果是处理看广告拿奖励,那直接服务端验证时间戳呗,和广告来源的下载时间做核对,如果请求有异常就直接 ban 这个微信 id 一段时间
    nong99
        42
    nong99  
       199 天前 via iPhone   ❤️ 1
    @haython 每个请求都加上小程序 appID ,接口层面白名单仅允许你自己的小程序访问,可行吗?
    pennai
        43
    pennai  
       199 天前
    搜零知识证明验证身份看看
    v2nika
        44
    v2nika  
       199 天前   ❤️ 2
    你附加里面的其实是两个问题: 一个是如何避免前端伪造证明自己看过广告领奖的接口调用, 另一个是如何证明广告是真被看过的.

    前面一个其实不难, 滑块验证码这类的技术方案很成熟. 但是后面一个不太常见, 类似于要自己实现一个滑块验证码. 主要是要把看广告的过程转化为特征值供校验. 我感觉业界应该是有解决方案的, 比如那些在线视频学习网站, 要求必须看完整个视频才能完成课时.

    有个解决方案是: 基于隐藏式的滑块验证码技术收集前端特征, 保证前端环境是可信的, 然后视频每看一秒, 就对看过的内容进行一次签名, 得到两个签名一起提交的服务器. 服务器做校验.
    Huelse
        45
    Huelse  
       199 天前
    最简单的还是通过广告 id 校验播放开始与结束时间的唯一性。加速、重复看同一广告等问题都能解决。
    wzy44944
        46
    wzy44944  
       199 天前
    可以加一些风控措施,在领取奖励到兑现奖励之间加一个检查环节,检查奖励来源、用户近期调用频率,是否同 ip 之类的
    encro
        47
    encro  
       199 天前   ❤️ 1
    看你广告价值了,如果对方不是很特殊针对你,那么就简单客户端解决,前端 JS 通过看过这个特征处理:比如看的时长,从什么时间开始看看,从哪来的,手机倾斜角度等,这些数据上报上来,然后分析特征,将不符合要求的的屏蔽。对方拿了你的 wasm ,不分析源码,那么没法伪造行为数据,会被发现特征。

    用户自我证明,比如移动滑块验证,观看内容考核。

    这些搞起来,都会比做加密通信要麻烦。。。
    ch2
        48
    ch2  
       199 天前   ❤️ 1
    最切实可用的就是走 wx 的协议,你自己搞 99%会先于 wx 被破解
    aino
        49
    aino  
       199 天前
    预防的场景是这样,小程序有些功能是需要看广告才能领取的奖励,但是小程序的源码被人下载到了,直接绕过了看广告,直接调用了领取奖励接口,怎么能确保领取奖励接口一定是在我的小程序里调用的?
    ------------------------------------------------------------------------------------------------------------------------------------------------
    既然如此服务端检验看完广告才能领取奖励不就得了,防护做的再多,只是增加难度而已,不如回归本源,你这就是一个很明显的越权漏洞啊。。
    nothingistrue
        50
    nothingistrue  
       199 天前   ❤️ 1
    楼主这并不是防止接口被非授权用户访问,而是防止接口被授权用户自行调整访问顺序。可以洗洗睡了。给说几个跟楼主类似的场景,大家就知道这预防难度了:
    一、跳过优酷视频开头广告。
    二、客户端网游用外挂,甚至脱机外挂,刷经验金币。

    尤其注意第二个场景,网游客户端这可是闭源且不可反编译的,应用层网络通信协议也大抵是私有的,这样并不防止被破解特定场景。
    3825995121
        51
    3825995121  
       199 天前   ❤️ 1
    并不能完全防止 只能增加破解难度

    我每个请求都用 请求参数+请求数据+时间戳 +salt 生成一个散列值 做 sign 然后请求加上刚才的时间戳

    服务端 拿到之后判断时间戳是否大于 1 分钟 然后 请求参数+请求数据+时间戳 +salt 生成一个散列值 和 sign 对比

    salt 值可以在小程序端混淆一下 小程序打的包也可以混淆
    增加破解难度
    bruce0
        52
    bruce0  
       199 天前
    @summerLast 有了 chatGPT, 混淆基本没用了, chatGPT 能直接给还原了, 还附带注释😂
    xFrye
        53
    xFrye  
       199 天前
    激励视频一般会有服务端回调的 api ,小程序广告有没有这个 api 就不知道了。激励视频的奖励如果想要严格,肯定是要服务端验证的
    haython
        54
    haython  
    OP
       199 天前
    @XiLingHost 微信的广告,我应该是没办法获取每次广告的时长的
    haython
        55
    haython  
    OP
       199 天前
    @nong99 不可行,因为 appID 也是一个普通参数,也是前端发起的请求
    haython
        56
    haython  
    OP
       199 天前
    @3825995121 你说的这个,就是我说的请求添加签名,前端代码被拿到的情况下,没有用啊
    haython
        57
    haython  
    OP
       199 天前
    @xFrye 微信的激励视频没看到服务端回调 api
    xuxu5112
        58
    xuxu5112  
       199 天前   ❤️ 1
    奖励是发送到账户的吗?统计下每个账户获得奖励的次数和间隔,间隔过小的(比如小于 10s )、频次过高的就可能是程序刷的。把异常用户 block 。
    d873139022
        59
    d873139022  
       199 天前   ❤️ 1
    用 wx.login 获取登录凭证的 code ,然后每个接口都加上这玩意,这是一次性的。基本上就可以阻止了。
    haython
        60
    haython  
    OP
       199 天前
    @xuxu5112 不过这属于事后补救了,算是提高对方成本
    jadelike
        61
    jadelike  
       199 天前
    @haython 笑,‘我拿到了小程序源码,你一个 jwt 能阻挡我模拟你的请求吗’。你就是在防重放攻击。哪有人通过 http 请求能拿到源码的。
    mxT52CRuqR6o5
        62
    mxT52CRuqR6o5  
       199 天前   ❤️ 1
    微信小程序的能力不足,像 app 的那些激励广告 sdk ,是提供服务端校验的,保证不会被偷奖励
    haython
        63
    haython  
    OP
       199 天前
    @d873139022 这个前提是 wx.login 返回的 code 没被破解,我是看到有人发过,不需要打开小程序就可以获取这个 code ,并且可以在服务端正常使用
    jadelike
        64
    jadelike  
       199 天前
    @jiayouzl 谢谢认可
    6397like
        65
    6397like  
       199 天前
    是否可以拿小程序本身的一些信息比如小程序 api 获取到的 appid 作为请求的一个加密参数,服务端再解密校验下?
    jadelike
        66
    jadelike  
       199 天前
    前端的东西,肯定会被人拿到加密算法。你加密解密不能在后端做么,前端调用接口嘛。我个人和楼上另一位持不同意见,我认为是防止重放攻击
    lizuoqiang
        67
    lizuoqiang  
       199 天前   ❤️ 2
    banlink
        68
    banlink  
       199 天前 via Android   ❤️ 2
    一、云函数
    直接把领取奖励的接口放云函数上就行了

    二、wx.login
    激励视频播放的时候调用一次,把用户信息,code 传到后台验证 同时返回一个临时 token ,
    领取奖励的时候再调 wx.login 验证 code,token

    缺点:wx.login 接口有限额,网上好像有可以拿到 code 的方法

    三、wx.getUserCryptoManager
    文档原话:
    “为了避免小程序与开发者后台通信时数据被截取和篡改,微信侧维护了一个用户维度的可靠 key ,用于小程序和后台通信时进行加密和签名。
    开发者可以分别通过小程序前端和微信后台提供的接口,获取用户的加密 key 。”
    微信维护的 key 应该足够安全,不过 wx.login 能破解的这个原理也差不多,网上关于破解的信息还没看到


    这 3 个方法都可以解决你的问题,都是依赖微信,有能力破解微信来搞你的说明你们价值很大。
    mxT52CRuqR6o5
        69
    mxT52CRuqR6o5  
       199 天前   ❤️ 1
    我觉得最根本的方法就是不要在微信小程序的广告激励提供价值太高成本太高的奖励,因为没法完美地去校验,你提供的奖励价值够高,就会有黑灰产过来嫖你
    什么 jwt 、grpc 、wasm 、混淆,无非都是成本的问题,你提供的奖励价值够高,自然会有人克服这些障碍来嫖你了
    d873139022
        70
    d873139022  
       199 天前   ❤️ 1
    @haython 没有绝对意义上的不被破解,能破解 wx.login 这个的只有少少数。微信 hook 取小程序 code 的,它都把微信搞定了,你觉得你的技术有微信高吗。。
    再说个,演唱会抢票软件,逆向大佬也都解决了,你觉得你的防破解能比得上淘系 app 防破解的技术吗。你只需要防住大部分人,增加小部分人的破解门槛就行了,而不是在纠结绝对防破解
    datehoer
        71
    datehoer  
       199 天前   ❤️ 1
    结论:防不住,花钱加密比较合适。
    现在都可以给小程序注入开发者工具了,根本不需要将小程序反编译。
    mxT52CRuqR6o5
        72
    mxT52CRuqR6o5  
       199 天前   ❤️ 1
    @d873139022 #70
    当然没有绝对意义上的不被破解,即使是有服务端验证的激励奖励;但有没有服务端验证,风险承受方就不一样了
    像一些广告平台的 app sdk 有服务端验证的激励,如果恶意用户像白嫖奖励,风险承受方是广告平台/广告投放商,广告平台由于体量大,可以做一些法律层面的保护;而且作为平台,做技术上的防护是更高效的
    像小程序这种没有服务端验证的激励,风险承受方就是广告接入方了,想好做保护的话,每个接入方就得各自做保护,非常低效,小体量的开发者也很难寻求法律保护
    haython
        73
    haython  
    OP
       199 天前
    @jadelike 建议你看看别人的回复,真的不是防止重放攻击
    jaylee4869
        74
    jaylee4869  
       199 天前
    SSL Pinning
    c2const
        75
    c2const  
       199 天前   ❤️ 1
    1.用户端的代码都会被逆向和反混淆,模拟点击广告,或者软件都不开,直接模拟网络请求;甚至跳过直接领奖励,你也没有太好的没办法,只能见招拆招,毕竟软件和硬件都在用户的手上 :(

    2.关键还是服务器做检测,广告开始和结束时都要调 api ,时间间隔对不上,或者领取奖励频率明显异常的就自动永久封了呗,能做的检测还有很多,甚至你故意挖坑也行 :)

    3.用户端、网络接口这块,人机验证、混淆、加密都只是提高攻击的成本而已,挡住一批菜鸟 :(

    4.至于对高手,人家目的只是伪装自己是正常用户,白嫖奖励,并不是攻击你服务器;所以你没有太好办法,你能做的是提高用户端/网络接口的更新频率,让破解者和你一起多花时间,找到一个作弊者就永久封了,不停的对抗,对方肯定在你之后更新,所以会不断有账号在你的黑名单上 :(

    5.微信小程序的用户认证我不了解,但你需要一个用户的唯一标识,不管是微信提供的 code 还是用户手机号之类的,用来在服务器上永久封号 :)
    -----------
    这只是传统对抗,现代对抗还得考虑 AI 自动化 :(
    haython
        76
    haython  
    OP
       199 天前
    @c2const 你提到一个更新频率,这个是得考虑,只要我更新的够快,就没人能破解😂
    c2const
        77
    c2const  
       199 天前   ❤️ 1
    @haython

    1.传统对抗就是这样,公司下班前发布新版本,作弊者当天加班加点逆向,当天凌晨就出最新版破解 :(
    2.主要是你你这账号不收费,攻击成本太低了,像 steam 游戏之类的,如果作弊者不熟悉反作弊框架,那第一次基本得牺牲 5 个账号,才能破解;后续每次更新都会牺牲账号,以此来提高攻击成本 :(
    haython
        78
    haython  
    OP
       199 天前
    @c2const 对,还可以增加手机号和身份证绑定来提高对方成本
    duck200
        79
    duck200  
       199 天前
    直接云开发吧,阿里或者微信云函数都挺便宜,OP 如果服务端都写好了,就写一个代理转发请求的云函数吧,我目前有一个自己的产品就是这样做的,就是体感请求时间稍微长了点
    nozer
        80
    nozer  
       199 天前
    我记得小程序有个 formid ,是微信给生成的,你接口要一个这个 formid 然后验证他的有效性。

    我以前试图 crack 过一个小程序,然后遇到这个问题,没解决,放弃了。
    jadelike
        81
    jadelike  
       198 天前
    @haython 别人的回复我看了,我觉得有一定道理。我反对的是你的话语。
    ‘我拿到了小程序源码,你一个 jwt 能阻挡我模拟你的请求吗’,前端源码不妨碍,也不会透露出后端解密密钥。
    ‘前端的东西,肯定会被人拿到加密算法’。你加密解密不能在后端做么,前端调用接口嘛。
    3825995121
        82
    3825995121  
       198 天前
    我以前用过微信的云托管
    上边请求走微信内网
    用微信云托管增加一层转发
    但是设备成本增加一些
    haython
        83
    haython  
    OP
       198 天前
    @jadelike 你真是我大哥啊,前端为什么要解密 jwt ,后端下发的,我再提交回去就行了,jwt 本来就是一个用户标识。我说的被人拿到加密算法,是指前端提交参数的签名算法,这个只能是前端做,不能后端做
    cquan
        84
    cquan  
       198 天前
    我印象中 uniapp 的广告激励是可以回调验证的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2500 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 15:44 · PVG 23:44 · LAX 08:44 · JFK 11:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.