freeBuf
主站

分類

漏洞 工具 極客 Web安全 系統安全 網絡安全 無線安全 設備/客戶端安全 數據安全 安全管理 企業安全 工控安全

特色

頭條 人物志 活動 視頻 觀點 招聘 報告 資訊 區塊鏈安全 標準與合規 容器安全 公開課

官方公眾號企業安全新浪微博

FreeBuf.COM網絡安全行業門戶,每日發布專業的安全資訊、技術剖析。

FreeBuf+小程序

FreeBuf+小程序

基于開源蜜罐的實踐與功能擴展
2019-10-28 13:30:07

0x00 前言

具有一定規模的公司都會有自己的機房,當網絡規模和硬件系統到達一定程度,就需要跟進各種安全預警防護手段,而蜜罐系統就是一種常見的防護手段之一,蜜罐主要是通過在網絡環境當中,用虛擬各種真實服務的守護進程,去模擬各種常見的應用服務,比如http、mysql、FTP服務等。

一般情況下,蜜罐系統是模擬出來的服務,不具備提供真實服務的能力,比如有蜜罐監聽的ftp端口21,但21端口其實只是一個空的監聽,不能提供FTP服務,并且己方人員,知道蜜罐是一個報警裝置,不會去刻意訪問,只有不明身份的攻擊者才有可能去訪問蜜罐進行漏洞嘗試探測。

如果有人對蜜罐進行了大量的針對性操作,并且訪問操作的Payload屬于攻擊數據,我們可以蜜罐的報警日志,判斷這個可能是一個可以的攻擊行為,或是誤碰蜜罐行為,雖然服務不是真實的服務,但攻擊的的滲透Payload數據都是真實的。

1.png

一般可以在網絡環境中,通過交換機的端口聚合技術,在一臺機器上創建多個網段的IP,將流量引入集中到一臺機器上,然后在這臺機器上部署各個IP的監聽,理想的狀態下是可以提供這種機制的,如果不行也可以通過樹莓派等手段,創建蜜罐?,F在有很多種的蜜罐系統可以提供給安全運維人員使用,進行蜜罐系統部署,在各色的開源蜜罐系統中,我們選了相對比較有代表性的蜜罐系統給大家介紹,一般會根據蜜罐的:難易性、可用性、展示性、交互性等方面考察蜜罐系統的特點,從另一個角度劃分,可分成純命令行和UI畫面支持的。

a):純命令行式的操作方式,比如Opencanary這個蜜罐系統。

b):有Dashboard界面的可視化蜜罐系統,比如OpenCanary,Hfish等,這次主要介紹的是Opecanary。

OpenCanary蜜罐系統

OpenCanary是一種開源蜜罐系統,在黑帽在2015開源的,實現語言采用Python實現,因為是開源的代碼,我們可基于這一套代碼,進行擴展和改寫, 也因為Python的友好性,可以相對快速的實現我們想要的新功能。Opencanary的代碼量真的不是很大,代碼結構清晰,擴展簡單,設計的不復雜。

OpenCanay是一種基于命令行式的蜜罐服務系統,沒有給出過多的UI操作界面,基本操作都是通過命令行,然后通過改寫配置文件,完成對蜜罐的各種配置。通過配置文件的方式對專家啊來說,不是一問題,但操作友好性上還是一般,但是可以達到正配置目的。

Opencanary的基本實現原理也是通過設置各種監聽的端口,模擬各種流行的服務,而底層實現端口監聽,依賴于twisted的python庫實現。

0x01 安裝Python

opencanary是基于Python的運行環境的,提到運行環境,我們往往就面臨著一個不同操作系統Python環境不同的問題,為了避免各種平臺差異造成的依賴包困擾,我們選擇虛擬的Python環境virtualenv來安裝Opencananry,這樣所需環境都在虛擬的環境下安裝。同時又在默認的系統環境下,通過pip安裝部署,大多數情況下,是不會出現問題。

部署Opencanary之前請確保您的機器上有大于等Python2.7版本的Python語言環境系統,至少可以用于運行Python語言,之后基于這個創建我們需要的Opencanary運行環境。

0x02 部署依賴

使用virtualenv保證Python環境下依賴包互隔離不影響,還是要強調一下,不用這個也可以正常裝,這樣可以直接在系統默認的庫下改源碼。

相關的依賴庫,在Python安裝之后,都是通過pip來安裝。

2.1 安裝PIP

python get-pip.py

在安裝PIP的前,還要需要安裝Python的開發安裝包:python-deve,如果不安裝python開發包,會提示找不到python.h這個文件,pip是沒有辦法正常安裝。

2.2 安裝VirtualEnv

安裝virtualenv之后,我們可以將之后使用的各種依賴包,都裝到虛擬環境中,而不裝到python默認的庫文件中,一般用root用戶安裝的virtualenv生成文件都在/root/.virtualenvs/中。而系統默認安裝的庫文件的位置是在,/usr/lib/python2.7/site-packages/中,這樣環境之間的依賴包不互相影響。

細分的這么清楚,是因為后續我們要修改opencanary源碼,不同的部署方法,源代碼的位置是不一樣的。opencanary是在python2.x下運行的,在官網github上可以看到更具體說明,而一些特別的需要關注點的,在這里給出一些重點的說明。

sudo pip install virtualenvsudo pip install virtualenvwrapper --upgrade --ignore-installed

有了virtualenv,我們可以在一臺機器上,裝多個python的環境。但實際我們裝個python2.7版本的環境就基本滿足目前的需求。

2.3 創建Python虛擬環境

編輯.bash_profile文件內容。

source /usr/local/bin/virtualenvwrapper.sh

virtualevnwrapper.sh的所在位置,取決于你安裝時指定的安裝位置,有可能在/usr/local/bin下,也可能在/usr/bin下,當初指定的安裝目錄位置,只有運行了這個 shell腳本,后續執行在shell中,才能找到mkvirtualenv執行文件。

我們創建了一個叫做py27的虛擬環境。

mkvirtualenv py27 -p /usr/bin/python

我們切換到py27這個Python環境下。

workon py27

2.4 安裝Opencananry

pip在安裝opencanary時,會自動安裝他所需求要的各種依賴,一般不出問題的話,一切都會順利安裝完成。

sudo?pip?install?opencanary

0x03 管理配置

Opencanary的配置幾乎都在配置文件里生成,第一次安裝的時候,我們可以通過命令行創建一個配置文件,這個配置默認只打開了FTP的蜜罐監聽

opencanaryd --copyconfig

加copyconfig選項的意思是,是生成了一個模板配置文件/root/.opencanary.conf,整個opencanary支持多種服務的監聽:

FTP

HTTP

Proxy

MSSQL

MySQL

NTP

Portscan

RDP

Samba

SIP

SNMP

SSH

Telnet

TFTP

VNC

為了更直觀一些,我們截取一段ftp監聽的代碼:

from opencanary.modules import CanaryService
from twisted.application import internet
from twisted.protocols.ftp import FTPFactory, FTPRealm, FTP, \
USR_LOGGED_IN_PROCEED, GUEST_LOGGED_IN_PROCEED, IFTPShell, \
AuthorizationError
from twisted.cred.portal import Portal
from zope.interface import implements
from twisted.cred.checkers import ICredentialsChecker
from twisted.python import failure
from twisted.cred import error as cred_error, credentials
FTP_PATH = "/briar/data/ftp"
class DenyAllAccess:
implements(ICredentialsChecker)
credentialInterfaces = (credentials.IAnonymous, credentials.IUsernamePassword)
def requestAvatarId(self, credentials):
return failure.Failure(cred_error.UnauthorizedLogin())
class LoggingFTP(FTP):
#ripped from main FTP class, overridden to extract connection info
def ftp_PASS(self, password):
"""
Second part of login. Get the password the peer wants to
authenticate with.
"""
if self.factory.allowAnonymous and self._user == self.factory.userAnonymous:
# anonymous login
creds = credentials.Anonymous()
reply = GUEST_LOGGED_IN_PROCEED
else:
# user login
creds = credentials.UsernamePassword(self._user, password)
reply = USR_LOGGED_IN_PROCEED
logdata = {'USERNAME': self._user, 'PASSWORD': password}
self.factory.canaryservice.log(logdata, transport=self.transport)
del self._user
def _cbLogin((interface, avatar, logout)):
assert interface is IFTPShell, "The realm is busted, jerk."
self.shell = avatar
self.logout = logout
self.workingDirectory = []
self.state = self.AUTHED
return reply
def _ebLogin(failure):
failure.trap(cred_error.UnauthorizedLogin, cred_error.UnhandledCredentials)
self.state = self.UNAUTH
raise AuthorizationError
d = self.portal.login(creds, None, IFTPShell)
d.addCallbacks(_cbLogin, _ebLogin)
return d
class CanaryFTP(CanaryService):
NAME = 'ftp'
def __init__(self,config=None, logger=None):
CanaryService.__init__(self, config=config, logger=logger)
self.banner = config.getVal('ftp.banner', default='FTP Ready.').encode('utf8')
self.port = config.getVal('ftp.port', default=21)
# find a place to check that logtype is initialised
# find a place to check that factory has service attached
self.logtype = logger.LOG_FTP_LOGIN_ATTEMPT
self.listen_addr = config.getVal('device.listen_addr', default='')
def getService(self):
p = Portal(FTPRealm(FTP_PATH), [DenyAllAccess()])
f = FTPFactory(p)
f.protocol = LoggingFTP
f.welcomeMessage = self.banner
f.canaryservice = self
return internet.TCPServer(self.port, f, interface=self.listen_addr)

ftp監聽服代碼在80多行,就完成模擬服務,可以看到使用twisted庫。

from twisted.application import internet
from twisted.protocols.ftp import FTPFactory, FTPRealm, FTP, \
USR_LOGGED_IN_PROCEED, GUEST_LOGGED_IN_PROCEED, IFTPShell, \
AuthorizationError

其它模擬代碼都在moules目錄下,都可參考。

配置文件中,默認打開了FTP的訪問,用一個正常的ftp客戶端,無論是命令行還是GUI工具都可以:

{
"device.node_id": "opencanary-1",
"git.enabled": false,
"git.port" : 9418,
"ftp.enabled": true,
"ftp.port": 21,
"ftp.banner": "FTP server ready",
"http.banner": "Apache/2.2.22 (Ubuntu)",
"http.enabled": false,
"http.port": 80,
"http.skin": "nasLogin",
"http.skin.list": [
{
"desc": "Plain HTML Login",
"name": "basicLogin"
},
{
"desc": "Synology NAS Login",
"name": "nasLogin"
}
],
"httpproxy.enabled" : false,
"httpproxy.port": 8080,
"httpproxy.skin": "squid",
"httproxy.skin.list": [
{
"desc": "Squid",
"name": "squid"
},
{
"desc": "Microsoft ISA Server Web Proxy",
"name": "ms-isa"
}
],
"logger": {
"class": "PyLogger",
"kwargs": {
"formatters": {
"plain": {
"format": "%(message)s"
}
},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"stream": "ext://sys.stdout"
},
"file": {
"class": "logging.FileHandler",
"filename": "/var/tmp/opencanary.log"
}
}
}
},
"portscan.enabled": false,
"portscan.logfile":"/var/log/kern.log",
"portscan.synrate": 5,
"portscan.nmaposrate": 5,
"portscan.lorate": 3,
"smb.auditfile": "/var/log/samba-audit.log",
"smb.enabled": false,
"mysql.enabled": false,
"mysql.port": 3306,
"mysql.banner": "5.5.43-0ubuntu0.14.04.1",
"ssh.enabled": false,
"ssh.port": 22,
"ssh.version": "SSH-2.0-OpenSSH_5.1p1 Debian-4",
"redis.enabled": false,
"redis.port": 6379,
"rdp.enabled": false,
"rdp.port": 3389,
"sip.enabled": false,
"sip.port": 5060,
"snmp.enabled": false,
"snmp.port": 161,
"ntp.enabled": false,
"ntp.port": "123",
"tftp.enabled": false,
"tftp.port": 69,
"tcpbanner.maxnum":10,
"tcpbanner.enabled": false,
"tcpbanner_1.enabled": false,
"tcpbanner_1.port": 8001,
"tcpbanner_1.datareceivedbanner": "",
"tcpbanner_1.initbanner": "",
"tcpbanner_1.alertstring.enabled": false,
"tcpbanner_1.alertstring": "",
"tcpbanner_1.keep_alive.enabled": false,
"tcpbanner_1.keep_alive_secret": "",
"tcpbanner_1.keep_alive_probes": 11,
"tcpbanner_1.keep_alive_interval":300,
"tcpbanner_1.keep_alive_idle": 300,
"telnet.enabled": false,
"telnet.port": "23",
"telnet.banner": "",
"telnet.honeycreds": [
{
"username": "admin",
"password": "$pbkdf2-sha512$19000$bG1NaY3xvjdGyBlj7N37Xw$dGrmBqqWa1okTCpN3QEmeo9j5DuV2u1EuVFD8Di0GxNiM64To5O/Y66f7UASvnQr8.LCzqTm6awC8Kj/aGKvwA"
},
{
"username": "admin",
"password": "admin1"
}
],
"mssql.enabled": false,
"mssql.version": "2012",
"mssql.port":1433,
"vnc.enabled": false,
"vnc.port":5000
}

當配置文件用--copyconfig生成后,我們執行Opencanary服務啟動程序。對于我們想創建的監聽服務,我們把對應服務在配置中的.enabled選項設置成true即可,用--restart重啟opencanary服務之后,就可以打開服務端口監聽

啟動服務

opencanaryd --start

當所有的模擬監聽服務都打開的時候,會出現類似下面的進程信息。

netstat -plunt
tcp 0 0 0.0.0.0:2222 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:23 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:1433 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:3389 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:8001 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:5000 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:9418 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 12683/python
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 12683/python
udp 0 0 0.0.0.0:57197 0.0.0.0:* 8994/python
udp 0 0 0.0.0.0:5060 0.0.0.0:* 12683/python
udp 0 0 0.0.0.0:69 0.0.0.0:* 12683/python
udp 0 0 0.0.0.0:123 0.0.0.0:* 12683/python
udp 0 0 0.0.0.0:161 0.0.0.0:* 12683/python

重啟服務

opencanaryd --restart

關閉服務

opencanaryd --stop

其它的命令參數使用可以用--help查一下。

opencanaryd --help

0x04 報警日志

Opencanary模擬了各種服務的監聽,當模擬監聽被觸發的時候就會報警,產生日志,下面給出發報警的方式和產生的日志格式。一般情況下,我們會在機房和內網的網絡環境下部署蜜罐。如果蜜罐系統放到外網,會不時的被各種組織的探測手段發現,進行標識統計。而在內網外部的探測行為是進不了內網的,除非節點被攻破,成為攻擊的入口。

正是當有人非法進入內網后,才會出現勿碰蜜罐的事件發生概率提高,而內部防御不只是一種防御手段,各家公司都提供了流量監聽產品,HIDS這種工具,Opencanary就像您居家過日子,晚上門口多放了幾個啤酒瓶子,如真的門鎖被破開,入侵者有能會碰到屋中放置的啤酒瓶子。

蜜罐系統,可以模擬各種程序協議,我們以FTP為例,展示一下蜜罐的觸碰與報警日志生成的流程,Opencanary中各種服務的觸碰方法,我們會這個例子的后面列出來。

關于FTP,我們測試蜜罐服務器是192.168.0.6,我們啟動了opencanary,然后用ftp客戶端進行訪問:

ftp 192.168.0.6

一般會出現,類似下面的操作過程:

[root@localhost opencanary]# ftp 192.168.0.6
Connected to 192.168.0.6 (192.168.0.6).
220 FTP server ready
Name (192.168.0.6:root): test
331 Password required for test.
Password:
530 Sorry, Authentication failed.
Login failed.
ftp>

這個過程交互結束之后,就會生成一條json數據,json日志數據如下:

{"src_port": 35990, "logdata": {"USERNAME": "test", "PASSWORD": "123456"}, "logtype": 2000, "dst_host": "192.168.0.6", "dst_port": 21, "src_host": "192.168.0.5"}

這是一次針對192.168.0.6的21號端口ftp訪問,OpenCanary有一個ftp模擬的python監聽實現腳本,之前也說過是基于twisted的實現,當蜜罐系統監聽到入侵者訪問時,就會把相應的paylog存起來,然后記錄到日志文件中,在opencanary.conf中設置的日志文件位置是/usr/tmp/opencanary.log中。

官方的opencanary的日志都是生成到本地,后面我們會給出一,如何將日志轉存到其它地方。

下面我們列舉出,幾乎所有opencanary蜜罐支持協議的觸發方法:

4.1 HTTP

觸發方法

curl 0.0.0.0:80

日志數據

{"dst_host": "172.18.200.58", "dst_port": 80, "local_time": "2019-01-07 13:47:45.817940", "logdata": {"HOSTNAME": "172.18.200.58", "PASSWORD": "admin888", "PATH": "/index.html", "SKIN": "nasLogin", "USERAGENT": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:61.0) Gecko/20100101 Firefox/61.0", "USERNAME": "admin"}, "logtype": 3001, "node_id": "opencanary-1", "src_host": "172.18.205.14", "src_port": 54488}

4.2 FTP

觸發方法

ftp?172.12.200.58

日志數據

{"dst_host": "172.18.200.58", "dst_port": 80, "local_time": "2019-01-07 13:47:45.817940", "logdata": {"HOSTNAME": "172.18.200.58", "PASSWORD": "admin888", "PATH": "/index.html", "SKIN": "nasLogin", "USERAGENT": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:61.0) Gecko/20100101 Firefox/61.0", "USERNAME": "admin"}, "logtype": 3001, "node_id": "opencanary-1", "src_host": "172.18.205.14", "src_port": 54488}

4.3 SSH

觸發方法

ssh root@172.18.200.58

日志

{"dst_host": "172.18.200.58", "dst_port": 2222, "local_time": "2019-01-07 13:54:27.811101", "logdata": {"SESSION": "3"}, "logtype": 4000, "node_id": "opencanary-1", "src_host": "172.18.205.14", "src_port": 54639}

4.4 Telnet

觸發方法

telnet 172.18.200.58

日志數據

{"dst_host": "172.18.200.58", "dst_port": 23, "honeycred": false, "local_time": "2019-01-07 13:56:45.341785", "logdata": {"PASSWORD": "admin888", "USERNAME": "admin123"}, "logtype": 6001, "node_id": "opencanary-1", "src_host": "172.18.205.14", "src_port": 54676}

4.5 Mysql

觸發方法

mysql -h172.18.200.58 -uroot -p

日志數據

{"dst_host": "172.18.200.58", "dst_port": 3306, "local_time": "2019-01-07 13:58:25.922257", "logdata": {"PASSWORD": "18076c09615de80ddb2903191b783714918b4c4f", "USERNAME": "root"}, "logtype": 8001, "node_id": "opencanary-1", "src_host": "172.18.220.253", "src_port": 46662}

4.6 Git

觸發方法

git clone git://192.168.1.7:9418/tmp.git

日志數據

{"dst_host": "192.168.1.7", "dst_port": 9418, "local_time": "2019-01-05 15:38:46.368627", "logdata": {"HOST": "192.168.1.7:9418", "REPO": "tmp.git"}, "logtype": 16001, "node_id": "opencanary-1", "src_host": "192.168.1.3", "src_port": 57606}

4.7 NTP

觸發方法

git clone git://192.168.1.7:9418/tmp.git

日志數據

{"dst_host": "0.0.0.0", "dst_port": 123, "local_time": "2019-01-05 15:58:52.075987", "logdata": {"NTP CMD": "monlist"}, "logtype": 11001, "node_id": "opencanary-1", "src_host": "192.168.1.6", "src_port": 57886}

4.8 Redis

觸發方法

(env) [root@honeypot Honeypot]# redis-cli -h 192.168.1.7192.168.1.7:6379> keys *(error) NOAUTH Authentication required.192.168.1.7:6379> config get requirepass(error) ERR unknown command 'config'192.168.1.7:6379> auth admin(error) ERR invalid password192.168.1.7:6379>

日志數據

{"dst_host": "192.168.1.7", "dst_port": 6379, "local_time": "2019-01-05 16:05:11.637269", "logdata": {"ARGS": "", "CMD": "COMMAND"}, "logtype": 17001, "node_id": "opencanary-1", "src_host": "192.168.1.6", "src_port": 34471}

4.9 TCP

觸發方法

telnet 192.168.1.6 8001

日志

{"dst_host": "192.168.1.6", "dst_port": 8001, "local_time": "2019-01-05 17:18:51.601478", "logdata": {"BANNER_ID": "1", "DATA": "", "FUNCTION": "CONNECTION_MADE"}, "logtype": 18002, "node_id": "opencanary-1", "src_host": "192.168.1.3", "src_port": 59176}

4.10 VNC

觸發方法

用VNC客戶端訪問

日志數據

{"dst_host": "192.168.1.7", "dst_port": 5000, "local_time": "2019-01-06 08:21:28.951940", "logdata": {"VNC Client Response": "58c00be9ee5b7f3b666771dd2bda9309", "VNC Password": "<Password was not in the common list>", "VNC Server Challenge": "953e2dff7e4d3a3114527c282817ce1d"}, "logtype": 12001, "node_id": "opencanary-1", "src_host": "192.168.1.6", "src_port": 54634}

4.11 RDP

觸發方法

日志數據

{"dst_host": "192.168.1.7", "dst_port": 3389, "local_time": "2019-01-06 08:59:13.890934", "logdata": {"DOMAIN": "", "HOSTNAME": "HelloHost", "PASSWORD": "helloword", "USERNAME": "administrator1"}, "logtype": 14001, "node_id": "opencanary-1", "src_host": "192.168.1.6", "src_port": 59955}

4.12 SIP

觸發方法

hydra?-l?adminsip?-p?password?192.168.1.7?sip

日志格式

{"dst_host": "0.0.0.0", "dst_port": 5060, "local_time": "2019-01-06 09:55:12.578148", "logdata": {"HEADERS": {"call-id": ["1337@192.168.1.7"], "content-length": ["0"], "cseq": ["1 REGISTER"], "from": ["<sip:adminsip@192.168.1.7>"], "to": ["<sip:adminsip@192.168.1.7>"], "via": ["SIP/2.0/UDP 10.0.2.15:46759;received=192.168.1.7"]}}, "logtype": 15001, "node_id": "opencanary-1", "src_host": "192.168.1.7", "src_port": 46759}

4.13 SNMP

觸發方法

hydra -p password 192.168.1.7 snmp

日志數據

{"dst_host": "0.0.0.0", "dst_port": 161, "local_time": "2019-01-06 11:17:27.266214", "logdata": {"COMMUNITY_STRING": "password", "REQUESTS": ["1.3.6.1.2.1.1.1"]}, "logtype": 13001, "node_id": "opencanary-1", "src_host": "192.168.1.7", "src_port": 47112}

4.14 NMAP

觸發方法

sudo nmap -v -Pn -O 192.168.1.7

日志數據

{"dst_host": "192.168.1.7", "dst_port": "21", "local_time": "2019-01-06 16:35:24.356080", "logdata": {"FIN": "", "ID": "37499", "IN": "eth1", "LEN": "60", "MAC": "08:00:27:da:4c:e2:6c:96:cf:dd:ee:bd:08:00", "OUT": "", "PREC": "0x00", "PROTO": "TCP", "PSH": "", "RES": "0x00", "SYN": "", "TOS": "0x00", "TTL": "56", "URG": "", "URGP": "0", "WINDOW": "256"}, "logtype": 5002, "node_id": "opencanary-1", "src_host": "192.168.1.6", "src_port": "40098"}

4.15 SYN探測

觸發方法

sudo nmap -sS 192.168.1.7

日志數據

{"dst_host": "192.168.1.7", "dst_port": "21", "local_time": "2019-01-06 16:35:24.190176", "logdata": {"ID": "51918", "IN": "eth1", "LEN": "56", "MAC": "08:00:27:da:4c:e2:6c:96:cf:dd:ee:bd:08:00", "OUT": "", "PREC": "0x00", "PROTO": "TCP", "RES": "0x00", "SYN": "", "TOS": "0x00", "TTL": "58", "URGP": "0", "WINDOW": "512"}, "logtype": 5001, "node_id": "opencanary-1", "src_host": "192.168.1.6", "src_port": "40088"}

4.16 FIN探測

觸發方法

sudo nmap -sF 192.168.1.7

日志數據

{"dst_host": "192.168.1.7", "dst_port": "23", "local_time": "2019-01-06 16:46:18.336954", "logdata": {"FIN": "", "ID": "29768", "IN": "eth1", "LEN": "40", "MAC": "08:00:27:da:4c:e2:6c:96:cf:dd:ee:bd:08:00", "OUT": "", "PREC": "0x00", "PROTO": "TCP", "RES": "0x00", "TOS": "0x00", "TTL": "59", "URGP": "0", "WINDOW": "1024"}, "logtype": 5005, "node_id": "opencanary-1", "src_host": "192.168.1.6", "src_port": "35116"}

4.17 XmasTree探測

觸發方法

sudo nmap -sX 192.168.1.7

日志數據

{"dst_host": "192.168.1.7", "dst_port": "139", "local_time": "2019-01-06 16:48:46.225539", "logdata": {"FIN": "", "ID": "19984", "IN": "eth1", "LEN": "40", "MAC": "08:00:27:da:4c:e2:6c:96:cf:dd:ee:bd:08:00", "OUT": "", "PREC": "0x00", "PROTO": "TCP", "PSH": "", "RES": "0x00", "TOS": "0x00", "TTL": "56", "URG": "", "URGP": "0", "WINDOW": "1024"}, "logtype": 5004, "node_id": "opencanary-1", "src_host": "192.168.1.6", "src_port": "50913"}

4.18 Null探測

觸發方法

sudo nmap -sN 192.168.1.7

日志數據

{"dst_host": "192.168.1.7", "dst_port": "5060", "local_time": "2019-01-06 16:51:07.789903", "logdata": {"ID": "26441", "IN": "eth1", "LEN": "40", "MAC": "08:00:27:da:4c:e2:6c:96:cf:dd:ee:bd:08:00", "OUT": "", "PREC": "0x00", "PROTO": "TCP", "RES": "0x00", "TOS": "0x00", "TTL": "50", "URGP": "0", "WINDOW": "1024"}, "logtype": 5003, "node_id": "opencanary-1", "src_host": "192.168.1.6", "src_port": "58015"}

4.19 MSSQL

觸發方法

MSSQL客戶端工具

日志數據

{"dst_host": "172.18.200.58", "dst_port": 1433, "local_time": "2019-01-07 09:04:58.690137", "logdata": {"AppName": "SQLPro for MSSQL (hankinsoft.com)", "CltIntName": "DB-Library", "Database": "test", "HostName": "Piroguehost", "Language": "us_english", "Password": "sa123456", "ServerName": "172.18.200.58:1433", "UserName": "sa"}, "logtype": 9001, "node_id": "opencanary-1", "src_host": "172.18.205.14", "src_port": 64344}

4.20 HTTPProxy

觸發方法

瀏覽器配置

日志數據

{"dst_host": "172.18.200.58", "dst_port": 8080, "local_time": "2019-01-07 13:26:47.761297", "logdata": {"PASSWORD": "passsquid", "USERNAME": "squidadmin"}, "logtype": 7001, "node_id": "opencanary-1", "src_host": "172.18.205.14", "src_port": 53798}

0x05 Opencanary的功能擴展

Opencanay是用Python開源的,我們可以根據我們具體的需求,擴展opencanary的功能,這個需求產生的原因,是我們需要對報警日志進行匯聚。

蜜罐日志是日常威脅日志收集的一部分,蜜罐報警的日志分析的優先級相對是很高的,因為一般情況下,蜜罐的誤碰不應該太多(白名單),所以第一時間出現問題,需要蜜罐把數據推給日志分析系統、或是日志接收服務,數據的取得有多種方式,之前一種方式是把日志存到本地的日志文本文件中,實時也寫到mysql數據中,然后再由其它程序進行輪訓,這種處理方式有一個問題是,輪詢是有時間間隔的,定時任務的輪訓機制,真實的報警時間和攻擊實際發生時間可能不在一個時間點,這樣在做關聯分析時,如果沒有唯一標識機器屬性時,比如:mac,沒法判斷內網IP對應的是同一個人的行為,所以,我們要第一時間接收到蜜罐的報警。

OpenCanary的代碼是開源的, 我們只需要改源代碼,就可以實現我們的需求,OpenCanary有一個logger日志寫入類,我們只要改這個模塊的代碼即可。

我們一般有幾種日志數據存儲形式:

1.RESTAPI:我們在蜜罐寫日志的地方,調用一個REST API的接口服務,將報警數據轉發給其它的REST接口,由接口寫數據,分析,報警。

2.RPC:在蜜罐寫日志的地方加一個RPC調用接口,像調用一般函數一樣,調用一個遠程RPC寫日志方法。然后在PPC服務端加入各種判定策略邏輯,就像我們之間介紹的semaphore那個項目。

3.UDP Syslog:在蜜罐寫日志的地方,直接通過socketc通過syslog協議數據,把json數據發給一個syslog監聽,有不同的開源方案都能解決這個問題, 我們一般采用的都是Graylog的數據收集方法,將syslog監聽的數據接收后,對其中的json格式數據時進行解析,然后存入到多復本的ES集群中,這個過程中Graylog做了很多ES數據的管理工作,讓ES操作管理變得容易,而Splunk如果數據量不大是可以免費使用的, 對于一般數據規模,幾個ES集群這種情況,Graylog就可以解決,功能看實際需求,根據自己情況進行擴展,開源可以省下很多開發人月。

修改源代碼位置:

logger是一人單例模式的類,logger.py在 opencanary的庫文件中,如果不出意外的話,位置應該是:

/usr/lib/python2.7/site-packages/opencanary

如果您是用virtualenv安裝,那庫的位置就在您的虛擬化python的位置的庫文件中。

logger.py源代碼大家可以在庫文件中找到, 我們不列出所有源代碼,為了方便展示,我們不在文件中重寫一個handler類,而是直接在寫本地日志的地方,將報警日志外發到Syslog監聽,或是直接放給Graylog服務器,作為數據接收端接受數據,后期對數據進行黑白名單處理,數據聚合處理。

這樣進行擴展的好處就是,不破壞原有的執行時序,達到數據轉存的目的。

def log(self, logdata, retry=True):
import syslog_client
graylog = syslog_client.Syslog("198.168.0.8")
graylog.send(json.dumps(logdata), syslog_client.Level.INFO)
logdata = self.sanitizeLog(logdata)
self.logger.warn(json.dumps(logdata, sort_keys=True))

下面這句話是寫日志,

self.logger.warn(json.dumps(logdata, sort_keys=True))

我們另外加入幾行轉發syslog的日志處理:

import syslog_client
graylog = syslog_client.Syslog("198.168.0.8")
graylog.send(json.dumps(logdata), syslog_client.Level.INFO)

這里要特別注意的地方是,在發送日志數據之前,要把數據包裝成json數據格式,這樣當數據發送給Graylog之后, 就可能直接對數據按json格式的數據切割。

2.png

也可以通過自定義的syslog監聽服務,對數據進行各種加工處理。

我們看一下opencanary.conf中是如何關聯到logger這個類的。

    "logger": {
        "class": "PyLogger",
        "kwargs": {
            "formatters": {
                "plain": {
                    "format": "%(message)s"
                }
            },
            "handlers": {
                "console": {
                    "class": "logging.StreamHandler",
                    "stream": "ext://sys.stdout"
                },
                "file": {
                    "class": "logging.FileHandler",
                    "filename": "/var/tmp/opencanary.log"
                }
            }
        }
    },

從這個配置里我們可以看到是,直接關聯到了logging.FileaHandler這個類,就是直接寫了文件。

實際上我們可以根據Opencanry提供的Exampler.py的模式寫一個模塊來擴展蜜罐的功能,一樣可以在opencanary.conf中引用,這種模板是基于創建監聽的。

下面是模塊編寫的模板。

from opencanary.modules import CanaryService
from twisted.internet.protocol import Protocol
from twisted.internet.protocol import Factory
from twisted.application import internet
class Example0Protocol(Protocol):
"""
Example (Fictional) Protocol
$ nc localhost 8007
Welcome!
password: wrong0
password: wrong1
password: wrong2
Bad passwords
$
"""
def __init__(self):
self.prompts = 0
def connectionMade(self):
self.transport.write("Welcome!\r\npassword: ")
self.prompts += 1
def dataReceived(self, data):
"""
Careful, data recieved here is unbuffered. See example1
for how this can be better handled.
"""
password = data.strip("\r\n")
logdata = {"PASSWORD" : password}
self.factory.log(logdata, transport=self.transport)
if self.prompts < 3:
self.transport.write("\r\npassword: ")
self.prompts += 1
else:
self.transport.write("\r\nBad passwords\r\n")
self.transport.loseConnection()
class CanaryExample0(Factory, CanaryService):
NAME = 'example0'
protocol = Example0Protocol
def __init__(self, config=None, logger=None):
CanaryService.__init__(self, config, logger)
self.port = 8007
self.logtype = logger.LOG_BASE_EXAMPLE
CanaryServiceFactory = CanaryExample0

還有一種方式,我們在logger文件中直接加一個handler處理,把FileHandler變成syslog的SyslogHandler。

class DemoHandler(logging.Handler):
    def __init__(self, demo_userid, demo_authkey, allowed_ports):
        logging.Handler.__init__(self)
        self.demo_userid = str(demo_userid)
        self.demo_authkey = str(demo_authkey)
        try:
            # Extract the list of allowed ports
            self.allowed_ports = map(int, str(allowed_ports).split(','))
        except:
            # By default, report only port 22
            self.allowed_ports = [ 22 ]

    def emit(self, record):
        ...

再修改opencanary.conf配置文件。

"logger": {
    "class" : "PyLogger",
    "kwargs" : {
        "formatters": {
            "plain": {
                "format": "%(message)s"
            }
        },
        "handlers": {
            "dshield": {
                "class": "opencanary.logger.DemoHandler",
                "demo_userid": "test",
                "demo_authkey": "$%$##$#%$%",
                "allowed_ports": "22,23"
            }
        }
    }
}

syslog協議是一種可以基于UDP協議進行數據傳輸的協議,在早期數據野蠻生長的階段,我們創建很多基于syslog的服務數據收集,因為一般的安全設備都支持syslog數據的發送。

后期ELK是一種最常見的數據管理,包括Graylog和Clickhosue這些數據管理手段,都可以很好的集中管理數據,但是這是一種粗放的日志數據管理,還沒有進入數據深加工的階段。

0x06 蜜罐與威脅情報

對于內網蜜罐來說,很多時候的攻擊IP可能是內網的IP, 并不都是外網IP,所有在與威脅情報庫進行比對的時候,查不到相關的數據。但是內網IP會與其它的設備發生關聯,在其它的一些網絡防護設備上,我們可能看到相關的內網IP發生的其它報警行為。

如果我們將所有防御設備上的交通流量,直接進入關聯,那將是一個海量數據的比較,這種情況下, 為了快速的索引數據,我們可能要用ClickHouse這種級別的數據據庫產品,在初期階段,我們相對大量的收集了日志數據,交通數據和報警數據都有,但問題是數據操作起來不靈活。

隨著業務數據不斷的增長,這種方式不一定適合我們新數據分析場景,我們用一個IP與海量的日志數據,進行比對,是一個很耗費性能資源和時間的事情,所以我們考慮,在原始數據日志之上,建立新一層日數據匯聚層,將有用的數據進行深入的加工和匯聚,我們的安全策略不再直接基于海量的原始日志數據,而是建立在更精準的數據匯聚層的,簡單說這些數據是進過整理、整形、去重、提純的數據,數據之間存在更強的關聯,并且是更精巧的數據集。

我們原始的日志數據,基于REST API,這樣服務之間的通信友好,不需要特定客戶端協議的依賴,只要支持 REST就可以。中間層的數據是對原始數據的精括聚合,我們使用RPC的方式進行數據的查詢,我們可以將業務模塊的數據,變成像普通函數一樣的RPC調用。

對于中間的數據服務來說,無論是RPC還是REST,其實都可以實現我們數據劃分的目的,技術手段多種多樣,但本質上的問題,某些場景下,用空間換時間, 或是時間換空間。

對于蜜罐報警,我們可以作為一個事件發現的起始點,也是很重要的一點時間點,攻擊進行時,因為內網蜜罐的報警,一般情況下是不應該出現高頻率的報警的, 所以,實時推送報警信息,在并發生性能上沒有太大的壓力,直接在可以威脅發生的時間點就報警,異步進行關聯分析。

如果是采用報警寫數據庫,再用有時間間隔的定時計劃任務去輪訓就會有時間延遲,這也是我們想直接改造opencanary的源代碼的一個原因,當然這個問題產生本身和opencanary沒關系。

0x07 蜜罐的集中管理

一般在交換機上支持端口復用的環境下,都可以在一臺機器上,配置多個IP,opencanary提供了一個報警蜜罐的實現解決方案,但是更多的時候是提供了一個agent,場景多用于內網蜜罐的部署。修改配置文件中的server.ip,對應多個指定的IP。

企業都有很多的機房,所以蜜罐的結點管理就是一個課題,國人在Opencanay的基礎上開發社區版的后面管理界面:opencanary web。

640?wx_fmt=jpeg

這個圖上的agent就是opencanary, 報警的方式還是傳統的郵件,這里就存一個問題,這個郵件告警是集中后的后發出,從圖上沒有看出是在agent上直接發出的,除非在寫入數據庫時就報警,這樣是第一時間進行的報警,另外大家可以將郵件告警,增加到用公眾號報警和syslog告警。

系統實現基于nginx和tornadoweb,數據庫系統使用的是mysql,前端口使用的是vue, 具體的安裝方法大家可以直接看github。

3.png

Opencanary支持Hpfeeds,還記得那個客戶端嗎:

hpfeeds-client --host localhost -p 10000 -i honeymap -s cfdd6a68be69464666ae60b66dae69f6 -c geoloc.events publish "{countrycode:'NA', latitude:37.7749, longitude:-122.4194, city:'San Francisco'}"

這個Opencanary也是支持和hpfeeds進行交互的,但是Opencanary用于內網部署,很多IP都是內網IP,不太容易看出地圖炮效果。有的IP可以看到在國內的位置地理信息,和CMDB系統關聯信息。

有沒有一種方法不用WEB管理端也能聚合報警日志呢,其實可以的,用本文的擴展方法,直接將報警數據,第一時間轉存到Graylog上,用Graylog管理ES集群,直接在Graylog加查詢,聚合,還有報警功能,如果你們公司,有spluk,用splunk也可以做到,總是有很多的方案都可以達到您的目的,但是基于數據關聯的策略,還是需要本地中間層數據聚合。

最直接的蜜罐探活監聽就是fping,最簡單,間隔判斷這些機器的網絡是否通,zabbix也可以監控到服務,但是需要對zabbix加白名單。

5.png

如果使用Graylog或是splunk這種系統,地圖信息管理IP和地圖炮功能都是有的,但是一篇肯定是寫不完了,不介紹可自行實驗。

0x08 總結:

Opencanary是一款適合內網使用的蜜罐系統,部署簡單,配置容易,擴展方便,但在模擬服務的數據量上可能還不是最全的,我們旨在通過一個蜜罐的例子,來串起整個系統,從感知Agent到威脅報警日志數據匯聚的過程。Opencanary有很大的擴展潛能,因為Opencanary本身的易的擴展性,簡單性,只要自己動手豐衣足食,進行大型擴展也要看增加的特性量。Opencanary用于內網蜜罐還是可以滿足常用需求的。

傳統的管理后臺,是一種結點監控和數據日志匯總的角色,再加上報警處理等,然而威脅發現的確認邏輯,是要將所以盡可能取得的關聯信息進行策略的過濾匹配,而傳統系統如果只是報警存儲,威脅的可視范圍就局限于自己的威脅發現區域,特別是這種陷阱式的蜜罐。變成威脅信息孤島,不如將蜜罐作為檢查威脅事件的觸發者,事件起始點,一旦蜜罐發生報警,將蜜罐與提前準備好的關聯威脅數據視圖,按內部安全邏輯進行交互,得出更精確的判斷,效果要好于白名單的嚴格和黑名單的粗放控制。

*本文原創作者:糖果L5Q,本文屬FreeBuf原創獎勵計劃,未經許可禁止轉載

本文作者:, 屬于FreeBuf原創獎勵計劃,未經許可禁止轉載

# 安全防護 # 實踐 # 開源蜜罐
被以下專輯收錄,發現更多精彩內容
+ 收入我的專輯
評論 按熱度排序

登錄/注冊后在FreeBuf發布內容哦

相關推薦
  • 0 文章數
  • 0 評論數
  • 0 關注者
登錄 / 注冊后在FreeBuf發布內容哦
收入專輯
四月天小说网