Skip to content

Commit

Permalink
Feat: LLM Honeypot allow specifying the custom prompt #152 (#153)
Browse files Browse the repository at this point in the history
* implement new feature, custom prompt

* Add doc for custom prompt
  • Loading branch information
mariocandela authored Jan 14, 2025
1 parent f1b35e9 commit c3d2ff8
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 22 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,25 @@ plugin:
llmModel: "llama3"
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:
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
Expand Down
1 change: 1 addition & 0 deletions parser/configurations_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ type Plugin struct {
OpenAISecretKey string `yaml:"openAISecretKey"`
Host string `yaml:"host"`
LLMModel string `yaml:"llmModel"`
Prompt string `yaml:"prompt"`
}

// BeelzebubServiceConfiguration is the struct that contains the configurations of the honeypot service
Expand Down
2 changes: 2 additions & 0 deletions parser/configurations_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ plugin:
openAISecretKey: "qwerty"
llmModel: "llama3"
host: "localhost:1563"
prompt: "hello world"
`)
return beelzebubServiceConfiguration, nil
}
Expand Down Expand Up @@ -133,6 +134,7 @@ func TestReadConfigurationsServicesValid(t *testing.T) {
assert.Equal(t, firstBeelzebubServiceConfiguration.Plugin.OpenAISecretKey, "qwerty")
assert.Equal(t, firstBeelzebubServiceConfiguration.Plugin.LLMModel, "llama3")
assert.Equal(t, firstBeelzebubServiceConfiguration.Plugin.Host, "localhost:1563")
assert.Equal(t, firstBeelzebubServiceConfiguration.Plugin.Prompt, "hello world")
}

func TestGelAllFilesNameByDirName(t *testing.T) {
Expand Down
27 changes: 20 additions & 7 deletions plugins/llm-integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ const (
)

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
Model LLMModel
Host string
CustomPrompt string
}

type Choice struct {
Expand Down Expand Up @@ -211,8 +212,20 @@ func (llmHoneypot *LLMHoneypot) ollamaCaller(messages []Message) (string, error)

func (llmHoneypot *LLMHoneypot) ExecuteModel(command string) (string, error) {
var err error
var prompt []Message

prompt, err := buildPrompt(llmHoneypot.Histories, llmHoneypot.Protocol, command)
if llmHoneypot.CustomPrompt != "" {
prompt = append(prompt, Message{
Role: SYSTEM.String(),
Content: llmHoneypot.CustomPrompt,
})
prompt = append(prompt, Message{
Role: USER.String(),
Content: command,
})
} else {
prompt, err = buildPrompt(llmHoneypot.Histories, llmHoneypot.Protocol, command)
}

if err != nil {
return "", err
Expand Down
45 changes: 45 additions & 0 deletions plugins/llm-integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,51 @@ 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", openAIGPTEndpoint,
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: GPT4O,
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{
Expand Down
11 changes: 6 additions & 5 deletions protocols/strategies/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ func (httpStrategy HTTPStrategy) Init(beelzebubServiceConfiguration parser.Beelz
}

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: llmModel,
CustomPrompt: beelzebubServiceConfiguration.Plugin.Prompt,
}

llmHoneypotInstance := plugins.InitLLMHoneypot(llmHoneypot)
Expand Down
22 changes: 12 additions & 10 deletions protocols/strategies/ssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,12 @@ func (sshStrategy *SSHStrategy) Init(beelzebubServiceConfiguration parser.Beelze
}

llmHoneypot := plugins.LLMHoneypot{
Histories: make([]plugins.Message, 0),
OpenAIKey: beelzebubServiceConfiguration.Plugin.OpenAISecretKey,
Protocol: tracer.SSH,
Host: beelzebubServiceConfiguration.Plugin.Host,
Model: llmModel,
Histories: make([]plugins.Message, 0),
OpenAIKey: beelzebubServiceConfiguration.Plugin.OpenAISecretKey,
Protocol: tracer.SSH,
Host: beelzebubServiceConfiguration.Plugin.Host,
Model: llmModel,
CustomPrompt: beelzebubServiceConfiguration.Plugin.Prompt,
}

llmHoneypotInstance := plugins.InitLLMHoneypot(llmHoneypot)
Expand Down Expand Up @@ -137,11 +138,12 @@ func (sshStrategy *SSHStrategy) Init(beelzebubServiceConfiguration parser.Beelze
}

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: llmModel,
CustomPrompt: beelzebubServiceConfiguration.Plugin.Prompt,
}

llmHoneypotInstance := plugins.InitLLMHoneypot(llmHoneypot)
Expand Down

0 comments on commit c3d2ff8

Please sign in to comment.