用ChatGPT开发一个智能蜜罐
来用ChatGPT做个蜜罐,have fun~😎
提示词工程(Prompt Engineering)
教程BV号:BV1No4y1t7Zn
编写原则:
- 编写明确和具体的指令
- 给模型足够的时间思考
一个Prompt的样例:
import openai
openai.api_key = 'sk-' # OpenAI API Key
def get_completion(prompt, model="gpt-3.5-turbo"):
messages = [{"role": "user", "content": prompt}]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=0,
)
return response.choices[0].message["content"]
prompt = "" # 提问
response = get_completion(prompt)
print(response)
直接来吧!
先在网页测试整个流程。
先做个Demo
第一轮提问
先直接生成一些简单的的看看效果。

中文prompt:
我需要用docker做一些蜜罐。你在做这件事可以从以下几个内容考虑:
- 怎么样的网络设置可以让蜜罐被同一个网络中的主机访问。
- 构建蜜罐的dockerfile需要按规律的保存。最好为每个蜜罐创建一个对应的文件夹,一个文件夹存放一个蜜罐的dockerfile。
- 现在蜜罐上不会运行任何服务,它只用对类似ping这样的命令做应答即可。
- 这样的蜜罐我需要一次生成多个,所以你需要考虑怎么设置IP来避免与网络上已经存在的真实主机冲突。
- 蜜罐所在网段为10.211.55.0/255
你可以写一个python脚本来完成上面的工作。
翻译:
I need to make some honeypots with docker. Here are a few things you can consider when doing this:
- What kind of network settings allow the honeypot to be accessed by hosts in the same network.
- The dockerfile for building the honeypot needs to be saved regularly. It is best to create a corresponding folder for each honeypot, and a folder stores the dockerfile of a honeypot.
- Now there is no service running on the honeypot, it just responds to commands like ping.
- I need to generate multiple such honeypots at a time, so you need to consider how to set the IP to avoid conflicts with real hosts that already exist on the network.
- The network segment where the honeypot is located is 10.211.55.0/255
You can write a python script to do the above.
ChatGPT:
import os
# Define the base IP address for the honeypots
base_ip = "10.211.55."
# Define the number of honeypots to create
num_honeypots = 5
# Define the path to the directory where the Dockerfiles will be stored
dockerfiles_dir = "/path/to/dockerfiles"
# Loop through each honeypot and create a Dockerfile and container for it
for i in range(num_honeypots):
# Define the IP address for the current honeypot
ip_address = base_ip + str(i+1)
# Create a directory for the current honeypot's Dockerfile
honeypot_dir = os.path.join(dockerfiles_dir, "honeypot_" + str(i+1))
os.makedirs(honeypot_dir, exist_ok=True)
# Write the Dockerfile for the current honeypot
with open(os.path.join(honeypot_dir, "Dockerfile"), "w") as f:
f.write(f"FROM alpine\n")
f.write(f"RUN apk add --no-cache bash\n")
f.write(f"CMD [\"bash\"]\n")
# Build the Docker image for the current honeypot
os.system(f"docker build -t honeypot_{i+1} {honeypot_dir}")
# Run the Docker container for the current honeypot
os.system(f"docker run --name honeypot_{i+1} --ip {ip_address} --network honeypot_net -d honeypot_{i+1}")

分析:
两个问题
- IP设置没有考虑冲突
- 运行docker中的network honeypot_net没有设置
迭代1
一个一个解决,首先是network honeypot_net的设置。
中文prompt:
上面你所用的network 'honeypot_net' 并没有设置,请在代码中添加一个函数完成这一功能。
这个功能你可以从下面几点考虑:
- 设置一个docker的macvlan网络
- 设置的时候看当前的网络中是否已经有符合要求的网络设置
- 运行docker的物理主机的网卡名称为'eth0'
翻译:
The network 'honeypot_net' you used above is not set, please add a function to the code to complete this function.
You can consider the following points for this function:
- Set up a docker macvlan network
- When setting, check whether there is already a network setting that meets the requirements in the current network
- The NIC name of the physical host running docker is 'eth0'

ChatGPT:
import os
# Define the base IP address for the honeypots
base_ip = "10.211.55."
# Define the number of honeypots to create
num_honeypots = 5
# Define the path to the directory where the Dockerfiles will be stored
dockerfiles_dir = "/path/to/dockerfiles"
# Define the name and subnet of the Docker network
network_name = "honeypot_net"
network_subnet = "10.211.55.0/24"
# Check if the network already exists
network_exists = os.system(f"docker network inspect {network_name} >/dev/null 2>&1") == 0
# Create the network if it doesn't exist
if not network_exists:
os.system(f"docker network create --driver macvlan --subnet {network_subnet} --gateway {base_ip}1 -o parent=eth0 {network_name}")
# Loop through each honeypot and create a Dockerfile and container for it
for i in range(num_honeypots):
# Define the IP address for the current honeypot
ip_address = base_ip + str(i+1)
# Create a directory for the current honeypot's Dockerfile
honeypot_dir = os.path.join(dockerfiles_dir, "honeypot_" + str(i+1))
os.makedirs(honeypot_dir, exist_ok=True)
# Write the Dockerfile for the current honeypot
with open(os.path.join(honeypot_dir, "Dockerfile"), "w") as f:
f.write(f"FROM alpine\n")
f.write(f"RUN apk add --no-cache bash\n")
f.write(f"CMD [\"bash\"]\n")
# Build the Docker image for the current honeypot
os.system(f"docker build -t honeypot_{i+1} {honeypot_dir}")
# Run the Docker container for the current honeypot, connecting it to the network
os.system(f"docker run --name honeypot_{i+1} --ip {ip_address} --network {network_name} -d honeypot_{i+1}")

修改dockerfile的保存路径/home/hp/dockerfiles和蜜罐IP

运行,成功启动了5个蜜罐。

然而这五个蜜罐无法ping通
迭代2
直接询问无法ping通的原因

并没有找到问题的核心
提问:
我认为蜜罐无法ping通并不是cap-add=NET_ADMIN的原因,我用docker ps -a命令查看容器状态的时候显示的信息为‘Exited (0) 12 seconds ago’,我认为这个原因应该是dockerfile导致的。
翻译:
I don't think the honeypot can't be pinged because of cap-add=NET_ADMIN. When I use the docker ps -a command to check the container status, the information displayed is 'Exited (0) 12 seconds ago'. I think the reason should be the dockerfile caused by.

导致这个的原因是因为之前的docker运行一行命令就退出了,添加这一行在生成dockerfile的部分:

成功生成了想要的蜜罐:

ping测试:

dockerfiles目录结构

至于第一个IP冲突问题在这儿先不管了,感觉在这儿做也是重复造轮子。不如加一点智能!
来点智能!
虽然写了点东西,但是总感觉差点“智能”。毕竟这些代码自己也可以写,何必要用GPT写的呢?最好的方法是让GPT参与到这个生成过程里,而不是扮演一个提供代码的角色。
那么GPT可以做什么呢?既然是生成式AI,那么就让它来生成不同的蜜罐类型。
于是尝试用gpt来智能生成dockerfile,编写以一个prompt模版来的生成不同的蜜罐类型。
中文:
按找需求编写一个dockerfile,这个dockerfile用于生成一个镜像。
需求的格式为:
- 部署的服务1: 服务描述1, 服务描述2
对于没有服务描述的服务你可以自行判断,下面是我的需求:
英文:
Write a dockerfile according to the requirements, and this dockerfile is used to generate a mirror image.
The required format is:
- Deployed Service 1: Service Description 1, Service Description 2
For services without service descriptions, you can judge by yourself. The following are my requirements:
提出的服务需求随机组合,这里简单准备了两个服务Apache和Nginx,对每个服务有两个描述端口和页面信息:
import random
def random_combine_lists(product, port, detail, num=1):
result = []
for i in range(num):
combined_string = "- {}: {}, {}".format(random.choice(product), random.choice(port), random.choice(detail))
result.append(combined_string)
return result
product = ['Apache', 'nginx']
port = ['This service runs on port 80', 'This service runs on port 8080']
detail = ['Display a 404 page by default', 'Display a background login page by default',]
result = random_combine_lists(product, port, detail)
service = result[0]
在代码中实现:
import openai
openai.api_key = '' # 输入自己的api_key
def get_completion(prompt, model="gpt-3.5-turbo"):
messages = [{"role": "user", "content": prompt}]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=0,
)
return response.choices[0].message["content"]
import random
def random_combine_lists(product, port, detail, num=1):
result = []
for i in range(num):
combined_string = "- {}: {}, {}".format(random.choice(product), random.choice(port), random.choice(detail))
result.append(combined_string)
return result
product = ['Apache', 'nginx']
port = ['This service runs on port 80', 'This service runs on port 8080']
detail = ['Display a 404 page by default', 'Display a background login page by default']
result = random_combine_lists(product, port, detail)
service = result[0]
prompt = f"""Write a dockerfile according to the requirements, and this dockerfile is used to generate a mirror image.
The required format is:
- Deployed Service 1: Service Description 1, Service Description 2
For services without service descriptions, you can judge by yourself. The following are my requirements:
{service}
"""
# print(prompt)
response = get_completion(prompt)
print(response)
乍一看效果还不错?(但其实有大问题

不过先不管,简单封装一下与之前的代码进行组合:honeypottest.py
import os
from gpt import honey_gpt
base_ip = "10.211.55."
num_honeypots = 3
dockerfiles_dir = "/home/hp/dockerfiles"
network_name = "honeypot_net"
network_subnet = "10.211.55.0/24"
network_exists = os.system("docker network inspect {} >/dev/null 2>&1".format(network_name)) == 0
if not network_exists:
os.system("docker network create --driver macvlan --subnet {} --gateway {}1 -o parent=eth0 {}".format(network_subnet, base_ip, network_name))
for i in range(num_honeypots):
ip_address = base_ip + str(i+128)
honeypot_dir = os.path.join(dockerfiles_dir, "honeypot_" + str(i+1))
os.makedirs(honeypot_dir, exist_ok=True)
with open(os.path.join(honeypot_dir, "Dockerfile"), "w") as f:
f.write(honey_gpt())
os.system("docker build -t honeypot_{} {}".format(i+1, honeypot_dir))
os.system("docker run --name honeypot_{} --ip {} --network {} -d honeypot_{}".format(i+1, ip_address, network_name, i+1))
gpt.py
import openai
import random
openai.api_key = 'sk-'
def get_completion(prompt, model="gpt-3.5-turbo"):
messages = [{"role": "user", "content": prompt}]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=0,
)
return response.choices[0].message["content"]
def random_combine_lists(product, port, detail, num=1):
result = []
for i in range(num):
combined_string = "- {}: {}, {}".format(random.choice(product), random.choice(port), random.choice(detail))
result.append(combined_string)
return result
def honey_gpt():
product = ['Apache', 'nginx']
port = ['This service runs on port 80', 'This service runs on port 8080']
detail = ['Display a 404 page by default', 'Display a background login page by default']
result = random_combine_lists(product, port, detail)
service = result[0]
prompt = f"""Write a dockerfile according to the requirements, and this dockerfile is used to generate a mirror image.
The required format is:
- Deployed Service 1: Service Description 1, Service Description 2
For services without service descriptions, you can judge by yourself. The following are my requirements:
{service}
"""
print(service)
response = get_completion(prompt)
return response
问题来了

所有服务都不能访问,看下dockerfile

这里copy本机不存在的文件,既然都智能了这些东西就给gpt做了。修改下prompt
按找需求编写一个dockerfile,这个dockerfile用于生成一个镜像。
需求的格式为:
- 部署的服务1: 服务描述1, 服务描述2
对于没有服务描述的服务你可以自行判断。
这些需求只能在dockerfile中实现,物理机中没有用来可用的任何文件。需求如下:
英文:
Write a dockerfile according to the requirements, and this dockerfile is used to generate a mirror image.
The required format is:
- Deployed Service 1: Service Description 1, Service Description 2
For services without service descriptions, you can judge by yourself.
These requirements can only be realized in the dockerfile, and there are no available files in the physical machine. The requirements are as follows:
生成的dockerfile依然在用COPY

明确不要使用COPY,追加prompt:因此,你无法使用COPY来将物理机中文件复制到容器中。
Write a dockerfile according to the requirements, and this dockerfile is used to generate a mirror image.
The required format is:
- Service 1: Description 1, Description 2
For services without descriptions, you can judge by yourself.
These requirements can only be realized in the dockerfile, and there are no available files in the physical machine. Therefore, you cannot use COPY to copy files from the physical machine to the container.
The requirements are as follows:
感觉好些了

重新运行下。然而并不太行,即使说明不要使用COPY。它写的dockerfile还是有概率出现COPY。怀疑是中间那句you can judge by yourself有干扰,先删了。
再加一句:如果你需要复制一个文件到容器中,你可使用sed在已有文件中插入,或者使用echo直接将内容输出到文件中。更新后的prompt:
prompt = f"""Write a dockerfile according to the requirements, and this dockerfile is used to generate a mirror image.
The required format is:
- Service 1: Description 1, Description 2
Because you don't know what files exist on the physical machine, it is imperative that you DO NOT use the COPY instruction when writing the Dockerfile!
If you need to copy a file into the container, you can use sed to insert it into an existing file, or use echo to output the contents directly into a file.
The requirements are as follows:
{service}
"""
这个prompt后,输出几次后似乎是没有用COPY了,但是在不同端口暴露服务似乎有问题,前面知道我这里用了三个列表来组合一个要求,在product和port相同的情况下,不同的detail居然会写出复杂度两种完全不同的dockerfile。显然第一个无法将服务暴露在8080上。
product = ['Apache', 'nginx']
port = ['This service runs on port 80', 'This service runs on port 8080']
detail = ['Return 404 for all requests', 'Display a background login page']

现在来解决这个问题,怀疑是Display a background login page这种表述有点模糊。
对detail中描述进行进一步的细化Replace the default page with a login page.
然而并不能解决问题。转向port的表述。
服务组合针对测试
两个web服务都暴露在8080端口上,都用一个登录页面作为默认页面的代替。
product = ['Apache', 'nginx']
port = ['This service runs on port 8080']
detail = ['Replace the default page with a login page']
生成的3个dockerfile虽然都是一个很蠢的页面,但用Apache组合的至少端口对了,nginx连端口都没对上。

修改一下port的描述:This service needs to be exposed on port 8080

更简陋了,这次连nginx都没有运行
This service can be accessed through port 8080

搜了一下,发现英语在做这件事的时候,多用的表述为listen。修改prompt:This service is listening on port 8080.

搞定~

两个的404页面也没有什么问题


总结
算简单做了个prompt实验,这种还是只有不断试才能找到个比较理想的。
目前这蜜罐个还是过于简陋了,虽然真实相比差的还挺大,不过感觉GPT做这个还是有点潜力的。
最后记下最终版代码:
gpt.py
import openai
import random
openai.api_key = 'sk-'
def get_completion(prompt, model="gpt-3.5-turbo"):
messages = [{"role": "user", "content": prompt}]
response = openai.ChatCompletion.create(
model=model,
messages=messages,
temperature=0,
)
return response.choices[0].message["content"]
def random_combine_lists(product, port, detail, num=1):
result = []
for i in range(num):
combined_string = "- {}: {}, {}".format(random.choice(product), random.choice(port), random.choice(detail))
result.append(combined_string)
return result
def honey_gpt():
product = ['Apache', 'Nginx']
port = ['This service listens on port 80','This service listens on port 8080']
detail = ['Return 404 for all requests', 'This service listens on port 8080']#, 'Replace the default page with a login page'
result = random_combine_lists(product, port, detail)
service = result[0]
prompt = f"""Write a dockerfile according to the requirements, and this dockerfile is used to generate a mirror image.
The required format is:
- Service 1: Description 1, Description 2
Because you don't know what files exist on the physical machine, it is imperative that you DO NOT use the COPY instruction when writing the Dockerfile!
If you need to copy a file into the container, you can use sed to insert it into an existing file, or use echo to output the contents directly into a file.
The requirements are as follows:
{service}
"""
# print(service)
response = get_completion(prompt)
print(response)
return response
if __name__ == "__main__":
honey_gpt()
honeygpt.py
import os
from gpt import honey_gpt
base_ip = "10.211.55."
num_honeypots = 3
dockerfiles_dir = "/home/hp/dockerfiles"
network_name = "honeypot_net"
network_subnet = "10.211.55.0/24"
network_exists = os.system("docker network inspect {} >/dev/null 2>&1".format(network_name)) == 0
if not network_exists:
os.system("docker network create --driver macvlan --subnet {} --gateway {}1 -o parent=eth0 {}".format(network_subnet, base_ip, network_name))
for i in range(num_honeypots):
ip_address = base_ip + str(i+128)
honeypot_dir = os.path.join(dockerfiles_dir, "honeypot_" + str(i+1))
os.makedirs(honeypot_dir, exist_ok=True)
with open(os.path.join(honeypot_dir, "Dockerfile"), "w") as f:
f.write(honey_gpt())
os.system("docker build -t honeypot_{} {}".format(i+1, honeypot_dir))
os.system("docker run --name honeypot_{} --ip {} --network {} -d honeypot_{}".format(i+1, ip_address, network_name, i+1))