zoukankan      html  css  js  c++  java
  • API验证插件

    前言

    如果在访问某WebAPI过程中request信息被他人截获,若是get请求获取数据还好,如果是post提交数据,势必威胁数据安全,所以对于一个对安全性要求较高的API来说,对每个请求做身份验证显得尤为重要;

    防范策略解析

    策略1

    客户端发送http请求访问API时,在请求头里设置一个双方约定好的key;

    知识点:

    1、如果给Django程序发送请求头,headers携带内容包含下滑杠 _,Django会不认识;

    2、客户端 auth-api ----->服务端 转换成 'HTTP_AUTH_API'格式

    3、服务端获取clent_key=request.META.get('HTTP_AUTH_API')

    客户端

    import  requests
    key='sssdkjrjefjewfakfhkj'
    respose=requests.get(url='http://127.0.0.1:8000/test.html/',headers={'auth-api':key}).text
    #如果给Django程序发送请求头,如果headers里面的内容使用下滑杠 _,Django会不认识;
    #auth-api  -----> 转换成 'HTTP_AUTH_API'格式
    #服务端获取clent_key=request.META.get('HTTP_AUTH_API')
    print(respose)
    View Code

    服务端

    def test(request):
        key='sssdkjrjefjewfakfhkj'
        clent_key=request.META.get('HTTP_AUTH_API')
        if clent_key == key:
            return HttpResponse('你得到我了')
        else:
            return HttpResponse('休想')
    View Code

    漏洞:虽然双方约定好了key,但是请求头依然会被截获到;

    策略2

    1.key+当前客户端时间戳 组成1个MD5加密字符串

    2.MD5加密字符串|当前时间戳 组成1串密码,hearder携带

    3.服务端接收到客户端发送的那1串密码,split 出客户端时间

    4.来着客户端时间+服务端key做MD5加密还原,对比客户端和服务端

    客户端

    import  requests
    import time
    import hashlib
    key='sssdkjrjefjewfakfhkj'
    ctime=str(time.time())
    def MD5(arg):
        hs=hashlib.md5()
        hs.update(arg.encode('utf-8'))  #python3加密使用字节类型
        return hs.hexdigest()
    
    
    new_key='%s|%s' % (key,ctime)  # sssdkjrjefjewfakfhkj | 时间戳
    md5_str=MD5(new_key)
    auth_api_val='%s|%s'%(md5_str,ctime)  #d0e0ca7d1f8f72d60715696d4baac3b2(key和时间戳加密后的结果)| 时间戳
    print(md5_str)
    respose=requests.get(url='http://127.0.0.1:8000/test.html/',headers={'auth-api':auth_api_val}).text
    print(respose)
    View Code

    服务端

    import hashlib
    import time
    
    def MD5(arg):
        hs = hashlib.md5()
        hs.update(arg.encode('utf-8'))  # python3加密使用字节类型
        return hs.hexdigest()
    
    def test(request):
        key='sssdkjrjefjewfakfhkj'
        auth_api_val=request.META.get('HTTP_AUTH_API')  #052dd27c130f4b9b5a8a4ec4b243962d | 1507374976.4620001
        client_md5_str,client_ctime =auth_api_val.split('|',maxsplit=1)
        server_md5_str=MD5('%s|%s'%(key,client_ctime))
    
        if client_md5_str== server_md5_str:
            return HttpResponse('你得到我了')
        else:
            return HttpResponse('休想')
    View Code

     

    漏洞:折腾了半天虽然可以动态加密,但依然可以获取到,且客户端会生成很多加密字符串,黑客获取任意一个都可以访问到API

    策略3

    1.key+当前客户端时间戳 组成1个MD5加密字符串

    2.MD5加密字符串|当前时间戳 组成1串密码,hearder携带

    3.服务端接收到客户端发送的那1串密码,split 出客户端时间

    4.来着客户端时间+服务端key做MD5加密还原,对比客户端和服务端是否相等

    5.动态密码有时间限制,超过5秒失效

    客户端

    import  requests
    import time
    import hashlib
    key='sssdkjrjefjewfakfhkj'
    ctime=str(time.time())
    def MD5(arg):
        hs=hashlib.md5()
        hs.update(arg.encode('utf-8'))  #python3加密使用字节类型
        return hs.hexdigest()
    
    
    new_key='%s|%s' % (key,ctime)  # sssdkjrjefjewfakfhkj | 时间戳
    md5_str=MD5(new_key)
    auth_api_val='%s|%s'%(md5_str,ctime)  #d0e0ca7d1f8f72d60715696d4baac3b2(key和时间戳加密后的结果)| 时间戳
    print(md5_str)
    respose=requests.get(url='http://127.0.0.1:8000/test.html/',headers={'auth-api':auth_api_val}).text
    print(respose)
    View Code

    服务端

    def test(request):
        server_float_ctime=time.time()
        key='sssdkjrjefjewfakfhkj'
        auth_api_val=request.META.get('HTTP_AUTH_API')  #052dd27c130f4b9b5a8a4ec4b243962d | 1507374976.4620001
        client_md5_str,client_ctime =auth_api_val.split('|',maxsplit=1)
        client_float_ctime=float(client_ctime)
    
        if client_float_ctime+5 < server_float_ctime:
            return HttpResponse('想要破解密码最在5秒之内')
    
        server_md5_str = MD5('%s|%s' % (key, client_ctime))
        if client_md5_str== server_md5_str:
            return HttpResponse('你得到我了')
        else:
            return HttpResponse('休想')
    View Code

    漏洞:虽然加密字符串有了时间限制,但时间就是漏洞

     

     

    策略4

    1.key+当前客户端时间戳 组成1个MD5加密字符串

    2.MD5加密字符串|当前时间戳 组成1串密码,hearder携带

    3.服务端接收到客户端发送的那1串密码,split 出客户端时间

    4.来着客户端时间+服务端key做MD5加密还原,对比客户端和服务端是否相等

    5.动态+加密字符串+时间限制,超过5秒失效

    6.记录最近5秒访问客户端的加密字符串,如果当前客户端使用的字符串存在记录中,说明是窃取(因为正常用户每次,访问API会携带不同的加密字符串)

    客户端

    import  requests
    import time
    import hashlib
    key='sssdkjrjefjewfakfhkj'
    ctime=str(time.time())
    def MD5(arg):
        hs=hashlib.md5()
        hs.update(arg.encode('utf-8'))  #python3加密使用字节类型
        return hs.hexdigest()
    
    
    new_key='%s|%s' % (key,ctime)  # sssdkjrjefjewfakfhkj | 时间戳
    md5_str=MD5(new_key)
    auth_api_val='%s|%s'%(md5_str,ctime)  #d0e0ca7d1f8f72d60715696d4baac3b2(key和时间戳加密后的结果)| 时间戳
    print(md5_str)
    respose=requests.get(url='http://127.0.0.1:8000/test.html/',headers={'auth-api':auth_api_val}).text
    print(respose)
    
    
    
    
    #如果给Django程序发送请求头,如果headers里面的内容使用下滑杠 _,Django会不认识;
    #auth-api  -----> 转换成 'HTTP_AUTH_API'格式
    #服务端获取clent_key=request.META.get('HTTP_AUTH_API')
    View Code

    服务端

    #api验证装饰器
    def api_auth(func):
        def inner(request,*args,**kwargs):
            server_float_ctime = time.time()
            key = 'sssdkjrjefjewfakfhkj'
            auth_api_val = request.META.get('HTTP_AUTH_API')  # 052dd27c130f4b9b5a8a4ec4b243962d | 1507374976.4620001
            client_md5_str, client_ctime = auth_api_val.split('|', maxsplit=1)
            client_float_ctime = float(client_ctime)
            # 第1关时间限制
            if client_float_ctime + 5 < server_float_ctime:
                return HttpResponse('想要破解密码最在5秒之内')
            # 第二关 MD5加密
            server_md5_str = MD5('%s|%s' % (key, client_ctime))
            if client_md5_str != server_md5_str:
                return HttpResponse('休想')
            # 第三关
            for k in list(visited_keys.keys()): #清空字典访问记录
                v=visited_keys[k]
                if server_float_ctime > v:
                    del visited_keys[k]
            #已经使用过 MD5加密字符串(访问记录)
            if visited_keys.get(client_md5_str):
                return HttpResponse('你放弃吧')
            visited_keys[client_md5_str] = client_float_ctime+5#(只需维护5秒之内访问记录即可,因为超过5秒第一关都过不去了)
            return func(request,*args,**kwargs)
        return inner
    View Code

    漏洞:待各位看官补充。。。。

    参考:http://www.cnblogs.com/wupeiqi/articles/6746744.html

  • 相关阅读:
    nexus 安装与启动(windows本版)
    linux 安装 mysql8
    02、linux 常用指令
    linux 安装tomcat8
    CentOS7使用firewalld打开关闭防火墙与端口
    03、linux 安装jdk
    rabbit mq的使用
    跨域与同源策略
    JDK1.8新特性04--Optional处理空指针问题
    HttpAsyncClient异步调用
  • 原文地址:https://www.cnblogs.com/sss4/p/7635272.html
Copyright © 2011-2022 走看看