From 99c51938895012bd55322856c4ff6522f6f624aa Mon Sep 17 00:00:00 2001 From: Mario Date: Sat, 2 Jul 2022 22:58:39 +0200 Subject: [PATCH 1/3] Added configuration file --- configurations/beelzebub.yaml | 4 ++-- configurations/services/tcp-3306.yaml | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 configurations/services/tcp-3306.yaml diff --git a/configurations/beelzebub.yaml b/configurations/beelzebub.yaml index 5b2fe43..6d8597a 100644 --- a/configurations/beelzebub.yaml +++ b/configurations/beelzebub.yaml @@ -5,5 +5,5 @@ core: logDisableTimestamp: true logsPath: ./logs tracing: - rabbitMQEnabled: false - rabbitMQURI: "" + rabbitMQEnabled: true + rabbitMQURI: "amqp://beelzebub:b33lz3b4b@localhost:8888/" diff --git a/configurations/services/tcp-3306.yaml b/configurations/services/tcp-3306.yaml new file mode 100644 index 0000000..d15ce20 --- /dev/null +++ b/configurations/services/tcp-3306.yaml @@ -0,0 +1,7 @@ +apiVersion: "v1" +protocol: "tcp" +address: ":3306" +description: "Mysql" +commands: + - regex: "hello" + handler: "WORLD" \ No newline at end of file From 39a23b007537efce10ea6334a91bee5eb179159a Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 3 Jul 2022 12:39:27 +0200 Subject: [PATCH 2/3] Improve initial TCP honeypot structure --- configurations/beelzebub.yaml | 4 +- configurations/services/tcp-3306.yaml | 5 +- parser/configurationsParser.go | 1 + .../transmissionControlProtocolStrategy.go | 49 +++++++++++++++++++ 4 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 protocols/transmissionControlProtocolStrategy.go diff --git a/configurations/beelzebub.yaml b/configurations/beelzebub.yaml index 6d8597a..5b2fe43 100644 --- a/configurations/beelzebub.yaml +++ b/configurations/beelzebub.yaml @@ -5,5 +5,5 @@ core: logDisableTimestamp: true logsPath: ./logs tracing: - rabbitMQEnabled: true - rabbitMQURI: "amqp://beelzebub:b33lz3b4b@localhost:8888/" + rabbitMQEnabled: false + rabbitMQURI: "" diff --git a/configurations/services/tcp-3306.yaml b/configurations/services/tcp-3306.yaml index d15ce20..3e66c4b 100644 --- a/configurations/services/tcp-3306.yaml +++ b/configurations/services/tcp-3306.yaml @@ -2,6 +2,5 @@ apiVersion: "v1" protocol: "tcp" address: ":3306" description: "Mysql" -commands: - - regex: "hello" - handler: "WORLD" \ No newline at end of file +banner: "mysql 4.0" +deadlineTimeoutSeconds: 60 \ No newline at end of file diff --git a/parser/configurationsParser.go b/parser/configurationsParser.go index 8b5e837..11d375f 100644 --- a/parser/configurationsParser.go +++ b/parser/configurationsParser.go @@ -38,6 +38,7 @@ type BeelzebubServiceConfiguration struct { DeadlineTimeoutSeconds int `yaml:"deadlineTimeoutSeconds"` PasswordRegex string `yaml:"passwordRegex"` Description string `yaml:"description"` + Banner string `yaml:"banner"` } type Command struct { diff --git a/protocols/transmissionControlProtocolStrategy.go b/protocols/transmissionControlProtocolStrategy.go new file mode 100644 index 0000000..0950f48 --- /dev/null +++ b/protocols/transmissionControlProtocolStrategy.go @@ -0,0 +1,49 @@ +package protocols + +import ( + "beelzebub/parser" + "beelzebub/tracer" + log "github.com/sirupsen/logrus" + "net" + "time" +) + +type TransmissionControlProtocolStrategy struct { +} + +func (TCPStrategy *TransmissionControlProtocolStrategy) Init(beelzebubServiceConfiguration parser.BeelzebubServiceConfiguration, tr tracer.Tracer) error { + listen, err := net.Listen("TCP", beelzebubServiceConfiguration.Address) + if err != nil { + log.Errorf("Error during init TCP Protocol: %s", err.Error()) + return err + } + defer listen.Close() + + go func() { + for { + if conn, err := listen.Accept(); err == nil { + conn.SetDeadline(time.Now().Add(time.Duration(beelzebubServiceConfiguration.DeadlineTimeoutSeconds) * time.Second)) + go handleIncomingRequest(conn) + } + } + }() + + log.WithFields(log.Fields{ + "port": beelzebubServiceConfiguration.Address, + "banner": beelzebubServiceConfiguration.Banner, + }).Infof("Init service %s", beelzebubServiceConfiguration.Protocol) + return nil +} + +func handleIncomingRequest(conn net.Conn) { + buffer := make([]byte, 1024) + _, err := conn.Read(buffer) + if err != nil { + log.Fatal(err) + } + // respond + conn.Write([]byte("Hi back!\n")) + + // close conn + conn.Close() +} From 882066f0a67cf6a59131a212d1bbfd2ba1a8f3e5 Mon Sep 17 00:00:00 2001 From: Mario Date: Sun, 3 Jul 2022 17:15:38 +0200 Subject: [PATCH 3/3] Implemented tcp honeypot --- .github/dependabot.yml | 9 +--- .github/workflows/ci.yml | 2 +- README.md | 14 ++++++- configurations/services/tcp-3306.yaml | 6 +-- docker-compose.yml | 1 + main.go | 4 ++ .../transmissionControlProtocolStrategy.go | 42 +++++++++++-------- tracer/tracer.go | 3 +- 8 files changed, 51 insertions(+), 30 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b444581..3938344 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,11 +1,6 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - version: 2 updates: - - package-ecosystem: "gomod" # See documentation for possible values - directory: "/" # Location of package manifests + - package-ecosystem: "gomod" + directory: "/" schedule: interval: "daily" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6fc69ca..f43477b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: echo "Quality Gate: checking test coverage is above threshold ..." echo "Threshold : $TESTCOVERAGE_THRESHOLD %" # Excluded the concrete strategy - cat coverage.tmp.out | grep -v "secureShellStrategy.go" | grep -v "hypertextTransferProtocolStrategy.go" > coverage.out + cat coverage.tmp.out | grep -v "secureShellStrategy.go" | grep -v "hypertextTransferProtocolStrategy.go" | grep -v "transmissionControlProtocolStrategy.go" > coverage.out totalCoverage=`go tool cover -func=coverage.out | grep total | grep -Eo '[0-9]+\.[0-9]+'` echo "Current test coverage : $totalCoverage %" if (( $(echo "$totalCoverage $TESTCOVERAGE_THRESHOLD" | awk '{print ($1 > $2)}') )); then diff --git a/README.md b/README.md index d587439..35b32dd 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,12 @@ $ go build $ ./beelzebub ``` +Unit Test: + +```bash +$ go test ./... + ``` + ## Example configuration service The configurations are inside the /configurations/services directory, just add a new file for each service/port. @@ -116,6 +122,7 @@ deadlineTimeoutSeconds: 60 - SSH Honeypot - HTTP Honeypot +- TCP Honeypot - Easy to create a new strategy - Easy to extend event tracking logic - Strong code quality @@ -125,7 +132,12 @@ deadlineTimeoutSeconds: 60 ## TODO - telnet -- tcp +- UDP + +# ROADMAP + +- SaaS Platform + ## Documentation diff --git a/configurations/services/tcp-3306.yaml b/configurations/services/tcp-3306.yaml index 3e66c4b..b3e9ec5 100644 --- a/configurations/services/tcp-3306.yaml +++ b/configurations/services/tcp-3306.yaml @@ -1,6 +1,6 @@ apiVersion: "v1" protocol: "tcp" address: ":3306" -description: "Mysql" -banner: "mysql 4.0" -deadlineTimeoutSeconds: 60 \ No newline at end of file +description: "Mysql 8.0.29" +banner: "8.0.29" +deadlineTimeoutSeconds: 10 \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 48eb8df..f40a391 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,6 +10,7 @@ services: - "22:22" - "8080:8080" - "80:80" + - "3306:3306" environment: RABBITMQ_URI: ${RABBITMQ_URI} volumes: diff --git a/main.go b/main.go index 3b28ee7..60ff49c 100644 --- a/main.go +++ b/main.go @@ -45,6 +45,7 @@ func main() { // Init Protocol strategies secureShellStrategy := &protocols.SecureShellStrategy{} hypertextTransferProtocolStrategy := &protocols.HypertextTransferProtocolStrategy{} + transmissionControlProtocolStrategy := &protocols.TransmissionControlProtocolStrategy{} // Init protocol manager, with simple log on stout trace strategy and default protocol HTTP protocolManager := protocols.InitProtocolManager(traceStrategyStdoutAndRabbitMQ, hypertextTransferProtocolStrategy) @@ -57,6 +58,9 @@ func main() { case "ssh": protocolManager.SetProtocolStrategy(secureShellStrategy) break + case "tcp": + protocolManager.SetProtocolStrategy(transmissionControlProtocolStrategy) + break default: log.Fatalf("Protocol %s not managed", beelzebubServiceConfiguration.Protocol) continue diff --git a/protocols/transmissionControlProtocolStrategy.go b/protocols/transmissionControlProtocolStrategy.go index 0950f48..53b0b96 100644 --- a/protocols/transmissionControlProtocolStrategy.go +++ b/protocols/transmissionControlProtocolStrategy.go @@ -3,6 +3,8 @@ package protocols import ( "beelzebub/parser" "beelzebub/tracer" + "fmt" + "github.com/google/uuid" log "github.com/sirupsen/logrus" "net" "time" @@ -12,18 +14,37 @@ type TransmissionControlProtocolStrategy struct { } func (TCPStrategy *TransmissionControlProtocolStrategy) Init(beelzebubServiceConfiguration parser.BeelzebubServiceConfiguration, tr tracer.Tracer) error { - listen, err := net.Listen("TCP", beelzebubServiceConfiguration.Address) + listen, err := net.Listen("tcp", beelzebubServiceConfiguration.Address) if err != nil { log.Errorf("Error during init TCP Protocol: %s", err.Error()) return err } - defer listen.Close() go func() { for { if conn, err := listen.Accept(); err == nil { - conn.SetDeadline(time.Now().Add(time.Duration(beelzebubServiceConfiguration.DeadlineTimeoutSeconds) * time.Second)) - go handleIncomingRequest(conn) + go func() { + conn.SetDeadline(time.Now().Add(time.Duration(beelzebubServiceConfiguration.DeadlineTimeoutSeconds) * time.Second)) + conn.Write([]byte(fmt.Sprintf("%s\n", beelzebubServiceConfiguration.Banner))) + + buffer := make([]byte, 1024) + command := "" + + if n, err := conn.Read(buffer); err == nil { + command = string(buffer[:n]) + } + + tr.TraceEvent(tracer.Event{ + Msg: "New TCP attempt", + Protocol: tracer.TCP.String(), + Command: command, + Status: tracer.Stateless.String(), + RemoteAddr: conn.RemoteAddr().String(), + ID: uuid.New().String(), + Description: beelzebubServiceConfiguration.Description, + }) + conn.Close() + }() } } }() @@ -34,16 +55,3 @@ func (TCPStrategy *TransmissionControlProtocolStrategy) Init(beelzebubServiceCon }).Infof("Init service %s", beelzebubServiceConfiguration.Protocol) return nil } - -func handleIncomingRequest(conn net.Conn) { - buffer := make([]byte, 1024) - _, err := conn.Read(buffer) - if err != nil { - log.Fatal(err) - } - // respond - conn.Write([]byte("Hi back!\n")) - - // close conn - conn.Close() -} diff --git a/tracer/tracer.go b/tracer/tracer.go index cc05355..9c6f0d8 100644 --- a/tracer/tracer.go +++ b/tracer/tracer.go @@ -52,10 +52,11 @@ type Protocol int const ( HTTP Protocol = iota SSH + TCP ) func (status Protocol) String() string { - return [...]string{"HTTP", "SSH"}[status] + return [...]string{"HTTP", "SSH", "TCP"}[status] } type Status int