-
Notifications
You must be signed in to change notification settings - Fork 1
/
apiendpointlister.py
136 lines (107 loc) · 4.7 KB
/
apiendpointlister.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#!/usr/bin/env python3
# # # # # # # # # # # # # # # # # # # # # # # #
# made by hitemSec
# github: https://github.com/hitem
# mastodon: @[email protected]
# # # # # # # # # # # # # # # # # # # # # # # #
import requests
import json
import argparse
from urllib.parse import urlparse
from collections import defaultdict
from colorama import Fore, Style, init
init(autoreset=True)
def interpolate_color(color1, color2, factor):
"""Interpolate between two RGB colors."""
return [int(color1[i] + (color2[i] - color1[i]) * factor) for i in range(3)]
def rgb_to_ansi(r, g, b):
"""Convert RGB to ANSI color code."""
return f'\033[38;2;{r};{g};{b}m'
def print_logo_and_instructions():
logo = """
▄ .▄▪ ▄▄▄▄▄▄▄▄ .• ▌ ▄ ·. .▄▄ · ▄▄▄ . ▄▄·
██▪▐███ •██ ▀▄.▀··██ ▐███▪▐█ ▀. ▀▄.▀·▐█ ▌▪
██▀▐█▐█· ▐█.▪▐▀▀▪▄▐█ ▌▐▌▐█·▄▀▀▀█▄▐▀▀▪▄██ ▄▄
██▌▐▀▐█▌ ▐█▌·▐█▄▄▌██ ██▌▐█▌▐█▄▪▐█▐█▄▄▌▐███▌
▀▀▀ ·▀▀▀ ▀▀▀ ▀▀▀ ▀▀ █▪▀▀▀ ▀▀▀▀ ▀▀▀ ·▀▀▀
"""
colors = [
(255, 0, 255), # Purple
(0, 0, 255) # Blue
]
num_colors = len(colors)
rainbow_logo = ""
color_index = 0
num_chars = sum(len(line) for line in logo.split("\n"))
for char in logo:
if char != " " and char != "\n":
factor = (color_index / num_chars) * (num_colors - 1)
idx = int(factor)
next_idx = min(idx + 1, num_colors - 1)
local_factor = factor - idx
color = interpolate_color(colors[idx], colors[next_idx], local_factor)
rainbow_logo += rgb_to_ansi(*color) + char
color_index += 1
else:
rainbow_logo += char
instructions = f"""
{rainbow_logo}{Style.RESET_ALL}
{Fore.LIGHTBLACK_EX}Improve your reconnaissance by {Fore.RED}hitemSec{Style.RESET_ALL}
{Fore.LIGHTBLACK_EX}How-To: {Fore.YELLOW}python3 apiendpointlister.py -h{Style.RESET_ALL}
{Fore.GREEN}APIendpointlister - Usage Instructions{Style.RESET_ALL}
{Fore.YELLOW}--------------------------------------{Style.RESET_ALL}
This tool lists all API Endpoints available in swagger.json (openAPI)
{Fore.YELLOW}Usage:{Style.RESET_ALL}
python3 apiendpointlister.py [OPTIONS]
{Fore.YELLOW}Options:{Style.RESET_ALL}
-u, --urls Path to the URL list file
-o, --output Output file for results
{Fore.YELLOW}Examples:{Style.RESET_ALL}
Check endpoints from a URL list:
python3 apiendpointlister.py -u urllist.txt -o output.txt
{Fore.GREEN}Happy Recon!{Style.RESET_ALL}
"""
print(instructions)
def fetch_swagger_json(url):
try:
response = requests.get(url)
response.raise_for_status()
print(f"[{Fore.GREEN}{response.status_code}{Style.RESET_ALL}] {url}")
return response.json()
except requests.exceptions.RequestException as e:
print(f"[{Fore.RED}ERROR{Style.RESET_ALL}] {url} - {e}")
return None
def extract_endpoints(swagger_json, base_url):
if not swagger_json or 'paths' not in swagger_json:
return []
endpoints = []
for path in swagger_json['paths'].keys():
endpoints.append(base_url + path)
return endpoints
from urllib.parse import urlparse, urlunparse
def process_urls(input_file, output_file):
with open(input_file, 'r') as file:
urls = file.readlines()
all_endpoints = []
for url in urls:
url = url.strip()
parsed_url = urlparse(url)
if not parsed_url.scheme:
url = 'https://' + url
parsed_url = urlparse(url)
base_url = '{uri.scheme}://{uri.netloc}'.format(uri=parsed_url)
swagger_json = fetch_swagger_json(url)
if swagger_json:
endpoints = extract_endpoints(swagger_json, base_url)
all_endpoints.extend(endpoints)
all_endpoints = sorted(all_endpoints)
with open(output_file, 'w') as file:
for endpoint in all_endpoints:
file.write(endpoint + '\n')
if __name__ == "__main__":
print_logo_and_instructions()
parser = argparse.ArgumentParser(description="Extract endpoints from Swagger/OpenAPI JSON files.")
parser.add_argument('-u', '--urls', required=True, help="File containing list of Swagger/OpenAPI JSON URLs")
parser.add_argument('-o', '--output', required=True, help="File to save the extracted apiendpoints")
args = parser.parse_args()
process_urls(args.urls, args.output)