求大佬给点思路,web api 接口怎么防止被恶意重复访问? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
twg
V2EX    信息安全

求大佬给点思路,web api 接口怎么防止被恶意重复访问?

  •  
  •   twg 2020-11-24 14:10:29 +08:00 6165 次点击
    这是一个创建于 1787 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景:

    设计一个 http 接口,给客户端访问,但是这个接口会访问 redis 和 mysql,所以这个接口如果被别人知道,恶意攻击,可能会导致 redis 或 mysql 炸掉,所以有没有什么可行性的方案? 

    我的解决方法:

    后端和前端约定一个 token,该接口是 post 方法请求,客户端每次请求都会在 form 中携带这个 token,后端通过比较这个 token,如果一致则执行业务代码,反之返回。因为 web 服务器前有一层 slb,ssl/tls 加在 slb 上,所以这样中间人应该获取不到这个 token 吧? 这样安全吗?比如说,攻击人能从 app 程序二进制获取 token? 

    或者还有没有别的方案?

    37 条回复    2020-11-25 10:18:45 +08:00
    VVVV7
        1
    VVVV7  
       2020-11-24 14:12:33 +08:00
    1. sign 签名 + time 时间戳
    2. IP 限流
    twg
        2
    twg  
    OP
       2020-11-24 14:18:57 +08:00
    @VVVV7 因为这个接口是登录之前,也就是还没到权限验证阶段,这样的话,sign 签名怎么实现?
    tabris17
        3
    tabris17  
       2020-11-24 14:21:33 +08:00
    @twg 私钥+nonce (时间戳),hash 算出来,不过需要客户端和服务器段时间同步
    twg
        4
    twg  
    OP
       2020-11-24 14:25:46 +08:00
    额..其实我想问的重点是,我想怎么区别这个客户端是我们 app 用户还是恶意用户?
    lsylsy2
        5
    lsylsy2  
       2020-11-24 14:27:26 +08:00
    @twg 那没啥特别好的方法,在前面包一层验证码之类的东西(本质是登录了)
    streamrx
        6
    streamrx  
       2020-11-24 14:2731 +08:00 via iPhone
    @twg 请求的频率
    locoz
        7
    locoz  
       2020-11-24 14:28:31 +08:00 via Android
    如果你这个接口是公开的,别人在你的网站或者 app 上抓个包就能看到,并且接口返回的内容对用户来说有实际意义的话,那就老老实实加风控,你自己整的那些花里胡哨的没啥意义。
    locoz
        8
    locoz  
       2020-11-24 14:29:24 +08:00 via Android
    #7 加风控 -> 加风控厂商的风控产品
    twg
        9
    twg  
    OP
       2020-11-24 14:32:11 +08:00
    @locoz 这个是公开接口,但是 https 协议也能看到吗?
    zxCoder
        10
    zxCoder  
       2020-11-24 14:34:59 +08:00
    限制请求频率?
    imdong
        11
    imdong  
       2020-11-24 14:41:12 +08:00   2
    接口签名,客户端将密钥保护好,没有更好的办法。

    最近开项目,就遇到同样的问题我的做法是这样的(也是比较通用的做法):

    具体思路就是,客户端与服务端约定一个密钥(密码串),然后将请求的 GET POST 数据与客户端版本,当前时间戳,唯一随机数打包成一个字符串后用密钥签名( RSA Sign or hash ),放进 header 头传回服务器。

    服务器根据客户端版本选择密钥对数据进行验签核对时间,并检查 Redis 是否存在此唯一随机数,通过就将 唯一随机数存至 Redis,一分钟后过期。

    只要保证客户端这边没有被反编译,就基本安全(没有绝对的安全,涉及到客户端的,一定有可能被破解)
    xuanbg
        12
    xuanbg  
       2020-11-24 14:47:02 +08:00
    限流,可以根据来源 IP 进行访问限制,譬如每秒只允许同一 IP 请求 1 次,超过的就丢掉。问题是会误杀,因为很多局域网的用户对外都是同一个 IP 。
    xuanbg
        13
    xuanbg  
       2020-11-24 14:50:43 +08:00
    @imdong 客户端加密就是防君子不防小人,或者说防菜鸟不防老手。还不如服务端对 IP 限流,虽然有误杀率,但基本上也不太会影响正常的访问。
    twg
        14
    twg  
    OP
       2020-11-24 14:55:22 +08:00
    @imdong 感谢老哥,随便问一下,你说的`接口签名`是指啥?
    soulmt
        15
    soulmt  
       2020-11-24 14:58:36 +08:00
    参照微信小程序 login,设计一次性 token 用完过期, token 用对称加密即可,除非反编译源码,否则这个 token 可以解决这个问题。
    Jooooooooo
        16
    Jooooooooo  
       2020-11-24 14:59:04 +08:00
    1l 的方法基本就是通用的

    约定好加密方法然后每次请求带上时间戳和加密数据, 用事先交换好的密钥去加密 请求参数+时间戳, 得到的数据和服务器上计算对比, 不一致直接返回错误

    如果你想问 4l 这种风控的问题, 就没那么简单了

    限制访问可以用限流+拉黑这种方法
    qiayue
        17
    qiayue  
    PRO
       2020-11-24 15:00:24 +08:00
    @twg 上面这些大哥说的签名是很常用的方式,可以参考微信的这个文档
    https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Access_Overview.html
    locoz
        18
    locoz  
       2020-11-24 15:02:02 +08:00
    @twg #9 当然能看到,抓包、反编译、Hook 随便一个操作就能看到了。加签名、IP 限流之类的也没啥用的,一般做开发的人弄出来的防护都是跟纸糊的一样,随便就能捅破。所以如果你的这个接口想要确保绝大多数情况下的安全,那就老老实实用专业做这块的人弄的服务...如果你感觉没必要的话,那就说明这个接口没有重要到那种程度,随便加个限流就好了。
    opengps
        19
    opengps  
       2020-11-24 15:02:23 +08:00
    用 redis 做个访问频率限流,或者幂等性处理从缓存里直接返回同样的数据
    twg
        20
    twg  
    OP
       2020-11-24 15:03:15 +08:00
    @qiayue
    @Jooooooooo
    @soulmt
    @xuanbg
    感谢各位老哥解答.
    twg
        21
    twg  
    OP
       2020-11-24 15:10:15 +08:00
    @locoz 涨见识了
    zhiguang
        22
    zhiguang  
       2020-11-24 15:12:01 +08:00
    如果是私有接口弄个 ssl 双向认证
    zjsxwc
        23
    zjsxwc  
       2020-11-24 15:19:32 +08:00
    每隔一段时间给你客户一个你的证书与私钥, 参考农行的 K 宝
    meshell
        24
    meshell  
       2020-11-24 15:20:11 +08:00
    app 签名方式 防不住大佬的。就像 #13 说得一样,加一些风控吧,验证码这些 增加破解难道 .
    Macv1994
        25
    Macv1994  
       2020-11-24 15:31:23 +08:00
    谷歌翻译的 secret 字段大佬都能给你破译出来 哈哈哈 不过现在好像没有用了
    shellic
        26
    shellic  
       2020-11-24 15:37:13 +08:00
    Nginx 可以限制请求频率
    murmur
        27
    murmur  
       2020-11-24 15:40:35 +08:00
    首先要注册,实名制使用接口,然后在注册鉴权这部分拦截,微信有 token 但是 token 也是人获取的可以查到是谁
    gadsavesme
        28
    gadsavesme  
       2020-11-24 16:14:15 +08:00
    限流呗,如果是恶意攻击前端加密也不靠谱的。
    AkideLiu
        29
    AkideLiu  
       2020-11-24 16:50:04 +08:00 via iPhone
    如果简简单单就能解决,那些做 cyber security 的早去开滴滴了
    yscg
        30
    yscg  
       2020-11-24 16:54:32 +08:00
    看看重放攻击的解决方案
    polymerdg
        31
    polymerdg  
       2020-11-24 17:07:11 +08:00
    对称加密签名
    polymerdg
        32
    polymerdg  
       2020-11-24 17:07:31 +08:00
    约定大于配置
    tqrj
        33
    tqrj  
       2020-11-24 17:12:01 +08:00
    没有绝对的安全
    如果是没有登录的接口:可以根据 IP 去限制并发量这是最简单的
    然后就是前端 JS 生成 token 后端进行效验具体细节 自己研究 参考 国外 CloudFlare 俗称五秒 cdn 最开始几代很容易破解其实。目前第三代还是有一定难度 JS 有混淆 vm 加密之类的解密很耗精力
    登录之后的接口:其实可以直接 redis 限制并发为 1 这样?再配合 nginx 完成一些基础的限制
    上面都是我瞎想的没有实践经验
    Koral
        34
    Koral  
       2020-11-24 18:16:24 +08:00
    https://docs.konghq.com/hub/kong-inc/rate-limiting/
    看下这个呢?不知道满不满足需求
    LLaMA2
        35
    LLaMA2  
       2020-11-25 00:06:09 +08:00   1
    假定你的接口叫 api,GET 请求, 且传递的参数是 data=abc 。

    为了防止恶意重放攻击,可以实现如下:

    api?data=abc&time=时间戳&code=1000&hash=xxxx

    其中 hash 规则是 md5(abc + 时间戳 + 干扰码)

    时间戳和 time 的保持一致,为了后端做超时检测, 干扰码和 code=1000 存在对应关系。

    即你有一张表,事先生成了一堆序号和干扰码,干扰码对应的序号只有你和 APP 知晓,保证不能泄漏(实际上坏人需要花时间破解)

    你每次收到消息后按照同样的方法计算 hash 比较,发现 hash 比对不上,就说明数据被篡改,时间戳超时可能是重放。服务器就直接丢弃,返回错误给前端
    aawei
        36
    aawei  
       2020-11-25 00:15:11 +08:00 via iPhone
    验证码
    twg
        37
    twg  
    OP
       2020-11-25 10:18:45 +08:00
    @ye4tar 感谢解答,我准备采取类似方法.
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2771 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 34ms UTC 14:29 PVG 22:29 LAX 07:29 JFK 10:29
    Do have faith in what you're doing.
    ubao msn 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