diff --git a/README.en.md b/README.en.md
index 9dffe73..878ca72 100644
--- a/README.en.md
+++ b/README.en.md
@@ -1,196 +1,86 @@
-# :rooster:0x00 Preface
+
-
-
-> March 7, 2022
->
-> I think the documentation is not very clear, wait for the time to update the full documentation of the use of tutorials
-> March 8, 2022
->
-> May 29, 2022
->
-> 1. updated the aws storage bucket detection feature
->
-> 2. feel that the update is a bit slow, this is a busy time, in fact, the new local version is written, has not been push
-
-**Using tutorial**: [Using tutorial](使用教程.md)
-
-**Language**
-
-English README: [English](README.en.md)
-
-I want to write a storage bucket utilization, first draw a pie for myself
-
-+ Aliyun Cloud (Aliyun Cloud Oss)
-+ Tencent Cloud COS
-+ Huawei Cloud (HuaWei Cloud OBS)
-+ AWS (Amazon S3 Bucket)
-+ Azure (Azure Blob)
-+ GCP (Google Cloud Bucket)
-
-I don't even think about the name of the tool, I believe the big guys will know when they see the project name... King of machine flip
-
-If you think it works fine, you can raise an issue to give the tool a name? :sos:
-
-:waning_crescent_moon:**painting pie progress**
-
-1, Ali cloud storage bucket use
-
-Not too good with Git, code writing also sucks, there are bugs directly mention Issue can (as if I may not even use issue to understand)
-
-> Good thing the second master recommended to me GitHub Desktop second master YYDS
-
-2, AWS storage bucket use
-
-# :pill:0x01 dependency
-
-+ pip3 install oss2
-+ pip3 install colorlog
-+ pip3 install argparse
-+ pip3 install boto3
-
-# :gun:0x02 Usage
+# :rooster:Tutorial
```bash
git clone https://github.com/UzJu/Cloud-Bucket-Leak-Detection-Tools.git
+cd Cloud-Bucket-Leak-Detection-Tools/
+pip3 install -r requirements.txt
python3 main.py -h
```
-Then write your own Aliyun AK in config/conf.py, the role is as follows
+
-1, if you can hijack, will use the AK to create a storage bucket of the same name
+You need to configure your corresponding cloud vendor AK in the `config/conf.py` file before using it.
-2, used to verify the legitimate user
+
-
+## 1、Ariyun storage bucket
-## 1. When storage bucket Policy permission is available
+### 1.1, single storage bucket detection
-
+```bash
+python3 main.py -aliyun [BucketURL]
+```
-## 2. When the storage bucket does not exist (automatically created and hijacked)
+
-
+### 1.2. Automatic bucket hijacking
-## 3、Batch detection of storage buckets
+Automatically hijack a bucket when it is detected as not existing
-New detection function of batch storage bucket, recommend fofa to export all assets with one click
+
-**fofa**
+### 1.3. Bulk bucket address detection
```bash
+# fofa syntax
domain="aliyuncs.com"
-server="AliyunOSS" domain="aliyuncs.com" #This syntax is not recommended
+server="AliyunOSS" domain="aliyuncs.com"
```
```bash
-python3 main.py -f aws/aliyun filepath
-
-# For example
-python3 main.py -f aws . /url.tx\\\\\\\``````````````````````````````````````````````````````````````````````````
+# Use -faliyun
+python3 main.py -faliyun url.txt
```
-Then just wait, the scan results will be in the results directory with the date of the day as the filename
-
-
-
-
-
-Only buckets that have permission to operate will be saved
-
-
-Input the storage bucket address to detect automatically, the function is as follows
-
-+ 1. detect whether the current bucket can be hijacked
- + If it can be hijacked, automatically create a bucket with the same name on the AK account written in the config and open all permissions
-+ 2. detect whether the current bucket can list Object
-+ 3. Check if the current bucket can get ACL
-+ 4、Check if the current bucket can get Policy policy table
-+ 5、Detect whether the bucket can upload Objects
-+ 6、Batch detection function
-
-## 4、Domain name detection function
-
-Many storage buckets have resolved the domain name, the new judgment of the domain name CNAME, and then take the CNAME to detect
-
-** can now directly import a large number of domain name assets for detection, will automatically determine the CNAME of the domain name **
-
-
+
-# 0x03 Ali cloud storage bucket utilization
-
-### 1、Implementation ideas
-
-First implement the `OssBucketCheckFromSDK` class
-
-+ AliyunOssBucketDoesBucketExist
-
- + AliyunOssBucketDoesBucketExist is used to determine whether the current bucket exists, first if the bucket exists then return a True, continue with the following process, if the bucket does not exist, then call the OssBucketExploitFromSDK class, create the bucket, and set ACL permissions, upload access policy, then upload a file for verification, if the bucket exists at this time or AccessDenied, continue with the following process
-
-+ AliyunOssGetBucketObjectList
-
- + determine if the contents of the bucket can be traversed, and if so, the first 3 contents will be selected for traversal and displayed
-
- > If you want to iterate through more content, you can check the AliyunOssGetBucketObjectList method in aliyunOss.py
-
-+ AliyunOssGetBucketAcl
-
- + determine if the current Bucket's ACL can be accessed, if so, return the current Bucket's ACL, if not, continue with the following Check process
-
-+ AliyunOssGetBucketPolicy
-
- + Determine if the policy of the current Bucket can be accessed, if so, the ACL of the current Bucket will be returned, if not, continue with the following Check process
-
-+ AliyunOssGetBucketObject
-
- + Try to upload a file, whether it can be successfully uploaded
-
-# 0x04 Aws storage bucket utilization
+## 2. Tencent cloud storage bucket
```bash
-python3 main.py -aws xxxx
+python3 main.py -tcloud [storage bucket address]
```
-
+
-# 0x05 Explanation of the results file after use
+## 3. Huawei cloud storage bucket
-You can see the problematic bucket in the results directory
-
-
-
-1, ListObject means the contents of the bucket can be listed
-
-2、PutObject means that the bucket can upload any file
-
-3、NoSuchBucket means the bucket can be taken over
-
-4、GetBucketACL means you can get the ACL of the bucket
-
-5、GetBucketPolicy means you can get the policy configuration of the bucket
-
-# :older_man:0x040001 Update Log
+```bash
+python3 main.py -hcloud [storage bucket address]
+```
-**March 6, 2022**
+
-+ Add batch scan function
-+ Fix the Fake_UserAgent error reporting problem
+## 4. AWS storage bucket
-> actually just delete this library, don't use it ^ ^
+```bash
+python3 main.py -aws [storage bucket address]
+```
-**March 7, 2022**
+images/image-20220716142431142.png)
-+ Added domain detection
+## 5. Scan results saving
-**May 29, 2022**
+The scan results will be stored in the `results` directory
-- Added AWS storage bucket scan
+
-# :cop:0xffffffff Disclaimer
+
-Disclaimers
+# :cop:0xFFFFFFFF Disclaimer
-1、This tool is for academic exchange only, it is forbidden to use the tool to do illegal things
+1、This tool is only for academic exchange, it is forbidden to use the tool to do illegal things
2, just writing for fun
@@ -198,8 +88,13 @@ Disclaimers
> If you have a better suggestion or make a friend
-
+
+
+4、Blog: UzzJu.com
+5、Public
+
+
# Curve chart
-[](https://starchart.cc/UzJu/Cloud-Bucket-Leak-Detection-Tools)
\ No newline at end of file
+[](https://starchart.cc/UzJu/Cloud-Bucket-Leak-Detection-Tools)
\ No newline at end of file
diff --git a/README.md b/README.md
index 7ed1c46..29a2a91 100644
--- a/README.md
+++ b/README.md
@@ -1,162 +1,86 @@
-# :rooster:0x00 前言
-

-**使用教程**: [使用教程](使用教程.md)
-
-**语言/Language**
-
-English README: [English](README.en.md)
-
-# :pill:0x01 依赖
-
-```bash
-pip3 install -r requirements.txt
-```
-
-# :gun:0x02 使用方法
+# :rooster:使用教程
```bash
git clone https://github.com/UzJu/Cloud-Bucket-Leak-Detection-Tools.git
+cd Cloud-Bucket-Leak-Detection-Tools/
+# 安装依赖 建议使用Python3.8以上的版本 我的版本: Python 3.9.13 (main, May 24 2022, 21:28:31)
+pip3 install huaweicloud-sdk-python
+pip3 install -r requirements.txt
python3 main.py -h
```
-随后在config/conf.py中写入自己的AK,作用如下
+
-1、如果可以劫持,会用该AK创建同名的存储桶
+使用之前需要在`config/conf.py`文件配置自己对应的云厂商AK
-2、用来验证合法用户
+
-
+## 1、阿里云存储桶
-## 1、当存储桶Policy权限可获取时
+### 1.1、单个存储桶检测
-
+```bash
+python3 main.py -aliyun [存储桶URL]
+```
-## 2、当存储桶不存在时(自动创建并劫持)
+
-
+### 1.2、自动存储桶劫持
-## 3、批量检测存储桶
+当如果检测存储桶不存在时会自动劫持该存储桶
-新增批量存储桶的检测功能,推荐fofa一键导出所有资产
+
-**fofa**
+### 1.3、批量存储桶地址检测
```bash
+# fofa语法
domain="aliyuncs.com"
-server="AliyunOSS"domain="aliyuncs.com" #不推荐该语法
+server="AliyunOSS"domain="aliyuncs.com"
```
```bash
- python3 main.py -faliyun url.txt
+# 使用-faliyun
+python3 main.py -faliyun url.txt
```
-随后等待即可,扫描结果会在results目录下,文件名为当天的日期
-
-
-
-随后会将结果保存至csv
-
-
-输入存储桶地址即可自动检测,功能如下
-
-+ 1、检测当前存储桶是否可劫持
- + 如果可劫持,自动在config中写入的AK账号上创建同命名的存储桶并开放所有权限
-+ 2、检测当前存储桶是否可列出Object
-+ 3、检测当前存储桶是否可获取ACL
-+ 4、检测当前存储桶是否可获取Policy策略表
-+ 5、检测存储桶是否可上传Object
-+ 6、批量检测功能
-
-## 4、域名检测功能(v0.3.0暂未支持)
-
-很多存储桶都解析了域名,新增判断域名的CNAME,然后取CNAME来进行检测
-
-**现在可以直接导入大量域名资产来进行检测,会自动判断域名的CNAME**
-
-
-
-# 0x03 阿里云存储桶利用
-
-### 1、实现思路
-
-首先实现了`OssBucketCheckFromSDK`类
-
-+ AliyunOssBucketDoesBucketExist
+
- + 用来判断当前存储桶是否存在,首先如果存储桶存在那么就返回一个True,继续走下面的流程,如果存储桶不存在,那么就调用OssBucketExploitFromSDK类,创建存储桶,并且设置ACL权限,上传访问策略,随后上传一个文件进行验证,如果存储桶此时存在或者为AccessDenied,继续走下面的流程
-
-+ AliyunOssGetBucketObjectList
-
- + 判断是否可以遍历存储桶中的内容,如果可以,则会选择前3个内容进行遍历并显示
-
- > 如果想遍历更多的内容,可以查看aliyunOss.py中的AliyunOssGetBucketObjectList方法
-
-+ AliyunOssGetBucketAcl
-
- + 判断能否访问当前Bucket的ACL,如果可以的话,就返回当前Bucket的ACL,如果不可以就继续走下面的Check流程
-
-+ AliyunOssGetBucketPolicy
-
- + 判断能否访问当前Bucket的Policy,如果可以的话,就会返回当前Bucket的ACL,如果不可以就继续走下面的Check
-
-+ AliyunOssGetBucketObject
-
- + 尝试上传一个文件,是否可以成功上传
-
-# 0x04 Aws存储桶利用
+## 2、腾讯云存储桶
```bash
-python3 main.py -aws xxxx
+python3 main.py -tcloud [存储桶地址]
```
-
-
-# 0x05 利用后results文件解释
-
-在results目录下可以看到存在问题的存储桶
-
-
+
-1、ListObject 代表该存储桶的内容可以列出来
+## 3、华为云存储桶
-2、PutObject 代表该存储桶可以上传任意的文件
-
-3、NoSuchBucket 代表该存储桶可以接管
-
-4、GetBucketACL 代表可以获取该存储桶的ACL
-
-5、GetBucketPolicy 代表可以获取该存储桶的策略配置
-
-# :older_man:0x040001 更新日志
-
-**2022年3月6日**
-
-+ 新增批量扫描功能
-+ 修复Fake_UserAgent报错的问题
+```bash
+python3 main.py -hcloud [存储桶地址]
+```
-> 其实是直接把这个库删了,不用了^ ^
+
-**2022年3月7日**
+## 4、AWS存储桶
-+ 新增域名检测
+```bash
+python3 main.py -aws [存储桶地址]
+```
-**2022年5月29日**
+
-- 新增AWS存储桶扫描
+## 5、扫描结果保存
-**2022年7月3日**
+扫描结果会存放在`results`目录下
-- 重构项目
- - aliyunoss模块
- - aws模块
- - main模块
- - 扫描模块
+
-# :cop:0xffffffff 免责声明
+
-免责声明
+# :cop:0xFFFFFFFF 免责声明
1、本工具只作为学术交流,禁止使用工具做违法的事情
@@ -166,9 +90,13 @@ python3 main.py -aws xxxx
> 如果你有更好的建议或者交个朋友
-
+
-# 曲线图
+4、博客: UzzJu.com
+5、公众号
+
+
-[](https://starchart.cc/UzJu/Cloud-Bucket-Leak-Detection-Tools)
+# 曲线图
+[](https://starchart.cc/UzJu/Cloud-Bucket-Leak-Detection-Tools)
\ No newline at end of file
diff --git a/UPDATE.md b/UPDATE.md
deleted file mode 100644
index d3caa50..0000000
--- a/UPDATE.md
+++ /dev/null
@@ -1,17 +0,0 @@
-# 阿里云
-## **已完成**
-1、GetObjectList ✅
-2、GetBucketPolicy ✅
-3、PutBucketPolicy ✅
-4、GetBucketAcl ✅
-5、PutBucketAcl ✅
-6、PutBucketObject✅
-7、批量检测✅
-
-8、批量获取域名的CNAME来进行检测✅
-
-## **待完成[画饼,反正画了也不一定写]**
-1、存储桶名称爆破/Object爆破
-
-> 不过感觉还是有点问题,感觉可以试试
-
diff --git a/config/conf.py b/config/conf.py
index 360e7b8..f62b83d 100644
--- a/config/conf.py
+++ b/config/conf.py
@@ -18,8 +18,15 @@
AWS_ACCESS_KEY = ""
AWS_SECRET_KEY = ""
+# tencent
+tencent_cam_id = ""
+tencent_cam_key = ""
-version = "v.0.3.0"
+# huawei
+huawei_access_key_id = ""
+huawei_access_key_key = ""
+
+version = "v.0.4.0"
author = "UzJu"
email = "UzJuer@163.com"
github = "GitHub.com/UzJu"
diff --git a/core/__init__.py b/core/__init__.py
new file mode 100644
index 0000000..77bd5fc
--- /dev/null
+++ b/core/__init__.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python3.8.4 (python版本)
+# -*- coding: utf-8 -*-
+# @Author : UzJu@菜菜狗
+# @Email : UzJuer@163.com
+# @Software: PyCharm
+# @Time : 2022/7/15 14:25
+# @File : __init__.py.py
diff --git a/core/aliyun/__init__.py b/core/aliyun/__init__.py
new file mode 100644
index 0000000..90d82e7
--- /dev/null
+++ b/core/aliyun/__init__.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python3.8.4 (python版本)
+# -*- coding: utf-8 -*-
+# @Author : UzJu@菜菜狗
+# @Email : UzJuer@163.com
+# @Software: PyCharm
+# @Time : 2022/7/15 14:24
+# @File : __init__.py.py
diff --git a/core/aliyunOss.py b/core/aliyun/oss.py
similarity index 99%
rename from core/aliyunOss.py
rename to core/aliyun/oss.py
index 08c0ec6..50e91f1 100644
--- a/core/aliyunOss.py
+++ b/core/aliyun/oss.py
@@ -4,7 +4,7 @@
# @Email : UzJuer@163.com
# @Software: PyCharm
# @Time : 2022/7/2 14:22
-# @File : aliyunOss.py
+# @File : oss.py
import json
import os
from itertools import islice
diff --git a/core/aws/__init__.py b/core/aws/__init__.py
new file mode 100644
index 0000000..77bd5fc
--- /dev/null
+++ b/core/aws/__init__.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python3.8.4 (python版本)
+# -*- coding: utf-8 -*-
+# @Author : UzJu@菜菜狗
+# @Email : UzJuer@163.com
+# @Software: PyCharm
+# @Time : 2022/7/15 14:25
+# @File : __init__.py.py
diff --git a/core/aws.py b/core/aws/aws.py
similarity index 100%
rename from core/aws.py
rename to core/aws/aws.py
diff --git a/core/huaweiyun/__init__.py b/core/huaweiyun/__init__.py
new file mode 100644
index 0000000..77bd5fc
--- /dev/null
+++ b/core/huaweiyun/__init__.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python3.8.4 (python版本)
+# -*- coding: utf-8 -*-
+# @Author : UzJu@菜菜狗
+# @Email : UzJuer@163.com
+# @Software: PyCharm
+# @Time : 2022/7/15 14:25
+# @File : __init__.py.py
diff --git a/core/huaweiyun/obs.py b/core/huaweiyun/obs.py
new file mode 100644
index 0000000..5de8e22
--- /dev/null
+++ b/core/huaweiyun/obs.py
@@ -0,0 +1,55 @@
+#!/usr/bin/python3.8.4 (python版本)
+# -*- coding: utf-8 -*-
+# @Author : UzJu@菜菜狗
+# @Email : UzJuer@163.com
+# @Software: PyCharm
+# @Time : 2022/7/15 14:22
+# @File : obs.py
+
+from obs import ObsClient
+from config import conf
+from config.logs import logger
+
+
+class HuaWeiCloud_OBS_Check:
+ def __init__(self, target, location):
+ self.target = target
+ self.client = ObsClient(
+ access_key_id=conf.huawei_access_key_id,
+ secret_access_key=conf.huawei_access_key_key,
+ server=f'https://obs.{location}.myhuaweicloud.com'
+ )
+
+ def ListObject(self):
+ try:
+ resp = self.client.listObjects(self.target, max_keys=3)
+ for content in resp.body.contents:
+ logger.log("INFOR",
+ f"ObjectKey: {content.key}, owner_id: {content.owner.owner_id}, owner_name: {content.owner.owner_name}")
+ return True
+ except Exception as e:
+ logger.log("ALERT", f"BucketName: {self.target}> ListObject权限不足")
+ logger.log("ERROR", f"BucketName: {self.target}> ListObject > {repr(e)}")
+
+ def PutObject(self):
+ try:
+ resp = self.client.putFile(self.target, objectKey="UzJu.html", file_path="./config/UzJu.html")
+ if resp['status'] == 403:
+ logger.log("ALERT", f"BucketName: {self.target}> PutObject权限不足")
+ else:
+ logger.log("INFOR", f"BucketName: {self.target}> PutObject成功, 访问UzJu.html查看")
+ return True
+ except Exception as e:
+ logger.log("ERROR", repr(e))
+
+ def GetBucketACL(self):
+ try:
+ resp = self.client.getBucketAcl(self.target)
+ if resp['status'] == 200:
+ logger.log("INFOR", f"BucketName: {self.target}> GetBucketACL成功, {resp}")
+ return True
+ elif resp['status'] == 403:
+ logger.log("ALERT", f"BucketName: {self.target}> GetBucketACL权限不足")
+ except Exception as e:
+ logger.log("ERROR", repr(e))
+
diff --git a/core/main.py b/core/main.py
index 401ad10..a2f2c6a 100644
--- a/core/main.py
+++ b/core/main.py
@@ -7,25 +7,28 @@
# @File : main.py
from config.logs import logger
-from plugins.results import aliyun_save_file
-from core import aliyunOss
-from core import aws
+from plugins.results import *
import urllib.parse
import prettytable as pt
import multiprocessing
+from core.aliyun import oss
+from core.aws import aws
+from core.tencent import cos
+from core.huaweiyun import obs
-def aliyun_file_scan(filename):
+
+def Aliyun_file_scan(filename):
target_file = open(filename, mode='r', encoding='utf-8')
p = multiprocessing.Pool(processes=3)
for i in target_file.read().splitlines():
- p.apply_async(aliyun, args=(i,))
+ p.apply_async(Aliyun_OSS, args=(i,))
p.close()
p.join()
p.terminate()
-def aliyun(target):
+def Aliyun_OSS(target):
"""
:desc: aliyun Bucket Scan function
@@ -36,14 +39,23 @@ def aliyun(target):
aliyun_print_table_header = pt.PrettyTable(
['Bucket', 'BucketHijack', 'GetBucketObjectList', 'PutBucketObject', 'GetBucketAcl', 'PutBucketAcl',
'GetBucketPolicy'])
- aliyun_scan_results = {}
+ aliyun_scan_results = {
+ "BucketName": target,
+ "BucketDoesBucketExist": False,
+ "BucketHijack": False,
+ "GetBucketObjectList": False,
+ "PutBucketObject": False,
+ "GetBucketAcl": False,
+ "PutBucketAcl": False,
+ "GetBucketPolicy": False,
+ }
get_domain = urllib.parse.urlparse(target).netloc
if get_domain == "":
get_target_list = target.split('.')
- aliyunOss_Check_init = aliyunOss.Aliyun_Oss_Bucket_Check(target=get_target_list[0],
- location=get_target_list[1])
- aliyunOss_Exploit_init = aliyunOss.Aliyun_Oss_Bucket_Exploit(target=get_target_list[0],
- location=get_target_list[1])
+ aliyunOss_Check_init = oss.Aliyun_Oss_Bucket_Check(target=get_target_list[0],
+ location=get_target_list[1])
+ aliyunOss_Exploit_init = oss.Aliyun_Oss_Bucket_Exploit(target=get_target_list[0],
+ location=get_target_list[1])
if aliyunOss_Check_init.Aliyun_Oss_BucketDoesBucketExist():
logger.log("INFOR", f"{target}> 当前存储桶不存在, 尝试劫持存储桶")
if aliyunOss_Exploit_init.Aliyun_Oss_CreateBucket_Exp():
@@ -53,45 +65,38 @@ def aliyun(target):
aliyunOss_Exploit_init.Aliyun_Oss_PutBucketPolicy_Exp()
aliyunOss_Exploit_init.Aliyun_Oss_GetBucketPolicy_Exp()
aliyunOss_Exploit_init.Aliyun_Oss_PutBucketAcl_Exp()
- aliyun_scan_results.update({"BucketDoesBucketExist": "true"})
else:
- aliyun_scan_results.update({"BucketDoesBucketExist": "false"})
if aliyunOss_Check_init.Aliyun_Oss_GetBucketObject_List():
logger.log("INFOR", f"{target}> 存储桶对象可遍历")
- aliyun_scan_results.update({"GetBucketObject": "true"})
+ aliyun_scan_results['GetBucketObject'] = True
else:
logger.log("ALERT", f"{target}> 存储桶对象不可遍历")
- aliyun_scan_results.update({"GetBucketObject": "false"})
if aliyunOss_Check_init.Aliyun_Oss_PutBucketObject():
logger.log("INFOR", f"{target}> 可未授权上传对象至存储桶(可导致覆盖已有对象)")
- aliyun_scan_results.update({"PutBucketObject": "true"})
+ aliyun_scan_results['PutBucketObject'] = True
else:
logger.log("ALERT", f"{target}> 不可未授权上传对象至存储桶")
- aliyun_scan_results.update({"PutBucketObject": "false"})
if aliyunOss_Check_init.Aliyun_Oss_GetBucketAcl():
logger.log("INFOR", f"{target}> 可公开访问存储桶ACL策略")
- aliyun_scan_results.update({"GetBucketAcl": "true"})
+ aliyun_scan_results['GetBucketAcl'] = True
else:
logger.log("ALERT", f"{target}> 不可公开访问存储桶ACL策略")
- aliyun_scan_results.update({"GetBucketAcl": "false"})
if aliyunOss_Check_init.Aliyun_Oss_PutBucketAcl():
logger.log("INFOR", f"{target}> 可上传覆盖存储桶ACL策略")
- aliyun_scan_results.update({"PutBucketAcl": "true"})
+ aliyun_scan_results['PutBucketAcl'] = True
else:
logger.log("ALERT", f"{target}> 不可上传覆盖存储桶ACL策略")
- aliyun_scan_results.update({"PutBucketAcl": "false"})
results_policy = aliyunOss_Check_init.Aliyun_Oss_GetBucketPolicy()
if results_policy:
logger.log("INFOR", f"{target}> 可公开获取存储桶Policy策略组")
logger.log("INFOR", f"{target}Policy> {results_policy}")
- aliyun_scan_results.update({"GetBucketPolicy": "true"})
+ aliyun_scan_results['GetBucketPolicy'] = True
else:
logger.log("ALERT", f"{target}> 不可公开获取存储桶Policy策略")
- aliyun_scan_results.update({"GetBucketPolicy": "false"})
aliyun_print_table_header.add_row([target,
aliyun_scan_results['BucketDoesBucketExist'],
@@ -107,9 +112,83 @@ def aliyun(target):
aliyun_scan_results['GetBucketAcl'],
aliyun_scan_results['PutBucketAcl'],
aliyun_scan_results['GetBucketPolicy'])
- print(aliyun_print_table_header, "\n")
+ print(aliyun_print_table_header)
+ else:
+ Aliyun_OSS(get_domain)
+
+
+def Tencent_Cloud_Cos(target):
+ tencent_cloud_print_table_header = pt.PrettyTable(
+ ['Bucket', 'ListObject', 'PutObject', 'GetBucketACL'])
+ tencent_cloud_results = {
+ "BucketName": target,
+ "ListObject": False,
+ "PutObject": False,
+ "GetBucketACL": False
+ }
+ get_domain = urllib.parse.urlparse(target).netloc
+ if get_domain == "":
+ if "cos" not in target:
+ logger.log("ALERT", f"当前{target}非COS存储桶地址")
+ return
+ logger.log("INFOR", f"开始扫描> {target}")
+ get_target_list = target.split(".")
+ tencent_check_init = cos.TenCent_Cloud_OBS_Check(target=get_target_list[0],
+ location=get_target_list[2])
+ if tencent_check_init.ListObject():
+ tencent_cloud_results['ListObject'] = True
+ if tencent_check_init.PutObject():
+ tencent_cloud_results['PutObject'] = True
+ if tencent_check_init.GetBucketACL():
+ tencent_cloud_results['GetBucketACL'] = True
+ else:
+ Tencent_Cloud_Cos(target)
+ tencent_cloud_print_table_header.add_row([target,
+ tencent_cloud_results['ListObject'],
+ tencent_cloud_results['PutObject'],
+ tencent_cloud_results['GetBucketACL']])
+ tencent_save_file(target,
+ tencent_cloud_results['ListObject'],
+ tencent_cloud_results['PutObject'],
+ tencent_cloud_results['GetBucketACL'])
+ print(tencent_cloud_print_table_header)
+
+
+def Huawei_Cloud_OBS(target):
+ huawei_cloud_print_table_header = pt.PrettyTable(
+ ['Bucket', 'ListObject', 'PutObject', 'GetBucketACL'])
+ huawei_cloud_results = {
+ "BucketName": target,
+ "ListObject": False,
+ "PutObject": False,
+ "GetBucketACL": False
+ }
+ get_domain = urllib.parse.urlparse(target).netloc
+ if get_domain == "":
+ if "obs" not in target:
+ logger.log("ALERT", f"当前{target}非OBS存储桶地址")
+ return
+ logger.log("INFOR", f"开始扫描> {target}")
+ get_target_list = target.split(".")
+ huaweiyun_check_init = obs.HuaWeiCloud_OBS_Check(target=get_target_list[0],
+ location=get_target_list[2])
+ if huaweiyun_check_init.ListObject():
+ huawei_cloud_results['ListObject'] = True
+ if huaweiyun_check_init.PutObject():
+ huawei_cloud_results['PutObject'] = True
+ if huaweiyun_check_init.GetBucketACL():
+ huawei_cloud_results['GetBucketACL'] = True
else:
- aliyun(get_domain)
+ Huawei_Cloud_OBS(target)
+ huawei_cloud_print_table_header.add_row([target,
+ huawei_cloud_results['ListObject'],
+ huawei_cloud_results['PutObject'],
+ huawei_cloud_results['GetBucketACL']])
+ huawei_save_file(target,
+ huawei_cloud_results['ListObject'],
+ huawei_cloud_results['PutObject'],
+ huawei_cloud_results['GetBucketACL'])
+ print(huawei_cloud_print_table_header)
def AmazoneS3(target):
@@ -119,6 +198,14 @@ def AmazoneS3(target):
:param target: bucket url
:return:
"""
+ aws_print_table_header = pt.PrettyTable(
+ ['Bucket', 'ListObject', 'PutObject', 'GetBucketACL'])
+ aws_results = {
+ "BucketName": target,
+ "ListObject": False,
+ "PutObject": False,
+ "GetBucketACL": False
+ }
get_domain = urllib.parse.urlparse(target).netloc
if get_domain == "":
logger.log("INFOR", f"开始扫描> {target}")
@@ -127,17 +214,29 @@ def AmazoneS3(target):
location=get_target_list[1])
if aws_check_init.Check_Bucket_ListObject():
logger.log("INFOR", f"{target}> 存储桶对象可遍历")
+ aws_results['ListObject'] = True
else:
logger.log("ALERT", f"{target}> 存储桶对象不可遍历")
if aws_check_init.Check_Bucket_PutObject():
logger.log("INFOR", f"{target}> 可未授权上传对象至存储桶(可覆盖存储桶已有对象)")
+ aws_results['PutObject'] = True
else:
logger.log("ALERT", f"{target}> 不可未授权上传对象至存储桶(可覆盖存储桶已有对象)")
if aws_check_init.Check_Bucket_GetBucketAcl():
logger.log("INFOR", f"{target}> 存储桶ACL策略可公开获取")
+ aws_results['GetBucketACL'] = True
else:
logger.log("ALERT", f"{target}> 存储桶ACL策略不可公开")
else:
AmazoneS3(get_domain)
+ aws_print_table_header.add_row([target,
+ aws_results['ListObject'],
+ aws_results['PutObject'],
+ aws_results['GetBucketACL']])
+ aws_save_file(target,
+ aws_results['ListObject'],
+ aws_results['PutObject'],
+ aws_results['GetBucketACL'])
+ print(aws_print_table_header)
diff --git a/core/tencent/__init__.py b/core/tencent/__init__.py
new file mode 100644
index 0000000..90d82e7
--- /dev/null
+++ b/core/tencent/__init__.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python3.8.4 (python版本)
+# -*- coding: utf-8 -*-
+# @Author : UzJu@菜菜狗
+# @Email : UzJuer@163.com
+# @Software: PyCharm
+# @Time : 2022/7/15 14:24
+# @File : __init__.py.py
diff --git a/core/tencent/cos.py b/core/tencent/cos.py
new file mode 100644
index 0000000..9c33e81
--- /dev/null
+++ b/core/tencent/cos.py
@@ -0,0 +1,61 @@
+#!/usr/bin/python3.8.4 (python版本)
+# -*- coding: utf-8 -*-
+# @Author : UzJu@菜菜狗
+# @Email : UzJuer@163.com
+# @Software: PyCharm
+# @Time : 2022/7/15 11:58
+# @File : cos.py
+
+from qcloud_cos import CosConfig
+from qcloud_cos import CosS3Client
+from config import conf
+from config.logs import logger
+
+
+class TenCent_Cloud_OBS_Check:
+ def __init__(self, target, location):
+ self.target = target
+ config = CosConfig(Region=location, SecretId=conf.tencent_cam_id, SecretKey=conf.tencent_cam_key)
+ self.client = CosS3Client(config)
+
+ def ListObject(self):
+ try:
+ resp = self.client.list_objects(Bucket=self.target)
+ if 'Contents' in resp:
+ for content in resp['Contents']:
+ logger.log("INFOR", f"ListObject> {content['Key']}")
+ return True
+ except Exception as e:
+ if "Access Denied." in repr(e):
+ logger.log("ALERT", f"{self.target}> ListObject权限不足")
+ else:
+ logger.log("ERROR", repr(e))
+ return False
+
+ def PutObject(self):
+ try:
+ self.client.upload_file(Bucket=self.target,
+ Key="index.html",
+ LocalFilePath="./config/UzJu.html",
+ ACL="public-read",
+ ContentType="text/html")
+ logger.log("INFOR", f"{self.target}> PutObject成功 访问index.html查看结果")
+ return True
+ except Exception as e:
+ if "Access Denied." in repr(e):
+ logger.log("ALERT", f"{self.target}> PutObject权限不足")
+ else:
+ logger.log("ERROR", repr(e))
+ return False
+
+ def GetBucketACL(self):
+ try:
+ resp = self.client.get_bucket_acl(Bucket=self.target)
+ logger.log("INFOR", f"{self.target}> GetBucketACL成功, 策略: {resp}")
+ return True
+ except Exception as e:
+ if "Access Denied." in repr(e):
+ logger.log("ALERT", f"{self.target}> GetBucketACL权限不足")
+ else:
+ logger.log("ERROR", repr(e))
+ return False
diff --git a/images/Cloud-Bucket-Leak-Detection-Tools.svg b/images/Cloud-Bucket-Leak-Detection-Tools.svg
new file mode 100644
index 0000000..b100662
--- /dev/null
+++ b/images/Cloud-Bucket-Leak-Detection-Tools.svg
@@ -0,0 +1,572 @@
+
\ No newline at end of file
diff --git a/images/image-20220703202549284.png b/images/image-20220703202549284.png
new file mode 100644
index 0000000..29d0516
Binary files /dev/null and b/images/image-20220703202549284.png differ
diff --git a/images/image-20220716140707903.png b/images/image-20220716140707903.png
new file mode 100644
index 0000000..dea5f54
Binary files /dev/null and b/images/image-20220716140707903.png differ
diff --git a/images/image-20220716140934866.png b/images/image-20220716140934866.png
new file mode 100644
index 0000000..5f25eb2
Binary files /dev/null and b/images/image-20220716140934866.png differ
diff --git a/images/image-20220716141132931.png b/images/image-20220716141132931.png
new file mode 100644
index 0000000..6ebff15
Binary files /dev/null and b/images/image-20220716141132931.png differ
diff --git a/images/image-20220716141356518.png b/images/image-20220716141356518.png
new file mode 100644
index 0000000..c08c8ad
Binary files /dev/null and b/images/image-20220716141356518.png differ
diff --git a/images/image-20220716141554856.png b/images/image-20220716141554856.png
new file mode 100644
index 0000000..ffd6d02
Binary files /dev/null and b/images/image-20220716141554856.png differ
diff --git a/images/image-20220716141948046.png b/images/image-20220716141948046.png
new file mode 100644
index 0000000..337f848
Binary files /dev/null and b/images/image-20220716141948046.png differ
diff --git a/images/image-20220716142431142.png b/images/image-20220716142431142.png
new file mode 100644
index 0000000..ff8e8f4
Binary files /dev/null and b/images/image-20220716142431142.png differ
diff --git a/images/image-20220716142617997.png b/images/image-20220716142617997.png
new file mode 100644
index 0000000..eeb7a38
Binary files /dev/null and b/images/image-20220716142617997.png differ
diff --git a/images/image-20220716142641883.png b/images/image-20220716142641883.png
new file mode 100644
index 0000000..076f324
Binary files /dev/null and b/images/image-20220716142641883.png differ
diff --git a/images/image-20220716143619529.png b/images/image-20220716143619529.png
new file mode 100644
index 0000000..0e67179
Binary files /dev/null and b/images/image-20220716143619529.png differ
diff --git a/main.py b/main.py
index 07d35ab..4e3bdc5 100644
--- a/main.py
+++ b/main.py
@@ -17,12 +17,18 @@
parser = argparse.ArgumentParser()
parser.add_argument('-aliyun', dest='aliyun', help='python3 main.py -aliyun Bucketurl')
parser.add_argument('-faliyun', dest='faliyun', help='python3 main.py -faliyun filename')
+ parser.add_argument('-tcloud', dest='tencent_cloud', help='python3 main.py -tcloud BucketUrl')
+ parser.add_argument('-hcloud', dest='huawei_cloud', help='python3 main.py -hcloud BucketUrl')
parser.add_argument('-aws', dest='aws', help='python3 main.py -aws bucketurl')
args = parser.parse_args()
if args.aliyun:
- main.aliyun(args.aliyun)
+ main.Aliyun_OSS(args.aliyun)
elif args.faliyun:
- main.aliyun_file_scan(args.faliyun)
+ main.Aliyun_file_scan(args.faliyun)
+ elif args.tencent_cloud:
+ main.Tencent_Cloud_Cos(args.tencent_cloud)
+ elif args.huawei_cloud:
+ main.Huawei_Cloud_OBS(args.huawei_cloud)
elif args.aws:
main.AmazoneS3(args.aws)
diff --git a/plugins/results.py b/plugins/results.py
index f722a96..cea1d75 100644
--- a/plugins/results.py
+++ b/plugins/results.py
@@ -12,9 +12,11 @@
from config.conf import NowTime
-def aliyun_save_file(target, BucketHijack, GetBucketObjectList, PutBucketObject, GetBucketAcl, PutBucketAcl, GetBucketPolicy):
- headers = ['Bucket', 'BucketHijack', 'GetBucketObjectList', 'PutBucketObject', 'GetBucketAcl', 'PutBucketAcl', 'GetBucketPolicy']
- filepath = f'{os.getcwd()}/results/{NowTime}.csv'
+def aliyun_save_file(target, BucketHijack, GetBucketObjectList, PutBucketObject, GetBucketAcl, PutBucketAcl,
+ GetBucketPolicy):
+ headers = ['Bucket', 'BucketHijack', 'GetBucketObjectList', 'PutBucketObject', 'GetBucketAcl', 'PutBucketAcl',
+ 'GetBucketPolicy']
+ filepath = f'{os.getcwd()}/results/aliyun_{NowTime}.csv'
rows = [
[f"{target}", BucketHijack, GetBucketObjectList, PutBucketObject, GetBucketAcl, PutBucketAcl, GetBucketPolicy]
]
@@ -28,3 +30,53 @@ def aliyun_save_file(target, BucketHijack, GetBucketObjectList, PutBucketObject,
f_csv = csv.writer(f)
f_csv.writerows(rows)
+
+def tencent_save_file(target, ListObject, PutObject, GetBucketACL):
+ headers = ['Bucket', 'ListObject', 'PutObject', 'GetBucketACL']
+ filepath = f'{os.getcwd()}/results/tencentcloud_{NowTime}.csv'
+ rows = [
+ [f"{target}", ListObject, PutObject, GetBucketACL]
+ ]
+ if not os.path.isfile(filepath):
+ with open(filepath, 'a+', newline='') as f:
+ f = csv.writer(f)
+ f.writerow(headers)
+ f.writerows(rows)
+ else:
+ with open(filepath, 'a+', newline='') as f:
+ f_csv = csv.writer(f)
+ f_csv.writerows(rows)
+
+
+def huawei_save_file(target, ListObject, PutObject, GetBucketACL):
+ headers = ['Bucket', 'ListObject', 'PutObject', 'GetBucketACL']
+ filepath = f'{os.getcwd()}/results/huaweicloud_{NowTime}.csv'
+ rows = [
+ [f"{target}", ListObject, PutObject, GetBucketACL]
+ ]
+ if not os.path.isfile(filepath):
+ with open(filepath, 'a+', newline='') as f:
+ f = csv.writer(f)
+ f.writerow(headers)
+ f.writerows(rows)
+ else:
+ with open(filepath, 'a+', newline='') as f:
+ f_csv = csv.writer(f)
+ f_csv.writerows(rows)
+
+
+def aws_save_file(target, ListObject, PutObject, GetBucketACL):
+ headers = ['Bucket', 'ListObject', 'PutObject', 'GetBucketACL']
+ filepath = f'{os.getcwd()}/results/aws_{NowTime}.csv'
+ rows = [
+ [f"{target}", ListObject, PutObject, GetBucketACL]
+ ]
+ if not os.path.isfile(filepath):
+ with open(filepath, 'a+', newline='') as f:
+ f = csv.writer(f)
+ f.writerow(headers)
+ f.writerows(rows)
+ else:
+ with open(filepath, 'a+', newline='') as f:
+ f_csv = csv.writer(f)
+ f_csv.writerows(rows)
diff --git a/requirements.txt b/requirements.txt
index 50b3933..19c1053 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,36 @@
-boto3==1.23.9
-colorama==0.4.4
+aliyun-python-sdk-core==2.13.36
+aliyun-python-sdk-kms==2.15.0
+boto3==1.24.31
+botocore==1.27.31
+certifi==2022.6.15
+cffi==1.15.1
+charset-normalizer==2.1.0
+colorama==0.4.5
+crcmod==1.7
+cryptography==37.0.4
+deprecation==2.1.0
dnspython==2.2.1
-loguru==0.5.3
+huaweicloud-sdk-python==1.0.28
+idna==3.3
+iso8601==1.0.2
+jmespath==0.10.0
+keystoneauth1==3.4.0
+loguru==0.6.0
+numpy==1.23.1
oss2==2.15.0
+packaging==21.3
pandas==1.4.3
-prettytable==3.2.0
+pbr==5.9.0
+prettytable==3.3.0
+pycparser==2.21
+pycryptodome==3.15.0
+pyparsing==3.0.9
+python-dateutil==2.8.2
+pytz==2022.1
+qcloud-cos==1.0.3
+requests==2.28.1
+s3transfer==0.6.0
+six==1.16.0
+stevedore==4.0.0
+urllib3==1.26.10
+wcwidth==0.2.5