From 235350617055af7f5ad5e066973b0ddb8eae3adf Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Thu, 12 Jan 2023 15:33:39 -0500 Subject: [PATCH 01/23] Added new features and disabled banner for integration with other tools --- wpdetect/__main__.py | 117 ++++++++++++------------------------------ wpdetect/lessURLs.txt | 22 ++++++++ 2 files changed, 56 insertions(+), 83 deletions(-) create mode 100644 wpdetect/lessURLs.txt diff --git a/wpdetect/__main__.py b/wpdetect/__main__.py index 7edd49a..f4c4a92 100644 --- a/wpdetect/__main__.py +++ b/wpdetect/__main__.py @@ -5,134 +5,88 @@ wp_domains = [] header = "'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A'" def wp_check(url): - url_wpl = url + "/wp-login.php" - url_wpac = url + "/wp-content/" - url_wpad = url + "/wp-admin/" - url_wpc = url + "/wp-cron.php" - url_wpx = url + "/xmlrpc.php" - url_wpa = url + "/wp-json/wp/v2/" - url_wpact = url + "/wp-content/themes/" + url_wpl = url + "/wp-login.php" + url_wpa = url + "/wp-json/wp/v2/" + req_wpl = urllib.request.Request(url_wpl, headers={'User-Agent': header}) - req_wpac = urllib.request.Request(url_wpac, headers={'User-Agent': header}) - req_wpact = urllib.request.Request(url_wpact, headers={'User-Agent': header}) - req_wpacp = urllib.request.Request(url_wpact, headers={'User-Agent': header}) - req_wpad = urllib.request.Request(url_wpad, headers={'User-Agent': header}) - req_wpc = urllib.request.Request(url_wpc, headers={'User-Agent': header}) - req_wpx = urllib.request.Request(url_wpx, headers={'User-Agent': header}) req_wpa = urllib.request.Request(url_wpa, headers={'User-Agent': header}) - print("Please wait.../") + #print("Please wait.../") try: if urllib.request.urlopen(req_wpa): - print("\nGood news, " + str(url) + " is using WordPress!\n") wp_domains.append(url) + print(url) except urllib.error.HTTPError: try: if urllib.request.urlopen(req_wpl): - print("\nGood news, " + str(url) + " is using WordPress!\n") wp_domains.append(url) + print(url) except urllib.error.HTTPError: - try: - if urllib.request.urlopen(req_wpac): - print("\nGood news, " + str(url) + " is using WordPress!\n") - wp_domains.append(url) - except urllib.error.HTTPError: - try: - if urllib.request.urlopen(req_wpact): - print("\nGood news, " + str(url) + " is using WordPress!\n") - wp_domains.append(url) - except urllib.error.HTTPError: - try: - if urllib.request.urlopen(req_wpacp): - print("\nGood news, " + str(url) + " is using WordPress!\n") - wp_domains.append(url) - except urllib.error.HTTPError: - try: - if urllib.request.urlopen(req_wpad): - print("\nGood news, " + str(url) + " is using WordPress!\n") - wp_domains.append(url) - except urllib.error.HTTPError: - try: - if urllib.request.urlopen(req_wpc): - print("\nGood news, " + str(url) + " is using WordPress!\n") - wp_domains.append(url) - except urllib.error.HTTPError: - try: - if urllib.request.urlopen(req_wpx): - print("\nGood news, " + str(url) + " is using WordPress!\n") - wp_domains.append(url) - except urllib.error.HTTPError: - print("\n" + str(url) + " may not be using WordPress.\n") + pass def url_check(url): - print("Checking: " + str(url)) + #print("Checking: " + str(url)) try: if url[:4] != "http": - print("[!] No protocol specified.") + #print("[!] No protocol specified.") url = "http://" + url - print("[+] Going with HTTP.\n") - print("Checking: " + str(url)) + #print("[+] Going with HTTP.\n") + #print("Checking: " + str(url)) req = urllib.request.Request(url, headers={'User-Agent': header}) u = urllib.request.urlopen(req) if url != u.geturl(): - print("[!] " + url + " redirected to "+u.geturl()) + #print("[!] " + url + " redirected to "+u.geturl()) url = u.geturl() - print("Checking: " + str(url)) + #print("Checking: " + str(url)) wp_check(url) except urllib.error.HTTPError as e: if e.code == 403: - print("Got 403! Website seems to be behind a WAF.") + pass except urllib.error.URLError: if url[:5] == "https": - print("[!] Couldn't connect over HTTPS.") - print("[+] Trying with HTTP.\n") + #print("[!] Couldn't connect over HTTPS.") + #print("[+] Trying with HTTP.\n") url = "http://" + url[8:] - print("Checking: " + str(url)) + #print("Checking: " + str(url)) try: url_check(url) except urllib.error.URLError: - print("Couldn't open url, please make sure to type a valid and publicly accessible url.\n") + pass else: - print("Couldn't open url, please make sure to type a valid and publicly accessible url.\n") + pass except ValueError: - print("Invalid url! Please type in correct url.\n") + pass def help(): print("\nSyntax: wpdetect ") print("Example: wpdetect https://iamlizu.com/") print("or supply a list with '-f' flag") print("Example: wpdetect -f domainlist.txt\n") + print("Example: cat urls.txt | wpdetect \n") def main(): try: - print(figlet_format(' wpdetect ')) - print("=================== version: 1.3.6 ===================\n") - if sys.argv[1] == '-h' or sys.argv[1] == '--help': - help() - sys.exit() - if sys.argv[1] == '-v' or sys.argv[1] == '--version': - print("Version: 1.3.6") - sys.exit() - if sys.argv[1] == '-f' or sys.argv[1] == '--file': + if len(sys.argv) > 1: + if sys.argv[1] == '-h' or sys.argv[1] == '--help': + help() + sys.exit() + if sys.argv[1] == '-v' or sys.argv[1] == '--version': + print("Version: 1.3.7") + sys.exit() + + if not sys.stdin.isatty(): + for line in sys.stdin: + url_check(line.strip()) + elif sys.argv[1] == '-f' or sys.argv[1] == '--file': try: if len(sys.argv) > 2: file = open(sys.argv[2], 'r') domains = file.readlines() - print("Targets.../\n") - for domain in domains: - print(domain.strip()) - print("\n") for domain in domains: url = domain.strip() url_check(url) - if len(wp_domains) > 0: - print("Found WordPress installation in.../") - for domain in wp_domains: - print(domain) - elif len(wp_domains) == 0: - print("No WordPress installation found!") sys.exit() else: print("No list supplied!") @@ -143,11 +97,8 @@ def main(): url = sys.argv[1] url_check(url) - except IndexError: - print("You didn't enter anything! Please try agian, make sure to enter a valid url.") - help() except KeyboardInterrupt: - print("\nAborted by user.") + pass if __name__ == '__main__': diff --git a/wpdetect/lessURLs.txt b/wpdetect/lessURLs.txt new file mode 100644 index 0000000..41901a6 --- /dev/null +++ b/wpdetect/lessURLs.txt @@ -0,0 +1,22 @@ +http://api.analytics.america.gov +https://api.dev.america.gov +http://techcamp.edit.america.gov +https://api.analytics.america.gov +http://www.share.america.gov +https://techcamp.edit.america.gov +http://commons.america.gov +https://commons.america.gov +http://www.stories.dev.america.gov +https://app-lorawan.fan.gov +https://www.stories.dev.america.gov +http://commons-stage.america.gov +http://commons-beta.america.gov +https://commons-stage.america.gov +https://commons-beta.america.gov +http://devtechcamp.edit.america.gov +http://devtechcamp.america.gov +https://devtechcamp.edit.america.gov +https://devtechcamp.america.gov +http://publications.america.gov +http://www.courses.dev.america.gov +https://publications.america.gov \ No newline at end of file From 88ce8babe1d74ae451d21e5c3a1bdc701b5cd398 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Thu, 12 Jan 2023 15:35:24 -0500 Subject: [PATCH 02/23] Updated README --- .vscode/launch.json | 16 +++++ README.md | 13 +++- build/lib/wpdetect/__init__.py | 0 build/lib/wpdetect/__main__.py | 105 +++++++++++++++++++++++++++++++++ 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 .vscode/launch.json create mode 100644 build/lib/wpdetect/__init__.py create mode 100644 build/lib/wpdetect/__main__.py diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..306f58e --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 4ca0d94..a47fd95 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,23 @@ A WordPress detection tool, detects if a website is running WordPress. wpdetect ### Installation You can install wpdetect using pip, ```sh -pip install wpdetect +git clone repository_url +sudo python setup.py install ``` wpdetect requires Python 3 or above to run. If you have Python 2 installed too, make sure to use the right pip. ### Usage Syntax + +```sh +cat URLs.txt | wpdetect +``` + +```sh +echo https://hackerone.com | wpdetect +``` + + ```sh wpdetect ``` diff --git a/build/lib/wpdetect/__init__.py b/build/lib/wpdetect/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/build/lib/wpdetect/__main__.py b/build/lib/wpdetect/__main__.py new file mode 100644 index 0000000..f4c4a92 --- /dev/null +++ b/build/lib/wpdetect/__main__.py @@ -0,0 +1,105 @@ +import urllib.request +import sys +from pyfiglet import figlet_format + +wp_domains = [] +header = "'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A'" +def wp_check(url): + url_wpl = url + "/wp-login.php" + url_wpa = url + "/wp-json/wp/v2/" + + + req_wpl = urllib.request.Request(url_wpl, headers={'User-Agent': header}) + req_wpa = urllib.request.Request(url_wpa, headers={'User-Agent': header}) + + #print("Please wait.../") + try: + if urllib.request.urlopen(req_wpa): + wp_domains.append(url) + print(url) + except urllib.error.HTTPError: + try: + if urllib.request.urlopen(req_wpl): + wp_domains.append(url) + print(url) + except urllib.error.HTTPError: + pass + + +def url_check(url): + #print("Checking: " + str(url)) + try: + if url[:4] != "http": + #print("[!] No protocol specified.") + url = "http://" + url + #print("[+] Going with HTTP.\n") + #print("Checking: " + str(url)) + req = urllib.request.Request(url, headers={'User-Agent': header}) + u = urllib.request.urlopen(req) + if url != u.geturl(): + #print("[!] " + url + " redirected to "+u.geturl()) + url = u.geturl() + #print("Checking: " + str(url)) + wp_check(url) + except urllib.error.HTTPError as e: + if e.code == 403: + pass + except urllib.error.URLError: + if url[:5] == "https": + #print("[!] Couldn't connect over HTTPS.") + #print("[+] Trying with HTTP.\n") + url = "http://" + url[8:] + #print("Checking: " + str(url)) + try: + url_check(url) + except urllib.error.URLError: + pass + else: + pass + except ValueError: + pass + +def help(): + print("\nSyntax: wpdetect ") + print("Example: wpdetect https://iamlizu.com/") + print("or supply a list with '-f' flag") + print("Example: wpdetect -f domainlist.txt\n") + print("Example: cat urls.txt | wpdetect \n") + +def main(): + try: + if len(sys.argv) > 1: + if sys.argv[1] == '-h' or sys.argv[1] == '--help': + help() + sys.exit() + if sys.argv[1] == '-v' or sys.argv[1] == '--version': + print("Version: 1.3.7") + sys.exit() + + if not sys.stdin.isatty(): + for line in sys.stdin: + url_check(line.strip()) + elif sys.argv[1] == '-f' or sys.argv[1] == '--file': + try: + if len(sys.argv) > 2: + file = open(sys.argv[2], 'r') + domains = file.readlines() + for domain in domains: + url = domain.strip() + url_check(url) + sys.exit() + else: + print("No list supplied!") + help() + except FileNotFoundError: + print("Please enter file name correctly, file not found!\n") + else: + url = sys.argv[1] + url_check(url) + + except KeyboardInterrupt: + pass + + +if __name__ == '__main__': + main() \ No newline at end of file From 756a8ec3528f1920cbee57453b031eff48956d25 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Thu, 12 Jan 2023 15:37:02 -0500 Subject: [PATCH 03/23] Deleted unimportant files --- .gitignore | 2 + .vscode/launch.json | 16 ----- build/lib/wpdetect/__init__.py | 0 build/lib/wpdetect/__main__.py | 105 --------------------------------- 4 files changed, 2 insertions(+), 121 deletions(-) create mode 100644 .gitignore delete mode 100644 .vscode/launch.json delete mode 100644 build/lib/wpdetect/__init__.py delete mode 100644 build/lib/wpdetect/__main__.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ab24a97 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode +build/* \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 306f58e..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Current File", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal", - "justMyCode": true - } - ] -} \ No newline at end of file diff --git a/build/lib/wpdetect/__init__.py b/build/lib/wpdetect/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/build/lib/wpdetect/__main__.py b/build/lib/wpdetect/__main__.py deleted file mode 100644 index f4c4a92..0000000 --- a/build/lib/wpdetect/__main__.py +++ /dev/null @@ -1,105 +0,0 @@ -import urllib.request -import sys -from pyfiglet import figlet_format - -wp_domains = [] -header = "'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A'" -def wp_check(url): - url_wpl = url + "/wp-login.php" - url_wpa = url + "/wp-json/wp/v2/" - - - req_wpl = urllib.request.Request(url_wpl, headers={'User-Agent': header}) - req_wpa = urllib.request.Request(url_wpa, headers={'User-Agent': header}) - - #print("Please wait.../") - try: - if urllib.request.urlopen(req_wpa): - wp_domains.append(url) - print(url) - except urllib.error.HTTPError: - try: - if urllib.request.urlopen(req_wpl): - wp_domains.append(url) - print(url) - except urllib.error.HTTPError: - pass - - -def url_check(url): - #print("Checking: " + str(url)) - try: - if url[:4] != "http": - #print("[!] No protocol specified.") - url = "http://" + url - #print("[+] Going with HTTP.\n") - #print("Checking: " + str(url)) - req = urllib.request.Request(url, headers={'User-Agent': header}) - u = urllib.request.urlopen(req) - if url != u.geturl(): - #print("[!] " + url + " redirected to "+u.geturl()) - url = u.geturl() - #print("Checking: " + str(url)) - wp_check(url) - except urllib.error.HTTPError as e: - if e.code == 403: - pass - except urllib.error.URLError: - if url[:5] == "https": - #print("[!] Couldn't connect over HTTPS.") - #print("[+] Trying with HTTP.\n") - url = "http://" + url[8:] - #print("Checking: " + str(url)) - try: - url_check(url) - except urllib.error.URLError: - pass - else: - pass - except ValueError: - pass - -def help(): - print("\nSyntax: wpdetect ") - print("Example: wpdetect https://iamlizu.com/") - print("or supply a list with '-f' flag") - print("Example: wpdetect -f domainlist.txt\n") - print("Example: cat urls.txt | wpdetect \n") - -def main(): - try: - if len(sys.argv) > 1: - if sys.argv[1] == '-h' or sys.argv[1] == '--help': - help() - sys.exit() - if sys.argv[1] == '-v' or sys.argv[1] == '--version': - print("Version: 1.3.7") - sys.exit() - - if not sys.stdin.isatty(): - for line in sys.stdin: - url_check(line.strip()) - elif sys.argv[1] == '-f' or sys.argv[1] == '--file': - try: - if len(sys.argv) > 2: - file = open(sys.argv[2], 'r') - domains = file.readlines() - for domain in domains: - url = domain.strip() - url_check(url) - sys.exit() - else: - print("No list supplied!") - help() - except FileNotFoundError: - print("Please enter file name correctly, file not found!\n") - else: - url = sys.argv[1] - url_check(url) - - except KeyboardInterrupt: - pass - - -if __name__ == '__main__': - main() \ No newline at end of file From 3b4c78acffa322e9cbe8934fd412ab97b375574b Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Thu, 12 Jan 2023 15:37:53 -0500 Subject: [PATCH 04/23] Updated readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a47fd95..c45ba14 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ A WordPress detection tool, detects if a website is running WordPress. wpdetect ### Installation You can install wpdetect using pip, ```sh -git clone repository_url +git clone https://github.com/serialfuzzer/wpdetect.git sudo python setup.py install ``` wpdetect requires Python 3 or above to run. If you have Python 2 installed too, make sure to use the right pip. From 96f404c253d8bccffb04b8a737e1313ee6e9d466 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Thu, 12 Jan 2023 15:58:44 -0500 Subject: [PATCH 05/23] Added multi threading support --- wpdetect/__main__.py | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/wpdetect/__main__.py b/wpdetect/__main__.py index f4c4a92..1281097 100644 --- a/wpdetect/__main__.py +++ b/wpdetect/__main__.py @@ -1,6 +1,6 @@ import urllib.request import sys -from pyfiglet import figlet_format +import threading wp_domains = [] header = "'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A'" @@ -45,17 +45,7 @@ def url_check(url): if e.code == 403: pass except urllib.error.URLError: - if url[:5] == "https": - #print("[!] Couldn't connect over HTTPS.") - #print("[+] Trying with HTTP.\n") - url = "http://" + url[8:] - #print("Checking: " + str(url)) - try: - url_check(url) - except urllib.error.URLError: - pass - else: - pass + pass except ValueError: pass @@ -77,8 +67,15 @@ def main(): sys.exit() if not sys.stdin.isatty(): + urls = [] for line in sys.stdin: - url_check(line.strip()) + urls.append(line.strip()) + threads = [threading.Thread(target=url_check, args=(url,)) for url in urls] + for thread in threads: + thread.start() + for thread in threads: + thread.join() + sys.exit() elif sys.argv[1] == '-f' or sys.argv[1] == '--file': try: if len(sys.argv) > 2: From 2bb59e3d3d5cb1e9ebf471c2f0bfd0bd1b7e0f5e Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Thu, 15 Jun 2023 15:06:43 +0530 Subject: [PATCH 06/23] Some updates --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c45ba14..2f2669c 100644 --- a/README.md +++ b/README.md @@ -41,4 +41,10 @@ http://www.techcrunch.com/ Please note that, it is not always possible to detect the presence of WordPress, website admins can take extra measures to remove sign of WordPress. ### What's new in version 1.3.6 -* Fixed minor bugs \ No newline at end of file +* Fixed minor bugs + + +### To implement +1. Use 1000 requests per thread +2. Each thread should work in a concurrent way +3. Implement two methods: i. Fast (Some false positives but blazingly fast) ii. Slow (Highly accurate but slow) \ No newline at end of file From 0104ef4debb052d262e055f7442ef0fcfc88572a Mon Sep 17 00:00:00 2001 From: _ Date: Thu, 15 Jun 2023 16:29:55 +0530 Subject: [PATCH 07/23] Update README.md --- README.md | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2f2669c..9654360 100644 --- a/README.md +++ b/README.md @@ -46,5 +46,37 @@ Please note that, it is not always possible to detect the presence of WordPress, ### To implement 1. Use 1000 requests per thread -2. Each thread should work in a concurrent way -3. Implement two methods: i. Fast (Some false positives but blazingly fast) ii. Slow (Highly accurate but slow) \ No newline at end of file +2. Each request should be sent in an asynchronous way +3. Implement two methods: i. Fast (Some false positives but blazingly fast) ii. Slow (Highly accurate but slow) + + +Fast mode (default) +------------- + +i. Will send 1 request and analyse it for wordpress patterns + +Slow mode +------------ + +ii. Will send multiple requests and analyse it for wordpress patterns + +User interface design +----------------------- +-slow option should trigger the scans in slow mode +-t option should specift the number of threads + +Input options +-------------- + +Three methods to supply input: +1. File +2. Standard input +3. Command line argument + +If all of the input contains values then combine the target from all the sources + +Some additional optimisations +------------------------------- + +Sort the input to avoid sending multiple requests to the same URL + From c34a9af8794daf96e2d53a5af7e5d21b3372588d Mon Sep 17 00:00:00 2001 From: _ Date: Thu, 15 Jun 2023 16:31:31 +0530 Subject: [PATCH 08/23] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9654360..5b879c3 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,10 @@ Three methods to supply input: 2. Standard input 3. Command line argument -If all of the input contains values then combine the target from all the sources +If all of the input methods contains values then combine the targets from all the sources instead of priotizing one and ignoring other Some additional optimisations ------------------------------- -Sort the input to avoid sending multiple requests to the same URL +Remove duplications from the targets container to avoid sending multiple requests to the same URL From af38b7c36e2da510be85427ae71acd226153f090 Mon Sep 17 00:00:00 2001 From: _ Date: Thu, 15 Jun 2023 16:32:49 +0530 Subject: [PATCH 09/23] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 5b879c3..cdfecf9 100644 --- a/README.md +++ b/README.md @@ -80,3 +80,6 @@ Some additional optimisations Remove duplications from the targets container to avoid sending multiple requests to the same URL +Create test scripts +-------------------- + From 3f2e963e87d0480d13e1b622a59384b0f9bc921c Mon Sep 17 00:00:00 2001 From: _ Date: Thu, 15 Jun 2023 17:12:16 +0530 Subject: [PATCH 10/23] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index cdfecf9..6d93607 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,8 @@ Please note that, it is not always possible to detect the presence of WordPress, * Fixed minor bugs +# DEV-Notes (Development mind map) + ### To implement 1. Use 1000 requests per thread 2. Each request should be sent in an asynchronous way From 02b9b30afc83eef5e4e537906fbe3f5dab622fa9 Mon Sep 17 00:00:00 2001 From: _ Date: Fri, 16 Jun 2023 08:34:05 +0530 Subject: [PATCH 11/23] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6d93607..4946eb9 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ Please note that, it is not always possible to detect the presence of WordPress, 1. Use 1000 requests per thread 2. Each request should be sent in an asynchronous way 3. Implement two methods: i. Fast (Some false positives but blazingly fast) ii. Slow (Highly accurate but slow) +4. Combine URLs from standard input, CLI argument and file into a single array, also filter out the incorrect URLs (completed, will push later) ✅ Fast mode (default) From 4075b142dffba41ac75b721d92bc93ab2ba0f938 Mon Sep 17 00:00:00 2001 From: _ Date: Fri, 16 Jun 2023 08:34:34 +0530 Subject: [PATCH 12/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4946eb9..a5f10c6 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Please note that, it is not always possible to detect the presence of WordPress, ### To implement 1. Use 1000 requests per thread 2. Each request should be sent in an asynchronous way -3. Implement two methods: i. Fast (Some false positives but blazingly fast) ii. Slow (Highly accurate but slow) +3. Implement two methods: i. Fast (Some false positives but blazingly fast) ii. Slow (Highly accurate but slow) ✅ 4. Combine URLs from standard input, CLI argument and file into a single array, also filter out the incorrect URLs (completed, will push later) ✅ From 47b7deeccf7992fb1a9c6ed5b3227121281f1a30 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Fri, 16 Jun 2023 16:02:25 +0530 Subject: [PATCH 13/23] Changed code structure and added multi-threading support --- wpdetect/README.rst | 54 ++++++------- wpdetect/__main__.py | 174 +++++++++++++++++++++--------------------- wpdetect/helpers.py | 8 ++ wpdetect/lessURLs.txt | 22 ------ 4 files changed, 123 insertions(+), 135 deletions(-) create mode 100644 wpdetect/helpers.py delete mode 100644 wpdetect/lessURLs.txt diff --git a/wpdetect/README.rst b/wpdetect/README.rst index fdaf97c..26ad8b4 100644 --- a/wpdetect/README.rst +++ b/wpdetect/README.rst @@ -1,40 +1,40 @@ -WP Detect -========= - -A WordPress detection tool, detects if a website is running -WordPress. wpdetect is a great tool when you just want to check -WordPress' presence but do not want to scan the site for vulnerabilities -or issues. - -Installation -~~~~~~~~~~~~ - +# WP DETECT +A WordPress detection tool, detects if a website is running WordPress. wpdetect is a great tool when you just want to check WordPress' presence but do not want to scan the site for vulnerabilities or issues. +### Installation You can install wpdetect using pip, +```sh +pip install wpdetect +``` +wpdetect requires Python 3 or above to run. If you have Python 2 installed too, make sure to use the right pip. -.. code:: sh +### Usage +Syntax - pip install wpdetect -wpdetect requires Python 3 or above to run. If you have Python 2 -installed too, make sure to use the right pip. +```sh +wpdetect --url https://iamlizu.com/ +``` -Usage -~~~~~ -Syntax +```sh +cat URLs.txt | wpdetect +``` -.. code:: sh +```sh +echo https://hackerone.com | wpdetect +``` - wpdetect -Example +```sh +wpdetect --file urls.txt +``` -.. code:: sh - wpdetect https://iamlizu.com/ +Where `urls.txt` will contain domains like this, +```sh +https://iamlizu.com/ +https://www.newyorker.com/ +http://www.techcrunch.com/ +``` Please note that, it is not always possible to detect the presence of WordPress, website admins can take extra measures to remove sign of WordPress. - -What's new in version 1.3.3 -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* Minor bug fixes. \ No newline at end of file diff --git a/wpdetect/__main__.py b/wpdetect/__main__.py index 1281097..f8f04b7 100644 --- a/wpdetect/__main__.py +++ b/wpdetect/__main__.py @@ -1,102 +1,104 @@ -import urllib.request +import click import sys +import os +import helpers import threading +import urllib.request +from urllib.parse import urlparse -wp_domains = [] -header = "'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A'" -def wp_check(url): - url_wpl = url + "/wp-login.php" - url_wpa = url + "/wp-json/wp/v2/" +def wp_check(url): # this function is defined to support the implementation of previous version of the tool + try: + isWp = False + checks = ['wp-content', 'wp-includes', 'wp-json'] + hostname = urlparse(url).netloc + request = urllib.request.Request(url, headers={'User-Agent': UserAgent}) + response = urllib.request.urlopen(request).read().decode() + for check in checks: + checkStr = hostname + "/" + check + if checkStr in response: + isWp=True + return isWp + except: + return False - req_wpl = urllib.request.Request(url_wpl, headers={'User-Agent': header}) - req_wpa = urllib.request.Request(url_wpa, headers={'User-Agent': header}) - #print("Please wait.../") - try: - if urllib.request.urlopen(req_wpa): - wp_domains.append(url) - print(url) - except urllib.error.HTTPError: - try: - if urllib.request.urlopen(req_wpl): - wp_domains.append(url) - print(url) - except urllib.error.HTTPError: - pass +UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A" -def url_check(url): - #print("Checking: " + str(url)) +def isWordpress(urls, mode, timeOut): try: - if url[:4] != "http": - #print("[!] No protocol specified.") - url = "http://" + url - #print("[+] Going with HTTP.\n") - #print("Checking: " + str(url)) - req = urllib.request.Request(url, headers={'User-Agent': header}) - u = urllib.request.urlopen(req) - if url != u.geturl(): - #print("[!] " + url + " redirected to "+u.geturl()) - url = u.geturl() - #print("Checking: " + str(url)) - wp_check(url) - except urllib.error.HTTPError as e: - if e.code == 403: + if mode == "fast": + checks = ['wp-content', 'wp-includes', 'wp-json'] + for url in urls: + try: + isWp = False + hostname = urlparse(url).netloc + request = urllib.request.Request(url, headers={'User-Agent': UserAgent}) + response = urllib.request.urlopen(request, timeout=timeOut).read().decode() + for check in checks: + checkStr = hostname + "/" + check + if checkStr in response: + print(url) + isWp=True + break + if isWp == True: + continue + except Exception as err: + pass + else: pass - except urllib.error.URLError: - pass - except ValueError: + except Exception as e: pass -def help(): - print("\nSyntax: wpdetect ") - print("Example: wpdetect https://iamlizu.com/") - print("or supply a list with '-f' flag") - print("Example: wpdetect -f domainlist.txt\n") - print("Example: cat urls.txt | wpdetect \n") +def import_targets(arrayOfTargets, singleTarget, fileName): + targets = [] + if len(arrayOfTargets) > 0: + for target in arrayOfTargets: + if len(target) > 0: ## if targets is not an empty string + targets.append(target) + + if len(singleTarget) != 0: + targets.append(singleTarget) -def main(): - try: - if len(sys.argv) > 1: - if sys.argv[1] == '-h' or sys.argv[1] == '--help': - help() - sys.exit() - if sys.argv[1] == '-v' or sys.argv[1] == '--version': - print("Version: 1.3.7") - sys.exit() - - if not sys.stdin.isatty(): - urls = [] - for line in sys.stdin: - urls.append(line.strip()) - threads = [threading.Thread(target=url_check, args=(url,)) for url in urls] - for thread in threads: - thread.start() - for thread in threads: - thread.join() - sys.exit() - elif sys.argv[1] == '-f' or sys.argv[1] == '--file': - try: - if len(sys.argv) > 2: - file = open(sys.argv[2], 'r') - domains = file.readlines() - for domain in domains: - url = domain.strip() - url_check(url) - sys.exit() - else: - print("No list supplied!") - help() - except FileNotFoundError: - print("Please enter file name correctly, file not found!\n") - else: - url = sys.argv[1] - url_check(url) + if os.path.isfile(fileName): + with open(fileName, "r") as targetsFile: + for line in targetsFile: + if line.strip() != "": + targets.append(line.strip()) + + targets = list(filter(helpers.isUrl, targets)) + return targets - except KeyboardInterrupt: - pass +@click.command() +@click.option("--mode", default="fast",help="Mode of the scan [fast | slow]") +@click.option("--url", help="Url that you want to scan", default="") +@click.option("--file", help="File to import URLs from", default="") +@click.option("--targets", default=sys.stdin, type=click.File('r')) +@click.option("--threads", default=10, help="Number of threads") +@click.option("--timeout", default=5, help="HTTP Timeout in seconds") +def scan(url, mode, file, targets, threads, timeout): + if sys.stdin.isatty() == False: # if targets are passed via the standard input + with targets: + stdinTargets = targets.read().split("\n") + targets = import_targets(stdinTargets, url, file) + targetsArray = helpers.splitArray(targets, threads) + allThreads = [] + for t in targetsArray: + thread = threading.Thread(target=isWordpress, args=[t, mode, timeout]) + thread.start() + #isWordpress(targets, mode) + + else: # if standard input is empty + targets = import_targets([], url, file) + targetsArray = helpers.splitArray(targets, threads) + allThreads = [] + for t in targetsArray: + thread = threading.Thread(target=isWordpress, args=[t, mode, timeout]) + thread.start() + #isWordpress(targets, mode) -if __name__ == '__main__': - main() \ No newline at end of file +if __name__ == "__main__": + + scan() \ No newline at end of file diff --git a/wpdetect/helpers.py b/wpdetect/helpers.py new file mode 100644 index 0000000..4ff7045 --- /dev/null +++ b/wpdetect/helpers.py @@ -0,0 +1,8 @@ +import validators + +def isUrl(string): + return validators.url(string) + +def splitArray(array, n): + final = [array[i * n:(i + 1) * n] for i in range((len(array) + n - 1) // n )] + return final diff --git a/wpdetect/lessURLs.txt b/wpdetect/lessURLs.txt deleted file mode 100644 index 41901a6..0000000 --- a/wpdetect/lessURLs.txt +++ /dev/null @@ -1,22 +0,0 @@ -http://api.analytics.america.gov -https://api.dev.america.gov -http://techcamp.edit.america.gov -https://api.analytics.america.gov -http://www.share.america.gov -https://techcamp.edit.america.gov -http://commons.america.gov -https://commons.america.gov -http://www.stories.dev.america.gov -https://app-lorawan.fan.gov -https://www.stories.dev.america.gov -http://commons-stage.america.gov -http://commons-beta.america.gov -https://commons-stage.america.gov -https://commons-beta.america.gov -http://devtechcamp.edit.america.gov -http://devtechcamp.america.gov -https://devtechcamp.edit.america.gov -https://devtechcamp.america.gov -http://publications.america.gov -http://www.courses.dev.america.gov -https://publications.america.gov \ No newline at end of file From db90044fd727c1c2aed8a9196a9223a74992ee34 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Fri, 16 Jun 2023 16:04:27 +0530 Subject: [PATCH 14/23] Changes to READMEs, removed pyfiglet --- README.md | 38 +++++++++++++++---------------- README.rst | 65 ++++++++++++++++++++++-------------------------------- setup.py | 3 ++- 3 files changed, 46 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 2f2669c..d4b9a17 100644 --- a/README.md +++ b/README.md @@ -3,48 +3,46 @@ A WordPress detection tool, detects if a website is running WordPress. wpdetect ### Installation You can install wpdetect using pip, ```sh -git clone https://github.com/serialfuzzer/wpdetect.git -sudo python setup.py install +pip install wpdetect ``` wpdetect requires Python 3 or above to run. If you have Python 2 installed too, make sure to use the right pip. ### Usage Syntax -```sh -cat URLs.txt | wpdetect -``` ```sh -echo https://hackerone.com | wpdetect +wpdetect --url https://iamlizu.com/ ``` ```sh -wpdetect +cat URLs.txt | wpdetect ``` -Example + ```sh -wpdetect https://iamlizu.com/ +echo https://hackerone.com | wpdetect ``` -Or feed a text file with a list of domains, each domain should be separated with new lines. + + ```sh -wpdetect -f sites.txt +wpdetect --file urls.txt ``` -Where `sites.txt` will contain domains like this, + + +Where `urls.txt` will contain domains like this, ```sh https://iamlizu.com/ https://www.newyorker.com/ http://www.techcrunch.com/ ``` -Please note that, it is not always possible to detect the presence of WordPress, website admins can take extra measures to remove sign of WordPress. - -### What's new in version 1.3.6 -* Fixed minor bugs +Please note that, it is not always possible to detect the presence of WordPress, website admins can take extra measures to remove sign of WordPress. -### To implement -1. Use 1000 requests per thread -2. Each thread should work in a concurrent way -3. Implement two methods: i. Fast (Some false positives but blazingly fast) ii. Slow (Highly accurate but slow) \ No newline at end of file +| Option | Description | Default Vaue | +|--------|-------------|--------------| +| --file | Path of the file containing URLs separated by new line characters | Empty String | +| --url | URL of the target | | +|--threads| Number of threads|1| +|--timeout| Timeout of the HTTP request in seconds | 5 | \ No newline at end of file diff --git a/README.rst b/README.rst index 99d16d5..99d151c 100644 --- a/README.rst +++ b/README.rst @@ -1,54 +1,41 @@ -WP Detect -========= - -A WordPress detection tool, detects if a website is running -WordPress. wpdetect is a great tool when you just want to check -WordPress' presence but do not want to scan the site for vulnerabilities -or issues. - -Installation -~~~~~~~~~~~~ - +# WP DETECT +A WordPress detection tool, detects if a website is running WordPress. wpdetect is a great tool when you just want to check WordPress' presence but do not want to scan the site for vulnerabilities or issues. +### Installation You can install wpdetect using pip, +```sh +pip install wpdetect +``` +wpdetect requires Python 3 or above to run. If you have Python 2 installed too, make sure to use the right pip. -.. code:: sh - - pip install wpdetect - -wpdetect requires Python 3 or above to run. If you have Python 2 -installed too, make sure to use the right pip. - -Usage -~~~~~ - +### Usage Syntax -.. code:: sh - wpdetect +```sh +wpdetect --url https://iamlizu.com/ +``` -Example -.. code:: sh +```sh +cat URLs.txt | wpdetect +``` - wpdetect https://iamlizu.com/ +```sh +echo https://hackerone.com | wpdetect +``` -Or feed a text file with a list of domains, each domain should be separated with new lines. -.. code:: sh +```sh +wpdetect --file urls.txt +``` - wpdetect -f sites.txt -Where sites.txt will contain domains like this, +Where `urls.txt` will contain domains like this, +```sh +https://iamlizu.com/ +https://www.newyorker.com/ +http://www.techcrunch.com/ +``` -.. code:: sh - - https://iamlizu.com/ - https://www.newyorker.com/ - http://www.techcrunch.com/ Please note that, it is not always possible to detect the presence of WordPress, website admins can take extra measures to remove sign of WordPress. - -What's new in version 1.3.6 -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -* Fixed minor bugs \ No newline at end of file diff --git a/setup.py b/setup.py index 3908dad..e76ae2f 100644 --- a/setup.py +++ b/setup.py @@ -17,7 +17,8 @@ download_url = 'https://github.com/IamLizu/wpdetect/archive/v_1_3_6.tar.gz', keywords = ['WordPress', 'Detect', 'wpdetect'], install_requires=[ - 'pyfiglet', + 'click', + 'validators' ], entry_points = { 'console_scripts': [ From 1ff002baa0f11497ecf7d10a967c4475c968ce23 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Fri, 16 Jun 2023 16:10:30 +0530 Subject: [PATCH 15/23] Added options --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d4b9a17..d383f5a 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ http://www.techcrunch.com/ Please note that, it is not always possible to detect the presence of WordPress, website admins can take extra measures to remove sign of WordPress. +## Options + | Option | Description | Default Vaue | |--------|-------------|--------------| | --file | Path of the file containing URLs separated by new line characters | Empty String | From d28b31cd840dab7a5f1ff7eb8ff4a00ca7615bd2 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Fri, 16 Jun 2023 16:25:16 +0530 Subject: [PATCH 16/23] Updated the default number of threads. --- wpdetect/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wpdetect/__main__.py b/wpdetect/__main__.py index f8f04b7..f2d8412 100644 --- a/wpdetect/__main__.py +++ b/wpdetect/__main__.py @@ -76,7 +76,7 @@ def import_targets(arrayOfTargets, singleTarget, fileName): @click.option("--url", help="Url that you want to scan", default="") @click.option("--file", help="File to import URLs from", default="") @click.option("--targets", default=sys.stdin, type=click.File('r')) -@click.option("--threads", default=10, help="Number of threads") +@click.option("--threads", default=1, help="Number of threads") @click.option("--timeout", default=5, help="HTTP Timeout in seconds") def scan(url, mode, file, targets, threads, timeout): if sys.stdin.isatty() == False: # if targets are passed via the standard input From d29cc7bb7cb7ed5f091ff8e3a636ac8f58d3e47e Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Fri, 16 Jun 2023 16:36:21 +0530 Subject: [PATCH 17/23] Some minor changes --- wpdetect/__main__.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/wpdetect/__main__.py b/wpdetect/__main__.py index f2d8412..9c9cc08 100644 --- a/wpdetect/__main__.py +++ b/wpdetect/__main__.py @@ -1,12 +1,22 @@ import click import sys import os -import helpers +import validators import threading import urllib.request from urllib.parse import urlparse + +def isUrl(string): + return validators.url(string) + +def splitArray(array, n): + final = [array[i * n:(i + 1) * n] for i in range((len(array) + n - 1) // n )] + return final + + + def wp_check(url): # this function is defined to support the implementation of previous version of the tool try: isWp = False @@ -67,7 +77,7 @@ def import_targets(arrayOfTargets, singleTarget, fileName): if line.strip() != "": targets.append(line.strip()) - targets = list(filter(helpers.isUrl, targets)) + targets = list(filter(isUrl, targets)) return targets @@ -78,13 +88,12 @@ def import_targets(arrayOfTargets, singleTarget, fileName): @click.option("--targets", default=sys.stdin, type=click.File('r')) @click.option("--threads", default=1, help="Number of threads") @click.option("--timeout", default=5, help="HTTP Timeout in seconds") -def scan(url, mode, file, targets, threads, timeout): +def main(url, mode, file, targets, threads, timeout): if sys.stdin.isatty() == False: # if targets are passed via the standard input with targets: stdinTargets = targets.read().split("\n") targets = import_targets(stdinTargets, url, file) - targetsArray = helpers.splitArray(targets, threads) - allThreads = [] + targetsArray = splitArray(targets, threads) for t in targetsArray: thread = threading.Thread(target=isWordpress, args=[t, mode, timeout]) thread.start() @@ -92,13 +101,11 @@ def scan(url, mode, file, targets, threads, timeout): else: # if standard input is empty targets = import_targets([], url, file) - targetsArray = helpers.splitArray(targets, threads) - allThreads = [] + targetsArray = splitArray(targets, threads) for t in targetsArray: thread = threading.Thread(target=isWordpress, args=[t, mode, timeout]) thread.start() #isWordpress(targets, mode) if __name__ == "__main__": - - scan() \ No newline at end of file + main() \ No newline at end of file From 697679afe6e67269575a455347a902b5c056f8f7 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Sat, 17 Jun 2023 00:30:48 +0530 Subject: [PATCH 18/23] Removed helper file --- wpdetect/helpers.py | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 wpdetect/helpers.py diff --git a/wpdetect/helpers.py b/wpdetect/helpers.py deleted file mode 100644 index 4ff7045..0000000 --- a/wpdetect/helpers.py +++ /dev/null @@ -1,8 +0,0 @@ -import validators - -def isUrl(string): - return validators.url(string) - -def splitArray(array, n): - final = [array[i * n:(i + 1) * n] for i in range((len(array) + n - 1) // n )] - return final From 90c2377afe66c27abaec3dbea5ebc7bf0c9d801c Mon Sep 17 00:00:00 2001 From: _ Date: Sat, 17 Jun 2023 05:21:39 +0530 Subject: [PATCH 19/23] Update README.md --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d383f5a..826f60e 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,23 @@ # WP DETECT A WordPress detection tool, detects if a website is running WordPress. wpdetect is a great tool when you just want to check WordPress' presence but do not want to scan the site for vulnerabilities or issues. ### Installation + +#### Installing from pip You can install wpdetect using pip, ```sh pip install wpdetect ``` wpdetect requires Python 3 or above to run. If you have Python 2 installed too, make sure to use the right pip. +#### Installing locally + +```sh +git clone https://github.com/serialfuzzer/wpdetect.git +cd wpdetect +python setup.py install +``` + + ### Usage Syntax @@ -47,4 +58,4 @@ Please note that, it is not always possible to detect the presence of WordPress, | --file | Path of the file containing URLs separated by new line characters | Empty String | | --url | URL of the target | | |--threads| Number of threads|1| -|--timeout| Timeout of the HTTP request in seconds | 5 | \ No newline at end of file +|--timeout| Timeout of the HTTP request in seconds | 5 | From e42da3c0443932f2183affd72133b17e7f4cfd26 Mon Sep 17 00:00:00 2001 From: _ Date: Wed, 21 Jun 2023 06:09:05 +0530 Subject: [PATCH 20/23] Update README.md --- README.md | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 826f60e..2899e94 100644 --- a/README.md +++ b/README.md @@ -9,21 +9,13 @@ pip install wpdetect ``` wpdetect requires Python 3 or above to run. If you have Python 2 installed too, make sure to use the right pip. -#### Installing locally - -```sh -git clone https://github.com/serialfuzzer/wpdetect.git -cd wpdetect -python setup.py install -``` - ### Usage Syntax ```sh -wpdetect --url https://iamlizu.com/ +wpdetect --url https://www.malcare.com/ ``` @@ -43,7 +35,7 @@ wpdetect --file urls.txt Where `urls.txt` will contain domains like this, ```sh -https://iamlizu.com/ +https://www.malcare.com/ https://www.newyorker.com/ http://www.techcrunch.com/ ``` @@ -59,3 +51,6 @@ Please note that, it is not always possible to detect the presence of WordPress, | --url | URL of the target | | |--threads| Number of threads|1| |--timeout| Timeout of the HTTP request in seconds | 5 | + +## Upcoming features +1. **Asynchronous**: We're designing the tool to work in an asynchronous way, this means that there will be further improvements in speed. From e45f6194ef3d2351f31716c905f0f70c46cb5fd5 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Thu, 22 Jun 2023 14:09:23 +0530 Subject: [PATCH 21/23] Added backward compatibility features --- README.md | 29 +++++++++---- README.rst | 41 ------------------ setup.py | 3 +- wpdetect/README.rst | 40 ------------------ wpdetect/__main__.py | 99 +++++++++++++++++++++++++++++++++++++------- 5 files changed, 108 insertions(+), 104 deletions(-) delete mode 100644 README.rst delete mode 100644 wpdetect/README.rst diff --git a/README.md b/README.md index 2899e94..71a48d7 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Syntax ```sh -wpdetect --url https://www.malcare.com/ +wpdetect --url https://www.wordpress.com/ ``` @@ -24,7 +24,7 @@ cat URLs.txt | wpdetect ``` ```sh -echo https://hackerone.com | wpdetect +echo https://www.wordpress.com | wpdetect ``` @@ -35,7 +35,7 @@ wpdetect --file urls.txt Where `urls.txt` will contain domains like this, ```sh -https://www.malcare.com/ +https://www.wordpress.com/ https://www.newyorker.com/ http://www.techcrunch.com/ ``` @@ -43,14 +43,27 @@ http://www.techcrunch.com/ Please note that, it is not always possible to detect the presence of WordPress, website admins can take extra measures to remove sign of WordPress. + ## Options -| Option | Description | Default Vaue | +| Option | Description | Default Value (Behavior) | |--------|-------------|--------------| -| --file | Path of the file containing URLs separated by new line characters | Empty String | -| --url | URL of the target | | -|--threads| Number of threads|1| -|--timeout| Timeout of the HTTP request in seconds | 5 | +| --file, -f | Path of the file containing URLs separated by new line characters | Empty String | +| --url, -u | URL of the target | | +|--threads, -tr| Number of threads |1 | +|--timeout, -t| Timeout of the HTTP request in seconds |5 | +|--silent, -s| Only display URLs using wordpress, don't display banners and any other text | False| +|--preferhttp, -ph| If URL doesn't have http or https, only scan http | Scan both| +|--preferhttps, -phs| If URL doesn't have http or https, only scan https | Scan both | + ## Upcoming features 1. **Asynchronous**: We're designing the tool to work in an asynchronous way, this means that there will be further improvements in speed. + + +### What's new in version 1.3.7 +1. Improved performance +2. Multi-Threading +3. Silent Mode +4. Ability to feed targets from standard input +5. Ability to tune HTTP Request timeout \ No newline at end of file diff --git a/README.rst b/README.rst deleted file mode 100644 index 99d151c..0000000 --- a/README.rst +++ /dev/null @@ -1,41 +0,0 @@ -# WP DETECT -A WordPress detection tool, detects if a website is running WordPress. wpdetect is a great tool when you just want to check WordPress' presence but do not want to scan the site for vulnerabilities or issues. -### Installation -You can install wpdetect using pip, -```sh -pip install wpdetect -``` -wpdetect requires Python 3 or above to run. If you have Python 2 installed too, make sure to use the right pip. - -### Usage -Syntax - - -```sh -wpdetect --url https://iamlizu.com/ -``` - - -```sh -cat URLs.txt | wpdetect -``` - -```sh -echo https://hackerone.com | wpdetect -``` - - -```sh -wpdetect --file urls.txt -``` - - -Where `urls.txt` will contain domains like this, -```sh -https://iamlizu.com/ -https://www.newyorker.com/ -http://www.techcrunch.com/ -``` - - -Please note that, it is not always possible to detect the presence of WordPress, website admins can take extra measures to remove sign of WordPress. diff --git a/setup.py b/setup.py index e76ae2f..6813e7e 100644 --- a/setup.py +++ b/setup.py @@ -18,7 +18,8 @@ keywords = ['WordPress', 'Detect', 'wpdetect'], install_requires=[ 'click', - 'validators' + 'validators', + 'pyfiglet' ], entry_points = { 'console_scripts': [ diff --git a/wpdetect/README.rst b/wpdetect/README.rst deleted file mode 100644 index 26ad8b4..0000000 --- a/wpdetect/README.rst +++ /dev/null @@ -1,40 +0,0 @@ -# WP DETECT -A WordPress detection tool, detects if a website is running WordPress. wpdetect is a great tool when you just want to check WordPress' presence but do not want to scan the site for vulnerabilities or issues. -### Installation -You can install wpdetect using pip, -```sh -pip install wpdetect -``` -wpdetect requires Python 3 or above to run. If you have Python 2 installed too, make sure to use the right pip. - -### Usage -Syntax - - -```sh -wpdetect --url https://iamlizu.com/ -``` - - -```sh -cat URLs.txt | wpdetect -``` - -```sh -echo https://hackerone.com | wpdetect -``` - - -```sh -wpdetect --file urls.txt -``` - - -Where `urls.txt` will contain domains like this, -```sh -https://iamlizu.com/ -https://www.newyorker.com/ -http://www.techcrunch.com/ -``` - -Please note that, it is not always possible to detect the presence of WordPress, website admins can take extra measures to remove sign of WordPress. diff --git a/wpdetect/__main__.py b/wpdetect/__main__.py index 9c9cc08..2ebf4f6 100644 --- a/wpdetect/__main__.py +++ b/wpdetect/__main__.py @@ -5,17 +5,44 @@ import threading import urllib.request from urllib.parse import urlparse +from pyfiglet import figlet_format +banner=figlet_format(' wpdetect ') +UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A" + + +cliOptions = { + "silent": False, + "preferHttps": False, + "preferHttp": False +} + + +def notSilentMode(): + return cliOptions["silent"] == False + +def output(str): + if notSilentMode(): + print(str) def isUrl(string): return validators.url(string) def splitArray(array, n): - final = [array[i * n:(i + 1) * n] for i in range((len(array) + n - 1) // n )] - return final - - + if n != 1: + final = [array[i * n:(i + 1) * n] for i in range((len(array) + n - 1) // n )] + return final + else: + return [array] + +def checkProtocol(url): + if url[:6] == 'https:': + return True + elif url[:5] == 'http:': + return True + else: + return False def wp_check(url): # this function is defined to support the implementation of previous version of the tool try: @@ -33,7 +60,6 @@ def wp_check(url): # this function is defined to support the implementation of p return False -UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A" def isWordpress(urls, mode, timeOut): @@ -49,7 +75,10 @@ def isWordpress(urls, mode, timeOut): for check in checks: checkStr = hostname + "/" + check if checkStr in response: - print(url) + if notSilentMode(): + print("Good news, " + str(url) + " is using WordPress!") + else: + print(url) isWp=True break if isWp == True: @@ -65,35 +94,76 @@ def import_targets(arrayOfTargets, singleTarget, fileName): targets = [] if len(arrayOfTargets) > 0: for target in arrayOfTargets: - if len(target) > 0: ## if targets is not an empty string + if len(target) > 0: ## if target is not an empty string targets.append(target) if len(singleTarget) != 0: targets.append(singleTarget) - if os.path.isfile(fileName): - with open(fileName, "r") as targetsFile: - for line in targetsFile: - if line.strip() != "": - targets.append(line.strip()) + if fileName != "": + if os.path.isfile(fileName): + with open(fileName, "r") as targetsFile: + for line in targetsFile: + if line.strip() != "": + targets.append(line.strip()) + + for target in targets: + mutatedTarget = [] + if checkProtocol(target) == False: + if cliOptions['preferHttp']: + mutatedTarget.append("http://" + target) + elif cliOptions['preferHttps']: + mutatedTarget.append("https://" + target) + else: + mutatedTarget.append("http://" + target) + mutatedTarget.append("https://" + target) + else: + pass + for tgt in mutatedTarget: + targets.append(tgt) targets = list(filter(isUrl, targets)) return targets @click.command() -@click.option("--mode", default="fast",help="Mode of the scan [fast | slow]") +@click.argument("domain", default="") +@click.option("--mode", default="fast",help="Mode of the scan [fast | slow] Experimental: Dont use this now") +@click.option("-m", "mode", default="fast",help="Mode of the scan [fast | slow] Experimental: Dont use this now") @click.option("--url", help="Url that you want to scan", default="") +@click.option("-u", "url", help="Url that you want to scan", default="") @click.option("--file", help="File to import URLs from", default="") +@click.option("-f", "file", default="") +@click.option("--preferhttp/--not-preferhttp", default=False) +@click.option("-ph/-np", "preferhttp", default=False) +@click.option("--preferhttps/--not-preferhttps", default=False) +@click.option("-phs/-nphs", "preferhttps", default=False) @click.option("--targets", default=sys.stdin, type=click.File('r')) @click.option("--threads", default=1, help="Number of threads") +@click.option("-tr", "threads", default=1, help="Number of threads") +@click.option("--silent/--not-silent", default=False, help="Do not display banner, just return URLs in the output") +@click.option("-s/--ns", "silent", default=False, help="Do not display banner, just return URLs in the output") @click.option("--timeout", default=5, help="HTTP Timeout in seconds") -def main(url, mode, file, targets, threads, timeout): +@click.option("-t", "timeout", default=5, help="HTTP Timeout in seconds") +@click.help_option('-h', '--help') +def main(url, mode, file, targets, threads, timeout, silent, preferhttp, preferhttps, domain): + if domain != "": + url=domain + + cliOptions["silent"] = silent + cliOptions["url"] = url + cliOptions["file"] = file + cliOptions["threads"] = threads + cliOptions["timeout"] = timeout + cliOptions["preferHttp"] = preferhttp + cliOptions["preferHttps"] = preferhttps + output(banner) if sys.stdin.isatty() == False: # if targets are passed via the standard input with targets: stdinTargets = targets.read().split("\n") targets = import_targets(stdinTargets, url, file) targetsArray = splitArray(targets, threads) + output("Please wait.../") for t in targetsArray: thread = threading.Thread(target=isWordpress, args=[t, mode, timeout]) thread.start() @@ -102,6 +172,7 @@ def main(url, mode, file, targets, threads, timeout): else: # if standard input is empty targets = import_targets([], url, file) targetsArray = splitArray(targets, threads) + output("Please wait.../") for t in targetsArray: thread = threading.Thread(target=isWordpress, args=[t, mode, timeout]) thread.start() From 4a53d21eba7e6d0abf48d603b56ed50c955e751d Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Thu, 22 Jun 2023 16:54:06 +0530 Subject: [PATCH 22/23] Update readme --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 71a48d7..36a6c32 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,12 @@ wpdetect requires Python 3 or above to run. If you have Python 2 installed too, Syntax + +```sh +wpdetect https://www.wordpress.com/ +``` + + ```sh wpdetect --url https://www.wordpress.com/ ``` From 1519f56bbbfe71b5ecd430865f4d89f02afc2098 Mon Sep 17 00:00:00 2001 From: Suyogya Khanal Date: Thu, 22 Jun 2023 17:13:30 +0530 Subject: [PATCH 23/23] Updated documentation --- wpdetect/__main__.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/wpdetect/__main__.py b/wpdetect/__main__.py index 2ebf4f6..89c195a 100644 --- a/wpdetect/__main__.py +++ b/wpdetect/__main__.py @@ -131,20 +131,20 @@ def import_targets(arrayOfTargets, singleTarget, fileName): @click.option("--mode", default="fast",help="Mode of the scan [fast | slow] Experimental: Dont use this now") @click.option("-m", "mode", default="fast",help="Mode of the scan [fast | slow] Experimental: Dont use this now") @click.option("--url", help="Url that you want to scan", default="") -@click.option("-u", "url", help="Url that you want to scan", default="") +@click.option("-u", "url", help="Short flag of --url", default="") @click.option("--file", help="File to import URLs from", default="") -@click.option("-f", "file", default="") -@click.option("--preferhttp/--not-preferhttp", default=False) -@click.option("-ph/-np", "preferhttp", default=False) -@click.option("--preferhttps/--not-preferhttps", default=False) -@click.option("-phs/-nphs", "preferhttps", default=False) -@click.option("--targets", default=sys.stdin, type=click.File('r')) -@click.option("--threads", default=1, help="Number of threads") -@click.option("-tr", "threads", default=1, help="Number of threads") +@click.option("-f", "file", help="Short flag of --file",default="") +@click.option("--preferhttp/--not-preferhttp", help="If a URL without protocol is specified, only check for wordpress in HTTP port 80", default=False) +@click.option("-ph/-np", "preferhttp", help="Short flag of --preferhttp",default=False) +@click.option("--preferhttps/--not-preferhttps", help="If a URL without protocol is specified, only check for wordpress in HTTPS port 443", default=False) +@click.option("-phs/-nphs", "preferhttps", help="Short flag of --preferhttps", default=False) +@click.option("--targets", default=sys.stdin, help="This is used to refer to the values sent in standard input", type=click.File('r')) +@click.option("--threads", default=1, help="Specify the number of threads") +@click.option("-tr", "threads", default=1, help="Short flag for --threads") @click.option("--silent/--not-silent", default=False, help="Do not display banner, just return URLs in the output") -@click.option("-s/--ns", "silent", default=False, help="Do not display banner, just return URLs in the output") +@click.option("-s/--ns", "silent", default=False, help="Short flag for --silent") @click.option("--timeout", default=5, help="HTTP Timeout in seconds") -@click.option("-t", "timeout", default=5, help="HTTP Timeout in seconds") +@click.option("-t", "timeout", default=5, help="Short flag for --timeout") @click.help_option('-h', '--help') def main(url, mode, file, targets, threads, timeout, silent, preferhttp, preferhttps, domain): if domain != "":