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"
)
funcmain() {
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)
iferr!=nil {
log.Fatal(err)
}
for_, match:=rangeresult.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 themifmatch.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 pagenginxSearch.Query.Port=443// or add new search termresult, err=client.Search(ctx, nginxSearch) // and reuse modified parameters objectiferr!=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:=rangeresult.Matches {
ifmatch.MongoDB!=nil&&!match.MongoDB.Authentication {
fmt.Println("exposed mongodb:", match.IpAndPort())
databases:=match.MongoDB.ListDatabases.Databasesfmt.Println("databases:", len(databases), "size:", match.MongoDB.ListDatabases.TotalSize)
for_, db:=rangedatabases {
for_, collectionName:=rangedb.Collections {
fmt.Println(collectionName)
}
}
}
ifmatch.SSL!=nil&&match.SSL.Cert.Expired {
fmt.Println("expired certificate:", match.IpAndPort())
}
ifmatch.Elastic!=nil {
fmt.Println("exposed elastic:", match.IpAndPort())
forindexName, index:=rangematch.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).