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
漏洞:待各位看官補充。。。。
API驗證插件