前言
在最近遇到一个需求,就是需要把Bugcrowd上全部测试目标需要全部获取。于是便想到了使用自己老久以前学过的简单爬虫来实现。主要就是把全部能够获取赏金的项目的测试URL全部爬取后存储到本地,然后直接丢进扫描工具进行扫描,使得实现自动化挖洞。
分析
首先查看有赏金的项目页面是这样的
访问的URL:
https://bugcrowd.com/programs?vdp[]=false&hidden[]=false&sort[]=promoted-desc
使用burp抓包发现,我们只需访问接口:
https://bugcrowd.com/programs.json?vdp[]=false&sort[]=promoted-desc&page[]=1
然后通过更换page[]的参数即可实现换页。而响应包里面的program_url正是打开每一个项目的所对应的URI地址,只需要拼接一下即可访问到项目。
继续抓包分析发现,我们访问这类的地址:
https://bugcrowd.com/program_url/target_groups
URL格式:https://bugcrowd.com/项目名称/target_groups;于是就会得到targets_url接口
当我把这个接口拼接上域名访问,即可获得所被测试的目标。响应包中所有的URI即 我们需要的测试目标
大概三个步骤:
1.获取每一页的项目,得到项目的program_url
2.根据每个项目的program_url去请求target_groups,得到接口,接口可能是一个或者两个或者更多
3.请求上述得到的接口,在响应包里面的uri有我们想要的内容
编写
实现请求多个页面获取项目的program_url的代码
def getTarget():
#获取范围从1到9的整数,这里就是1-9页的数据
for i in range(1,10):
url = f'https://bugcrowd.com/programs.json?vdp[]=false&sort[]=promoted-desc&hidden[]=false&page[]={i}'
print("第"+ str(i) +"页:"+url)
# 请求发送
response = httpx.get(url=url, headers=headers,timeout=None,verify=False)
# 获取响应数据
json_data = json.loads(response.text)
#因为返回的是json,所以比较好处理直接通过for输出我们想要的目标
for program in json_data["programs"]:
#获取了资产(公司)的名称
program_url = program.get("program_url")
if program_url:
#根据资产构建获取URL的api
programUrlEnd = "https://bugcrowd.com" + program_url+"/target_groups"
# 获取每个目标的Api,如特斯拉的资产Api
getTargetApi(program_url,programUrlEnd)
#随机延迟一下,时间是4-15s这个区间
time = random.randint(4,16)
print("延迟"+str(time)+"s")
sleep(time)
print("n")
实现请求target_groups,得到接口的代码
def getTargetApi(program_url,url):
#根据资产名称的接口获取能够获取资产的API
print("资产名:"+program_url.replace("/", ""))
print("探测获取API:"+url)
response = httpx.get(url=url, headers=headers, timeout=None,verify=False)
print("状态:"+str(response.status_code))
#如果不能资产名称的接口,就忽略掉,这里只要成功200的
if response.status_code == 200:
targetApiArry = []
#这里是存储了能获取到资产的公司的名称(或项目名称)
programNameArry.append(program_url.replace("/", ""))
#拿到了获取资产的结果
json_data = json.loads(response.text)
for targets in json_data["groups"]:
#也是json格式的数据,我们把想要的拿出来
targets_url = targets.get("targets_url")
if targets_url:
targets_url = "https://bugcrowd.com" + targets_url
print("Api:"+ targets_url)
targetApiArry .append(targets_url)
#封装为一个字典,每一个资产对应属于自己的接口
targetApiDit[program_url.replace("/", "")] = targetApiArry
print("n")
实现根据资产获取uri的代码
def getTargetUrl():
#遍历我们上面拿到的一个字典,里面存储着项目名称以及能够获取到测试URL的接口
for key, values in targetApiDit.items():
print("当前资产:"+key)
#定义一个空数组,循环一次就清空一次,同时下面也会同步写入到一个新的字典里面,实现了每个项目名称所对应的测试URL
TargetUrl = []
for value in values:
#进行请求获取测试URL的API
response = httpx.get(url=value, headers=headers, timeout=None,verify=False)
#获取响应数据
json_data = json.loads(response.text)
#遍历一下,拿到uri
for uri in json_data["targets"]:
uri_url = uri.get("uri")
if uri_url:
#把同一个项目的URI存到这个数组里面
TargetUrl.append(uri_url)
#把所有的URI都存到这个数组里面,下面直接调用就输出了一个全部URI的txt文件
MergeTxt.append(uri_url)
#根据测试项目做为key,所属项目的测试URI做为value 构造成一个新的字典,下面写到Excel的时候用到
resultXlsxDit[key] = TargetUrl
实现把所有测试URL写入到txt的代码
def outPutMergeTxt():
# 打开文本文件进行写入
with open('output.txt', 'w') as file:
# 将数组中的每个元素写入文本文件的新行中
for item in MergeTxt:
file.write(str(item) + 'n')
实现使用panda模块把对应测试项目的URL写入到Excel表格的代码
def outPutXlsx():
# 将字典转换为DataFrame
df = pd.DataFrame(pd.DataFrame.from_dict(resultXlsxDit, orient='index').values.T,
columns=list(resultXlsxDit.keys())) # 防止输入的数值长度不一样的时候会崩掉
# 将DataFrame保存为XLSX文件
df.to_excel('output.xlsx', engine='xlsxwriter',index=False)
在主函数中进行一次调用即可。
最终效果:
所生成的txt
所生成的Excel
总结
1.目前的不足:所获取到的URL里面有些是下载移动端的链接,如跳转到谷歌或苹果商城的URL,这个后续可以写一段代码进行匹配过滤。
2.踩坑,一开始打算使用xpath来实现。当我已经实现了获取测试的URL之后,发现这个是异步请求的,如果需要使用xpath的话,就要先把加载好的页面下载到本地之后,才能有完整的数据,最后抓包发现,直接使用接口请求,处理一下json格式的响应包即可。
原文始发于微信公众号(pentest):编写爬虫获取Bugcrowd的测试目标
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论