zoukankan      html  css  js  c++  java
  • 破解另一家网站的反爬机制 & HMAC 算法

    零、写在前面


    本文涉及的反爬技术,仅供个人技术学习,禁止并做到:

    • 干扰被访问网站的正常运行
    • 抓取受到法律保护的特定类型的数据或信息
    • 搜集到的数据禁止传播、交给第三方使用、或者牟利
    • 如有可能,在爬到数据后24小时候内删除

    具体可参考 2019年5月28号 颁布的 《数据安全管理办法(征求意见稿)》

    一、背景


    今天在爬另一家网站数据时,想直接从 ajax 接口入手,但是发现这些 request 加了额外参数来防止爬取,即在 request header 里,有一对随机key-value 参数:形如 e931588bc0dfbc5e6323 : c43dfe7cdc49b6318f43907ad4e7d9b69a23719d2e3b7b59799124408aa11cf383f459a4a558af8c64b289b7d974982aad58db705ac6784460733bd21784bde0,故意让你猜不到。

    但是操作了一会,我总结了如下规律:

    1、每个不同的接口 url,对应不同的 key ,但这个 key 刷新页面是不会变得。(看来 key 跟 url 有关)

    2、每个 key 对应的 value 一直在变。(事后才知道 value 是根据 url 和 post body 共同决定的)

    二、破解


    于是通过网站被混淆过的 js ,耐心的打断点分析。

    过程略。

    三、结果


    最后发现:

    key 和 value 都是通过 HMAC(Keyed-Hashing for Message Authentication) 算法得来的。

    1、HMAC 算法

    HMAC 其实就等于我们平常用的 MD5 / SHA-1 去加 salt 的操作。而采用 HMAC 的好处就是,替代我们自己的 salt 算法,使得程序算法更标准化,也更安全

    HMAC 可选择搭配 MD5 / SHA-1 或等等。这里用的是 SHA512

    >>> import hmac
    >>> key = b'secret'
    >>> message = b'Hello, world!'
    >>> h = hmac.new(key, message, digestmod='MD5')
    >>> h.hexdigest()
    'fa4ee7d173f2d97ee79022d1a7355bcf'
    

    注意:传入的 key 和 message 都是bytes类型,所以str类型需要首先被编码为bytes

    2、最终代码

    注意:敏感信息被隐藏处理。

    import hashlib
    import hmac
    import requests
    import json
    
    host = 'http://example.com'
    # request's param - 变化值
    uri = '/api/search/example'
    data = {
        "cityName": "上海",
        "cityCode": "31",
        # 等等
    }
    
    # hmac's secret - 固定值
    secret = b'abcdefg'
    
    # calculate key
    sign_key = hmac.new(secret, uri.lower().encode(), hashlib.sha512).hexdigest()
    header_key = sign_key[10:30]  
    
    # calculate value
    sign_value = (uri.lower()+uri.lower() +
                  json.dumps(data, separators=(',', ':'), ensure_ascii=False)).lower()
    header_value = hmac.new(secret, sign_value.encode(),
                            hashlib.sha512).hexdigest()
    # print result
    print(header_key, header_value)
    
    

    然后我们把算出来的 key 和 value 塞入到每一次请求的 header 里,即可成功调用。

    3、坑

    上面代码在算 value 的时候,用了 json.dumps(),把中文 上海 转为了 "u4e0au6d77",而不是上海,导致接口一直报错。

    解决办法:json.dumps 多传一个参数 ensure_ascii=False

  • 相关阅读:
    Tomcat6.0 sqlServer2000 配置连接池操作
    SQL GROUP BY 实例
    Java 获取当前系统时间 格式:yyyyMMdd HH:mm:ss
    银行科技与业务融合之道
    银行IT部门科技管理流程管控工作发展之路
    银行科技管理工作优化提升之我见
    事务脚本的缺点以及领域模型的优点
    异常的分级分类与处理策略
    软件高性能的思考
    软件行业的一个发展推力就是不断提高用来构造软件的基础元素,也就是所谓的编程模型
  • 原文地址:https://www.cnblogs.com/xjnotxj/p/11934756.html
Copyright © 2011-2022 走看看