从编程角度理解什么是蜜罐

Posted lsdb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从编程角度理解什么是蜜罐相关的知识,希望对你有一定的参考价值。

一、蜜罐定义

百度百科:蜜罐技术本质上是一种对攻击方进行欺骗的技术,通过布置一些作为诱饵的主机、网络服务或者信息,诱使攻击方对它们实施攻击,从而可以对攻击行为进行捕获和分析,了解攻击方所使用的工具与方法,推测攻击意图和动机,能够让防御方清晰地了解他们所面对的安全威胁,并通过技术和管理手段来增强实际系统的安全防护能力。

维基百科:蜜罐通常伪装成看似有利用价值的网络、数据、计算机系统,并故意设置了bug,用来吸引黑客攻击。由于蜜罐事实上并未对网络提供任何有价值的服务,所以任何对蜜罐的尝试都是可疑的。蜜罐中还可能装有监控软件,用以监视黑客入侵后的举动。

个人理解:密罐是仿照正常服务对客户端请求进行响应的软件,且一般比正常服务具有更强的操作记录功能。下面我将通过从使用角度和编程角度来讲解这一定义的具体含义。

 

二、从使用角度理解”仿照“的含义

现具有一个IIS搭建的ftp服务,和一个ftp蜜罐,我们对其进行如下操作:

服务 监听端口 用户 蜜码 文件 测试操作
IIS搭建的ftp服务 21 ls abcd1234 根目录下有一ftp_server.txt文件 登录---查看文件----退出
ftp服务密罐 21212 ls abcd1234 声称自己在根目录下有一ftp_server.txt文件 登录---查看文件----退出

 

 

 

IIS搭建的ftp服务ftp客户端操作截图如下:

技术分享图片

ftp服务密罐ftp客户端操作截图如下:

技术分享图片

总结如下:

服务类型 数据包 功能是否真正实现 客户端使用感受
IIS搭建的ftp服务 按协议发送 真正实现(比如2.1中的ls是真列出ftp目录中的文件) 正常ftp服务
ftp服务密罐 按协议发送 声称实现(比如2.2中的ls并不是真列出ftp目录中的文件,而是代码设定好的回应) 正常ftp服务

 

 

 

也就是说,在以上操作中,蜜罐”仿照“了正常服务对客户端请求进行响应,导致用户无法区分其是蜜罐还是正常服务。

 

三、从编程角度理解”仿照“的含义

使用上的”仿照“本质上是代码的”仿照“。此处代码正是上节ftp蜜罐的代码,从代码中我们可以看到蜜罐到底是如何从代码上对正常服务进行仿照的。

(由于代码略长为避免影响后文这里折叠起来。)

技术分享图片
import time
import socket
import threading

# 文件传输线程
class myThread (threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        # 被动模式启监听
        while True:
            ftp_data_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
            ftp_data_socket.setblocking(True)
            ftp_data_socket.bind(("10.10.6.91", 8361))
            print("listening")
            ftp_data_socket.listen(2)
            while True:
                try:
                    self.client_socket, addr = ftp_data_socket.accept()
                except:
                    continue

    # 被动模式列文件函数
    def pasv_send_msg(self):
        msg = "07-07-18  01:48PM                 5828 taiwan_ip_modify.txt
"
        self.client_socket.send(msg.encode())
        self.client_socket.close()

    # 主动模式列文件函数
    def port_send_msg(self,port):
        send_file_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        send_file_socket.connect((10.10.6.91, port))
        msg = "ftp_server.txt
"
        send_file_socket.send(msg.encode())
        send_file_socket.close()


class ftpd:
    def ftp_server(self):
        ip_addr = socket.gethostbyname(socket.gethostname())
        port = 21212
        data = ""
        # 文件传输线程
        self.thread_file = ""
        # 文件传输模式,port--主动,pasv--被动
        self.file_tran_mode = "port"

        # 启动监听
        server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        # server_socket.setblocking(True)
        server_socket.bind((ip_addr,port))
        server_socket.listen(5)
        while True:
            try:
                # 接收客户端连接
                client_socket,addr = server_socket.accept()
                # client_socket.setblocking(True)
                print(f"accept connect from {addr}")
                msg = "220 Microsoft FTP Service
".encode()
                client_socket.send(msg)
                # 接受客户端请求
                while True:
                    data = client_socket.recv(100)
                    if not data:
                        continue
                    # 处理用户登录指令
                    elif "USER" in data.decode():
                        print(f"data-{data.decode()}")
                        msg = (f"331 Password required for "
                               f"{data.decode()[5:-2]}.
")
                        client_socket.send(msg.encode())
                    # 处理密码验证指令
                    elif "PASS" in data.decode():
                        print(f"data-{data.decode()}")
                        msg = "230 User logged in.
"
                        client_socket.send(msg.encode())
                    # 处理查看系统信息指令
                    elif "SYST" in data.decode():
                        print(f"data-{data.decode()}")
                        msg = "215 Windows_NT
"
                        client_socket.send(msg.encode())
                    # 处理查看当前路径指令
                    elif "PWD" in data.decode():
                        print(f"data-{data.decode()}")
                        msg = 257 "/" is current directory.

                        client_socket.send(msg.encode())
                    # 处理编码指令
                    elif "OPTS UTF8" in data.decode():
                        print(f"data-{data.decode()}")
                        msg = "200 OPTS UTF8 command successful - UTF8 encoding now ON.
"
                        client_socket.send(msg.encode())
                    # 处理保持连接指令
                    elif "NOOP" in data.decode():
                        print(f"data-{data.decode()}")
                        msg = "200 NOOP command successful.
"
                        client_socket.send(msg.encode())
                    # 处理退出登录指令
                    elif "QUIT" in data.decode():
                        print(f"data-{data.decode()}")
                        msg = "221 Goodbye.
"
                        client_socket.send(msg.encode())
                        self.thread_file.join()
                        client_socket.close()
                    # 处理切换被动模式指令
                    elif "PASV" in data.decode():
                        print(f"data-{data.decode()}")
                        msg = "227 Entering Passive Mode (10,10,6,93,32,169).
"
                        client_socket.send(msg.encode())
                        if self.thread_file == "" or not self.thread_file.is_alive():
                                self.thread_file = myThread()
                                self.thread_file.start()
                        self.file_tran_mode = "pasv"
                    # 处理切换主动模式指令
                    elif "PORT" in data.decode():
                        print(f"data-{data.decode()}")
                        msg = "200 PORT command successful.
"
                        client_socket.send(msg.encode())
                        if self.thread_file == "" or not self.thread_file.is_alive():
                                self.thread_file = myThread()
                                self.thread_file.start()
                        self.file_tran_mode = "port"
                        tmp = data.decode().strip().replace("
", "")
                        tmp_dict = tmp.split(",")
                        self.port = int(tmp_dict[4]) * 256 + int(tmp_dict[5])
                    # 处理列目录指令,根据当是是主动还是被动模式调用发送函数
                    elif "NLST" in data.decode():
                        print(f"data-{data.decode()}")
                        if self.file_tran_mode == "port":
                            self.thread_file.port_send_msg(self.port)
                            time.sleep(1)
                            msg = "125 Data connection already open; Transfer starting.
"
                            client_socket.send(msg.encode())
                        else:
                            self.thread_file.pasv_send_msg()
                            time.sleep(1)
                        msg = "226 Transfer complete.
"
                        client_socket.send(msg.encode())
                    # 其他指令,未处理
                    else:
                        print(f"data-{data}")
            except:
                print("socket have been close")
                continue

if __name__ == "__main__":
    ftp_server = ftpd()
    ftp_server.ftp_server()
View Code

 

四、其他一些说明

4.1 蜜罐编写思路

密罐是仿照正常服务对客户端请求进行响应的软件,所以我们可以和正常服务开发一样根据服务的协议文档来编写蜜罐。

但是读协议文档往往是很费劲的一件事。我们可以先搭建一个正常的服务,再安装一个客户端,然后使用wireshark拦截客户端与服务端的交互数据包,最后收到什么客户端请求就模仿正常服务返回同样的数据包就可以了。

比如我这里实现的ftp蜜罐,就是通过先用IIS搭建ftp服务,然后使用windows自带的客户端,再然后使用wireshark拦截到如下数据包,最后编码模仿IIS的ftp服务进行响应实现的。

技术分享图片

 

4.2 蜜罐的分类

根据”仿照“的程度可以分为以下三类密罐:

低交互蜜罐:只是声称功能已经实现但实际没实现很容易看出破绽的蜜罐。比如我这里对get等指令都未做处理,用户很多命令都执行不了就会产生怀疑,所以只能算是一个低交互蜜罐。

高交互蜜罐:声称功能实现且大多功能让攻击者使用起来感觉就和真的服务没区别的密罐。比如我这里的ftp服务如果在现在基上对get等其他指令都做处理那就可以成为一个高交互蜜罐。

实系统蜜罐:真的实现所有服务功能的蜜罐。比如如果我这里的程序不是对指令做假的回应而是真真正正实现ftp的功能那就是一个实系统蜜罐。

                     但一般情况下实系统蜜罐并不是真自己从头去写,而是采用安装有漏洞版本辅以其他手段完成监控的方式。比如安装有漏洞版本的vsftpd加通过流量镜像进行监控的形式实现。

在常规介绍中蜜罐一般只指低交互蜜罐和高交互蜜罐,但在实际部署中为了提高逼真程度、让攻击者不疑有他地使用自己的攻击手段攻击系统经常直接部署实系统蜜罐。

 

4.3 蜜网

密网就是所有密罐的总和。我总怀疑密网和H5一样是销售制造的新名词,不过叫密码确实更能体现蜜罐系统的整体性,所以也不算一无是处:

在搭建密罐系统时,为了更强的诱捕能力,通常会不只单独部署一个密罐而经常是使用多台设备安装多个密罐,比如这台启ftp蜜罐那台启smtp蜜罐等。

在搭建密罐系统时,为了营造更逼真环境,通常会使用实系统蜜罐,而实系统蜜罐意味着真实的系统意味着真实的漏洞意味着机器可能真会被攻破,所以通常会将蜜罐系统放在独立的网络环境中。

在搭建蜜罐系统时,更了方便性,通常会有角色分工,比如有统一的流量监控主机和日志监控主机。

 

以上是关于从编程角度理解什么是蜜罐的主要内容,如果未能解决你的问题,请参考以下文章

闭包漫谈(从抽象代数及函数式编程角度)

2-5:套接字(Socket)编程之从内核角度深入理解套接字

从JVM的角度看JAVA代码--代码优化

从程序员视角和编程语言角度看中医:一种生命健康编程语言

从煎鸡蛋的角度理解编程的思维和流程,你适合学吗?

从工程的角度上理解coding