mirror of
https://github.com/UzJu/Cloud-Bucket-Leak-Detection-Tools.git
synced 2025-11-05 10:44:04 +00:00
feat: v0.0.3(BETA) 重构多个功能与模块
一、重构模块 1、阿里云OSS 2、Amazone S3 3、main.py 4、目录结构 5、logger输出样式 6、Banner输出样式 7、命令行参数 二、新增 1、multiprocessing的加入,帮助快速批量扫描存储桶地址 三、不支持 1、暂不支持传入域名,无法自动判断Cname
This commit is contained in:
parent
d793b206b4
commit
1445d0b445
8
.gitignore
vendored
Normal file
8
.gitignore
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
|
||||||
|
*.xml
|
||||||
|
*.iml
|
||||||
|
*.pyc
|
||||||
|
results/
|
||||||
|
logs/
|
||||||
|
.idea/
|
||||||
|
url.txt
|
||||||
72
README.md
72
README.md
@ -1,17 +1,6 @@
|
|||||||
# :rooster:0x00 前言
|
# :rooster:0x00 前言
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
> 2022年3月7日
|
|
||||||
>
|
|
||||||
> 我觉得文档写的还不是很清楚,等有空更新一下文档完整的使用教程
|
|
||||||
> 2022年3月8日
|
|
||||||
>
|
|
||||||
> 2022年5月29日
|
|
||||||
>
|
|
||||||
> 1、更新了aws存储桶检测功能
|
|
||||||
>
|
|
||||||
> 2、感觉更新有些慢了,这段时间比较忙,其实本地的新版本写好了,一直没有push
|
|
||||||
|
|
||||||
**使用教程**: [使用教程](使用教程.md)
|
**使用教程**: [使用教程](使用教程.md)
|
||||||
|
|
||||||
@ -19,35 +8,11 @@
|
|||||||
|
|
||||||
English README: [English](README.en.md)
|
English README: [English](README.en.md)
|
||||||
|
|
||||||
想写个存储桶的利用,先给自己画个饼
|
|
||||||
|
|
||||||
+ 阿里云(Aliyun Cloud Oss)
|
|
||||||
+ 腾讯云(Tencent Cloud COS)
|
|
||||||
+ 华为云 (HuaWei Cloud OBS)
|
|
||||||
+ AWS (Amazon S3 Bucket)
|
|
||||||
+ Azure (Azure Blob)
|
|
||||||
+ GCP (Google Cloud Bucket)
|
|
||||||
|
|
||||||
工具名称我都没想好,相信大佬们看到项目名就知道...机翻王
|
|
||||||
|
|
||||||
如果觉得用的还行,可以提issue给工具起个名字?:sos:
|
|
||||||
|
|
||||||
:waning_crescent_moon:**画饼进度**
|
|
||||||
|
|
||||||
1、阿里云存储桶利用
|
|
||||||
|
|
||||||
不太会用Git,代码写的也烂,有BUG直接提Issue即可(好像我连issue可能都用不明白)
|
|
||||||
|
|
||||||
> 好在二爷给我推荐的GitHub Desktop 二爷YYDS
|
|
||||||
|
|
||||||
2、AWS存储桶利用
|
|
||||||
|
|
||||||
# :pill:0x01 依赖
|
# :pill:0x01 依赖
|
||||||
|
|
||||||
+ pip3 install oss2
|
```bash
|
||||||
+ pip3 install colorlog
|
pip3 install -r requirements.txt
|
||||||
+ pip3 install argparse
|
```
|
||||||
+ pip3 install boto3
|
|
||||||
|
|
||||||
# :gun:0x02 使用方法
|
# :gun:0x02 使用方法
|
||||||
|
|
||||||
@ -62,15 +27,15 @@ python3 main.py -h
|
|||||||
|
|
||||||
2、用来验证合法用户
|
2、用来验证合法用户
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 1、当存储桶Policy权限可获取时
|
## 1、当存储桶Policy权限可获取时
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 2、当存储桶不存在时(自动创建并劫持)
|
## 2、当存储桶不存在时(自动创建并劫持)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 3、批量检测存储桶
|
## 3、批量检测存储桶
|
||||||
|
|
||||||
@ -84,20 +49,15 @@ server="AliyunOSS"domain="aliyuncs.com" #不推荐该语法
|
|||||||
```
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python3 main.py -f aws/aliyun filepath
|
python3 main.py -faliyun url.txt
|
||||||
|
|
||||||
# 例如
|
|
||||||
python3 main.py -f aws ./url.tx\\\\\\\``````````````````````````````````````````````````````````````````````````
|
|
||||||
```
|
```
|
||||||
|
|
||||||
随后等待即可,扫描结果会在results目录下,文件名为当天的日期
|
随后等待即可,扫描结果会在results目录下,文件名为当天的日期
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||

|
随后会将结果保存至csv
|
||||||
|

|
||||||
只会保存有权限操作的存储桶
|
|
||||||

|
|
||||||
|
|
||||||
输入存储桶地址即可自动检测,功能如下
|
输入存储桶地址即可自动检测,功能如下
|
||||||
|
|
||||||
@ -109,7 +69,7 @@ python3 main.py -f aws ./url.tx\\\\\\\``````````````````````````````````````````
|
|||||||
+ 5、检测存储桶是否可上传Object
|
+ 5、检测存储桶是否可上传Object
|
||||||
+ 6、批量检测功能
|
+ 6、批量检测功能
|
||||||
|
|
||||||
## 4、域名检测功能
|
## 4、域名检测功能(v0.3.0暂未支持)
|
||||||
|
|
||||||
很多存储桶都解析了域名,新增判断域名的CNAME,然后取CNAME来进行检测
|
很多存储桶都解析了域名,新增判断域名的CNAME,然后取CNAME来进行检测
|
||||||
|
|
||||||
@ -186,6 +146,14 @@ python3 main.py -aws xxxx
|
|||||||
|
|
||||||
- 新增AWS存储桶扫描
|
- 新增AWS存储桶扫描
|
||||||
|
|
||||||
|
**2022年7月3日**
|
||||||
|
|
||||||
|
- 重构项目
|
||||||
|
- aliyunoss模块
|
||||||
|
- aws模块
|
||||||
|
- main模块
|
||||||
|
- 扫描模块
|
||||||
|
|
||||||
# :cop:0xffffffff 免责声明
|
# :cop:0xffffffff 免责声明
|
||||||
|
|
||||||
免责声明
|
免责声明
|
||||||
|
|||||||
@ -1,189 +0,0 @@
|
|||||||
"""
|
|
||||||
Banner Info From http://patorjk.com/software/taag/#p=display&f=TRaC%20Mini&t=UzJu
|
|
||||||
"""
|
|
||||||
|
|
||||||
import random
|
|
||||||
|
|
||||||
Banner_1 = '''
|
|
||||||
,---._
|
|
||||||
.-- -.' \
|
|
||||||
,--, | | :
|
|
||||||
,'_ /| ,----, : ; | ,--,
|
|
||||||
.--. | | : .' .`| : | ,'_ /|
|
|
||||||
,'_ /| : . | .' .' .' | : : .--. | | :
|
|
||||||
| ' | | . . ,---, ' ./ : ,'_ /| : . |
|
|
||||||
| | ' | | | ; | .' / | ; || ' | | . .
|
|
||||||
: | | : ' ; `---' / ;--, ___ l | | ' | | |
|
|
||||||
| ; ' | | ' / / / .`|/ /\ J :: | : ; ; |
|
|
||||||
: | : ; ; | ./__; .'/ ../ `..- ,' : `--' \
|
|
||||||
' : `--' \; | .' \ \ ; : , .-./
|
|
||||||
: , .-./`---' \ \ ,' `--`----'
|
|
||||||
`--`----' "---....--'
|
|
||||||
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
'''
|
|
||||||
Banner_2 = '''
|
|
||||||
|
|
||||||
/$$ /$$ /$$$$$
|
|
||||||
| $$ | $$ |__ $$
|
|
||||||
| $$ | $$ /$$$$$$$$ | $$ /$$ /$$
|
|
||||||
| $$ | $$|____ /$$/ | $$| $$ | $$
|
|
||||||
| $$ | $$ /$$$$/ /$$ | $$| $$ | $$
|
|
||||||
| $$ | $$ /$$__/ | $$ | $$| $$ | $$
|
|
||||||
| $$$$$$/ /$$$$$$$$| $$$$$$/| $$$$$$/
|
|
||||||
\______/ |________/ \______/ \______/
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
'''
|
|
||||||
Banner_3 = '''
|
|
||||||
|
|
||||||
.----------------. .----------------. .----------------. .----------------.
|
|
||||||
| .--------------. || .--------------. || .--------------. || .--------------. |
|
|
||||||
| | _____ _____ | || | ________ | || | _____ | || | _____ _____ | |
|
|
||||||
| ||_ _||_ _|| || | | __ _| | || | |_ _| | || ||_ _||_ _|| |
|
|
||||||
| | | | | | | || | |_/ / / | || | | | | || | | | | | | |
|
|
||||||
| | | ' ' | | || | .'.' _ | || | _ | | | || | | ' ' | | |
|
|
||||||
| | \ `--' / | || | _/ /__/ | | || | | |_' | | || | \ `--' / | |
|
|
||||||
| | `.__.' | || | |________| | || | `.___.' | || | `.__.' | |
|
|
||||||
| | | || | | || | | || | | |
|
|
||||||
| '--------------' || '--------------' || '--------------' || '--------------' |
|
|
||||||
'----------------' '----------------' '----------------' '----------------'
|
|
||||||
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
'''
|
|
||||||
|
|
||||||
Banner_4 = '''
|
|
||||||
.------..------..------..------.
|
|
||||||
|U.--. ||Z.--. ||J.--. ||U.--. |
|
|
||||||
| (\/) || :(): || :(): || (\/) |
|
|
||||||
| :\/: || ()() || ()() || :\/: |
|
|
||||||
| '--'U|| '--'Z|| '--'J|| '--'U|
|
|
||||||
`------'`------'`------'`------'
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
'''
|
|
||||||
|
|
||||||
Banner_5 = '''
|
|
||||||
|
|
||||||
___ ___ ___
|
|
||||||
/\ \ /\__\ ___ /\ \
|
|
||||||
\:\ \ /::| | /\__\ \:\ \
|
|
||||||
\:\ \ /:/:| | /:/__/ \:\ \
|
|
||||||
___ \:\ \ /:/|:| |__ /::\ \ ___ \:\ \
|
|
||||||
/\ \ \:\__\ /:/ |:| /\__\ \/\:\ \ /\ \ \:\__|
|
|
||||||
\:\ \ /:/ / \/__|:|/:/ / ~~\:\ \ \:\ \ /:/ /
|
|
||||||
\:\ /:/ / |:/:/ / \:\__\ \:\ /:/ /
|
|
||||||
\:\/:/ / |::/ / /:/ / \:\/:/ /
|
|
||||||
\::/ / |:/ / /:/ / \::/ /
|
|
||||||
\/__/ |/__/ \/__/ \/__/
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
'''
|
|
||||||
Banner_6 = """
|
|
||||||
|
|
||||||
d b sSSSSSs d d b
|
|
||||||
S S s S S S
|
|
||||||
S S s S S S
|
|
||||||
S S s S S S
|
|
||||||
S S s d P S S
|
|
||||||
S S s S S S S
|
|
||||||
"sss" sSSSSSs "sss" "sss"
|
|
||||||
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
"""
|
|
||||||
|
|
||||||
Banner_7 = '''
|
|
||||||
_ _ _
|
|
||||||
| | | | ___ _ | | _ _
|
|
||||||
| |_| | |_ / | || | | +| |
|
|
||||||
\___/ _/__| _\__/ \_,_|
|
|
||||||
_|"""""|_|"""""|_|"""""|_|"""""|
|
|
||||||
"`-0-0-'"`-0-0-'"`-0-0-'"`-0-0-'
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
'''
|
|
||||||
Banner_8 = '''
|
|
||||||
|
|
||||||
██╗ ██╗███████╗ ██╗██╗ ██╗
|
|
||||||
██║ ██║╚══███╔╝ ██║██║ ██║
|
|
||||||
██║ ██║ ███╔╝ ██║██║ ██║
|
|
||||||
██║ ██║ ███╔╝ ██ ██║██║ ██║
|
|
||||||
╚██████╔╝███████╗╚█████╔╝╚██████╔╝
|
|
||||||
╚═════╝ ╚══════╝ ╚════╝ ╚═════╝
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
Banner_9 = '''
|
|
||||||
|
|
||||||
█ ██ ▒███████▒ ▄▄▄██▀▀▀█ ██
|
|
||||||
██ ▓██▒▒ ▒ ▒ ▄▀░ ▒██ ██ ▓██▒
|
|
||||||
▓██ ▒██░░ ▒ ▄▀▒░ ░██ ▓██ ▒██░
|
|
||||||
▓▓█ ░██░ ▄▀▒ ░▓██▄██▓ ▓▓█ ░██░
|
|
||||||
▒▒█████▓ ▒███████▒ ▓███▒ ▒▒█████▓
|
|
||||||
░▒▓▒ ▒ ▒ ░▒▒ ▓░▒░▒ ▒▓▒▒░ ░▒▓▒ ▒ ▒
|
|
||||||
░░▒░ ░ ░ ░░▒ ▒ ░ ▒ ▒ ░▒░ ░░▒░ ░ ░
|
|
||||||
░░░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░░░ ░ ░
|
|
||||||
░ ░ ░ ░ ░ ░
|
|
||||||
░
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
'''
|
|
||||||
|
|
||||||
Banner_10 = '''
|
|
||||||
|
|
||||||
▄ ▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄▄▄▄▄▄▄ ▄ ▄
|
|
||||||
▐░▌ ▐░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░▌ ▐░▌
|
|
||||||
▐░▌ ▐░▌ ▀▀▀▀▀▀▀▀▀█░▌ ▀▀▀▀▀█░█▀▀▀ ▐░▌ ▐░▌
|
|
||||||
▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌ ▐░▌
|
|
||||||
▐░▌ ▐░▌ ▄▄▄▄▄▄▄▄▄█░▌ ▐░▌ ▐░▌ ▐░▌
|
|
||||||
▐░▌ ▐░▌▐░░░░░░░░░░░▌ ▐░▌ ▐░▌ ▐░▌
|
|
||||||
▐░▌ ▐░▌▐░█▀▀▀▀▀▀▀▀▀ ▐░▌ ▐░▌ ▐░▌
|
|
||||||
▐░▌ ▐░▌▐░▌ ▐░▌ ▐░▌ ▐░▌
|
|
||||||
▐░█▄▄▄▄▄▄▄█░▌▐░█▄▄▄▄▄▄▄▄▄ ▄▄▄▄▄█░▌ ▐░█▄▄▄▄▄▄▄█░▌
|
|
||||||
▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░▌ ▐░░░░░░░░░░░▌
|
|
||||||
▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀▀
|
|
||||||
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
Banner_11 = '''
|
|
||||||
|
|
||||||
_ _ _ _ _ _ _ _
|
|
||||||
(c).-.(c) (c).-.(c) (c).-.(c) (c).-.(c)
|
|
||||||
/ ._. \ / ._. \ / ._. \ / ._. \
|
|
||||||
__\( Y )/__ __\( Y )/__ __\( Y )/__ __\( Y )/__
|
|
||||||
(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)(_.-/'-'\-._)
|
|
||||||
|| U || || Z || || J || || U ||
|
|
||||||
_.' `-' '._ _.' `-' '._ _.' `-' '._ _.' `-' '._
|
|
||||||
(.-./`-'\.-.)(.-./`-'\.-.)(.-./`-'\.-.)(.-./`-'\.-.)
|
|
||||||
`-' `-' `-' `-' `-' `-' `-' `-'
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
'''
|
|
||||||
Banner_12 = '''
|
|
||||||
|
|
||||||
===================================
|
|
||||||
= ==== ============== ========
|
|
||||||
= ==== =============== =========
|
|
||||||
= ==== =============== =========
|
|
||||||
= ==== == ======= === = =
|
|
||||||
= ==== ====== ======= === = =
|
|
||||||
= ==== ===== ======== === = =
|
|
||||||
= ==== ==== ==== === === = =
|
|
||||||
= == === ===== === === = =
|
|
||||||
== === === ===== =
|
|
||||||
===================================
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
'''
|
|
||||||
Banner_13 = '''
|
|
||||||
|
|
||||||
>=> >=> >=>
|
|
||||||
>=> >=> >=>
|
|
||||||
>=> >=> >====>>=> >=> >=> >=>
|
|
||||||
>=> >=> >=> >=> >=> >=>
|
|
||||||
>=> >=> >=> >=> >=> >=>
|
|
||||||
>=> >=> >=> >> >=> >=> >=>
|
|
||||||
>====> >=======> >===> >==>=>
|
|
||||||
Autor: UzJu Email: UzJuer@163.com GitHub: github.com/uzju
|
|
||||||
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
def echoRandomBannerInfo():
|
|
||||||
eval(f"print(Banner_{random.randint(1, 13)})")
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
#!/usr/bin/python3.8.4 (python版本)
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Author : UzJu@菜菜狗
|
|
||||||
# @Email : UzJuer@163.com
|
|
||||||
# @Software: PyCharm
|
|
||||||
# @Time : 2022/2/28 5:25 PM
|
|
||||||
# @File : __init__.py
|
|
||||||
@ -3,48 +3,32 @@
|
|||||||
# @Author : UzJu@菜菜狗
|
# @Author : UzJu@菜菜狗
|
||||||
# @Email : UzJuer@163.com
|
# @Email : UzJuer@163.com
|
||||||
# @Software: PyCharm
|
# @Software: PyCharm
|
||||||
# @Time : 2022/2/28 5:18 PM
|
# @Time : 2022/7/2 14:22
|
||||||
# @File : conf.py
|
# @File : conf.py
|
||||||
|
|
||||||
# from fake_useragent import UserAgent
|
|
||||||
# UA = UserAgent(use_cache_server=False)
|
|
||||||
|
|
||||||
# headers = {
|
|
||||||
# "UserAgent": UA.random
|
|
||||||
# }
|
|
||||||
import os
|
|
||||||
import datetime
|
import datetime
|
||||||
import csv
|
from colorama import init, Fore, Back, Style
|
||||||
|
|
||||||
NowTime = datetime.datetime.now().strftime('%Y-%m-%d')
|
NowTime = datetime.datetime.now().strftime('%Y-%m-%d')
|
||||||
"""
|
|
||||||
2022年3月6日 16:55
|
|
||||||
部分用户反馈该库存在报错的问题,故此目前删除该库
|
|
||||||
最开始使用该库是因为想用HTTP的方式实现功能,所以使用了fake_useragent
|
|
||||||
现在实现的方式是直接调SDK所以不需要这个Fake_useragent了
|
|
||||||
"""
|
|
||||||
|
|
||||||
# aliyun
|
# aliyun
|
||||||
AliyunAccessKey_ID = ""
|
aliyun_id = ""
|
||||||
AliyunAccessKey_Secret = ""
|
aliyun_key = ""
|
||||||
|
|
||||||
# aws
|
# aws
|
||||||
AWS_ACCESS_KEY = ''
|
AWS_ACCESS_KEY = ""
|
||||||
AWS_SECRET_KEY = ''
|
AWS_SECRET_KEY = ""
|
||||||
|
|
||||||
|
|
||||||
def save_results(target, info):
|
version = "v.0.3.0"
|
||||||
headers = ['存储桶地址', '权限']
|
author = "UzJu"
|
||||||
filepath = f'{os.getcwd()}/results/{NowTime}.csv'
|
email = "UzJuer@163.com"
|
||||||
rows = [
|
github = "GitHub.com/UzJu"
|
||||||
[f"{target}", info]
|
banner = f"""
|
||||||
]
|
{Fore.CYAN}______ _ _ _____
|
||||||
if not os.path.isfile(filepath):
|
{Fore.YELLOW}| ___ \ | | | | / ___|
|
||||||
with open(filepath, 'a+', newline='') as f:
|
{Fore.GREEN}| |_/ /_ _ ___| | _____| |_\ `--. ___ __ _ _ __
|
||||||
f = csv.writer(f)
|
{Fore.GREEN}| ___ \ | | |/ __| |/ / _ \ __|`--. \/ __/ _` | '_ \
|
||||||
f.writerow(headers)
|
{Fore.BLUE}| |_/ / |_| | (__| < __/ |_/\__/ / (_| (_| | | | |
|
||||||
f.writerows(rows)
|
{Fore.MAGENTA}\____/ \__,_|\___|_|\_\___|\__\____/ \___\__,_|_| |_|
|
||||||
else:
|
{Fore.RED} Author:{author} Version:{version}
|
||||||
with open(filepath, 'a+', newline='') as f:
|
"""
|
||||||
f_csv = csv.writer(f)
|
|
||||||
f_csv.writerows(rows)
|
|
||||||
|
|||||||
@ -1,14 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Author : UzJu@菜菜狗
|
|
||||||
# @Email : UzJuer@163.com
|
|
||||||
# @Software: PyCharm
|
|
||||||
# @Time : 2022/3/4 下午5:24
|
|
||||||
# @File : echoToFile.py
|
|
||||||
|
|
||||||
import csv
|
|
||||||
|
|
||||||
|
|
||||||
class Echo:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
45
config/logs.py
Normal file
45
config/logs.py
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/python3.8.4 (python版本)
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Author : UzJu@菜菜狗
|
||||||
|
# @Email : UzJuer@163.com
|
||||||
|
# @Software: PyCharm
|
||||||
|
# @Time : 2022/7/2 14:21
|
||||||
|
# @File : logs.py
|
||||||
|
import sys
|
||||||
|
import pathlib
|
||||||
|
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
|
# Log Code From https://github.com/shmilylty/OneForAll/
|
||||||
|
# 路径设置
|
||||||
|
relative_directory = pathlib.Path(__file__).parent.parent
|
||||||
|
result_save_dir = relative_directory.joinpath('logs')
|
||||||
|
log_path = result_save_dir.joinpath('bucket_scan.log')
|
||||||
|
|
||||||
|
# 日志配置
|
||||||
|
# 终端日志输出格式
|
||||||
|
stdout_fmt = '<cyan>{time:HH:mm:ss,SSS}</cyan> ' \
|
||||||
|
'[<level>{level: <5}</level>] ' \
|
||||||
|
'<blue>{module}</blue>:<cyan>{line}</cyan> - ' \
|
||||||
|
'<level>{message}</level>'
|
||||||
|
# 日志文件记录格式
|
||||||
|
logfile_fmt = '<light-green>{time:YYYY-MM-DD HH:mm:ss,SSS}</light-green> ' \
|
||||||
|
'[<level>{level: <5}</level>] ' \
|
||||||
|
'<cyan>{process.name}({process.id})</cyan>:' \
|
||||||
|
'<cyan>{thread.name: <18}({thread.id: <5})</cyan> | ' \
|
||||||
|
'<blue>{module}</blue>.<blue>{function}</blue>:' \
|
||||||
|
'<blue>{line}</blue> - <level>{message}</level>'
|
||||||
|
|
||||||
|
logger.remove()
|
||||||
|
logger.level(name='TRACE', color='<cyan><bold>', icon='✏️')
|
||||||
|
logger.level(name='DEBUG', color='<blue><bold>', icon='🐞 ')
|
||||||
|
logger.level(name='INFOR', no=20, color='<green><bold>', icon='ℹ️')
|
||||||
|
logger.level(name='QUITE', no=25, color='<green><bold>', icon='🤫 ')
|
||||||
|
logger.level(name='ALERT', no=30, color='<yellow><bold>', icon='⚠️')
|
||||||
|
logger.level(name='ERROR', color='<red><bold>', icon='❌️')
|
||||||
|
logger.level(name='FATAL', no=50, color='<RED><bold>', icon='☠️')
|
||||||
|
|
||||||
|
logger.add(sys.stderr, level='INFOR', format=stdout_fmt, enqueue=True)
|
||||||
|
|
||||||
|
logger.add(log_path, level='DEBUG', format=logfile_fmt, enqueue=True, encoding='utf-8')
|
||||||
|
logger.disabled = True
|
||||||
@ -1,121 +0,0 @@
|
|||||||
#!/usr/bin/python3.8.4 (python版本)
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
# @Author : UzJu@菜菜狗
|
|
||||||
# @Email : UzJuer@163.com
|
|
||||||
# @Software: PyCharm
|
|
||||||
# @Time : 2022/4/7 15:33
|
|
||||||
# @File : AmazoneCloudS3Bucket.py
|
|
||||||
import botocore
|
|
||||||
from boto3.session import Session
|
|
||||||
import boto3
|
|
||||||
from config import conf
|
|
||||||
import logging
|
|
||||||
import datetime
|
|
||||||
|
|
||||||
module_logger = logging.getLogger("mainModule.AmazoneCloudS3Bucket")
|
|
||||||
NowTime = datetime.datetime.now().strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
|
|
||||||
class AwsCloudS3Check:
|
|
||||||
def __init__(self, BucketName, BucketDomain):
|
|
||||||
'''
|
|
||||||
bucketName: 只取Bucket名字
|
|
||||||
BucketDomain: Bucket完整域名
|
|
||||||
'''
|
|
||||||
self.getBucketName = BucketName
|
|
||||||
self.getBucketDomain = BucketDomain
|
|
||||||
|
|
||||||
'''
|
|
||||||
Boto3 Session 和 Client
|
|
||||||
'''
|
|
||||||
session = Session(aws_access_key_id=conf.AWS_ACCESS_KEY,
|
|
||||||
aws_secret_access_key=conf.AWS_SECRET_KEY)
|
|
||||||
self.s3 = session.client('s3')
|
|
||||||
|
|
||||||
'''
|
|
||||||
为了解决boto3 Clinet中没有resource的问题
|
|
||||||
因为如果使用client, 在调用CheckBucketListObject的时候, 会提示没有Object
|
|
||||||
'''
|
|
||||||
self.s3_resource = session.resource('s3')
|
|
||||||
'''
|
|
||||||
Logger
|
|
||||||
'''
|
|
||||||
self.logger = logging.getLogger("mainModule.AmazoneCloudS3Bucket.Check.module")
|
|
||||||
|
|
||||||
'''
|
|
||||||
results_list 返回给CSV的列表
|
|
||||||
'''
|
|
||||||
self.results_list = []
|
|
||||||
|
|
||||||
def CheckBucketListObject(self):
|
|
||||||
try:
|
|
||||||
getObjectList = self.s3_resource.Bucket(self.getBucketName)
|
|
||||||
for getObject in getObjectList.objects.all():
|
|
||||||
self.logger.info(f"List Bucket Object > {getObject.key}")
|
|
||||||
self.results_list.append("ListObject")
|
|
||||||
break
|
|
||||||
except Exception as e:
|
|
||||||
'''
|
|
||||||
这里为什么要加判断
|
|
||||||
NoSuchBucket的报错是这样的botocore.errorfactory.NoSuchBucket
|
|
||||||
但是不知道为什么这边调不到这个方法,所以干脆直接判断字符
|
|
||||||
'''
|
|
||||||
if "NoSuchBucket" in str(e):
|
|
||||||
self.logger.info("NoSuchBucket")
|
|
||||||
self.results_list.append("NoSuchBucket")
|
|
||||||
else:
|
|
||||||
self.logger.error(e)
|
|
||||||
|
|
||||||
def CheckBucketPutObject(self):
|
|
||||||
try:
|
|
||||||
'''
|
|
||||||
下面为什么要把对象的元数据设置为text/html,原因是因为默认上传文件之后,元数据为binary/octet-stream,当元数据为binary/octet-stream的时候,访问HTML文件
|
|
||||||
会直接下载该文件,修改为text/html之后,我们访问xxxx/UzJu.html的时候,会像访问静态网站一样访问这个对象
|
|
||||||
'''
|
|
||||||
self.s3_resource.Object(self.getBucketName, "UzJu.html").put(
|
|
||||||
Body="Put By https://github.com/UzJu/Cloud-Bucket-Leak-Detection-Tools.git",
|
|
||||||
ContentType='text/html')
|
|
||||||
self.logger.info(f"Put File Success > {self.getBucketDomain}/UzJu.html")
|
|
||||||
self.results_list.append("PutObject")
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.error(e)
|
|
||||||
|
|
||||||
def CheckBucketAcl(self):
|
|
||||||
try:
|
|
||||||
response = self.s3.get_bucket_acl(Bucket=self.getBucketName)
|
|
||||||
self.logger.info(f"Get Bucket Acl Success > {response}")
|
|
||||||
self.results_list.append("GetBucketAcl")
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.error(repr(e))
|
|
||||||
|
|
||||||
def CheckNoSuchBucket(self):
|
|
||||||
'''
|
|
||||||
这里主要是用来确认,如果上面的那些方法报错了,显示NoSuchBucket的话,就证明该存储桶是可以接管的
|
|
||||||
但是这里不会自动取创建一个存储桶去接管,而只是提示可以接管
|
|
||||||
'''
|
|
||||||
try:
|
|
||||||
pass
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.error(repr(e))
|
|
||||||
|
|
||||||
def CheckResult(self):
|
|
||||||
return self.results_list
|
|
||||||
|
|
||||||
def test(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def CheckBucket(BucketName, BucketDomain):
|
|
||||||
'''
|
|
||||||
BucketName: 取下标后的存储桶名
|
|
||||||
BucketDomain: 完整的存储桶地址
|
|
||||||
'''
|
|
||||||
run = AwsCloudS3Check(BucketName, BucketDomain)
|
|
||||||
run.CheckBucketListObject()
|
|
||||||
run.CheckBucketPutObject()
|
|
||||||
run.CheckBucketAcl()
|
|
||||||
if not run.CheckResult():
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
conf.save_results(BucketDomain, run.CheckResult())
|
|
||||||
module_logger.info(">" * 80)
|
|
||||||
@ -3,63 +3,161 @@
|
|||||||
# @Author : UzJu@菜菜狗
|
# @Author : UzJu@菜菜狗
|
||||||
# @Email : UzJuer@163.com
|
# @Email : UzJuer@163.com
|
||||||
# @Software: PyCharm
|
# @Software: PyCharm
|
||||||
# @Time : 2022/2/28 4:52 PM
|
# @Time : 2022/7/2 14:22
|
||||||
# @File : aliyunOss.py
|
# @File : aliyunOss.py
|
||||||
# 你猜我什么时候画的饼:)
|
|
||||||
'''
|
|
||||||
代码实现思路
|
|
||||||
1、使用GET POST PUT的请求来获取
|
|
||||||
2、使用OSS2 SDK实现
|
|
||||||
'''
|
|
||||||
# 以下代码思路是使用OssSDK来实现
|
|
||||||
from itertools import islice
|
|
||||||
import oss2
|
|
||||||
import json
|
import json
|
||||||
from config import conf
|
|
||||||
import logging
|
|
||||||
import os
|
import os
|
||||||
import datetime
|
from itertools import islice
|
||||||
|
from config.logs import logger
|
||||||
|
from config import conf
|
||||||
|
import oss2
|
||||||
|
|
||||||
|
|
||||||
module_logger = logging.getLogger("mainModule.AliyunOss")
|
class Aliyun_Oss_Bucket_Check:
|
||||||
NowTime = datetime.datetime.now().strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
|
|
||||||
class OssBucketExploitFromSDK:
|
|
||||||
def __init__(self, target, location):
|
def __init__(self, target, location):
|
||||||
|
"""
|
||||||
|
:desc: class init need to pass in the bucket name and region
|
||||||
|
:param target: bucket name
|
||||||
|
:param location: bucket
|
||||||
|
"""
|
||||||
self.target = target
|
self.target = target
|
||||||
self.location = location
|
self.location = location
|
||||||
auth = oss2.Auth(conf.AliyunAccessKey_ID, conf.AliyunAccessKey_Secret)
|
init_auth = oss2.Auth(conf.aliyun_id, conf.aliyun_key)
|
||||||
self.bucket = oss2.Bucket(auth, f'http://{location}.aliyuncs.com', self.target)
|
self.bucket = oss2.Bucket(init_auth, f"{location}.aliyuncs.com", self.target)
|
||||||
self.logger = logging.getLogger("mainModule.AliyunOss.Exploit.module")
|
|
||||||
|
|
||||||
def AliyunOssCreateBucket_Exp(self):
|
def Aliyun_Oss_GetBucketObject_List(self):
|
||||||
|
"""
|
||||||
|
:desc: List objects in a bucket
|
||||||
|
:return: True/False
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
self.bucket.create_bucket()
|
for Object in islice(oss2.ObjectIterator(self.bucket), 3):
|
||||||
self.logger.info(f"BucketName {self.target} Ceate Success:)")
|
logger.log("INFOR", f"Object Name: {Object.key}")
|
||||||
self.AliyunOssPutBucketAcl_Exp()
|
return True
|
||||||
self.AliyunOssPutBucketPolicy_Exp()
|
except oss2.exceptions.AccessDenied:
|
||||||
self.AliyunOssPutObject_Exp()
|
return False
|
||||||
self.AliyunOssGetBucketPolicy_Exp()
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"BucketName {self.target} Ceate FAILD:( {e}")
|
"""
|
||||||
|
:desc: This indicates that the content returned by the bucket is not in the common format of the bucket, etc.
|
||||||
|
"""
|
||||||
|
logger.log("ERROR", repr(e))
|
||||||
|
return False
|
||||||
|
|
||||||
def AliyunOssPutBucketAcl_Exp(self):
|
def Aliyun_Oss_PutBucketObject(self):
|
||||||
|
"""
|
||||||
|
:desc: Upload objects to buckets
|
||||||
|
:return: True/False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.bucket.put_object_from_file('UzJu.txt', f'{os.getcwd()}/config/UzJu.html')
|
||||||
|
return True
|
||||||
|
except oss2.exceptions.AccessDenied:
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
"""
|
||||||
|
:desc: This indicates that the content returned by the bucket is not in the common format of the bucket, etc.
|
||||||
|
"""
|
||||||
|
logger.log("ERROR", repr(e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
def Aliyun_Oss_GetBucketAcl(self):
|
||||||
|
"""
|
||||||
|
:desc: get bucket acl
|
||||||
|
:return: True/False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
logger.log("INFOR", f"Target: {self.target} Bucket Acl: {self.bucket.get_bucket_acl().acl}")
|
||||||
|
return True
|
||||||
|
except oss2.exceptions.AccessDenied:
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
"""
|
||||||
|
:desc: This indicates that the content returned by the bucket is not in the common format of the bucket, etc.
|
||||||
|
"""
|
||||||
|
logger.log("ERROR", repr(e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
def Aliyun_Oss_PutBucketAcl(self):
|
||||||
|
"""
|
||||||
|
:desc: put bucket acl
|
||||||
|
:return: True/False
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
self.bucket.put_bucket_acl(oss2.BUCKET_ACL_PUBLIC_READ_WRITE)
|
self.bucket.put_bucket_acl(oss2.BUCKET_ACL_PUBLIC_READ_WRITE)
|
||||||
self.logger.info(f"BucketName {self.target} Acl Permissions PUBLIC_READ_WRITE:)")
|
return True
|
||||||
|
except oss2.exceptions.AccessDenied:
|
||||||
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"BucketName {self.target} Acl Put FAILD:( {e}")
|
"""
|
||||||
|
:desc: This indicates that the content returned by the bucket is not in the common format of the bucket, etc.
|
||||||
|
"""
|
||||||
|
logger.log("ERROR", repr(e))
|
||||||
|
return False
|
||||||
|
|
||||||
def AliyunOssGetBucketPolicy_Exp(self):
|
def Aliyun_Oss_GetBucketPolicy(self):
|
||||||
|
"""
|
||||||
|
:desc: get public bucket policy
|
||||||
|
:return: policy_json / False
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
result = self.bucket.get_bucket_policy()
|
result = self.bucket.get_bucket_policy()
|
||||||
policy_json = json.loads(result.policy)
|
policy_json = json.loads(result.policy)
|
||||||
self.logger.info(f"BucketName {self.target} Policy Get Success :)\n {policy_json}")
|
return policy_json
|
||||||
|
except oss2.exceptions.AccessDenied:
|
||||||
|
return False
|
||||||
|
except oss2.exceptions.NoSuchBucketPolicy:
|
||||||
|
logger.log("ALERT", "There is no Policy policy for the current storage bucket")
|
||||||
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"BucketName {self.target} Policy Get FAILD:( {e}")
|
"""
|
||||||
|
:desc: This indicates that the content returned by the bucket is not in the common format of the bucket, etc.
|
||||||
|
"""
|
||||||
|
logger.log("ERROR", repr(e))
|
||||||
|
return False
|
||||||
|
|
||||||
def AliyunOssPutBucketPolicy_Exp(self):
|
def Aliyun_Oss_BucketDoesBucketExist(self):
|
||||||
|
"""
|
||||||
|
:desc: Check whether the storage bucket exists
|
||||||
|
:return: True/False
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
self.bucket.get_bucket_info()
|
||||||
|
return False
|
||||||
|
except oss2.exceptions.NoSuchBucket:
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.log("ERROR", f"Target: {self.target} Except INFO: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class Aliyun_Oss_Bucket_Exploit:
|
||||||
|
def __init__(self, target, location):
|
||||||
|
"""
|
||||||
|
:desc: class init need to pass in the bucket name and region
|
||||||
|
:param target: bucket name
|
||||||
|
:param location: bucket
|
||||||
|
"""
|
||||||
|
self.target = target
|
||||||
|
self.location = location
|
||||||
|
init_auth = oss2.Auth(conf.aliyun_id, conf.aliyun_key)
|
||||||
|
self.bucket = oss2.Bucket(init_auth, f"http://{location}.aliyuncs.com", self.target)
|
||||||
|
|
||||||
|
def Aliyun_Oss_CreateBucket_Exp(self):
|
||||||
|
try:
|
||||||
|
self.bucket.create_bucket()
|
||||||
|
logger.log("INFOR", f"BucketName {self.target} Ceate Success:)")
|
||||||
|
except Exception as e:
|
||||||
|
logger.log("ERROR", f"BucketName {self.target} Ceate FAILD:( {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def Aliyun_Oss_PutBucketAcl_Exp(self):
|
||||||
|
try:
|
||||||
|
self.bucket.put_bucket_acl(oss2.BUCKET_ACL_PUBLIC_READ_WRITE)
|
||||||
|
logger.log("INFOR", f"BucketName {self.target} Acl Permissions PUBLIC_READ_WRITE:)")
|
||||||
|
except Exception as e:
|
||||||
|
logger.log("ERROR", f"BucketName {self.target} Acl Put FAILD:( {e}")
|
||||||
|
|
||||||
|
def Aliyun_Oss_PutBucketPolicy_Exp(self):
|
||||||
try:
|
try:
|
||||||
bucket_info = self.bucket.get_bucket_info()
|
bucket_info = self.bucket.get_bucket_info()
|
||||||
strategy = {
|
strategy = {
|
||||||
@ -80,119 +178,23 @@ class OssBucketExploitFromSDK:
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.bucket.put_bucket_policy(json.dumps(strategy))
|
self.bucket.put_bucket_policy(json.dumps(strategy))
|
||||||
self.logger.info(f"BucketName {self.target} Policy Put Success :)")
|
logger.log("INFOR", f"BucketName {self.target} Policy Put Success :)")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning(f"BucketName {self.target} Policy Put FAILD:( {e}")
|
logger.log("ERROR", f"BucketName {self.target} Policy Put FAILD:( {e}")
|
||||||
|
|
||||||
def AliyunOssPutObject_Exp(self):
|
def Aliyun_Oss_GetBucketPolicy_Exp(self):
|
||||||
try:
|
|
||||||
self.bucket.put_object_from_file("UzJu.html", f"{os.getcwd()}/config/UzJu.html")
|
|
||||||
self.logger.info(f"BucketName {self.target} Put Object Success:)")
|
|
||||||
self.logger.info(f"Go Browser Open {self.target}.{self.location}.aliyuncs.com/UzJu.html")
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
self.logger.warning(f"BucketName {self.target} Put Object FAILD:( {e}")
|
|
||||||
|
|
||||||
|
|
||||||
class OssBucketCheckFromSDK:
|
|
||||||
def __init__(self, target, location):
|
|
||||||
self.target = target
|
|
||||||
self.location = location
|
|
||||||
self.logger = logging.getLogger("mainModule.AliyunOss.module")
|
|
||||||
auth = oss2.Auth(conf.AliyunAccessKey_ID, conf.AliyunAccessKey_Secret)
|
|
||||||
self.bucket = oss2.Bucket(auth, f'http://{location}.aliyuncs.com', self.target)
|
|
||||||
self.Exploit = OssBucketExploitFromSDK(self.target, location)
|
|
||||||
self.results_list = []
|
|
||||||
|
|
||||||
def AliyunOssPutBucketPolicy(self, getOssResource):
|
|
||||||
"""
|
|
||||||
PutBucketPolicy
|
|
||||||
危险操作,会更改存储桶的策略组,建议查看AliyunOssgetBucketPolicy来自行判断
|
|
||||||
是否拥有AliyunOssPutBucketPolicy权限,如果用代码的方式写入会存在问题
|
|
||||||
1、写入后无法还原(当然这里可以使用备份原有的策略,然后再上传新的策略)这里又会遇到一个新的问题
|
|
||||||
如果只是存在PutBucketPolicy我们Put后是无法知道对方的ResourceID的
|
|
||||||
|
|
||||||
所以该函数只在OssBucketExploitFromSDK类中实现了,详情请看AliyunOssPutBucketPolicy_Exp方法
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
def AliyunOssGetBucketPolicy(self):
|
|
||||||
try:
|
try:
|
||||||
result = self.bucket.get_bucket_policy()
|
result = self.bucket.get_bucket_policy()
|
||||||
policy_json = json.loads(result.policy)
|
policy_json = json.loads(result.policy)
|
||||||
self.logger.info(f"Target: {self.target}, get Bucket Policy:)\n{policy_json}")
|
logger.log("INFOR", f"BucketName {self.target} Policy Get Success :)\n {policy_json}")
|
||||||
self.results_list.append("GetBucketPolicy")
|
|
||||||
except oss2.exceptions.AccessDenied:
|
|
||||||
self.logger.warning(f"Target: {self.target}, Bucket Policy AccessDenied:(")
|
|
||||||
|
|
||||||
def AliyunOssBucketDoesBucketExist(self):
|
|
||||||
try:
|
|
||||||
self.bucket.get_bucket_info()
|
|
||||||
self.logger.info(f"Target: {self.target}, Bucket Exist:)")
|
|
||||||
return True
|
|
||||||
except oss2.exceptions.NoSuchBucket:
|
|
||||||
self.results_list.append("NoSuckBucket_HiJack")
|
|
||||||
self.logger.warning(f"Target: {self.target}, NoSuckBucket:) Now Hijack Bucket")
|
|
||||||
self.Exploit.AliyunOssCreateBucket_Exp()
|
|
||||||
return False
|
|
||||||
except oss2.exceptions.AccessDenied:
|
|
||||||
self.logger.warning(f"Target: {self.target}, AccessDenied:(")
|
|
||||||
return True
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"Target: {self.target} Except INFO: {e}")
|
logger.log("ERROR", f"BucketName {self.target} Policy Get FAILD:( {e}")
|
||||||
|
|
||||||
def AliyunOssGetBucketAcl(self):
|
def Aliyun_Oss_PutObject_Exp(self):
|
||||||
try:
|
try:
|
||||||
self.logger.info(f"Target: {self.target} Bucket Acl: {self.bucket.get_bucket_acl().acl}")
|
self.bucket.put_object_from_file("UzJu.html", f"{os.getcwd()}/config/UzJu.html")
|
||||||
self.results_list.append("GetBucketAcl")
|
logger.log("INFOR", f"BucketName {self.target} Put Object Success:)")
|
||||||
except oss2.exceptions.AccessDenied:
|
logger.log("INFOR", f"Go Browser Open {self.target}.{self.location}.aliyuncs.com/UzJu.html")
|
||||||
self.logger.warning(f"Target: {self.target} get Bucket Acl AccessDenied:(")
|
|
||||||
|
|
||||||
def AliyunOssPutBucketAcl(self):
|
except Exception as e:
|
||||||
try:
|
logger.log("ERROR", f"BucketName {self.target} Put Object FAILD:( {e}")
|
||||||
self.bucket.put_bucket_acl(oss2.BUCKET_ACL_PUBLIC_READ_WRITE)
|
|
||||||
self.logger.info(f"Target: {self.target} Put Bucket Acl Success:)")
|
|
||||||
self.results_list.append("PutBucketAcl")
|
|
||||||
except oss2.exceptions.AccessDenied:
|
|
||||||
self.logger.warning(f"Target: {self.target} Put Bucket Acl AccessDenied:(")
|
|
||||||
|
|
||||||
def AliyunOssGetBucketObjectList(self):
|
|
||||||
try:
|
|
||||||
self.logger.info("Try to list Object")
|
|
||||||
for Object in islice(oss2.ObjectIterator(self.bucket), 3):
|
|
||||||
self.logger.info(f"Object Name: {Object.key}")
|
|
||||||
self.results_list.append("GetBucketObjectList")
|
|
||||||
except oss2.exceptions.AccessDenied:
|
|
||||||
self.logger.warning(f"Target: {self.target} ListObject AccessDenid")
|
|
||||||
return
|
|
||||||
self.logger.info(f"Target: {self.target} Exsit traverse Object:)")
|
|
||||||
# putCsvInfoResult(f"{self.target}.{self.location}.aliyuncs.com", "ListObject")
|
|
||||||
|
|
||||||
def AliyunOssPutBucketObject(self):
|
|
||||||
try:
|
|
||||||
self.bucket.put_object_from_file('UzJu.txt', f'{os.getcwd()}/config/UzJu.html')
|
|
||||||
self.logger.info(f"Target: {self.target} Put Object Success:)")
|
|
||||||
self.logger.info(f"Go Browser Open {self.target}.{self.location}.aliyuncs.com/UzJu.html")
|
|
||||||
self.results_list.append("PutBucketObject")
|
|
||||||
except oss2.exceptions.AccessDenied:
|
|
||||||
self.logger.warning(f"Target: {self.target} Put Object AccessDenied:(")
|
|
||||||
|
|
||||||
def CheckResult(self):
|
|
||||||
return self.results_list
|
|
||||||
|
|
||||||
|
|
||||||
def CheckBucket(target, location):
|
|
||||||
try:
|
|
||||||
check = OssBucketCheckFromSDK(target, location)
|
|
||||||
if check.AliyunOssBucketDoesBucketExist():
|
|
||||||
check.AliyunOssGetBucketObjectList()
|
|
||||||
check.AliyunOssGetBucketAcl()
|
|
||||||
check.AliyunOssGetBucketPolicy()
|
|
||||||
check.AliyunOssPutBucketObject()
|
|
||||||
if not check.CheckResult():
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
conf.save_results(f"{target}.{location}.aliyuncs.com", check.CheckResult())
|
|
||||||
module_logger.info(">" * 80)
|
|
||||||
except Exception as e:
|
|
||||||
module_logger.error(f"Target: {target} Chceck Faild:( {e}")
|
|
||||||
|
|||||||
63
core/aws.py
Normal file
63
core/aws.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/python3.8.4 (python版本)
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Author : UzJu@菜菜狗
|
||||||
|
# @Email : UzJuer@163.com
|
||||||
|
# @Software: PyCharm
|
||||||
|
# @Time : 2022/7/2 19:57
|
||||||
|
# @File : aws.py
|
||||||
|
|
||||||
|
from boto3.session import Session
|
||||||
|
from config.logs import logger
|
||||||
|
from config import conf
|
||||||
|
|
||||||
|
|
||||||
|
class Amazone_Cloud_S3Bucket_Check:
|
||||||
|
def __init__(self, target, location):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:desc: Aws class init
|
||||||
|
:param BucketName: aws bucket name
|
||||||
|
:param BucketDomain: aws bucket region
|
||||||
|
"""
|
||||||
|
self.getBucketName = target
|
||||||
|
self.getBucketDomain = location
|
||||||
|
session = Session(aws_access_key_id=conf.AWS_ACCESS_KEY,
|
||||||
|
aws_secret_access_key=conf.AWS_SECRET_KEY)
|
||||||
|
self.s3 = session.client('s3')
|
||||||
|
self.s3_resource = session.resource('s3')
|
||||||
|
|
||||||
|
def Check_Bucket_ListObject(self):
|
||||||
|
try:
|
||||||
|
getObjectList = self.s3_resource.Bucket(self.getBucketName)
|
||||||
|
for getObject in getObjectList.objects.all():
|
||||||
|
logger.log("INFOR", f"List Bucket Object > {getObject.key}")
|
||||||
|
break
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
if "NoSuchBucket" in str(e):
|
||||||
|
logger.log("ALERT", "NoSuchBucket")
|
||||||
|
else:
|
||||||
|
logger.log("ERROR", repr(e))
|
||||||
|
|
||||||
|
def Check_Bucket_PutObject(self):
|
||||||
|
try:
|
||||||
|
self.s3_resource.Object(self.getBucketName, "UzJu.html").put(
|
||||||
|
Body="Put By https://github.com/UzJu/Cloud-Bucket-Leak-Detection-Tools.git",
|
||||||
|
ContentType='text/html')
|
||||||
|
logger.log("INFOR", f"Put File Success > {self.getBucketDomain}/UzJu.html")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.log("ERROR", repr(e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
def Check_Bucket_GetBucketAcl(self):
|
||||||
|
try:
|
||||||
|
response = self.s3.get_bucket_acl(Bucket=self.getBucketName)
|
||||||
|
logger.log("INFOR", f"Get Bucket Acl Success > {response}")
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logger.log("ERROR", repr(e))
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
143
core/main.py
Normal file
143
core/main.py
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
#!/usr/bin/python3.8.4 (python版本)
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Author : UzJu@菜菜狗
|
||||||
|
# @Email : UzJuer@163.com
|
||||||
|
# @Software: PyCharm
|
||||||
|
# @Time : 2022/7/2 14:22
|
||||||
|
# @File : main.py
|
||||||
|
|
||||||
|
from config.logs import logger
|
||||||
|
from plugins.results import aliyun_save_file
|
||||||
|
from core import aliyunOss
|
||||||
|
from core import aws
|
||||||
|
import urllib.parse
|
||||||
|
import prettytable as pt
|
||||||
|
import multiprocessing
|
||||||
|
|
||||||
|
|
||||||
|
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.close()
|
||||||
|
p.join()
|
||||||
|
p.terminate()
|
||||||
|
|
||||||
|
|
||||||
|
def aliyun(target):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:desc: aliyun Bucket Scan function
|
||||||
|
:param target: Bucket URL
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
logger.log("INFOR", f"开始扫描> {target}")
|
||||||
|
aliyun_print_table_header = pt.PrettyTable(
|
||||||
|
['Bucket', 'BucketHijack', 'GetBucketObjectList', 'PutBucketObject', 'GetBucketAcl', 'PutBucketAcl',
|
||||||
|
'GetBucketPolicy'])
|
||||||
|
aliyun_scan_results = {}
|
||||||
|
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])
|
||||||
|
if aliyunOss_Check_init.Aliyun_Oss_BucketDoesBucketExist():
|
||||||
|
logger.log("INFOR", f"{target}> 当前存储桶不存在, 尝试劫持存储桶")
|
||||||
|
if aliyunOss_Exploit_init.Aliyun_Oss_CreateBucket_Exp():
|
||||||
|
logger.log("ALERT", f"{target}> 新创建/新版存储桶不可劫持")
|
||||||
|
else:
|
||||||
|
aliyunOss_Exploit_init.Aliyun_Oss_PutObject_Exp()
|
||||||
|
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"})
|
||||||
|
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"})
|
||||||
|
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"})
|
||||||
|
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"})
|
||||||
|
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"})
|
||||||
|
else:
|
||||||
|
logger.log("ALERT", f"{target}> 不可公开获取存储桶Policy策略")
|
||||||
|
aliyun_scan_results.update({"GetBucketPolicy": "false"})
|
||||||
|
|
||||||
|
aliyun_print_table_header.add_row([target,
|
||||||
|
aliyun_scan_results['BucketDoesBucketExist'],
|
||||||
|
aliyun_scan_results['GetBucketObject'],
|
||||||
|
aliyun_scan_results['PutBucketObject'],
|
||||||
|
aliyun_scan_results['GetBucketAcl'],
|
||||||
|
aliyun_scan_results['PutBucketAcl'],
|
||||||
|
aliyun_scan_results['GetBucketPolicy']])
|
||||||
|
aliyun_save_file(target,
|
||||||
|
aliyun_scan_results['BucketDoesBucketExist'],
|
||||||
|
aliyun_scan_results['GetBucketObject'],
|
||||||
|
aliyun_scan_results['PutBucketObject'],
|
||||||
|
aliyun_scan_results['GetBucketAcl'],
|
||||||
|
aliyun_scan_results['PutBucketAcl'],
|
||||||
|
aliyun_scan_results['GetBucketPolicy'])
|
||||||
|
print(aliyun_print_table_header, "\n")
|
||||||
|
else:
|
||||||
|
aliyun(get_domain)
|
||||||
|
|
||||||
|
|
||||||
|
def AmazoneS3(target):
|
||||||
|
"""
|
||||||
|
|
||||||
|
:desc: aws bucket scan
|
||||||
|
:param target: bucket url
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
get_domain = urllib.parse.urlparse(target).netloc
|
||||||
|
if get_domain == "":
|
||||||
|
logger.log("INFOR", f"开始扫描> {target}")
|
||||||
|
get_target_list = target.split(".")
|
||||||
|
aws_check_init = aws.Amazone_Cloud_S3Bucket_Check(target=get_target_list[0],
|
||||||
|
location=get_target_list[1])
|
||||||
|
if aws_check_init.Check_Bucket_ListObject():
|
||||||
|
logger.log("INFOR", f"{target}> 存储桶对象可遍历")
|
||||||
|
else:
|
||||||
|
logger.log("ALERT", f"{target}> 存储桶对象不可遍历")
|
||||||
|
|
||||||
|
if aws_check_init.Check_Bucket_PutObject():
|
||||||
|
logger.log("INFOR", f"{target}> 可未授权上传对象至存储桶(可覆盖存储桶已有对象)")
|
||||||
|
else:
|
||||||
|
logger.log("ALERT", f"{target}> 不可未授权上传对象至存储桶(可覆盖存储桶已有对象)")
|
||||||
|
|
||||||
|
if aws_check_init.Check_Bucket_GetBucketAcl():
|
||||||
|
logger.log("INFOR", f"{target}> 存储桶ACL策略可公开获取")
|
||||||
|
else:
|
||||||
|
logger.log("ALERT", f"{target}> 存储桶ACL策略不可公开")
|
||||||
|
else:
|
||||||
|
AmazoneS3(get_domain)
|
||||||
BIN
images/image-20220703201835328.png
Normal file
BIN
images/image-20220703201835328.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 60 KiB |
BIN
images/image-20220703202049560.png
Normal file
BIN
images/image-20220703202049560.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
BIN
images/image-20220703202339058.png
Normal file
BIN
images/image-20220703202339058.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 184 KiB |
BIN
images/image-20220703202518187.png
Normal file
BIN
images/image-20220703202518187.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 631 KiB |
BIN
images/image-20220703202635171.png
Normal file
BIN
images/image-20220703202635171.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 87 KiB |
BIN
images/image-20220703203021188.png
Normal file
BIN
images/image-20220703203021188.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 MiB |
152
main.py
152
main.py
@ -1,142 +1,30 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/python3.8.4 (python版本)
|
||||||
# -*- coding: UTF-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
'''
|
# @Author : UzJu@菜菜狗
|
||||||
@Project :UzJuSecurityTools
|
# @Email : UzJuer@163.com
|
||||||
@File :main.py
|
# @Software: PyCharm
|
||||||
@Author :UzJu
|
# @Time : 2022/7/2 14:16
|
||||||
@Date :2022/2/22 18:19
|
# @File : main.py
|
||||||
@Email :UzJuer@163.com
|
|
||||||
'''
|
|
||||||
import logging
|
|
||||||
import sys
|
|
||||||
|
|
||||||
import colorlog
|
|
||||||
import datetime
|
|
||||||
from config import BannerInfo
|
|
||||||
import requests
|
|
||||||
import argparse
|
import argparse
|
||||||
from core import aliyunOss
|
from core import main
|
||||||
from core import DnsResolution
|
from config.logs import logger
|
||||||
from core import AmazoneCloudS3Bucket
|
from config import conf
|
||||||
|
|
||||||
NowTime = datetime.datetime.now().strftime('%Y-%m-%d')
|
|
||||||
|
|
||||||
logger = logging.getLogger("mainModule")
|
|
||||||
log_colors_config = {
|
|
||||||
'DEBUG': 'white', # cyan white
|
|
||||||
'INFO': 'green',
|
|
||||||
'WARNING': 'yellow',
|
|
||||||
'ERROR': 'red',
|
|
||||||
'CRITICAL': 'bold_red',
|
|
||||||
}
|
|
||||||
|
|
||||||
# 输出到控制台
|
|
||||||
console_handler = logging.StreamHandler()
|
|
||||||
# 输出到文件
|
|
||||||
file_handler = logging.FileHandler(filename=f'./logs/{NowTime}.log', mode='a', encoding='utf8')
|
|
||||||
|
|
||||||
# 日志级别,logger 和 handler以最高级别为准,不同handler之间可以不一样,不相互影响
|
|
||||||
logger.setLevel(logging.DEBUG)
|
|
||||||
console_handler.setLevel(logging.DEBUG)
|
|
||||||
file_handler.setLevel(logging.INFO)
|
|
||||||
|
|
||||||
# 日志输出格式
|
|
||||||
file_formatter = logging.Formatter(
|
|
||||||
fmt='[%(asctime)s.%(msecs)03d] %(filename)s -> %(funcName)s line:%(lineno)d [%(levelname)s] : %(message)s',
|
|
||||||
datefmt='%Y-%m-%d %H:%M:%S'
|
|
||||||
)
|
|
||||||
console_formatter = colorlog.ColoredFormatter(
|
|
||||||
fmt='%(log_color)s[%(asctime)s.%(msecs)03d] %(filename)s -> %(funcName)s line:%(lineno)d [%(levelname)s] : %(message)s',
|
|
||||||
datefmt='%Y-%m-%d %H:%M:%S',
|
|
||||||
log_colors=log_colors_config
|
|
||||||
)
|
|
||||||
console_handler.setFormatter(console_formatter)
|
|
||||||
file_handler.setFormatter(file_formatter)
|
|
||||||
|
|
||||||
# 重复日志问题:
|
|
||||||
# 1、防止多次addHandler;
|
|
||||||
# 2、loggername 保证每次添加的时候不一样;
|
|
||||||
# 3、显示完log之后调用removeHandler
|
|
||||||
if not logger.handlers:
|
|
||||||
logger.addHandler(console_handler)
|
|
||||||
logger.addHandler(file_handler)
|
|
||||||
|
|
||||||
|
|
||||||
def initialize(target):
|
|
||||||
"""
|
|
||||||
UserDisable
|
|
||||||
错误消息:UserDisable
|
|
||||||
问题原因:账号欠费或者由于安全原因,账号被禁用。
|
|
||||||
解决方案:请检查账号是否已欠费,或联系技术支持进行安全受限核查。
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
resp = requests.get(f"http://{target}")
|
|
||||||
print("Target>>>> ", target)
|
|
||||||
print("resp.info>>>> ", resp.text)
|
|
||||||
if 'html' in resp.text or 'UserDisable' in resp.text:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
except requests.exceptions.ConnectionError as e:
|
|
||||||
logger.error(f"Target: {target}ConnectionError Except INFO: {e}")
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
BannerInfo.echoRandomBannerInfo()
|
print(conf.banner)
|
||||||
try:
|
try:
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('-aliyun', dest='aliyun', help='python3 -aliyun UzJu.oss-cn-beijing.aliyuncs.com')
|
parser.add_argument('-aliyun', dest='aliyun', help='python3 main.py -aliyun Bucketurl')
|
||||||
parser.add_argument('-aws', dest='aws', help='python3 -aws UzJu.oss-cn-beijing.aliyuncs.com')
|
parser.add_argument('-faliyun', dest='faliyun', help='python3 main.py -faliyun filename')
|
||||||
parser.add_argument('-f', '--file', dest='file', nargs='+', help='python3 -f/--file url.txt')
|
parser.add_argument('-aws', dest='aws', help='python3 main.py -aws bucketurl')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
'''
|
|
||||||
阿里云OSS模块
|
|
||||||
'''
|
|
||||||
if args.aliyun:
|
if args.aliyun:
|
||||||
existDomain = DnsResolution.GetDomainDnsResolution(args.aliyun)
|
main.aliyun(args.aliyun)
|
||||||
if existDomain:
|
elif args.faliyun:
|
||||||
aliyunOss.CheckBucket(existDomain.split(".")[0], existDomain.split(".")[1])
|
main.aliyun_file_scan(args.faliyun)
|
||||||
else:
|
elif args.aws:
|
||||||
getTargetBucket = args.aliyun.split(".")
|
main.AmazoneS3(args.aws)
|
||||||
aliyunOss.CheckBucket(getTargetBucket[0], getTargetBucket[1])
|
|
||||||
'''
|
|
||||||
aws S3模块
|
|
||||||
'''
|
|
||||||
if args.aws:
|
|
||||||
'''
|
|
||||||
这里本来是这样写的
|
|
||||||
bucketDomain = args.aws.split(".")
|
|
||||||
但是在Fofa中找资产测试发现一个问题,如果这样写,举个例子
|
|
||||||
xxx.xxx.cdn.s3.amazonaws.com
|
|
||||||
这种存储桶地址就会取出来
|
|
||||||
['xxx', 'xxx', 'cdn', 's3', 'amazonaws', 'com']
|
|
||||||
一般情况下,都能正常取下标来判断xxx就是存储桶名字,但是这里不一样,这里xxx.xxx.cdn都是存储桶的名字,这样取就会存在问题
|
|
||||||
|
|
||||||
bucketDomain = args.aws.split(".s3")
|
|
||||||
这种写法能解决上述的问题,为什么?
|
|
||||||
我们简单分析一下存储桶的地址构造
|
|
||||||
xxx.xxx.xxcdn.s3.amazonaws.com
|
|
||||||
xxx.xxx.xxcdn.s3.us-east-1.amazonaws.com
|
|
||||||
无非就是存储桶名+s3+地区+云厂商的域名 或者 存储桶名+s3+云厂商域名,这里可以用来分割的字段,.s3再适合不过了
|
|
||||||
'''
|
|
||||||
bucketDomain = args.aws.split(".s3")
|
|
||||||
AmazoneCloudS3Bucket.CheckBucket(bucketDomain[0], args.aws)
|
|
||||||
if args.file:
|
|
||||||
with open(args.file[1], 'r') as f:
|
|
||||||
for i in f.read().splitlines():
|
|
||||||
|
|
||||||
if args.file[0] == "aliyun":
|
|
||||||
existDomain = DnsResolution.GetDomainDnsResolution(i)
|
|
||||||
if existDomain:
|
|
||||||
aliyunOss.CheckBucket(existDomain.split(".")[0], existDomain.split(".")[1])
|
|
||||||
else:
|
|
||||||
getTargetBucket = i.split(".")
|
|
||||||
aliyunOss.CheckBucket(getTargetBucket[0], getTargetBucket[1])
|
|
||||||
|
|
||||||
elif args.file[0] == "aws":
|
|
||||||
bucketDomain = i.split(".s3")
|
|
||||||
AmazoneCloudS3Bucket.CheckBucket(bucketDomain[0], i)
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
logger.error("KeyError Out")
|
logger.log("ALERT", "Bye~")
|
||||||
|
|||||||
@ -1,24 +1,21 @@
|
|||||||
#!/usr/bin/python
|
#!/usr/bin/python3.8.4 (python版本)
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# @Author : UzJu@菜菜狗
|
# @Author : UzJu@菜菜狗
|
||||||
# @Email : UzJuer@163.com
|
# @Email : UzJuer@163.com
|
||||||
# @Software: PyCharm
|
# @Software: PyCharm
|
||||||
# @Time : 2022/3/7 上午11:38
|
# @Time : 2022/7/2 19:59
|
||||||
# @File : DnsResolution.py
|
# @File : DomainCname.py
|
||||||
|
|
||||||
|
|
||||||
import dns.resolver
|
import dns.resolver
|
||||||
import logging
|
from config.logs import logger
|
||||||
|
|
||||||
module_logger = logging.getLogger("mainModule.Dns")
|
|
||||||
|
|
||||||
|
|
||||||
def GetDomainDnsResolution(domain):
|
def Get_Domain_Cname(domain):
|
||||||
try:
|
try:
|
||||||
cname = dns.resolver.resolve(domain, 'CNAME')
|
cname = dns.resolver.resolve(domain, 'CNAME')
|
||||||
for i in cname.response.answer:
|
for i in cname.response.answer:
|
||||||
for j in i.items:
|
for j in i.items:
|
||||||
return j.to_text()
|
return j.to_text()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return False
|
logger.log("ERROR", repr(e))
|
||||||
|
return False
|
||||||
30
plugins/results.py
Normal file
30
plugins/results.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#!/usr/bin/python3.8.4 (python版本)
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# @Author : UzJu@菜菜狗
|
||||||
|
# @Email : UzJuer@163.com
|
||||||
|
# @Software: PyCharm
|
||||||
|
# @Time : 2022/7/3 13:31
|
||||||
|
# @File : results.py
|
||||||
|
|
||||||
|
import os
|
||||||
|
import csv
|
||||||
|
import pandas as pd
|
||||||
|
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'
|
||||||
|
rows = [
|
||||||
|
[f"{target}", BucketHijack, GetBucketObjectList, PutBucketObject, GetBucketAcl, PutBucketAcl, GetBucketPolicy]
|
||||||
|
]
|
||||||
|
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)
|
||||||
|
|
||||||
7
requirements.txt
Normal file
7
requirements.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
boto3==1.23.9
|
||||||
|
colorama==0.4.4
|
||||||
|
dnspython==2.2.1
|
||||||
|
loguru==0.5.3
|
||||||
|
oss2==2.15.0
|
||||||
|
pandas==1.4.3
|
||||||
|
prettytable==3.2.0
|
||||||
Loading…
x
Reference in New Issue
Block a user