配合mitmproxy使用自动化工具测试阿里云API网关接口

对阿里云API网关接口(ali api gateway)的每次请求都需要校验签名,url和body变动都会导致签名变化。这就导致在渗透测试过程中,无法使用SQLMAP这样的自动化工具来测试api gateway接口的sql注入漏洞。
mitmproxy(https://mitmproxy.readthedocs.io/en/v2.0.2/mitmproxy.htm) 顾名思义,mitmproxy 就是用于 MITM 的 proxy,MITM 即中间人攻击(Man-in-the-middle attack)。
用于中间人攻击的代理首先会向正常的代理一样转发请求,也可以查、记录其截获的数据,或篡改数据,引发服务端或客户端特定的行为。
同理,可以将一个没有签名header的request接获,添加签名头,再发给api服务器,从而让自动化测试工具只需要配置一个代理即可正常工作。

签名代码如下,修改了部分签名代码,将url和data作为参数,方便在mitm.py里面调用:

# -*- coding: UTF-8 -*-

import json
import requests
from sdk.util import UUIDUtil, DateUtil
from sdk.auth import md5_tool, signature_composer, sha_hmac256
try:
    from urllib.parse import urlparse
except ImportError:
     from urlparse import urlparse


appKey = "xxx"
appSecret = "xx"

def signreq(data,aurl):     
    u = urlparse(aurl)
    host = u.scheme + '://' + u.netloc
    url = u.path
    timestamp =  DateUtil.get_timestamp()
    Datet = DateUtil.get_rfc_2616_date() 
 
    accept = '*/*'
    request_method = "POST"
    xcanonce = UUIDUtil.get_uuid()
    contentmd5 = md5_tool.get_md5_base64_str(json.dumps(data))

    
    str_to_sign = ''

     
    headers = {
    'Content-MD5': contentmd5, 
    'User-Agent':'Mozilla/5.0 (iPhone; CPU iPhone OS 13_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 MicroMessenger/7.0.12(0x17000c2d) NetType/WIFI Language/zh_CN',
    #'Content-Length':'',
    'Content-Type': 'application/json',
    "Accept": '*/*',
    "Date": Datet
    }

    headers['x-ca-signaturemethod'] = 'HmacSHA356'
    headers['x-ca-nonce'] = xcanonce
    headers['x-ca-key']= appKey
    headers['X-ca-stage']= 'RELEASE'
    str_to_sign = signature_composer.build_sign_str(uri=url, method=request_method,
     
                                                           headers=headers)


    xcasignature = sha_hmac256.sign(str_to_sign, appSecret)
    headers['X-Ca-Signature'] = xcasignature
    headers['X-Ca-Signature-headers'] = "x-ca-key,x-ca-nonce,x-ca-signaturemethod"
    

    tstr_to_sign = str_to_sign.replace('\n','#',100)

    #print(100*'-'+ tstr_to_sign + 100*'-')

    headers['x-ca-signature'] = xcasignature
 
    #print(headers)

    return headers


if __name__ == '__main__':
    data = {"xxxx": "xxxx"}
    url = 'https://api.xx.xxx.cn/tier/get'
    head = signreq(data,url)
    r = requests.post(url, data=json.dumps(data), headers=head, verify=False)
    print(r.headers, r.text)

 



mitm.py 代码


"""
./mitmproxy --listen-host 0.0.0.0 --listen-port    -s mitm.py



"""
import json
from signreq import signreq
from mitmproxy import ctx

def request(flow):
    # 获取
    req= flow.request
    #print(req.headers)
    #print(dir(req))
    print(flow.request.pretty_url)
    url = flow.request.pretty_url
    body  = req.content.decode('UTF-8')
    data = json.loads(body)
    print(url)
    print(data)
    new_headers = signreq(data,url)
    #print(new_headers)
    for k,v in new_headers.items():
      req.headers[k] = v 


def response(flow):
    response = flow.response 
    print(response.text)
    ctx.log.info(str(response.status_code))

运行mitmweb或者mitmproxy,-s指定自己写得脚本mitm.py, 默认mitmproxy监听0.0.0.0:8080。


mitmweb -v  -s mitm.py  


可以使用proxychain跑个sqlmap测试是否配置成功:

proxychains sqlmap -u  https://xxx.cn/xx/xx/xx--data \{\"xxx\":\"xx\",\"xx\":\"xx*\"\}  --ignore-code=400  -v 7

跑burpsuite的话可以通过配置burpsuite upstream为mitmproxy的监听地址,这样所有burpsuite发出去的包都会经过mitmproxy添加签名头再发出去,这样有个缺点是在burp里面看不到mitmproxy修改后的包。

举一反三,也可以让burpsuite作为mitmproxy的upstream,192.168.137.1:8080是burp监听地址端口,这样所有的包都会先发到mitmproxy添加signature头,再发到burpsuite:

mitmproxy  -s mitm.py --mode upstream:192.168.137.1:8080 --ssl-insecure 

文中所有代码在
https://github.com/xiaoxiaoleo/mitmproxy_alicloud_api_gateway

--- --- --- --- From 小小leo 的博客 --- --- --- ---
posted @ 2020-05-23 23:12  小小leo  阅读(685)  评论(0编辑  收藏  举报