styx/plugins/shodan.go

138 lines
3.5 KiB
Go
Raw Permalink Normal View History

2020-02-25 10:05:31 +01:00
package plugins
import (
"context"
"encoding/json"
2020-02-25 10:05:31 +01:00
"sync"
"github.com/dgraph-io/dgo/v2"
"github.com/dgraph-io/dgo/v2/protos/api"
2020-02-25 10:05:31 +01:00
"github.com/ns3777k/go-shodan/v4/shodan"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
"gitlab.dcso.lolcat/LABS/styx/filters"
"gitlab.dcso.lolcat/LABS/styx/models"
)
// ShodanPlugin defines the general ShodanPlugin structure.
type ShodanPlugin struct {
Client *shodan.Client
ShodanChan chan *shodan.HostData
StopChan chan bool
StoppedChan chan bool
Running bool
}
// Initialize initialises the certstream configuration.
func (s *ShodanPlugin) Initialize() bool {
if !viper.GetBool("shodan.activated") {
return false
}
logrus.Info("shodan plugin is activated")
s.ShodanChan = make(chan *shodan.HostData)
2020-02-25 10:05:31 +01:00
return true
}
// Run runs the Shodan plugin.
func (s *ShodanPlugin) Run(wg *sync.WaitGroup, dgraphClient *dgo.Dgraph) {
2020-02-25 10:05:31 +01:00
if !s.Running {
s.StoppedChan = make(chan bool)
wg.Add(1)
go s.doRun(dgraphClient)
2020-02-25 10:05:31 +01:00
s.Running = true
}
}
// Stop stops the Shodan plugin.
func (s *ShodanPlugin) Stop(wg *sync.WaitGroup) {
if s.Running {
s.StoppedChan = make(chan bool)
close(s.StopChan)
<-s.StopChan
wg.Done()
s.Running = false
}
}
func (s *ShodanPlugin) doRun(graphClient *dgo.Dgraph) {
client := shodan.NewEnvClient(nil)
err := client.GetBannersByPorts(context.Background(), viper.GetIntSlice("shodan.ports"), s.ShodanChan)
if err != nil {
logrus.Panic(err)
}
2020-02-25 10:05:31 +01:00
for {
select {
default:
banner, ok := <-s.ShodanChan
if !ok {
logrus.Error("channel error: ", ok)
2020-02-25 10:05:31 +01:00
break
}
shodanNode := models.BuildShodanNode(banner)
// first filter poc
2020-06-10 12:31:07 +02:00
if shodanNode.HostData.HTML != "" {
if !filters.RunIPFilters(shodanNode.HostData.IP) {
hostnames := shodanNode.HostData.Hostnames
var hostNotInFilters, domainNotInFilters bool
if len(hostnames) != 0 {
for _, hostname := range hostnames {
hostNotInFilters = filters.RunDomainFilters(hostname)
if hostNotInFilters {
logrus.Info("host", hostname, " not in filters")
// keep track of new hostnames
// saveSingleValues(conn, "shodan_stream", "hostname", shodanNode.ID, hostname)
}
2020-02-25 10:05:31 +01:00
}
}
2020-06-10 12:31:07 +02:00
domains := shodanNode.HostData.Domains
if len(domains) != 0 {
for _, domain := range domains {
domainNotInFilters = filters.RunDomainFilters(domain)
logrus.Info("domain", domain, "not in filters")
// keep trakc of new domains
// saveSingleValues(conn, "shodan_stream", "domain", shodanNode.ID, domain)
}
}
2020-06-10 12:31:07 +02:00
if domainNotInFilters && hostNotInFilters {
// models.SaveShodanNode("raw_shodan.json", shodanNode)
mainNode := models.BuildNode("shodan", "shodan_stream", shodanNode.ID)
models.SaveNode("nodes.json", mainNode)
// edge := models.BuildEdge("shodan", structs.Map(shodanNode), structs.Map(mainNode))
// models.SaveEdge(edge)
e := models.Node{
ID: mainNode.ID,
NodeType: mainNode.NodeType,
2020-06-10 12:31:07 +02:00
NData: mainNode.NData,
Created: mainNode.Created,
Modified: mainNode.Modified,
ShodanNode: *shodanNode,
}
2020-06-10 12:31:07 +02:00
ctx := context.Background()
mu := &api.Mutation{
CommitNow: true,
}
2020-06-10 12:31:07 +02:00
pb, err := json.Marshal(e)
if err != nil {
logrus.Fatal(err)
}
2020-06-10 12:31:07 +02:00
mu.SetJson = pb
2020-06-10 12:31:07 +02:00
_, err = graphClient.NewTxn().Mutate(ctx, mu)
if err != nil {
logrus.Error(err)
}
2020-02-25 10:05:31 +01:00
}
2020-06-10 12:31:07 +02:00
} else {
logrus.Info(shodanNode.HostData.IP, "is akamain")
2020-02-25 10:05:31 +01:00
}
}
}
2020-02-25 10:05:31 +01:00
}
}