Yet another one Golang implementation of Shodan REST API client. This library is inspired by amazing Nikita Safonov's go-shodan library, but has different data models and query syntax.
- Library intended to be the most comprehensive and documented out there, letting you learn about all the API methods, search filters and gathered data types using method/model comments in this repo
- Search syntax allows you to change query without string formatting:
package main
import (
"context"
"github.com/shadowscatcher/shodan"
"github.com/shadowscatcher/shodan/search"
"github.com/shadowscatcher/shodan/search/ssl_versions"
"log"
"net/http"
"os"
)
func main() {
nginxSearch := search.Params{
Page:1,
Query: search.Query{
Product: "nginx",
ASN: "AS14618",
SSLOpts: search.SSLOpts{
Cert: search.CertOptions{
Expired: true,
},
Version: ssl_versions.TLSv1_2,
},
},
}
client, _ := shodan.GetClient(os.Getenv("SHODAN_API_KEY"), http.DefaultClient, true)
ctx := context.Background()
result, err := client.Search(ctx, nginxSearch)
if err != nil {
log.Fatal(err)
}
for _, match := range result.Matches {
// a lot of returned data can be used in another searches
// it's easy because you will get response with almost all possible fields, just don't forget to check them
if match.HTTP != nil && match.HTTP.Favicon != nil {
//newQuery := search.Query{HTTP: search.HTTP{Favicon: search.Favicon{Hash: match.HTTP.Favicon.Hash}}}
}
}
// later on you can change every part of search query or parameters:
nginxSearch.Page++ // for example, increase page
nginxSearch.Query.Port = 443 // or add new search term
result, err = client.Search(ctx, nginxSearch) // and reuse modified parameters object
if err != nil {
log.Fatal(err)
}
}
- Search results contain a lot of types that are ignored by most of the existing libraries, documented where possible:
for _, match := range result.Matches {
if match.MongoDB != nil && !match.MongoDB.Authentication {
fmt.Println("exposed mongodb:", match.IpAndPort())
databases := match.MongoDB.ListDatabases.Databases
fmt.Println("databases:", len(databases), "size:", match.MongoDB.ListDatabases.TotalSize)
for _, db := range databases {
for _, collectionName := range db.Collections {
fmt.Println(collectionName)
}
}
}
if match.SSL != nil && match.SSL.Cert.Expired {
fmt.Println("expired certificate:", match.IpAndPort())
}
if match.Elastic != nil {
fmt.Println("exposed elastic:", match.IpAndPort())
for indexName, index := range match.Elastic.Indices {
fmt.Println(indexName, index.UUID)
}
}
}
- The client can be configured to automatically make one second pause between requests (this interval required by Shodan's API terms of service).