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

服务端

import hashlib
import time

def MD5(arg):
    hs = hashlib.md5()
    hs.update(arg.encode('utf-8'))  # python3加密使用字节类型
    return hs.hexdigest()
visited_keys={} #使用memcached redis 超时时间5秒
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)
    #第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('休想')
    #第三关
    if visited_keys.get(client_md5_str):
        return HttpResponse('你放弃吧')
    visited_keys[client_md5_str]=client_float_ctime
    return HttpResponse('OK')
View Code

 

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

 

 
 
 

posted on 2017-10-07 21:35  bigdata_devops  阅读(350)  评论(0编辑  收藏  举报

导航