From 2304a8a8538673c46992036fe336f23b44e71627 Mon Sep 17 00:00:00 2001 From: Miguel Sanchez Date: Sun, 26 Feb 2023 17:01:24 -0500 Subject: [PATCH] New updates --- gsec.py | 20 +++++++++--- modules/fetch_requests.py | 24 +++++++++++++-- plugins/phpcheck.py | 22 +++++++------ plugins/robots.py | 4 ++- utils/portscanner.py | 63 ++++++++++++++++++++++---------------- utils/webserver_scanner.py | 21 +++++++++++++ vuln_db/ssrf.py | 43 ++++++++++++++++++++++++++ vuln_db/xss.py | 57 ++++++++++++++++++++++++++++++++++ 8 files changed, 210 insertions(+), 44 deletions(-) create mode 100644 utils/webserver_scanner.py create mode 100644 vuln_db/ssrf.py create mode 100644 vuln_db/xss.py diff --git a/gsec.py b/gsec.py index 3b5e92c..90a4e04 100644 --- a/gsec.py +++ b/gsec.py @@ -1,12 +1,14 @@ from colorama import Fore -from modules import fetch_requests, scan, urltoip +from modules import fetch_requests, scan, urltoip, sub_output from utils import portscanner, loginscanner, techscanner, cmsscanner, passive_recon, crawler from plugins import phpcheck, optionscheck, shellshock, robots, favicon, auth_tokens, cookies_check -from vuln_db import hostheader_injection, nuclei_vulns, corsmisconfig, crossdomain, head_vuln, cache_poisoning, path_traversal, webservers_vulns +from exploits import f5bigip_scanner +from vuln_db import hostheader_injection, nuclei_vulns, corsmisconfig, crossdomain, head_vuln, cache_poisoning, path_traversal, webservers_vulns, xss import argparse import os import asyncio + ################################################################################## # Good Security Scanner ################################################################################## @@ -22,7 +24,7 @@ | .___________________. |==| {Fore.YELLOW}Web Security Scanner{Fore.RESET} | | ................. | | | | | :::GSec Running!::| | | {Fore.YELLOW}Author: {Fore.MAGENTA}c0d3ninja{Fore.RESET} - | | ::::::::::::::::: | | | {Fore.YELLOW}Version: {Fore.MAGENTA}beta-v0.27{Fore.RESET} + | | ::::::::::::::::: | | | {Fore.YELLOW}Version: {Fore.MAGENTA}beta-v1.0{Fore.RESET} | | :1337 bugs found!:| | | {Fore.YELLOW}Instagram: {Fore.MAGENTA}gotr00t0day{Fore.RESET} | | ::::::::::::::::: | | | | | ::::::::::::::::: | | | @@ -92,7 +94,7 @@ async def main(): if "http://" in args.target: print(f"{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} PROTOCOL: {Fore.GREEN}http") optionscheck.Get_Options(args.target) - portscanner.portscanner(args.target) + portscanner.main(args.target) fetch_requests.get_headers(args.target) scan.commands(f"python3 {os.path.abspath(os.getcwd())}/utils/securityheaders.py --target {args.target} --headers X-XSS-Protection") scan.commands(f"python3 {os.path.abspath(os.getcwd())}/utils/securityheaders.py --target {args.target} --headers Content-Security-Policy") @@ -114,11 +116,19 @@ async def main(): head_vuln.head_auth_bypass(args.target) cache_poisoning.cache_dos_scan(args.target) webservers_vulns.Servers_scan(args.target) + xss.xss_scan(args.target) + sub_output.subpro_scan(f"python3 {os.path.abspath(os.getcwd())}/vuln_db/ssrf.py {args.target}") path_traversal.path_traversal_scan(args.target) + f5bigip_scanner.scan_vuln(args.target) crawler.scan(args.target) await loginscanner.main(args.target) print("\n") print(f"\t\t {Fore.MAGENTA} SCAN FINISHED{Fore.LIGHTMAGENTA_EX}!{Fore.MAGENTA}!{Fore.YELLOW}!{Fore.RESET}") if __name__ == "__main__": - asyncio.run(main()) + try: + asyncio.run(main()) + except ConnectionError: + pass + except ConnectionRefusedError: + pass diff --git a/modules/fetch_requests.py b/modules/fetch_requests.py index 5459344..fe9e63b 100644 --- a/modules/fetch_requests.py +++ b/modules/fetch_requests.py @@ -1,10 +1,12 @@ from bs4 import BeautifulSoup from colorama import Fore from plugins import agent_list +from utils import webserver_scanner import requests import urllib3 import sys -import os +import ssl +import re urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) @@ -43,6 +45,8 @@ def do_requests(url: str) -> str: sys.exit() except AttributeError: pass + except ssl.SSLCertVerificationError: + pass def get_headers(url: str) -> str: sessions = requests.Session() @@ -64,6 +68,20 @@ def get_headers(url: str) -> str: print(f"{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} SERVER: {Fore.GREEN}{', '.join(map(str,server_output))}") else: pass + if "Apache" in server_output: + apache_version = webserver_scanner.apache_version() + webpage_server = re.search(r'([\d.]+)', server_output).group(1) + if webpage_server < apache_version: + print(f"{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} Apache {webpage_server}: {Fore.GREEN} Is outdated, current version is {apache_version}") + + if "nginx" in server_output: + try: + nginx_version = webserver_scanner.nginx_version() + webpage_server = re.search(r'([\d.]+)', server_output).group(1) + if webpage_server < nginx_version: + print(f"{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} nginx {webpage_server}: {Fore.GREEN} Is outdated, current version is {nginx_version}") + except TypeError: + pass if via_output: print(f"{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} VIA: {Fore.GREEN}{', '.join(map(str,via_output))}") else: @@ -78,4 +96,6 @@ def get_headers(url: str) -> str: sys.exit() except requests.exceptions.MissingSchema: print("Invalid URL, please use http:// or https://") - sys.exit() \ No newline at end of file + sys.exit() + except ssl.SSLCertVerificationError: + pass \ No newline at end of file diff --git a/plugins/phpcheck.py b/plugins/phpcheck.py index 760e60c..e3d6d4f 100644 --- a/plugins/phpcheck.py +++ b/plugins/phpcheck.py @@ -2,6 +2,7 @@ from colorama import Fore from plugins import agent_list import requests +import ssl user_agent_ = agent_list.get_useragent() header = {"User-Agent": user_agent_} @@ -10,15 +11,18 @@ def php_ident(url: str) -> str: php_index = [] php_header = [] php_language = [] - sessions = requests.Session() - res = sessions.get(url, verify=False, headers=header) - for value, key in res.headers.items(): - if "X-Powered-By" in value and "PHP" in key: - php_header.append(f"PHP") - indexphp = sessions.get(f"{url}/index.php", verify=False, headers=header) - if indexphp.status_code == 200 and "404" not in indexphp.text: - php_index.append("index.php") - if indexphp.status_code == 429: + try: + sessions = requests.Session() + res = sessions.get(url, verify=False, headers=header) + for value, key in res.headers.items(): + if "X-Powered-By" in value and "PHP" in key: + php_header.append(f"PHP") + indexphp = sessions.get(f"{url}/index.php", verify=False, headers=header) + if indexphp.status_code == 200 and "404" not in indexphp.text: + php_index.append("index.php") + if indexphp.status_code == 429: + pass + except ssl.SSLCertVerificationError: pass try: info = builtwith(f"{url}") diff --git a/plugins/robots.py b/plugins/robots.py index 74213db..78726af 100644 --- a/plugins/robots.py +++ b/plugins/robots.py @@ -18,4 +18,6 @@ def robots_scan(domain: str) -> str: f.writelines(data.read()) print(f"{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} Robots: {Fore.MAGENTA}Content of robots.txt saved to /output") except urllib.error.HTTPError: - pass \ No newline at end of file + pass + except urllib.error.URLError: + pass \ No newline at end of file diff --git a/utils/portscanner.py b/utils/portscanner.py index c7624ee..ca21532 100644 --- a/utils/portscanner.py +++ b/utils/portscanner.py @@ -1,34 +1,43 @@ from colorama import Fore -import threading -import socket from modules import urltoip -import ipaddress +import socket +import threading -ports = [80, 8080, 443] +open_ports = [] +closed_ports = [] +start_port = 1 +end_port = 65000 -def portscanner(domain: str): - ip = urltoip.get_ip(domain) - open_ports = [] +# specify the range of ports to scan + +# define a function to scan a single port and print the service banner +def scan_port(port): try: - for port in ports: - sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - data = sck.connect_ex((ip, port)) - if data == 0: - open_ports.append(f"{port}") - sck.close() - else: - pass - print(f"{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} PORTS: {Fore.GREEN}{', '.join(map(str,open_ports))}") - except socket.error: - print (Fore.RED + "Could not connect to host") - pass - except KeyboardInterrupt: - print ("You pressed CTRL+C") - except ipaddress.AddressValueError: - print ("IP address not allowed") - except TypeError: + # create a TCP socket and attempt to connect to the specified port + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.settimeout(1) + result = sock.connect_ex((ip_address, port)) + + # if the connection is successful, attempt to receive the service banner + if result == 0: + open_ports.append(f"{port}") + print(f"{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} PORTS: {Fore.GREEN}{', '.join(map(str,open_ports))}") + + # close the socket + sock.close() + except: pass -if __name__=="__main__": - t1 = threading.Thread(target=portscanner, args=(ports,)) - t1.start() \ No newline at end of file +# create a list of threads to scan each port in the range +def main(domain: str): + global ip_address + ip_address = urltoip.get_ip(domain) + threads = [] + for port in range(start_port, end_port + 1): + thread = threading.Thread(target=scan_port, args=(port,)) + threads.append(thread) + thread.start() + + # wait for all threads to complete + for thread in threads: + thread.join() diff --git a/utils/webserver_scanner.py b/utils/webserver_scanner.py new file mode 100644 index 0000000..a643cee --- /dev/null +++ b/utils/webserver_scanner.py @@ -0,0 +1,21 @@ +import requests +import re +from bs4 import BeautifulSoup + +def apache_version(): + url = 'https://httpd.apache.org/download.cgi' + + response = requests.get(url) + soup = BeautifulSoup(response.text, 'html.parser') + version = soup.find("h1", attrs={'id':'apache24'}).get_text() + version_number = re.search(r'([\d.]+)', version).group(1) + return version_number + +def nginx_version(): + url = 'https://nginx.org/en/download.html' + + response = requests.get(url) + soup = BeautifulSoup(response.text, 'html.parser') + version = soup.find('a', attrs={'href':'/download/nginx-1.22.1.tar.gz'}).get_text() + version_number = re.search(r'([\d.]+)', version).group(1) + return version_number \ No newline at end of file diff --git a/vuln_db/ssrf.py b/vuln_db/ssrf.py new file mode 100644 index 0000000..1c2f83e --- /dev/null +++ b/vuln_db/ssrf.py @@ -0,0 +1,43 @@ +from colorama import Fore +import requests +import re +import threading +import sys + +# specify the URL to test +url = sys.argv[1] + +# create a list of domains to test for SSRF +domains = ["localhost", "127.0.0.1", "0.0.0.0", "localhost.localdomain", "localhost6.localdomain6", "0:0:0:0:0:0:0:1"] + +# define a function to check a single parameter for SSRF +def check_parameter(parameter): + for domain in domains: + try: + # send a GET request with the current domain in the parameter + response = requests.get(url.replace(parameter, domain)) + + # check the response for signs of successful SSRF exploitation + if re.search(r"connection refused|network is unreachable", response.text, re.IGNORECASE): + print(f'{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} SSRF Found in: {Fore.MAGENTA}{parameter}') + break + except: + # handle any exceptions that occur during the request + pass + +# send a GET request to the URL and extract all parameters +response = requests.get(url) +parameters = re.findall(r"\?(\w+)=", response.text) + +# create a list of threads to check each parameter for SSRF +if __name__ == "__main__": + threads = [] + for parameter in parameters: + thread = threading.Thread(target=check_parameter, args=(parameter,)) + threads.append(thread) + thread.start() + + # wait for all threads to complete + for thread in threads: + thread.join() + diff --git a/vuln_db/xss.py b/vuln_db/xss.py new file mode 100644 index 0000000..6c4b703 --- /dev/null +++ b/vuln_db/xss.py @@ -0,0 +1,57 @@ +from bs4 import BeautifulSoup +from colorama import Fore +import requests +import urllib.parse +import re + +payloads = [ + "", + "", + "", + "javascript:alert('XSS')", + "data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4=" +] + +def xss_scan(domain: str) -> str: + # send a GET request to the URL + response = requests.get(domain) + + # parse the HTML content using BeautifulSoup + soup = BeautifulSoup(response.content, "html.parser") + + # find all input fields in the form tag with user input options + input_fields = soup.find_all("input", {"type": ["text", "password", "email", "number", "search", "user"]}) + + # iterate through the input fields and send an XSS payload to each field + parsed_payloads = [] + for field in input_fields: + # create a sample XSS payloads + + # set the value of the current input field to the XSS payload + for payload in payloads: + encoded_payload = urllib.parse.quote_plus(payload) + field["value"] = payload + + # submit the form data using a POST request + form_data = {} + for form_field in soup.find_all("input"): + form_data[form_field.get("name")] = form_field.get("value") + response = requests.post(domain, data=form_data) + + # check the response for signs of successful XSS exploitation + if payload in response.text: + print(f'{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} XSS FOUND: {Fore.MAGENTA}{field.get("name")}') + + #if the XSS exploitation was not successful, URL encode the payload and try again + field["value"] = encoded_payload + form_data[field.get("name")] = encoded_payload + response = requests.post(domain, data=form_data) + + if encoded_payload in response.text: + print(f'{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} XSS FOUND: {Fore.MAGENTA}{field.get("name")}') + + scripts = soup.find_all("script") + # Iterate over all script tags + for script in scripts: + if re.search(r"(location|document|window)\.(hash|search|referrer|pathname|name|title|cookie|getElementById|getElementsByClassName|getElementsByTagName|write|writeln|innerHTML|outerHTML|setAttribute|getAttribute)\(", str(script)): + print(f'{Fore.MAGENTA}[+] {Fore.CYAN}-{Fore.WHITE} Potential DOM XSS: {Fore.MAGENTA}{str(script)}') \ No newline at end of file