mirror of
https://github.com/mariocandela/beelzebub.git
synced 2025-07-01 18:47:26 -04:00
Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
38297faed2 | |||
8703d1afda | |||
db804474d3 | |||
48dd70d523 | |||
4813685834 | |||
6f6acb212b | |||
99c7287c02 | |||
c3d2ff885d | |||
f1b35e9e43 | |||
d74499bb37 | |||
5bba406e6b | |||
ec931bd6f9 | |||
b7f7aa0170 | |||
79f9162f24 | |||
24828e503b | |||
acd5aa0e9c | |||
480b734834 | |||
7556c76652 | |||
11421665db | |||
cce0dcfa30 | |||
4740b2b6f5 | |||
27eb88e050 | |||
9eaa503def | |||
f07ce7d3be | |||
a924b2cb8b | |||
8e81a8721e | |||
f40ce9215e | |||
0fc9ebb05e |
32
README.md
32
README.md
@ -211,9 +211,9 @@ commands:
|
||||
|
||||
#### Example SSH Honeypot
|
||||
|
||||
###### Honeypot LLM Honeypots
|
||||
###### LLM Honeypots
|
||||
|
||||
Example with OpenAI GPT-4:
|
||||
Follow a SSH LLM Honeypot using OpenAI as provider LLM:
|
||||
|
||||
```yaml
|
||||
apiVersion: "v1"
|
||||
@ -228,11 +228,12 @@ serverName: "ubuntu"
|
||||
passwordRegex: "^(root|qwerty|Smoker666|123456|jenkins|minecraft|sinus|alex|postgres|Ly123456)$"
|
||||
deadlineTimeoutSeconds: 60
|
||||
plugin:
|
||||
llmModel: "gpt4-o"
|
||||
llmProvider: "openai"
|
||||
llmModel: "gpt4-o" #Models https://platform.openai.com/docs/models
|
||||
openAISecretKey: "sk-proj-123456"
|
||||
```
|
||||
|
||||
Example with Ollama Llama3:
|
||||
Examples with local Ollama instance using model codellama:7b:
|
||||
|
||||
```yaml
|
||||
apiVersion: "v1"
|
||||
@ -247,9 +248,30 @@ serverName: "ubuntu"
|
||||
passwordRegex: "^(root|qwerty|Smoker666|123456|jenkins|minecraft|sinus|alex|postgres|Ly123456)$"
|
||||
deadlineTimeoutSeconds: 60
|
||||
plugin:
|
||||
llmModel: "llama3"
|
||||
llmProvider: "ollama"
|
||||
llmModel: "codellama:7b" #Models https://ollama.com/search
|
||||
host: "http://example.com/api/chat" #default http://localhost:11434/api/chat
|
||||
```
|
||||
Example with custom prompt:
|
||||
|
||||
```yaml
|
||||
apiVersion: "v1"
|
||||
protocol: "ssh"
|
||||
address: ":2222"
|
||||
description: "SSH interactive OpenAI GPT-4"
|
||||
commands:
|
||||
- regex: "^(.+)$"
|
||||
plugin: "LLMHoneypot"
|
||||
serverVersion: "OpenSSH"
|
||||
serverName: "ubuntu"
|
||||
passwordRegex: "^(root|qwerty|Smoker666|123456|jenkins|minecraft|sinus|alex|postgres|Ly123456)$"
|
||||
deadlineTimeoutSeconds: 60
|
||||
plugin:
|
||||
llmProvider: "openai"
|
||||
llmModel: "gpt4-o"
|
||||
openAISecretKey: "sk-proj-123456"
|
||||
prompt: "You will act as an Ubuntu Linux terminal. The user will type commands, and you are to reply with what the terminal should show. Your responses must be contained within a single code block."
|
||||
```
|
||||
|
||||
###### SSH Honeypot on Port 22
|
||||
|
||||
|
@ -7,7 +7,9 @@ commands:
|
||||
plugin: "LLMHoneypot"
|
||||
serverVersion: "OpenSSH"
|
||||
serverName: "ubuntu"
|
||||
passwordRegex: "^(root|qwerty|Smoker666|123456|jenkins|minecraft|sinus|alex|postgres|Ly123456)$"
|
||||
passwordRegex: "^(root|qwerty|Smoker666|123456|jenkins|minecraft|sinus|alex|postgres|Ly123456|1234)$"
|
||||
deadlineTimeoutSeconds: 6000
|
||||
plugin:
|
||||
llmModel: "llama3"
|
||||
llmProvider: "openai"
|
||||
llmModel: "gpt4-o"
|
||||
openAISecretKey: "sk-proj-12345"
|
16
go.mod
16
go.mod
@ -3,16 +3,16 @@ module github.com/mariocandela/beelzebub/v3
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/gliderlabs/ssh v0.3.7
|
||||
github.com/go-resty/resty/v2 v2.14.0
|
||||
github.com/gliderlabs/ssh v0.3.8
|
||||
github.com/go-resty/resty/v2 v2.16.5
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jarcoal/httpmock v1.3.1
|
||||
github.com/melbahja/goph v1.4.0
|
||||
github.com/prometheus/client_golang v1.20.2
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
github.com/rabbitmq/amqp091-go v1.10.0
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/crypto v0.26.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
golang.org/x/crypto v0.33.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
@ -31,8 +31,8 @@ require (
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.55.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
golang.org/x/net v0.27.0 // indirect
|
||||
golang.org/x/sys v0.23.0 // indirect
|
||||
golang.org/x/term v0.23.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/term v0.29.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
)
|
||||
|
69
go.sum
69
go.sum
@ -8,12 +8,11 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||
github.com/go-resty/resty/v2 v2.14.0 h1:/rhkzsAqGQkozwfKS5aFAbb6TyKd3zyFRWcdRXLPCAU=
|
||||
github.com/go-resty/resty/v2 v2.14.0/go.mod h1:IW6mekUOsElt9C7oWr0XRt9BNSD6D5rr9mhk6NjmNHg=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
||||
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jarcoal/httpmock v1.3.1 h1:iUx3whfZWVf3jT01hQTO/Eo5sAYtB2/rqaUuOtpInww=
|
||||
@ -37,8 +36,8 @@ github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go=
|
||||
github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.20.2 h1:5ctymQzZlyOON1666svgwn3s6IKWgfbjsejTMiXIyjg=
|
||||
github.com/prometheus/client_golang v1.20.2/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
@ -52,42 +51,26 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
|
||||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -97,42 +80,22 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM=
|
||||
golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4=
|
||||
golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU=
|
||||
golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk=
|
||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
|
@ -52,6 +52,8 @@ type Plugin struct {
|
||||
OpenAISecretKey string `yaml:"openAISecretKey"`
|
||||
Host string `yaml:"host"`
|
||||
LLMModel string `yaml:"llmModel"`
|
||||
LLMProvider string `yaml:"llmProvider"`
|
||||
Prompt string `yaml:"prompt"`
|
||||
}
|
||||
|
||||
// BeelzebubServiceConfiguration is the struct that contains the configurations of the honeypot service
|
||||
@ -67,6 +69,8 @@ type BeelzebubServiceConfiguration struct {
|
||||
Description string `yaml:"description"`
|
||||
Banner string `yaml:"banner"`
|
||||
Plugin Plugin `yaml:"plugin"`
|
||||
TLSCertPath string `yaml:"tlsCertPath"`
|
||||
TLSKeyPath string `yaml:"tlsKeyPath"`
|
||||
}
|
||||
|
||||
// Command is the struct that contains the configurations of the commands
|
||||
|
@ -49,6 +49,8 @@ func mockReadfilebytesBeelzebubServiceConfiguration(filePath string) ([]byte, er
|
||||
apiVersion: "v1"
|
||||
protocol: "http"
|
||||
address: ":8080"
|
||||
tlsCertPath: "/tmp/cert.crt"
|
||||
tlsKeyPath: "/tmp/cert.key"
|
||||
commands:
|
||||
- regex: "wp-admin"
|
||||
handler: "login"
|
||||
@ -57,7 +59,9 @@ commands:
|
||||
plugin:
|
||||
openAISecretKey: "qwerty"
|
||||
llmModel: "llama3"
|
||||
llmProvider: "ollama"
|
||||
host: "localhost:1563"
|
||||
prompt: "hello world"
|
||||
`)
|
||||
return beelzebubServiceConfiguration, nil
|
||||
}
|
||||
@ -132,7 +136,11 @@ func TestReadConfigurationsServicesValid(t *testing.T) {
|
||||
assert.Equal(t, firstBeelzebubServiceConfiguration.Commands[0].Headers[0], "Content-Type: text/html")
|
||||
assert.Equal(t, firstBeelzebubServiceConfiguration.Plugin.OpenAISecretKey, "qwerty")
|
||||
assert.Equal(t, firstBeelzebubServiceConfiguration.Plugin.LLMModel, "llama3")
|
||||
assert.Equal(t, firstBeelzebubServiceConfiguration.Plugin.LLMProvider, "ollama")
|
||||
assert.Equal(t, firstBeelzebubServiceConfiguration.Plugin.Host, "localhost:1563")
|
||||
assert.Equal(t, firstBeelzebubServiceConfiguration.Plugin.Prompt, "hello world")
|
||||
assert.Equal(t, firstBeelzebubServiceConfiguration.TLSCertPath, "/tmp/cert.crt")
|
||||
assert.Equal(t, firstBeelzebubServiceConfiguration.TLSKeyPath, "/tmp/cert.key")
|
||||
}
|
||||
|
||||
func TestGelAllFilesNameByDirName(t *testing.T) {
|
||||
|
@ -6,25 +6,28 @@ import (
|
||||
"fmt"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/mariocandela/beelzebub/v3/tracer"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
systemPromptVirtualizeLinuxTerminal = "You will act as an Ubuntu Linux terminal. The user will type commands, and you are to reply with what the terminal should show. Your responses must be contained within a single code block. Do not provide explanations or type commands unless explicitly instructed by the user. Your entire response/output is going to consist of a simple text with \n for new line, and you will NOT wrap it within string md markers"
|
||||
systemPromptVirtualizeLinuxTerminal = "You will act as an Ubuntu Linux terminal. The user will type commands, and you are to reply with what the terminal should show. Your responses must be contained within a single code block. Do not provide note. Do not provide explanations or type commands unless explicitly instructed by the user. Your entire response/output is going to consist of a simple text with \n for new line, and you will NOT wrap it within string md markers"
|
||||
systemPromptVirtualizeHTTPServer = "You will act as an unsecure HTTP Server with multiple vulnerability like aws and git credentials stored into root http directory. The user will send HTTP requests, and you are to reply with what the server should show. Do not provide explanations or type commands unless explicitly instructed by the user."
|
||||
LLMPluginName = "LLMHoneypot"
|
||||
openAIGPTEndpoint = "https://api.openai.com/v1/chat/completions"
|
||||
openAIEndpoint = "https://api.openai.com/v1/chat/completions"
|
||||
ollamaEndpoint = "http://localhost:11434/api/chat"
|
||||
)
|
||||
|
||||
type LLMHoneypot struct {
|
||||
Histories []Message
|
||||
OpenAIKey string
|
||||
client *resty.Client
|
||||
Protocol tracer.Protocol
|
||||
Model LLMModel
|
||||
Host string
|
||||
Histories []Message
|
||||
OpenAIKey string
|
||||
client *resty.Client
|
||||
Protocol tracer.Protocol
|
||||
Provider LLMProvider
|
||||
Model string
|
||||
Host string
|
||||
CustomPrompt string
|
||||
}
|
||||
|
||||
type Choice struct {
|
||||
@ -70,21 +73,21 @@ func (role Role) String() string {
|
||||
return [...]string{"system", "user", "assistant"}[role]
|
||||
}
|
||||
|
||||
type LLMModel int
|
||||
type LLMProvider int
|
||||
|
||||
const (
|
||||
LLAMA3 LLMModel = iota
|
||||
GPT4O
|
||||
Ollama LLMProvider = iota
|
||||
OpenAI
|
||||
)
|
||||
|
||||
func FromStringToLLMModel(llmModel string) (LLMModel, error) {
|
||||
switch llmModel {
|
||||
case "llama3":
|
||||
return LLAMA3, nil
|
||||
case "gpt4-o":
|
||||
return GPT4O, nil
|
||||
func FromStringToLLMProvider(llmProvider string) (LLMProvider, error) {
|
||||
switch strings.ToLower(llmProvider) {
|
||||
case "ollama":
|
||||
return Ollama, nil
|
||||
case "openai":
|
||||
return OpenAI, nil
|
||||
default:
|
||||
return -1, fmt.Errorf("model %s not found", llmModel)
|
||||
return -1, fmt.Errorf("provider %s not found, valid providers: ollama, openai", llmProvider)
|
||||
}
|
||||
}
|
||||
|
||||
@ -95,14 +98,19 @@ func InitLLMHoneypot(config LLMHoneypot) *LLMHoneypot {
|
||||
return &config
|
||||
}
|
||||
|
||||
func buildPrompt(histories []Message, protocol tracer.Protocol, command string) ([]Message, error) {
|
||||
func (llmHoneypot *LLMHoneypot) buildPrompt(command string) ([]Message, error) {
|
||||
var messages []Message
|
||||
var prompt string
|
||||
|
||||
switch protocol {
|
||||
switch llmHoneypot.Protocol {
|
||||
case tracer.SSH:
|
||||
prompt = systemPromptVirtualizeLinuxTerminal
|
||||
if llmHoneypot.CustomPrompt != "" {
|
||||
prompt = llmHoneypot.CustomPrompt
|
||||
}
|
||||
messages = append(messages, Message{
|
||||
Role: SYSTEM.String(),
|
||||
Content: systemPromptVirtualizeLinuxTerminal,
|
||||
Content: prompt,
|
||||
})
|
||||
messages = append(messages, Message{
|
||||
Role: USER.String(),
|
||||
@ -112,13 +120,17 @@ func buildPrompt(histories []Message, protocol tracer.Protocol, command string)
|
||||
Role: ASSISTANT.String(),
|
||||
Content: "/home/user",
|
||||
})
|
||||
for _, history := range histories {
|
||||
for _, history := range llmHoneypot.Histories {
|
||||
messages = append(messages, history)
|
||||
}
|
||||
case tracer.HTTP:
|
||||
prompt = systemPromptVirtualizeHTTPServer
|
||||
if llmHoneypot.CustomPrompt != "" {
|
||||
prompt = llmHoneypot.CustomPrompt
|
||||
}
|
||||
messages = append(messages, Message{
|
||||
Role: SYSTEM.String(),
|
||||
Content: systemPromptVirtualizeHTTPServer,
|
||||
Content: prompt,
|
||||
})
|
||||
messages = append(messages, Message{
|
||||
Role: USER.String(),
|
||||
@ -143,7 +155,7 @@ func (llmHoneypot *LLMHoneypot) openAICaller(messages []Message) (string, error)
|
||||
var err error
|
||||
|
||||
requestJson, err := json.Marshal(Request{
|
||||
Model: "gpt-4o",
|
||||
Model: llmHoneypot.Model,
|
||||
Messages: messages,
|
||||
Stream: false,
|
||||
})
|
||||
@ -156,7 +168,7 @@ func (llmHoneypot *LLMHoneypot) openAICaller(messages []Message) (string, error)
|
||||
}
|
||||
|
||||
if llmHoneypot.Host == "" {
|
||||
llmHoneypot.Host = openAIGPTEndpoint
|
||||
llmHoneypot.Host = openAIEndpoint
|
||||
}
|
||||
|
||||
log.Debug(string(requestJson))
|
||||
@ -175,14 +187,14 @@ func (llmHoneypot *LLMHoneypot) openAICaller(messages []Message) (string, error)
|
||||
return "", errors.New("no choices")
|
||||
}
|
||||
|
||||
return response.Result().(*Response).Choices[0].Message.Content, nil
|
||||
return removeQuotes(response.Result().(*Response).Choices[0].Message.Content), nil
|
||||
}
|
||||
|
||||
func (llmHoneypot *LLMHoneypot) ollamaCaller(messages []Message) (string, error) {
|
||||
var err error
|
||||
|
||||
requestJson, err := json.Marshal(Request{
|
||||
Model: "llama3",
|
||||
Model: llmHoneypot.Model,
|
||||
Messages: messages,
|
||||
Stream: false,
|
||||
})
|
||||
@ -206,24 +218,30 @@ func (llmHoneypot *LLMHoneypot) ollamaCaller(messages []Message) (string, error)
|
||||
}
|
||||
log.Debug(response)
|
||||
|
||||
return response.Result().(*Response).Message.Content, nil
|
||||
return removeQuotes(response.Result().(*Response).Message.Content), nil
|
||||
}
|
||||
|
||||
func (llmHoneypot *LLMHoneypot) ExecuteModel(command string) (string, error) {
|
||||
var err error
|
||||
var prompt []Message
|
||||
|
||||
prompt, err := buildPrompt(llmHoneypot.Histories, llmHoneypot.Protocol, command)
|
||||
prompt, err = llmHoneypot.buildPrompt(command)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch llmHoneypot.Model {
|
||||
case LLAMA3:
|
||||
switch llmHoneypot.Provider {
|
||||
case Ollama:
|
||||
return llmHoneypot.ollamaCaller(prompt)
|
||||
case GPT4O:
|
||||
case OpenAI:
|
||||
return llmHoneypot.openAICaller(prompt)
|
||||
default:
|
||||
return "", errors.New("no model selected")
|
||||
return "", fmt.Errorf("provider %d not found, valid providers: ollama, openai", llmHoneypot.Provider)
|
||||
}
|
||||
}
|
||||
|
||||
func removeQuotes(content string) string {
|
||||
regex := regexp.MustCompile("(```( *)?([a-z]*)?(\\n)?)")
|
||||
return regex.ReplaceAllString(content, "")
|
||||
}
|
||||
|
@ -16,8 +16,13 @@ func TestBuildPromptEmptyHistory(t *testing.T) {
|
||||
var histories []Message
|
||||
command := "pwd"
|
||||
|
||||
honeypot := LLMHoneypot{
|
||||
Histories: histories,
|
||||
Protocol: tracer.SSH,
|
||||
}
|
||||
|
||||
//When
|
||||
prompt, err := buildPrompt(histories, tracer.SSH, command)
|
||||
prompt, err := honeypot.buildPrompt(command)
|
||||
|
||||
//Then
|
||||
assert.Nil(t, err)
|
||||
@ -35,21 +40,53 @@ func TestBuildPromptWithHistory(t *testing.T) {
|
||||
|
||||
command := "pwd"
|
||||
|
||||
honeypot := LLMHoneypot{
|
||||
Histories: histories,
|
||||
Protocol: tracer.SSH,
|
||||
}
|
||||
|
||||
//When
|
||||
prompt, err := buildPrompt(histories, tracer.SSH, command)
|
||||
prompt, err := honeypot.buildPrompt(command)
|
||||
|
||||
//Then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, SystemPromptLen+1, len(prompt))
|
||||
}
|
||||
|
||||
func TestBuildPromptWithCustomPrompt(t *testing.T) {
|
||||
//Given
|
||||
var histories = []Message{
|
||||
{
|
||||
Role: "cat hello.txt",
|
||||
Content: "world",
|
||||
},
|
||||
}
|
||||
|
||||
command := "pwd"
|
||||
|
||||
honeypot := LLMHoneypot{
|
||||
Histories: histories,
|
||||
Protocol: tracer.SSH,
|
||||
CustomPrompt: "act as calculator",
|
||||
}
|
||||
|
||||
//When
|
||||
prompt, err := honeypot.buildPrompt(command)
|
||||
|
||||
//Then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, prompt[0].Content, "act as calculator")
|
||||
assert.Equal(t, prompt[0].Role, SYSTEM.String())
|
||||
}
|
||||
|
||||
func TestBuildExecuteModelFailValidation(t *testing.T) {
|
||||
|
||||
llmHoneypot := LLMHoneypot{
|
||||
Histories: make([]Message, 0),
|
||||
OpenAIKey: "",
|
||||
Protocol: tracer.SSH,
|
||||
Model: GPT4O,
|
||||
Model: "gpt4-o",
|
||||
Provider: OpenAI,
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
@ -59,13 +96,60 @@ func TestBuildExecuteModelFailValidation(t *testing.T) {
|
||||
assert.Equal(t, "openAIKey is empty", err.Error())
|
||||
}
|
||||
|
||||
func TestBuildExecuteModelWithCustomPrompt(t *testing.T) {
|
||||
client := resty.New()
|
||||
httpmock.ActivateNonDefault(client.GetClient())
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
// Given
|
||||
httpmock.RegisterMatcherResponder("POST", openAIEndpoint,
|
||||
httpmock.BodyContainsString("hello world"),
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
resp, err := httpmock.NewJsonResponse(200, &Response{
|
||||
Choices: []Choice{
|
||||
{
|
||||
Message: Message{
|
||||
Role: SYSTEM.String(),
|
||||
Content: "[default]\nregion = us-west-2\noutput = json",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return httpmock.NewStringResponse(500, ""), nil
|
||||
}
|
||||
return resp, nil
|
||||
},
|
||||
)
|
||||
|
||||
llmHoneypot := LLMHoneypot{
|
||||
Histories: make([]Message, 0),
|
||||
OpenAIKey: "sdjdnklfjndslkjanfk",
|
||||
Protocol: tracer.HTTP,
|
||||
Model: "gpt4-o",
|
||||
Provider: OpenAI,
|
||||
CustomPrompt: "hello world",
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
openAIGPTVirtualTerminal.client = client
|
||||
|
||||
//When
|
||||
str, err := openAIGPTVirtualTerminal.ExecuteModel("GET /.aws/credentials")
|
||||
|
||||
//Then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "[default]\nregion = us-west-2\noutput = json", str)
|
||||
}
|
||||
|
||||
func TestBuildExecuteModelFailValidationStrategyType(t *testing.T) {
|
||||
|
||||
llmHoneypot := LLMHoneypot{
|
||||
Histories: make([]Message, 0),
|
||||
OpenAIKey: "",
|
||||
Protocol: tracer.TCP,
|
||||
Model: GPT4O,
|
||||
Model: "gpt4-o",
|
||||
Provider: OpenAI,
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
@ -80,7 +164,8 @@ func TestBuildExecuteModelFailValidationModelType(t *testing.T) {
|
||||
llmHoneypot := LLMHoneypot{
|
||||
Histories: make([]Message, 0),
|
||||
Protocol: tracer.SSH,
|
||||
Model: 5,
|
||||
Model: "llama3",
|
||||
Provider: 5,
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
@ -98,7 +183,7 @@ func TestBuildExecuteModelSSHWithResultsOpenAI(t *testing.T) {
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
// Given
|
||||
httpmock.RegisterResponder("POST", openAIGPTEndpoint,
|
||||
httpmock.RegisterResponder("POST", openAIEndpoint,
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
resp, err := httpmock.NewJsonResponse(200, &Response{
|
||||
Choices: []Choice{
|
||||
@ -121,7 +206,8 @@ func TestBuildExecuteModelSSHWithResultsOpenAI(t *testing.T) {
|
||||
Histories: make([]Message, 0),
|
||||
OpenAIKey: "sdjdnklfjndslkjanfk",
|
||||
Protocol: tracer.SSH,
|
||||
Model: GPT4O,
|
||||
Model: "gpt4-o",
|
||||
Provider: OpenAI,
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
@ -159,7 +245,8 @@ func TestBuildExecuteModelSSHWithResultsLLama(t *testing.T) {
|
||||
llmHoneypot := LLMHoneypot{
|
||||
Histories: make([]Message, 0),
|
||||
Protocol: tracer.SSH,
|
||||
Model: LLAMA3,
|
||||
Model: "llama3",
|
||||
Provider: Ollama,
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
@ -179,7 +266,7 @@ func TestBuildExecuteModelSSHWithoutResults(t *testing.T) {
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
// Given
|
||||
httpmock.RegisterResponder("POST", openAIGPTEndpoint,
|
||||
httpmock.RegisterResponder("POST", openAIEndpoint,
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
resp, err := httpmock.NewJsonResponse(200, &Response{
|
||||
Choices: []Choice{},
|
||||
@ -195,7 +282,8 @@ func TestBuildExecuteModelSSHWithoutResults(t *testing.T) {
|
||||
Histories: make([]Message, 0),
|
||||
OpenAIKey: "sdjdnklfjndslkjanfk",
|
||||
Protocol: tracer.SSH,
|
||||
Model: GPT4O,
|
||||
Model: "gpt4-o",
|
||||
Provider: OpenAI,
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
@ -214,7 +302,7 @@ func TestBuildExecuteModelHTTPWithResults(t *testing.T) {
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
// Given
|
||||
httpmock.RegisterResponder("POST", openAIGPTEndpoint,
|
||||
httpmock.RegisterResponder("POST", openAIEndpoint,
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
resp, err := httpmock.NewJsonResponse(200, &Response{
|
||||
Choices: []Choice{
|
||||
@ -237,7 +325,8 @@ func TestBuildExecuteModelHTTPWithResults(t *testing.T) {
|
||||
Histories: make([]Message, 0),
|
||||
OpenAIKey: "sdjdnklfjndslkjanfk",
|
||||
Protocol: tracer.HTTP,
|
||||
Model: GPT4O,
|
||||
Model: "gpt4-o",
|
||||
Provider: OpenAI,
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
@ -257,7 +346,7 @@ func TestBuildExecuteModelHTTPWithoutResults(t *testing.T) {
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
// Given
|
||||
httpmock.RegisterResponder("POST", openAIGPTEndpoint,
|
||||
httpmock.RegisterResponder("POST", openAIEndpoint,
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
resp, err := httpmock.NewJsonResponse(200, &Response{
|
||||
Choices: []Choice{},
|
||||
@ -273,7 +362,8 @@ func TestBuildExecuteModelHTTPWithoutResults(t *testing.T) {
|
||||
Histories: make([]Message, 0),
|
||||
OpenAIKey: "sdjdnklfjndslkjanfk",
|
||||
Protocol: tracer.HTTP,
|
||||
Model: GPT4O,
|
||||
Model: "gpt4-o",
|
||||
Provider: OpenAI,
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
@ -287,14 +377,105 @@ func TestBuildExecuteModelHTTPWithoutResults(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFromString(t *testing.T) {
|
||||
model, err := FromStringToLLMModel("llama3")
|
||||
model, err := FromStringToLLMProvider("openai")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, LLAMA3, model)
|
||||
assert.Equal(t, OpenAI, model)
|
||||
|
||||
model, err = FromStringToLLMModel("gpt4-o")
|
||||
model, err = FromStringToLLMProvider("ollama")
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, GPT4O, model)
|
||||
assert.Equal(t, Ollama, model)
|
||||
|
||||
model, err = FromStringToLLMModel("beelzebub-model")
|
||||
assert.Errorf(t, err, "model beelzebub-model not found")
|
||||
model, err = FromStringToLLMProvider("beelzebub-model")
|
||||
assert.Errorf(t, err, "provider beelzebub-model not found")
|
||||
}
|
||||
|
||||
func TestBuildExecuteModelSSHWithoutPlaintextSection(t *testing.T) {
|
||||
client := resty.New()
|
||||
httpmock.ActivateNonDefault(client.GetClient())
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
// Given
|
||||
httpmock.RegisterResponder("POST", ollamaEndpoint,
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
resp, err := httpmock.NewJsonResponse(200, &Response{
|
||||
Message: Message{
|
||||
Role: SYSTEM.String(),
|
||||
Content: "```plaintext\n```\n",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return httpmock.NewStringResponse(500, ""), nil
|
||||
}
|
||||
return resp, nil
|
||||
},
|
||||
)
|
||||
|
||||
llmHoneypot := LLMHoneypot{
|
||||
Histories: make([]Message, 0),
|
||||
Protocol: tracer.SSH,
|
||||
Model: "llama3",
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
openAIGPTVirtualTerminal.client = client
|
||||
|
||||
//When
|
||||
str, err := openAIGPTVirtualTerminal.ExecuteModel("ls")
|
||||
|
||||
//Then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "", str)
|
||||
}
|
||||
|
||||
func TestBuildExecuteModelSSHWithoutQuotesSection(t *testing.T) {
|
||||
client := resty.New()
|
||||
httpmock.ActivateNonDefault(client.GetClient())
|
||||
defer httpmock.DeactivateAndReset()
|
||||
|
||||
// Given
|
||||
httpmock.RegisterResponder("POST", ollamaEndpoint,
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
resp, err := httpmock.NewJsonResponse(200, &Response{
|
||||
Message: Message{
|
||||
Role: SYSTEM.String(),
|
||||
Content: "```\n```\n",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return httpmock.NewStringResponse(500, ""), nil
|
||||
}
|
||||
return resp, nil
|
||||
},
|
||||
)
|
||||
|
||||
llmHoneypot := LLMHoneypot{
|
||||
Histories: make([]Message, 0),
|
||||
Protocol: tracer.SSH,
|
||||
Model: "llama3",
|
||||
Provider: Ollama,
|
||||
}
|
||||
|
||||
openAIGPTVirtualTerminal := InitLLMHoneypot(llmHoneypot)
|
||||
openAIGPTVirtualTerminal.client = client
|
||||
|
||||
//When
|
||||
str, err := openAIGPTVirtualTerminal.ExecuteModel("ls")
|
||||
|
||||
//Then
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "", str)
|
||||
}
|
||||
|
||||
func TestRemoveQuotes(t *testing.T) {
|
||||
plaintext := "```plaintext\n```"
|
||||
bash := "```bash\n```"
|
||||
onlyQuotes := "```\n```"
|
||||
complexText := "```plaintext\ntop - 10:30:48 up 1 day, 4:30, 2 users, load average: 0.15, 0.10, 0.08\nTasks: 198 total, 1 running, 197 sleeping, 0 stopped, 0 zombie\n```"
|
||||
complexText2 := "```\ntop - 15:06:59 up 10 days, 3:17, 1 user, load average: 0.10, 0.09, 0.08\nTasks: 285 total\n```"
|
||||
|
||||
assert.Equal(t, "", removeQuotes(plaintext))
|
||||
assert.Equal(t, "", removeQuotes(bash))
|
||||
assert.Equal(t, "", removeQuotes(onlyQuotes))
|
||||
assert.Equal(t, "top - 10:30:48 up 1 day, 4:30, 2 users, load average: 0.15, 0.10, 0.08\nTasks: 198 total, 1 running, 197 sleeping, 0 stopped, 0 zombie\n", removeQuotes(complexText))
|
||||
assert.Equal(t, "top - 15:06:59 up 10 days, 3:17, 1 user, load average: 0.10, 0.09, 0.08\nTasks: 285 total\n", removeQuotes(complexText2))
|
||||
}
|
||||
|
@ -2,9 +2,6 @@ package strategies
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/mariocandela/beelzebub/v3/parser"
|
||||
"github.com/mariocandela/beelzebub/v3/plugins"
|
||||
"github.com/mariocandela/beelzebub/v3/tracer"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
@ -12,6 +9,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/mariocandela/beelzebub/v3/parser"
|
||||
"github.com/mariocandela/beelzebub/v3/plugins"
|
||||
"github.com/mariocandela/beelzebub/v3/tracer"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -37,19 +37,21 @@ func (httpStrategy HTTPStrategy) Init(beelzebubServiceConfiguration parser.Beelz
|
||||
|
||||
if command.Plugin == plugins.LLMPluginName {
|
||||
|
||||
llmModel, err := plugins.FromStringToLLMModel(beelzebubServiceConfiguration.Plugin.LLMModel)
|
||||
llmProvider, err := plugins.FromStringToLLMProvider(beelzebubServiceConfiguration.Plugin.LLMProvider)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Error fromString: %s", err.Error())
|
||||
log.Errorf("Error: %s", err.Error())
|
||||
responseHTTPBody = "404 Not Found!"
|
||||
}
|
||||
|
||||
llmHoneypot := plugins.LLMHoneypot{
|
||||
Histories: make([]plugins.Message, 0),
|
||||
OpenAIKey: beelzebubServiceConfiguration.Plugin.OpenAISecretKey,
|
||||
Protocol: tracer.HTTP,
|
||||
Host: beelzebubServiceConfiguration.Plugin.Host,
|
||||
Model: llmModel,
|
||||
Histories: make([]plugins.Message, 0),
|
||||
OpenAIKey: beelzebubServiceConfiguration.Plugin.OpenAISecretKey,
|
||||
Protocol: tracer.HTTP,
|
||||
Host: beelzebubServiceConfiguration.Plugin.Host,
|
||||
Model: beelzebubServiceConfiguration.Plugin.LLMModel,
|
||||
Provider: llmProvider,
|
||||
CustomPrompt: beelzebubServiceConfiguration.Plugin.Prompt,
|
||||
}
|
||||
|
||||
llmHoneypotInstance := plugins.InitLLMHoneypot(llmHoneypot)
|
||||
@ -66,13 +68,25 @@ func (httpStrategy HTTPStrategy) Init(beelzebubServiceConfiguration parser.Beelz
|
||||
}
|
||||
|
||||
setResponseHeaders(responseWriter, command.Headers, command.StatusCode)
|
||||
fmt.Fprintf(responseWriter, responseHTTPBody)
|
||||
fmt.Fprint(responseWriter, responseHTTPBody)
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
go func() {
|
||||
err := http.ListenAndServe(httpStrategy.beelzebubServiceConfiguration.Address, serverMux)
|
||||
var err error
|
||||
// Launch a TLS supporting server if we are supplied a TLS Key and Certificate.
|
||||
// If relative paths are supplied, they are relative to the CWD of the binary.
|
||||
// The can be self-signed, only the client will validate this (or not).
|
||||
if httpStrategy.beelzebubServiceConfiguration.TLSKeyPath != "" && httpStrategy.beelzebubServiceConfiguration.TLSCertPath != "" {
|
||||
err = http.ListenAndServeTLS(
|
||||
httpStrategy.beelzebubServiceConfiguration.Address,
|
||||
httpStrategy.beelzebubServiceConfiguration.TLSCertPath,
|
||||
httpStrategy.beelzebubServiceConfiguration.TLSKeyPath,
|
||||
serverMux)
|
||||
} else {
|
||||
err = http.ListenAndServe(httpStrategy.beelzebubServiceConfiguration.Address, serverMux)
|
||||
}
|
||||
if err != nil {
|
||||
log.Errorf("Error during init HTTP Protocol: %s", err.Error())
|
||||
return
|
||||
@ -94,7 +108,7 @@ func traceRequest(request *http.Request, tr tracer.Tracer, HoneypotDescription s
|
||||
}
|
||||
host, port, _ := net.SplitHostPort(request.RemoteAddr)
|
||||
|
||||
tr.TraceEvent(tracer.Event{
|
||||
event := tracer.Event{
|
||||
Msg: "HTTP New request",
|
||||
RequestURI: request.RequestURI,
|
||||
Protocol: tracer.HTTP.String(),
|
||||
@ -110,7 +124,13 @@ func traceRequest(request *http.Request, tr tracer.Tracer, HoneypotDescription s
|
||||
SourcePort: port,
|
||||
ID: uuid.New().String(),
|
||||
Description: HoneypotDescription,
|
||||
})
|
||||
}
|
||||
// Capture the TLS details from the request, if provided.
|
||||
if request.TLS != nil {
|
||||
event.Msg = "HTTPS New Request"
|
||||
event.TLSServerName = request.TLS.ServerName
|
||||
}
|
||||
tr.TraceEvent(event)
|
||||
}
|
||||
|
||||
func mapHeaderToString(headers http.Header) string {
|
||||
|
@ -31,6 +31,71 @@ func (sshStrategy *SSHStrategy) Init(beelzebubServiceConfiguration parser.Beelze
|
||||
|
||||
host, port, _ := net.SplitHostPort(sess.RemoteAddr().String())
|
||||
|
||||
if sess.RawCommand() != "" {
|
||||
for _, command := range beelzebubServiceConfiguration.Commands {
|
||||
matched, err := regexp.MatchString(command.Regex, sess.RawCommand())
|
||||
if err != nil {
|
||||
log.Errorf("Error regex: %s, %s", command.Regex, err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
if matched {
|
||||
commandOutput := command.Handler
|
||||
|
||||
if command.Plugin == plugins.LLMPluginName {
|
||||
|
||||
llmProvider, err := plugins.FromStringToLLMProvider(beelzebubServiceConfiguration.Plugin.LLMProvider)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Error: %s", err.Error())
|
||||
commandOutput = "command not found"
|
||||
llmProvider = plugins.OpenAI
|
||||
}
|
||||
|
||||
llmHoneypot := plugins.LLMHoneypot{
|
||||
Histories: make([]plugins.Message, 0),
|
||||
OpenAIKey: beelzebubServiceConfiguration.Plugin.OpenAISecretKey,
|
||||
Protocol: tracer.SSH,
|
||||
Host: beelzebubServiceConfiguration.Plugin.Host,
|
||||
Model: beelzebubServiceConfiguration.Plugin.LLMProvider,
|
||||
Provider: llmProvider,
|
||||
CustomPrompt: beelzebubServiceConfiguration.Plugin.Prompt,
|
||||
}
|
||||
|
||||
llmHoneypotInstance := plugins.InitLLMHoneypot(llmHoneypot)
|
||||
|
||||
if commandOutput, err = llmHoneypotInstance.ExecuteModel(sess.RawCommand()); err != nil {
|
||||
log.Errorf("Error ExecuteModel: %s, %s", sess.RawCommand(), err.Error())
|
||||
commandOutput = "command not found"
|
||||
}
|
||||
}
|
||||
|
||||
sess.Write(append([]byte(commandOutput), '\n'))
|
||||
|
||||
tr.TraceEvent(tracer.Event{
|
||||
Msg: "New SSH Session",
|
||||
Protocol: tracer.SSH.String(),
|
||||
RemoteAddr: sess.RemoteAddr().String(),
|
||||
SourceIp: host,
|
||||
SourcePort: port,
|
||||
Status: tracer.Start.String(),
|
||||
ID: uuidSession.String(),
|
||||
Environ: strings.Join(sess.Environ(), ","),
|
||||
User: sess.User(),
|
||||
Description: beelzebubServiceConfiguration.Description,
|
||||
Command: sess.RawCommand(),
|
||||
CommandOutput: commandOutput,
|
||||
})
|
||||
tr.TraceEvent(tracer.Event{
|
||||
Msg: "End SSH Session",
|
||||
Status: tracer.End.String(),
|
||||
ID: uuidSession.String(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tr.TraceEvent(tracer.Event{
|
||||
Msg: "New SSH Session",
|
||||
Protocol: tracer.SSH.String(),
|
||||
@ -42,7 +107,6 @@ func (sshStrategy *SSHStrategy) Init(beelzebubServiceConfiguration parser.Beelze
|
||||
Environ: strings.Join(sess.Environ(), ","),
|
||||
User: sess.User(),
|
||||
Description: beelzebubServiceConfiguration.Description,
|
||||
Command: sess.RawCommand(),
|
||||
})
|
||||
|
||||
term := terminal.NewTerminal(sess, buildPrompt(sess.User(), beelzebubServiceConfiguration.ServerName))
|
||||
@ -68,19 +132,21 @@ func (sshStrategy *SSHStrategy) Init(beelzebubServiceConfiguration parser.Beelze
|
||||
|
||||
if command.Plugin == plugins.LLMPluginName {
|
||||
|
||||
llmModel, err := plugins.FromStringToLLMModel(beelzebubServiceConfiguration.Plugin.LLMModel)
|
||||
llmProvider, err := plugins.FromStringToLLMProvider(beelzebubServiceConfiguration.Plugin.LLMProvider)
|
||||
|
||||
if err != nil {
|
||||
log.Errorf("Error fromString: %s", err.Error())
|
||||
commandOutput = "command not found"
|
||||
log.Errorf("Error: %s, fallback OpenAI", err.Error())
|
||||
llmProvider = plugins.OpenAI
|
||||
}
|
||||
|
||||
llmHoneypot := plugins.LLMHoneypot{
|
||||
Histories: histories,
|
||||
OpenAIKey: beelzebubServiceConfiguration.Plugin.OpenAISecretKey,
|
||||
Protocol: tracer.SSH,
|
||||
Host: beelzebubServiceConfiguration.Plugin.Host,
|
||||
Model: llmModel,
|
||||
Histories: histories,
|
||||
OpenAIKey: beelzebubServiceConfiguration.Plugin.OpenAISecretKey,
|
||||
Protocol: tracer.SSH,
|
||||
Host: beelzebubServiceConfiguration.Plugin.Host,
|
||||
Model: beelzebubServiceConfiguration.Plugin.LLMModel,
|
||||
Provider: llmProvider,
|
||||
CustomPrompt: beelzebubServiceConfiguration.Plugin.Prompt,
|
||||
}
|
||||
|
||||
llmHoneypotInstance := plugins.InitLLMHoneypot(llmHoneypot)
|
||||
|
@ -2,10 +2,11 @@
|
||||
package tracer
|
||||
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
)
|
||||
@ -36,6 +37,7 @@ type Event struct {
|
||||
Description string
|
||||
SourceIp string
|
||||
SourcePort string
|
||||
TLSServerName string
|
||||
}
|
||||
|
||||
type (
|
||||
|
Reference in New Issue
Block a user