From 568cd6254a1690ecbd2b3c2af64edfed4ee63364 Mon Sep 17 00:00:00 2001 From: mrrobot1o1 Date: Wed, 24 Jan 2024 22:00:00 +0530 Subject: [PATCH 1/4] Input as JS Files and save it in one HTML file --- linkfinder.py | 67 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/linkfinder.py b/linkfinder.py index a33f53f..4a4203a 100755 --- a/linkfinder.py +++ b/linkfinder.py @@ -8,7 +8,17 @@ os.environ["BROWSER"] = "open" # Import libraries -import re, sys, glob, html, argparse, jsbeautifier, webbrowser, subprocess, base64, ssl, xml.etree.ElementTree +import re +import sys +import glob +import html +import argparse +import jsbeautifier +import webbrowser +import subprocess +import base64 +import ssl +import xml.etree.ElementTree from gzip import GzipFile from string import Template @@ -25,6 +35,12 @@ except ImportError: from urllib2 import Request, urlopen +def combine_results(results): + combined_output = '' + for result in results: + combined_output += result + return combined_output + # Regex used regex_str = r""" @@ -77,7 +93,6 @@ def parser_error(errmsg): print("Error: %s" % errmsg) sys.exit() - def parser_input(input): ''' Parse Input @@ -98,7 +113,8 @@ def parser_input(input): items = xml.etree.ElementTree.fromstring(open(args.input, "r").read()) for item in items: - jsfiles.append({"js":base64.b64decode(item.find('response').text).decode('utf-8',"replace"), "url":item.find('url').text}) + jsfiles.append({"js": base64.b64decode(item.find('response').text).decode('utf-8', "replace"), + "url": item.find('url').text}) return jsfiles # Method 4 - Folder with a wildcard @@ -114,7 +130,6 @@ def parser_input(input): return [path if os.path.exists(input) else parser_error("file could not \ be found (maybe you forgot to add http/https).")] - def send_request(url): ''' Send requests with Requests @@ -198,7 +213,7 @@ def parser_file(content, regex_str, mode=1, more_regex=None, no_dup=1): if mode == 1: # Beautify if len(content) > 1000000: - content = content.replace(";",";\r\n").replace(",",",\r\n") + content = content.replace(";", ";\r\n").replace(",", ",\r\n") else: content = jsbeautifier.beautify(content) @@ -288,12 +303,12 @@ def check_url(url): # Parse command line parser = argparse.ArgumentParser() parser.add_argument("-d", "--domain", - help="Input a domain to recursively parse all javascript located in a page", + help="Input a domain to recursively parse all JavaScript located on a page", action="store_true") parser.add_argument("-i", "--input", help="Input a: URL, file or folder. \ For folders a wildcard can be used (e.g. '/*.js').", - required="True", action="store") + required=True, action="store") parser.add_argument("-o", "--output", help="Where to save the file, \ including file name. Default: output.html", @@ -321,22 +336,28 @@ def check_url(url): if args.output == "cli": mode = 0 - # Convert input to URLs or JS files - urls = parser_input(args.input) + # Check if input is a URL or a file + if os.path.isfile(args.input): + # Read URLs from the file + with open(args.input, 'r') as file: + urls = file.read().splitlines() + else: + # Single URL provided + urls = [args.input] # Convert URLs to JS - output = '' + results = [] for url in urls: if not args.burp: try: - file = send_request(url) + file_content = send_request(url) except Exception as e: parser_error("invalid input defined or SSL error: %s" % e) else: - file = url['js'] + file_content = url['js'] url = url['url'] - endpoints = parser_file(file, regex_str, mode, args.regex) + endpoints = parser_file(file_content, regex_str, mode, args.regex) if args.domain: for endpoint in endpoints: endpoint = html.escape(endpoint["link"]).encode('ascii', 'ignore').decode('utf8') @@ -346,14 +367,14 @@ def check_url(url): print("Running against: " + endpoint) print("") try: - file = send_request(endpoint) - new_endpoints = parser_file(file, regex_str, mode, args.regex) + file_content = send_request(endpoint) + new_endpoints = parser_file(file_content, regex_str, mode, args.regex) if args.output == 'cli': cli_output(new_endpoints) else: - output += ''' -

File: %s

- ''' % (html.escape(endpoint), html.escape(endpoint)) + output = ''' +

File: %s

+ ''' % (html.escape(endpoint), html.escape(endpoint)) for endpoint2 in new_endpoints: url = html.escape(endpoint2["link"]) @@ -370,6 +391,7 @@ def check_url(url): html.escape(endpoint2["link"]) ) output += header + body + results.append(output) except Exception as e: print("Invalid input defined or SSL error for: " + endpoint) continue @@ -377,8 +399,8 @@ def check_url(url): if args.output == 'cli': cli_output(endpoints) else: - output += ''' -

File: %s

+ output = ''' +

URL: %s

''' % (html.escape(url), html.escape(url)) for endpoint in endpoints: @@ -397,6 +419,9 @@ def check_url(url): ) output += header + body + results.append(output) if args.output != 'cli': - html_save(output) + html_save(combine_results(results)) + + From 7b3f50ac6c33a97f8b4c7329c94839ccabdbd321 Mon Sep 17 00:00:00 2001 From: mrrobot1o1 Date: Sun, 28 Jan 2024 00:16:38 +0530 Subject: [PATCH 2/4] ssl_PROTOCOL_TLSv1_2 is deprecated fix --- linkfinder.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/linkfinder.py b/linkfinder.py index 4a4203a..39e2349 100755 --- a/linkfinder.py +++ b/linkfinder.py @@ -145,10 +145,16 @@ def send_request(url): q.add_header('Cookie', args.cookies) try: - sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) - response = urlopen(q, timeout=args.timeout, context=sslcontext) + if args.insecure: + sslcontext = ssl.create_default_context() + sslcontext.check_hostname = False + sslcontext.verify_mode = ssl.CERT_NONE + response = urlopen(q, timeout=args.timeout, context=sslcontext) + else: + sslcontext = ssl.create_default_context() + response = urlopen(q, timeout=args.timeout, context=sslcontext) except: - sslcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1) + sslcontext = ssl.create_default_context() response = urlopen(q, timeout=args.timeout, context=sslcontext) if response.info().get('Content-Encoding') == 'gzip': @@ -327,6 +333,9 @@ def check_url(url): parser.add_argument("-t", "--timeout", help="How many seconds to wait for the server to send data before giving up (default: " + str(default_timeout) + " seconds)", default=default_timeout, type=int, metavar="") + parser.add_argument("--insecure", + help="Allow insecure SSL connections (disable certificate verification)", + action="store_true") args = parser.parse_args() if args.input[-1:] == "/": From 8faef8cdcb69759c15feb268a5fac8464a40abc1 Mon Sep 17 00:00:00 2001 From: mrrobot1o1 <66872759+mrrobot1o1@users.noreply.github.com> Date: Sun, 28 Jan 2024 00:47:15 +0530 Subject: [PATCH 3/4] Update README.md Image update with file input option. --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 34807bf..8adc20a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + ## About LinkFinder @@ -51,6 +51,10 @@ Short Form | Long Form | Description `python linkfinder.py -i https://example.com/1.js -o results.html` +OR + +`python linkfinder.py -i js_urls.txt -o results.html` + * CLI/STDOUT output (doesn't use jsbeautifier, which makes it very fast): `python linkfinder.py -i https://example.com/1.js -o cli` From 68798f8d090ab007380975a5725662773286c22e Mon Sep 17 00:00:00 2001 From: mrrobot1o1 <66872759+mrrobot1o1@users.noreply.github.com> Date: Sun, 28 Jan 2024 00:55:05 +0530 Subject: [PATCH 4/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8adc20a..532c85c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + ## About LinkFinder