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).