diff --git a/.gitignore b/.gitignore index 6228180..b3d8a55 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -events.log -.env \ No newline at end of file +.env +vuln-config.yaml \ No newline at end of file diff --git a/README.md b/README.md index 006261b..42d7bb1 100644 --- a/README.md +++ b/README.md @@ -65,21 +65,22 @@ psql -h localhost -p 5432 -U admin -V 'sslmode=disable' 3. **Storage of HTTP Request Headers:** A table named `http_request` is generated to capture HTTP requests. This table stores the attack ID, HTTP request method, and User-Agent. If an attacker sends an HTTP request via PUT or POST, the request body is saved in the Payload folder, with a maximum size of 100 MB. The associated HTTP body table contains the columns Content-Type and "Payload size". If the request is sent via a hidden contact form, the attacker's email address and name are stored in the `http_spam` table. ### 6. HTTP Endpoints -- Provides attack events details and statistics via HTTP endpoints on port `1112`. + +Provides attack events details and statistics via HTTP endpoints on port `1112`. + | Path | Description | | ----------------------- | -------------------------------------------------------------------------------------------------------- | -| /realtime | Provides real-time data on ongoing attacks and activities being recorded using Server-Side Events (SSE). | -| /latest-attacks | Provides latest attacks of each honeypot | -| /stats/count-in-24hours | Provides the number of attacks in the last 24 hours measured per hour | -| /stats/count-in-7days | Provides the number of attacks in the last 7 days measured per day | -| /stats/count-in-6months | Provides the number of attacks in the last 6 months measured per month | -| /stats/country | Provides statistics on the number of attacks originating from different countries. | -| /stats/ip | Provides statistics on the number of attacks originating from different IP addresses. | -| /stats/username | Provides statistics on the usernames used in login attempts. | -| /stats/password | Provides statistics on the passwords used in login attempts. | -| /stats/port | Provides statistics on the number of attacks per port. | -| /stats/path | Provides statistics on the HTTP paths accessed during attacks. | - +| `/realtime` | Provides real-time data on ongoing attacks and activities being recorded using Server-Side Events (SSE). | +| `/latest-attacks` | Provides latest attacks of each honeypot | +| `/stats/count-in-24hours` | Provides the number of attacks in the last 24 hours measured per hour | +| `/stats/count-in-7days` | Provides the number of attacks in the last 7 days measured per day | +| `/stats/count-in-6months` | Provides the number of attacks in the last 6 months measured per month | +| `/stats/country` | Provides statistics on the number of attacks originating from different countries. | +| `/stats/ip` | Provides statistics on the number of attacks originating from different IP addresses. | +| `/stats/username` | Provides statistics on the usernames used in login attempts. | +| `/stats/password` | Provides statistics on the passwords used in login attempts. | +| `/stats/port` | Provides statistics on the number of attacks per port. | +| `/stats/path` | Provides statistics on the HTTP paths accessed during attacks. | ## Installation @@ -100,23 +101,20 @@ cp .env.example .env 5. You can run the honeypot by executing the following command: ```bash - go run main.go - ``` 6. There is even a Makefile included in the project, so you can simply run: ```bash - make - ``` -This starts the honeypot. +This starts the honeypot. ## Configuration ### Vulnerability on honeypot + Vulnerabilities of HTTP Honeypot and SSH can be configured as follows: ```yaml http: @@ -126,6 +124,7 @@ http: ssh: ServerVersion: "SSH-2.0-OpenSSH_5.8p2" ``` + ### DB-IP The honeypot uses the [DB-IP](https://db-ip.com/) service to determine the geolocation of the IP addresses that interact with it. The db-ip lite database is included in the project and needs to be updated regularly. The link to download the latest version can be found [here](https://db-ip.com/db/download/ip-to-country-lite). The file needs to be extracted and placed in the `root` folder. The file name should be `dbip-country.csv`. diff --git a/cmd/main.go b/cmd/main.go index 07d7baf..4100bfc 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -33,7 +33,7 @@ func main() { // Load the .env file err = godotenv.Load(".env") if err != nil { - slog.Warn("Error loading .env file: %s", err) + slog.Warn("Error loading .env file", "err", err) } postgresqlDB := store.PostgreSQL{} @@ -50,6 +50,11 @@ func main() { httpHoneypot := honeypot.NewHTTP(honeypot.HTTPConfig{ Port: 80, + HTTPSConfig: honeypot.HTTPSConfig{ + Port: 443, + CertFile: "cert.pem", + KeyFile: "key.pem", + }, }) err = httpHoneypot.Start() if err != nil { @@ -73,17 +78,17 @@ func main() { } tcpHoneypot := honeypot.NewTCP(honeypot.MostUsedTCPPorts()) - udpHoneypot := honeypot.NewUDP(honeypot.MostUsedUDPPorts()) + // udpHoneypot := honeypot.NewUDP(honeypot.MostUsedUDPPorts()) err = tcpHoneypot.Start() if err != nil { panic(err) } - err = udpHoneypot.Start() - if err != nil { - panic(err) - } + // err = udpHoneypot.Start() + // if err != nil { + // panic(err) + // } httpTransport := transport.NewHTTP(transport.HTTPConfig{ Port: 1112, @@ -97,12 +102,19 @@ func main() { dbIp := dbip.NewIpToCountry("dbip-country.csv") // listen for SET events - setChannel := pipeline.Map(pipeline.Merge(sshHoneypot.GetSETChannel(), tcpHoneypot.GetSETChannel(), udpHoneypot.GetSETChannel(), httpHoneypot.GetSETChannel(), postgresHoneypot.GetSETChannel()), func(input types.Set) (types.Set, error) { - input.COUNTRY = dbIp.Lookup(net.ParseIP(input.SUB)) - input.HONEYPOT = string(os.Getenv("HONEYPOT_NAME")) - return input, nil - }) - + setChannel := + pipeline.Map( + pipeline.Merge( + sshHoneypot.GetSETChannel(), + httpHoneypot.GetSETChannel(), + tcpHoneypot.GetSETChannel(), + // udpHoneypot.GetSETChannel(), + postgresHoneypot.GetSETChannel()), + func(input types.Set) (types.Set, error) { + input.COUNTRY = dbIp.Lookup(net.ParseIP(input.SUB)) + input.HONEYPOT = string(os.Getenv("HONEYPOT_NAME")) + return input, nil + }) // save everything, which is send over the setChannel inside the database pipeline.Pipe(setChannel, dbChan) dbSubscription := postgresqlDB.SubscribeToDBChanges() diff --git a/go.mod b/go.mod index d764875..4097a2e 100644 --- a/go.mod +++ b/go.mod @@ -31,6 +31,7 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sethvargo/go-password v0.3.1 // indirect github.com/shopspring/decimal v1.4.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect diff --git a/go.sum b/go.sum index bb37cc0..7926590 100644 --- a/go.sum +++ b/go.sum @@ -55,6 +55,8 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sethvargo/go-password v0.3.1 h1:WqrLTjo7X6AcVYfC6R7GtSyuUQR9hGyAj/f1PYQZCJU= +github.com/sethvargo/go-password v0.3.1/go.mod h1:rXofC1zT54N7R8K/h1WDUdkf9BOx5OptoxrMBcrXzvs= github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= diff --git a/json-schema/credential-theft.json b/json-schema/credential-theft.json new file mode 100644 index 0000000..b22b755 --- /dev/null +++ b/json-schema/credential-theft.json @@ -0,0 +1,35 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "$id": "https://github.com/l3montree-dev/oh-my-honeypot/json-schema/credential_theft.json", + "type": "object", + "default": {}, + "title": "Root Schema", + "required": [ + "ssh_pw", + "db_pw" + ], + "properties": { + "ssh_pw": { + "type": "string", + "default": "", + "title": "The password Schema", + "examples": [ + "123456" + ] + }, + "db_pw": { + "type": "string", + "default": "", + "title": "The password Schema", + "examples": [ + "123456" + ] + } + }, + "examples": [ + { + "ssh_pw": "1234567", + "db_pw": "123456" + } + ] +} \ No newline at end of file diff --git a/packages/honeypot/honeypot.go b/packages/honeypot/honeypot.go index e294a4f..0468335 100644 --- a/packages/honeypot/honeypot.go +++ b/packages/honeypot/honeypot.go @@ -11,9 +11,10 @@ import ( ) const ( - PortEventID = "https://github.com/l3montree-dev/oh-my-honeypot/json-schema/port-scanning.json" - LoginEventID = "https://github.com/l3montree-dev/oh-my-honeypot/json-schema/ssh-login-attempt.json" - HTTPEventID = "https://github.com/l3montree-dev/oh-my-honeypot/json-schema/http-request.json" + PortEventID = "https://github.com/l3montree-dev/oh-my-honeypot/json-schema/port-scanning.json" + LoginEventID = "https://github.com/l3montree-dev/oh-my-honeypot/json-schema/ssh-login-attempt.json" + HTTPEventID = "https://github.com/l3montree-dev/oh-my-honeypot/json-schema/http-request.json" + CredentialEventID = "https://github.com/l3montree-dev/oh-my-honeypot/json-schema/credential-theft.json" ) type Honeypot interface { diff --git a/packages/honeypot/http.go b/packages/honeypot/http.go index 2953c5a..7e02ea5 100644 --- a/packages/honeypot/http.go +++ b/packages/honeypot/http.go @@ -2,8 +2,10 @@ package honeypot import ( "fmt" - "io" + "log" + "sort" + "log/slog" "net" "net/http" @@ -11,110 +13,351 @@ import ( "time" "github.com/google/uuid" - "github.com/l3montree-dev/oh-my-honeypot/packages/types" "github.com/l3montree-dev/oh-my-honeypot/packages/utils" + "github.com/sethvargo/go-password/password" "github.com/spf13/viper" ) +type httpsHoneypot struct { + port int + cert string + key string +} + type httpHoneypot struct { port int // setChan is the channel the honeypot is posting SET events to. setChan chan types.Set + httpsHoneypot +} + +type HTTPSConfig struct { + Port int + CertFile string + KeyFile string } type HTTPConfig struct { Port int + HTTPSConfig } +const headTemplate = ` + + + + + + + File share system + + +` +const loginTemplate = ` +
+
+
+

Internal NAS Server

+

Member Login

+
+
+ +
+
+ +
+ + +
+ + ` +const pagenotfoundTemplate = ` +
+

404 Not Found

+

Page not found

+

Main page

+
+` +const notallowedTemplate = ` +
+

405 Method Not Allowed

+

Method not allowed

+

Main page

+
+` + func (h *httpHoneypot) Start() error { mux := http.NewServeMux() - //FileServer to serve static files of hidden ontact form - fileServer := http.FileServer(http.Dir("./public")) - mux.Handle("/contact-us/", http.StripPrefix("/contact-us/", fileServer)) - mux.HandleFunc("/{path...}", func(w http.ResponseWriter, r *http.Request) { + // Common logging and data extraction functions + extractRequestData := func(r *http.Request) (string, []string, []byte, string, string, string, string, string, error) { useragent := split(r.UserAgent()) - remoteAddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr) - sub, _ := utils.NetAddrToIpStr(remoteAddr) - body, _ := io.ReadAll(r.Body) + remoteAddr, err := net.ResolveTCPAddr("tcp", r.RemoteAddr) + if err != nil { + slog.Error("Error resolving remote address", "err", err) + } + sub, err := utils.NetAddrToIpStr(remoteAddr) + if err != nil { + slog.Error("Error converting remote address to IP string", "err", err) + } + referrer := r.Header.Get("Referer") + username := r.FormValue("username") + password := r.FormValue("password") + bot := r.FormValue("lastname") + body, err := io.ReadAll(r.Body) + if err != nil { + slog.Error("Error reading request body", "err", err) + } mimeType := http.DetectContentType(body) - defer r.Body.Close() + return sub, useragent, body, mimeType, referrer, username, password, bot, nil + } + handleRequest := func(w http.ResponseWriter, r *http.Request, extraData map[string]interface{}) { + sub, useragent, body, mimeType, referrer, username, password, bot, err := extractRequestData(r) + if err != nil { + slog.Error("Error processing request", "err", err) + } + event := map[string]interface{}{ + "port": h.port, + "method": r.Method, + "accept-lang": r.Header.Get("Accept-Language"), + "user-agent": useragent, + "content-type": mimeType, + "body": string(body), + "bodysize": len(body), + "path": r.URL.Path, + "referrer": referrer, + "username": username, + "password": password, + "bot": bot, + } + // Merge extraData into the event map + for k, v := range extraData { + event[k] = v + } + h.setChan <- types.Set{ SUB: sub, ISS: "github.com/l3montree-dev/oh-my-honeypot/packages/honeypot/http", IAT: time.Now().Unix(), JTI: uuid.New().String(), Events: map[string]map[string]interface{}{ - HTTPEventID: { - "port": h.port, - "method": r.Method, - "accept-lang": r.Header.Get("Accept-Language"), - "user-agent": useragent, - "content-type": mimeType, - "body": string(body), - "bodysize": len(body), - "path": r.URL.Path, - }, + HTTPEventID: event, }, } - // Set the headers to make the honeypot look like an vulnerable server - //iterate over the headers and set them for key, value := range viper.GetStringMap("http.headers") { w.Header().Set(key, value.(string)) } - fmt.Fprintf(w, "Hello") + } + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + handleRequest(w, r, nil) + q := r.URL.Query() + if q.Get("page") == "login" && q.Get("param") == "wrongauthentication" { + if r.Method != "POST" { + htmlContent := fmt.Sprintf(` + + %s + + %s + + `, headTemplate, notallowedTemplate) + w.WriteHeader(http.StatusMethodNotAllowed) + fmt.Fprint(w, htmlContent) + return + } + htmlContent := fmt.Sprintf(` + + %s + + %s +

Wrong username or password

+ + `, headTemplate, loginTemplate) + fmt.Fprint(w, htmlContent) + } else if r.URL.Path == "/" || r.URL.Path == "/index.php" { + htmlContent := fmt.Sprintf(` + + %s + + %s + + `, headTemplate, loginTemplate) + + fmt.Fprint(w, htmlContent) + } else { + htmlContent := fmt.Sprintf(` + + %s + + %s + + `, headTemplate, pagenotfoundTemplate) + + fmt.Fprint(w, htmlContent) + } }) - // Handle the form submission - mux.HandleFunc("/contact-us/submit", func(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) - return + + mux.HandleFunc("/vendor/phpunit/phpunit/src/Util/PHP/eval-stdin.php", func(w http.ResponseWriter, r *http.Request) { + handleRequest(w, r, nil) + fmt.Fprint(w, "") + }) + + mux.HandleFunc("/.env", func(w http.ResponseWriter, r *http.Request) { + randomPW, err := password.Generate(16, 4, 4, false, false) + handleRequest(w, r, map[string]interface{}{ + "randomPW": randomPW, + "attack-type": "credential-theft", + }) + + envMap := viper.GetStringMap("http.env") + keys := make([]string, 0, len(envMap)) + for key := range envMap { + keys = append(keys, key) } - err := r.ParseForm() + sort.Strings(keys) + envString := "# Outdated as of 2016-02-03 \n" if err != nil { - http.Error(w, "Error parsing form", http.StatusBadRequest) + slog.Error("Error generating random password", "err", err) return } - useragent := split(r.UserAgent()) - remoteAddr, _ := net.ResolveTCPAddr("tcp", r.RemoteAddr) - sub, _ := utils.NetAddrToIpStr(remoteAddr) - contentType := r.Header.Get("Content-Type") - name := r.FormValue("First Name") + " " + r.FormValue("Last Name") - email := r.FormValue("E-Mail") - body := name + "\n" + email + "\n" + r.FormValue("Message") - h.setChan <- types.Set{ - SUB: sub, - ISS: "github.com/l3montree-dev/oh-my-honeypot/packages/honeypot/http", - IAT: time.Now().Unix(), - JTI: uuid.New().String(), - Events: map[string]map[string]interface{}{ - HTTPEventID: { - "port": h.port, - "method": r.Method, - "accept-lang": r.Header.Get("Accept-Language"), - "user-agent": useragent, - "content-type": contentType, - "body": body, - "bodysize": len(body), - "path": r.URL.Path, - "name": name, - "e-mail": email, - "attack-type": "Spam", - }, - }, + for _, key := range keys { + switch key { + case "ssh_password", "db_password": + envString += fmt.Sprintf("%s=%s\n", strings.ToUpper(key), randomPW) + default: + value := envMap[key] + envString += fmt.Sprintf("%s=%s\n", strings.ToUpper(key), value) + } } + w.Header().Set("Content-Type", "text/plain") + fmt.Fprint(w, envString) }) - // Set the headers to make the honeypot look like an vulnerable server slog.Info("HTTP Honeypot started", "port", h.port) + // HTTP Server go func() { for { err := http.ListenAndServe(":80", mux) if err != nil { - slog.Error("Error starting HTTP server", "port", h.port, "err", err) - continue + slog.Error("Error starting HTTP redirect server", "err", err) } } }() + // HTTPS server + go func() { + for { + svc := http.Server{ + Addr: ":443", + Handler: mux, + ErrorLog: log.New(io.Discard, "", 0), + } + err := svc.ListenAndServeTLS(h.cert, h.key) + if err != nil { + slog.Error("Error starting HTTPS server", "port", h.port, "err", err) + } + } + }() + return nil } @@ -137,5 +380,10 @@ func NewHTTP(config HTTPConfig) Honeypot { return &httpHoneypot{ port: config.Port, setChan: make(chan types.Set), + httpsHoneypot: httpsHoneypot{ + port: config.Port, + key: config.KeyFile, + cert: config.CertFile, + }, } } diff --git a/packages/honeypot/postgresql.go b/packages/honeypot/postgresql.go index 1c1f910..b1210bf 100644 --- a/packages/honeypot/postgresql.go +++ b/packages/honeypot/postgresql.go @@ -68,8 +68,7 @@ func (p *postgresHoneypot) Start() error { // n has to be greater than 0 since we are in the loop if isSSLRequest(msg) { conn.Write([]byte("N")) // nolint - conn.Close() - return + continue } else if isLoginMessage(msg) { username = searchUsername(msg) conn.Write(pwAuthResponse()) // nolint diff --git a/packages/honeypot/ssh.go b/packages/honeypot/ssh.go index 7d4c275..8faef7c 100644 --- a/packages/honeypot/ssh.go +++ b/packages/honeypot/ssh.go @@ -47,7 +47,6 @@ func (s *sshHoneypot) Start() error { }, }, } - slog.Info("Login attempt", "user", c.User(), "pass", string(pass), "ip", c.RemoteAddr()) return nil, fmt.Errorf("password rejected for %q", c.User()) }, } diff --git a/packages/honeypot/tcp.go b/packages/honeypot/tcp.go index ce6aa70..eae53a4 100644 --- a/packages/honeypot/tcp.go +++ b/packages/honeypot/tcp.go @@ -12,32 +12,35 @@ import ( func MostUsedTCPPorts() []int { return []int{ - //Most used TCP 20ports - 21, // FTP - 23, // Telnet - 25, // SMTP - 53, // DNS - 88, // Kerberos - 110, // POP3 - 143, // IMAP - 389, // LDAP - 465, // SMTPS - 546, // DHCPv6 Client - 547, // DHCPv6 Server - 636, // LDAPS - 989, // FTPS - 990, // FTPS - 993, // IMAPS - 995, // POP3S - 3306, // MySQL - 8001, // kubernetes dashboard default port - 6443, // kubernetes api server - 2379, // etcd - 2380, // etcd - 10250, // kubelet - 10251, // kube-scheduler - 10252, // kube-controller-manager - 10255, // kube-proxy + //File transfer ports + 21, // FTP + 989, // FTPS + 990, // FTPS + //File sharing ports + 445, // SMB + //Remote access ports + 23, // Telnet + 3389, // RDP + // 5900, // VNC + //Email ports + // 25, // SMTP + // 465, // SMTPS + // 110, // POP3 + // 995, // POP3S + // 143, // IMAP + // 993, // IMAPS + //Web ports + // 53, // DNS + //Security + // 88, // Kerberos + // 389, // LDAP + // 636, // LDAPS + //DHCP + // 546, // DHCPv6 Client + // 547, // DHCPv6 Server + //Database ports + // 1433, // MSSQL + // 3306, // MySQL } } diff --git a/packages/store/dbstore.go b/packages/store/dbstore.go index b68d52c..1bae523 100644 --- a/packages/store/dbstore.go +++ b/packages/store/dbstore.go @@ -139,31 +139,37 @@ func (p *PostgreSQL) Listen() chan<- types.Set { port = httpEvent["port"].(int) acceptLanguage := httpEvent["accept-lang"].(string) useragent := httpEvent["user-agent"].([]string) + referrer := httpEvent["referrer"].(string) //store the payload if the method is POST, PUT or PATCH if method == "POST" || method == "PUT" || method == "PATCH" { payload := httpEvent["body"].(string) - if httpEvent["attack-type"] == "Spam" { - name := httpEvent["name"].(string) - email := httpEvent["e-mail"].(string) - defer p.spamInsert(input.JTI, name, email) - } - payloadSize := httpEvent["bodysize"].(int) - maxSize := int64(100 * 1024 * 1024) - //store the payload if it is less than 100MB - if payloadSize < int(maxSize) { - attackID := input.JTI - if err := savePayload(attackID, payload); err != nil { - slog.Warn("could not save payload", "err", err) - } + if httpEvent["username"] != "" && httpEvent["password"] != "" { + username := httpEvent["username"].(string) + password := httpEvent["password"].(string) + bot := httpEvent["bot"].(string) + defer p.injectionInsert(input.JTI, username, password, bot) } else { - slog.Info("Payload size is greater than 100MB") + payloadSize := httpEvent["bodysize"].(int) + maxSize := int64(100 * 1024 * 1024) + //store the payload if it is less than 100MB + if payloadSize < int(maxSize) { + attackID := input.JTI + if err := savePayload(attackID, payload); err != nil { + slog.Warn("could not save payload", "err", err) + } + } else { + slog.Info("Payload size is greater than 100MB") + } + //store the content type and payload size + contentType := httpEvent["content-type"].(string) + defer p.bodyInsert(input.JTI, contentType, strconv.Itoa(payloadSize)+" bytes") } - //store the content type and payload size - contentType := httpEvent["content-type"].(string) - defer p.bodyInsert(input.JTI, contentType, strconv.Itoa(payloadSize)+" bytes") - } - defer p.httpInsert(input.JTI, method, path, acceptLanguage, useragent) + if httpEvent["attack-type"] == "credential-theft" { + randomPW := httpEvent["randomPW"].(string) + defer p.pwsInsert(input.JTI, randomPW) + } + defer p.httpInsert(input.JTI, method, path, acceptLanguage, useragent, referrer) } // Insert the basic information about all attacks into the database p.attackInsert(input.JTI, input.HONEYPOT, int(timestamp), port, input.SUB, input.COUNTRY, attackType) @@ -199,13 +205,13 @@ func (p *PostgreSQL) loginAttemptInsert(attackID string, service string, usernam } } -func (p *PostgreSQL) httpInsert(attackID string, method string, path string, acceptLanguage string, useragent []string) { +func (p *PostgreSQL) httpInsert(attackID string, method string, path string, acceptLanguage string, useragent []string, referrer string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _, err := p.DB.Exec(ctx, ` - INSERT INTO http_request (Attack_ID,method,path,accept_language,system,rendering_engine,platform) - VALUES ($1, $2, $3, $4, $5, $6,$7) - `, attackID, method, path, acceptLanguage, useragent[0], useragent[1], useragent[2]) + INSERT INTO http_request (Attack_ID,method,path,accept_language,system,rendering_engine,platform,referrer) + VALUES ($1, $2, $3, $4, $5, $6,$7,$8) + `, attackID, method, path, acceptLanguage, useragent[0], useragent[1], useragent[2], referrer) if err != nil { slog.Error("Error inserting into the database http_request", "err", err) } @@ -223,15 +229,26 @@ func (p *PostgreSQL) bodyInsert(attackID string, contentType string, payloadSize } } -func (p *PostgreSQL) spamInsert(attackID string, name string, email string) { +func (p *PostgreSQL) injectionInsert(attackID string, username string, password string, bot string) { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() _, err := p.DB.Exec(ctx, ` - INSERT INTO http_spam (Attack_ID,name,email) - VALUES ($1,$2,$3) - `, attackID, name, email) + INSERT INTO http_injection (Attack_ID,username,password,bot) + VALUES ($1,$2,$3,$4) + `, attackID, username, password, bot) if err != nil { - slog.Error("Error inserting into the database http_spam", "err", err) + slog.Error("Error inserting into the database http_injection", "err", err) + } +} +func (p *PostgreSQL) pwsInsert(attackID string, password string) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + _, err := p.DB.Exec(ctx, ` + INSERT INTO generated_pws (Attack_ID,password) + VALUES ($1,$2) + `, attackID, password) + if err != nil { + slog.Error("Error inserting into the database http_injection", "err", err) } } @@ -314,6 +331,7 @@ func (p *PostgreSQL) Start(host, port, user, password, dbname string) error { system TEXT, rendering_engine TEXT, platform TEXT, + referrer TEXT, FOREIGN KEY (Attack_ID) REFERENCES attack_log(Attack_ID) );`) if err != nil { @@ -329,20 +347,28 @@ func (p *PostgreSQL) Start(host, port, user, password, dbname string) error { slog.Error("Error creating table http_body", "err", err) } _, err = p.DB.Exec(ctx, ` - CREATE TABLE IF NOT EXISTS http_spam ( + CREATE TABLE IF NOT EXISTS http_injection ( + Attack_ID TEXT PRIMARY KEY, + username TEXT, + password TEXT, + bot TEXT, + FOREIGN KEY (Attack_ID) REFERENCES attack_log(Attack_ID));`) + if err != nil { + slog.Error("Error creating table http_injection", "err", err) + } + _, err = p.DB.Exec(ctx, ` + CREATE TABLE IF NOT EXISTS generated_pws ( Attack_ID TEXT PRIMARY KEY, - name TEXT, - email TEXT, - message_size TEXT, + password TEXT, FOREIGN KEY (Attack_ID) REFERENCES attack_log(Attack_ID));`) if err != nil { - slog.Error("Error creating table http_spam", "err", err) + slog.Error("Error creating table http_injection", "err", err) } _, err = p.DB.Exec(ctx, ` - CREATE INDEX attacklog_timestamp_hpid + CREATE INDEX IF NOT EXISTS attacklog_timestamp_hpid ON attack_log(honeypot_id, TO_TIMESTAMP(time_of_event));`) if err != nil { - slog.Error("Error creating table http_spam", "err", err) + slog.Error("Error creating index", "err", err) } slog.Info("PostgreSQL store started") @@ -730,7 +756,7 @@ func (p *PostgreSQL) GetIPStats() types.IPStatsResponse { WHERE attack_log.honeypot_id=$1 GROUP BY attack_log.ip_address, attack_log.country ORDER BY COUNT(attack_log.ip_address) - DESC; + DESC LIMIT 30; ` rows, err := p.DB.Query(ctx, query, honeypotID) if err != nil { @@ -781,7 +807,7 @@ func (p *PostgreSQL) GetUsernameStats() types.UsernameStatsResponse { JOIN attack_log al ON la.attack_id = al.attack_id WHERE al.honeypot_id = $1 GROUP BY la.username - ORDER BY COUNT(la.username) DESC; + ORDER BY COUNT(la.username) DESC LIMIT 30; ` rows, err := p.DB.Query(ctx, query, honeypotID) if err != nil { @@ -831,7 +857,7 @@ func (p *PostgreSQL) GetPasswordStats() types.PasswordStatsResponse { JOIN attack_log al ON la.attack_id = al.attack_id WHERE al.honeypot_id = $1 GROUP BY la.password - ORDER BY COUNT(la.password) DESC; + ORDER BY COUNT(la.password) DESC LIMIT 30; ` rows, err := p.DB.Query(ctx, query, honeypotID) if err != nil { diff --git a/public/bg.jpeg b/public/bg.jpeg deleted file mode 100644 index a1db178..0000000 Binary files a/public/bg.jpeg and /dev/null differ diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 55547e0..0000000 --- a/public/index.html +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - Coming Soon - - - - -

Website Is Under Maintenance

-

We're Launching Soon

-
-
- -
-
- -
-
- -
-
- -
- -
- -
-
- maintenance -
-
- - - \ No newline at end of file diff --git a/public/maintenance.png b/public/maintenance.png deleted file mode 100644 index cb452e0..0000000 Binary files a/public/maintenance.png and /dev/null differ diff --git a/public/style.css b/public/style.css deleted file mode 100644 index 3840a64..0000000 --- a/public/style.css +++ /dev/null @@ -1,96 +0,0 @@ -html { - font-family: Lato, "Segoe UI", Avenir, Ubuntu, Tahoma, Verdana, Helvetica, sans-serif; - background-image: url("bg.jpeg"); - scroll-behavior: smooth; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - text-align: center; - -} - -body { - display: table-cell; - vertical-align: middle; - text-align: center; -} - -h3 { - text-align: center; - margin-top: 8rem; - margin-bottom: 8rem; - margin-left: auto; - margin-right: auto; - font-size: 2rem; - color: #bddaff; -} - -h1 { - margin-top: 6rem; - margin-bottom: 8rem; - margin-left: auto; - margin-right: auto; - text-align: center; - font-size: 5rem; - text-transform: uppercase; - font-weight: 800; - color: #ffffff; -} - -input { - display: none; - opacity: 0; - visibility: hidden; -} - - -button { - display: none; - opacity: 0; - visibility: hidden; -} - -/* Small devices (landscape phones, 576px and up) */ -@media (min-width: 576px) { - h1 { - font-size: 3rem; - } - - h3 { - font-size: 1.5rem; - } -} - -/* Medium devices (tablets, 768px and up) */ -@media (min-width: 768px) { - h1 { - font-size: 4rem; - } - - h3 { - font-size: 2rem; - } -} - -/* Large devices (desktops, 992px and up) */ -@media (min-width: 992px) { - h1 { - font-size: 5rem; - } - - h3 { - font-size: 2.5rem; - } -} - -/* Extra large devices (large desktops, 1200px and up) */ -@media (min-width: 1200px) { - h1 { - font-size: 6rem; - } - - h3 { - font-size: 3rem; - } -} \ No newline at end of file diff --git a/vuln-config.example.yaml b/vuln-config.example.yaml new file mode 100644 index 0000000..f7c0cd6 --- /dev/null +++ b/vuln-config.example.yaml @@ -0,0 +1,14 @@ +http: + headers: + Server: "Apache/2.2.3 (Ubuntu)" + X-Powered-By: "PHP/4.1.0" + env: + SSH_USER: ohmyhoneypot + SSH_PASSWORD: secret + DB_HOST: localhost + DB_USER: ohmyhoneypot + DB_NAME: ohmyhoneypot + DB_PASSWORD: secret + DB_PORT: 5432 +ssh: + ServerVersion: SSH-2.0-OpenSSH_5.8p2 \ No newline at end of file diff --git a/vuln-config.yaml b/vuln-config.yaml deleted file mode 100644 index eef0be2..0000000 --- a/vuln-config.yaml +++ /dev/null @@ -1,6 +0,0 @@ -http: - headers: - Server: "Apache/2.2.3 (Ubuntu)" - X-Powered-By: "PHP/4.1.0" -ssh: - ServerVersion: "SSH-2.0-OpenSSH_5.8p2" \ No newline at end of file