HFish/core/protocol/elasticsearch/elasticsearch.go
2019-10-28 22:25:40 +08:00

206 lines
7.0 KiB
Go

package elasticsearch
import (
"fmt"
"net/http"
"time"
"strings"
"HFish/utils/is"
"HFish/core/rpc/client"
"HFish/core/report"
)
// Config represents the configuration information.
type Config struct {
LogFile string `json:"logfile"`
UseRemote bool `json:"use_remote"`
Remote Remote `json:"remote"`
HpFeeds HpFeeds `json:"hpfeeds"`
InstanceName string `json:"instance_name"`
Anonymous bool `json:"anonymous"`
SensorIP string `json:"honeypot_ip"`
SpoofedVersion string `json:"spoofed_version"`
PublicIpUrl string `json:"public_ip_url"`
}
// Remote is a struct used to contain the details for a remote server connection
type Remote struct {
URL string `json:"url"`
UseAuth bool `json:"use_auth"`
Auth Auth `json:"auth"`
}
type HpFeeds struct {
Host string `json:"host"`
Port int `json:"port"`
Channel string `json:"channel"`
Ident string `json:"ident"`
Secret string `json:"secret"`
Enabled bool `json:"enabled"`
}
// Auth contains the details in case basic auth is to be used when connecting
// to the remote server
type Auth struct {
Username string `json:"username"`
Password string `json:"password"`
}
// Conf holds the global config
var Conf Config
// Attack is a struct that contains the details of an attack entry
type Attack struct {
SourceIP string `json:"source"`
Timestamp time.Time `json:"@timestamp"`
URL string `json:"url"`
Method string `json:"method"`
Form string `json:"form"`
Payload string `json:"payload"`
Headers Headers `json:"headers"`
Type string `json:"type"`
SensorIP string `json:"honeypot"`
}
// Headers contains the filtered headers of the HTTP request
type Headers struct {
UserAgent string `json:"user_agent"`
Host string `json:"host"`
ContentType string `json:"content_type"`
AcceptLanguage string `json:"accept_language"`
}
func FakeBanner(w http.ResponseWriter, r *http.Request) {
printInfo(r)
response := fmt.Sprintf(`{
"status" : 200,
"name" : "%s",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "%s",
"build_hash" : "89d3241d670db65f994242c8e838b169779e2d4",
"build_snapshot" : false,
"lucene_version" : "4.10.2"
},
"tagline" : "You Know, for Search"
}`, Conf.InstanceName, Conf.SpoofedVersion)
WriteResponse(w, response)
return
}
// FakeNodes presents a fake /_nodes result
// TODO: Change IP Address with actual server IP address
func FakeNodes(w http.ResponseWriter, r *http.Request) {
printInfo(r)
response := fmt.Sprintf(`
{
"cluster_name" : "elasticsearch",
"nodes" : {
"x1JG6g9PRHy6ClCOO2-C4g" : {
"name" : "%s",
"transport_address" : "inet[/
%s:9300]",
"host" : "elk",
"ip" : "127.0.1.1",
"version" : "%s",
"build" : "89d3241",
"http_address" : "inet[/%s:9200]",
"os" : {
"refresh_interval_in_millis" : 1000,
"available_processors" : 12,
"cpu" : {
"total_cores" : 24,
"total_sockets" : 48,
"cores_per_socket" : 2
}
},
"process" : {
"refresh_interval_in_millis" : 1000,
"id" : 2039,
"max_file_descriptors" : 65535,
"mlockall" : false
},
"jvm" : {
"version" : "1.7.0_65"
},
"network" : {
"refresh_interval_in_millis" : 5000,
"primary_interface" : {
"address" : "%s",
"name" : "eth0",
"mac_address" : "08:01:c7:3F:15:DD"
}
},
"transport" : {
"bound_address" : "inet[/0:0:0:0:0:0:0:0:9300]",
"publish_address" : "inet[/%s:9300]"
},
"http" : {
"bound_address" : "inet[/0:0:0:0:0:0:0:0:9200]",
"publish_address" : "inet[/%s:9200]",
"max_content_length_in_bytes" : 104857600
}}
}
}`, Conf.InstanceName, Conf.SensorIP, Conf.SpoofedVersion, Conf.SensorIP, Conf.SensorIP, Conf.SensorIP, Conf.SensorIP)
WriteResponse(w, response)
return
}
// FakeSearch returns fake search results
func FakeSearch(w http.ResponseWriter, r *http.Request) {
printInfo(r)
response := fmt.Sprintf(`
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 6,
"successful" : 6,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 1.0,
"hits" : [ {
"_index" : ".kibana",
"_type" : "index-pattern",
"_id" : "logstash-*",
"_score" : 1.0,
"_source":{"title":"logstash-*","timeFieldName":"@timestamp","customFormats":"{}","fields":"[{\"type\":\"string\",\"indexed\":true,\"analyzed\":true,\"doc_values\":false,\"name\":\"host\",\"count\":0},{\"type\":\"string\",\"indexed\":false,\"analyzed\":false,\"name\":\"_source\",\"count\":0},{\"type\":\"string\",\"indexed\":true,\"analyzed\":false,\"doc_values\":false,\"name\":\"message.raw\",\"count\":0},{\"type\":\"string\",\"indexed\":false,\"analyzed\":false,\"name\":\"_index\",\"count\":0},{\"type\":\"string\",\"indexed\":true,\"analyzed\":false,\"doc_values\":false,\"name\":\"@version\",\"count\":0},{\"type\":\"string\",\"indexed\":true,\"analyzed\":true,\"doc_values\":false,\"name\":\"message\",\"count\":0},{\"type\":\"date\",\"indexed\":true,\"analyzed\":false,\"doc_values\":false,\"name\":\"@timestamp\",\"count\":0},{\"type\":\"string\",\"indexed\":true,\"analyzed\":false,\"name\":\"_type\",\"count\":0},{\"type\":\"string\",\"indexed\":true,\"analyzed\":false,\"name\":\"_id\",\"count\":0},{\"type\":\"string\",\"indexed\":true,\"analyzed\":false,\"doc_values\":false,\"name\":\"host.raw\",\"count\":0},{\"type\":\"geo_point\",\"indexed\":true,\"analyzed\":false,\"doc_values\":false,\"name\":\"geoip.location\",\"count\":0}]"}
}]
}
}`)
WriteResponse(w, response)
return
}
func WriteResponse(w http.ResponseWriter, d string) {
w.WriteHeader(200)
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.Write([]byte(d))
return
}
func printInfo(r *http.Request) {
info := "URL:" + r.URL.String() + "&&Method:" + r.Method + "&&RemoteAddr:" + r.RemoteAddr
arr := strings.Split(r.RemoteAddr, ":")
// 判断是否为 RPC 客户端
if is.Rpc() {
go client.ReportResult("ES", "ES蜜罐", arr[0], info, "0")
} else {
go report.ReportEs("ES蜜罐", "本机", arr[0], info)
}
}
func Start(address string) {
// Create the handlers
http.HandleFunc("/", FakeBanner)
http.HandleFunc("/_nodes", FakeNodes)
http.HandleFunc("/_search", FakeSearch)
// Start the server
http.ListenAndServe(address, nil)
}