From 099117c82d5038d575bdc6bea0441e577329041e Mon Sep 17 00:00:00 2001 From: Ayush Singh <26509147+g147@users.noreply.github.com> Date: Sun, 24 Nov 2024 16:16:40 +0530 Subject: [PATCH] puncia[0.25] --- README.md | 72 ++++++++++++++++++++++++++++++---------------- puncia/__init__.py | 3 ++ puncia/__main__.py | 67 +++++++++++++++++++++++++----------------- setup.py | 2 +- 4 files changed, 91 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index 90aa703..db3c14e 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,16 @@ -# The Panthera(P.)uncia of Cybersecurity +# The Panthera(P.)uncia of Cybersecurity + ### Official CLI utility for Subdomain Center & Exploit Observer [![Downloads](https://pepy.tech/badge/puncia)](https://pepy.tech/project/puncia) -GitHub stars +GitHub stars
- +
Puncia utilizes two of our intelligent APIs to gather the results -
-- [Subdomain Center - The World's Fastest Growing Subdomain & Shadow IT Intelligence Database](https://subdomain.center)
+ +- [Subdomain Center - The World's Largest Subdomain & Shadow IT Intelligence Database](https://subdomain.center)
- [Exploit Observer - The World's Largest Exploit & Vulnerability Intelligence Database](https://exploit.observer) **Please note that although these results can sometimes be pretty inaccurate & unreliable, they can greatly differ from time to time due to their self-improvement capabilities.** @@ -16,42 +18,61 @@ Puncia utilizes two of our intelligent APIs to gather the results -
**Aggressive rate-limits can be avoided with an API key: https://www.arpsyndicate.io/pricing.html** ## Installation + 1. From PyPi - `pip3 install puncia` 2. From Source - `pip3 install .`
## Usage -1. Store an API key (storekey) - `puncia storekey ` -2. Query Domains (subdomain) - `puncia subdomain ` -3. Query Exploit & Vulnerability Identifiers (exploit) + +1. Store an API key (storekey) - `puncia storekey ` +2. Query Domains (subdomain) - `puncia subdomain ` +3. Query Exploit & Vulnerability Identifiers (exploit) - Russian VIDs with no associated CVEs (^RU_NON_CVE) - `puncia exploit ^RU_NON_CVE ` - Chinese VIDs with no associated CVEs (^CN_NON_CVE) - `puncia exploit ^CN_NON_CVE ` - Vulnerability & Exploit Identifers Watchlist (^WATCHLIST_IDES) - `puncia exploit ^WATCHLIST_IDES ` - Vulnerable Technologies Watchlist (^WATCHLIST_TECH) - `puncia exploit ^WATCHLIST_TECH ` - [Supported Vulnerability Identifiers](https://github.com/ARPSyndicate/docs?tab=readme-ov-file#supported-vulnerability-identifiers) - `puncia exploit ` -4. Enrich CVE/GHSA Identifiers (enrich) - `puncia enrich ` -5. Multiple Queries (bulk/sbom) +4. Enrich CVE/GHSA Identifiers (enrich) - `puncia enrich ` +5. Multiple Queries (bulk/sbom) + - Bulk Input JSON File Format - `puncia bulk ` - ``` - { - "subdomain": [ - "domainA.com", - "domainB.com" - ], - "exploit": [ - "eoidentifierA", - "eoidentifierB" - ], - "enrich": [ - "eoidentifierA", - "eoidentifierB" - ] - } - ``` + ``` + { + "subdomain": [ + "domainA.com", + "domainB.com" + ], + "exploit": [ + "eoidentifierA", + "eoidentifierB" + ], + "enrich": [ + "eoidentifierA", + "eoidentifierB" + ] + } + ``` - [SBOM Input JSON File Format](https://github.com/CycloneDX/bom-examples/blob/master/SBOM/protonmail-webclient-v4-0912dff/bom.json) - `puncia sbom ` + +6. External Import + ``` + import puncia + + # Without API Key + print(puncia.query_api("exploit","CVE-2021-3450")) + print(puncia.query_api("subdomain","arpsyndicate.io")) + + # With API Key + puncia.store_key("ARPS-xxxxxxxxxx") + print(puncia.query_api("subdomain","arpsyndicate.io", apikey=puncia.read_key())) + print(puncia.query_api("exploit","CVE-2021-3450", apikey=puncia.read_key())) + ``` +
## Noteworthy Mentions + - [Around 1000 exploitable cybersecurity vulnerabilities that MITRE & NIST ‘might’ have missed but China or Russia didn’t.](https://blog.arpsyndicate.io/over-a-1000-vulnerabilities-that-mitre-nist-might-have-missed-but-china-or-russia-did-not-871b2364a526) - [Utilizing GitHub Actions for gathering Subdomain & Exploit Intelligence](https://blog.arpsyndicate.io/utilizing-github-actions-for-gathering-subdomain-exploit-intelligence-bbc79c19bb85) - [Introducing Exploit Observer — More than Shodan Exploits, Less than Vulners](https://blog.arpsyndicate.io/introducing-exploit-observer-more-than-shodan-exploits-less-than-vulners-23eaea466e4a) @@ -59,6 +80,7 @@ Puncia utilizes two of our intelligent APIs to gather the results -
- [Subdomain Enumeration Tool Face-off - 2023 Edition](https://blog.blacklanternsecurity.com/p/subdomain-enumeration-tool-face-off-4e5) ## More from [A.R.P. Syndicate](https://www.arpsyndicate.io) + - [Open Source Intelligence](https://asm.arpsyndicate.io/intelligence.html) - [Attack Surface Management](https://asm.arpsyndicate.io) - [Vulnerability Advisories AI](https://advisories.arpsyndicate.io) \ No newline at end of file diff --git a/puncia/__init__.py b/puncia/__init__.py index e69de29..37a9cd6 100644 --- a/puncia/__init__.py +++ b/puncia/__init__.py @@ -0,0 +1,3 @@ +from .__main__ import query_api, store_key, read_key + +__all__ = ["query_api", "store_key", "read_key"] \ No newline at end of file diff --git a/puncia/__main__.py b/puncia/__main__.py index 9ba4f28..3fa0f38 100755 --- a/puncia/__main__.py +++ b/puncia/__main__.py @@ -29,18 +29,16 @@ def read_key(): try: home = os.path.expanduser("~") with open(home + "/.puncia", "r") as f: - key = f.read() - return key - except: - pass - return "" + return f.read().strip() + except FileNotFoundError: + return "" -def query_api(mode, query, output_file=None, cid=None, akey=""): - if len(akey) > 0 and mode in ["exploit", "subdomain", "enrich"]: - url = API_URLS.get("auth_" + mode).format(akey) +def query_api(mode, query, output_file=None, cid=None, apikey=""): + if len(apikey) > 0 and mode in ["exploit", "subdomain", "enrich"]: + url = API_URLS.get("auth_" + mode).format(apikey) else: - time.sleep(60) + time.sleep(25) url = API_URLS.get(mode) if "^" in query and "exploit" in mode: if query == "^RU_NON_CVE": @@ -65,16 +63,21 @@ def query_api(mode, query, output_file=None, cid=None, akey=""): cid = "Vulnerable Technologies Watchlist" if not url: sys.exit("Invalid Mode") - try: - response = requests.get(url + query).json() - except: - print("An exception happened while requesting: " + query) - return + retries = 3 + counter = 0 + response = {} + while counter <= retries: + try: + response = requests.get(url + query).json() + if len(response) > 0: + break + except: + print("An exception happened while requesting: " + query) + counter = counter + 1 + time.sleep(60) if not response or len(response) == 0: - print("Null response from the API") + print("Null response from the API for: " + query) return - result = json.dumps(response, indent=4, sort_keys=True) - print(result) if mode in ["spec_exploit"]: os.system("rm " + output_file) for reurl in response: @@ -83,7 +86,7 @@ def query_api(mode, query, output_file=None, cid=None, akey=""): reurl, output_file, cid, - akey, + apikey, ) return if output_file: @@ -147,6 +150,8 @@ def query_api(mode, query, output_file=None, cid=None, akey=""): with open(output_file, "w") as f: json.dump(existing_data, f, indent=4, sort_keys=True) + return existing_data + return response def sbom_process(sbom): @@ -167,7 +172,7 @@ def add_component(name, version): def main(): try: print("---------") - print("Panthera(P.)uncia [v0.24]") + print("Panthera(P.)uncia [v0.25]") print("A.R.P. Syndicate [https://www.arpsyndicate.io]") print("---------") @@ -179,7 +184,7 @@ def main(): mode = sys.argv[1] query = sys.argv[2] output_file = sys.argv[3] if len(sys.argv) == 4 else None - akey = read_key() + apikey = read_key() if ( mode not in API_URLS @@ -207,35 +212,41 @@ def main(): if "subdomain" in input_file: for bulk_query in input_file["subdomain"]: try: - query_api( + rdata = query_api( "subdomain", bulk_query, output_file + "/subdomain/" + bulk_query + ".json", - akey=akey, + apikey=apikey, ) + if len(rdata) > 0: + print(json.dumps(rdata, indent=4, sort_keys=True)) except Exception as ne: sys.exit(f"Error: {str(ne)}") continue if "exploit" in input_file: for bulk_query in input_file["exploit"]: try: - query_api( + rdata = query_api( "exploit", bulk_query, output_file + "/exploit/" + bulk_query + ".json", - akey=akey, + apikey=apikey, ) + if len(rdata) > 0: + print(json.dumps(rdata, indent=4, sort_keys=True)) except Exception as ne: sys.exit(f"Error: {str(ne)}") if "enrich" in input_file: for bulk_query in input_file["enrich"]: try: - query_api( + rdata = query_api( "enrich", bulk_query, output_file + "/enrich/" + bulk_query + ".json", - akey=akey, + apikey=apikey, ) + if len(rdata) > 0: + print(json.dumps(rdata, indent=4, sort_keys=True)) except Exception as ne: sys.exit(f"Error: {str(ne)}") @@ -244,7 +255,9 @@ def main(): print("Successful!") else: - query_api(mode, query, output_file, akey=akey) + rdata = query_api(mode, query, output_file, apikey=apikey) + if len(rdata) > 0: + print(json.dumps(rdata, indent=4, sort_keys=True)) except Exception as e: sys.exit(f"Error: {str(e)}") diff --git a/setup.py b/setup.py index b7a1cad..917ab50 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup( name="puncia", - version="0.24", + version="0.25", author="A.R.P. Syndicate", author_email="ayush@arpsyndicate.io", keywords="subdomains subdomain exploits exploit sbom cyclonedx arpsyndicate panthera uncia puncia snow leopard",