broad.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package scan
  2. import (
  3. "crypto/tls"
  4. "crypto/x509"
  5. "net"
  6. "sync"
  7. "time"
  8. "github.com/cloudflare/cfssl/bundler"
  9. )
  10. // Broad contains scanners for large swaths of TLS hosts on the internet.
  11. var Broad = &Family{
  12. Description: "Large scale scans of TLS hosts",
  13. Scanners: map[string]*Scanner{
  14. "IntermediateCAs": {
  15. "Scans a CIDR IP range for unknown Intermediate CAs",
  16. intermediateCAScan,
  17. },
  18. },
  19. }
  20. func incrementBytes(bytes []byte) {
  21. lsb := len(bytes) - 1
  22. bytes[lsb]++
  23. if bytes[lsb] == 0 {
  24. incrementBytes(bytes[:lsb])
  25. }
  26. }
  27. var (
  28. caBundleFile = "/etc/cfssl/ca-bundle.crt"
  29. intBundleFile = "/etc/cfssl/int-bundle.crt"
  30. numWorkers = 32
  31. timeout = time.Second
  32. )
  33. // intermediateCAScan scans for new intermediate CAs not in the trust store.
  34. func intermediateCAScan(addr, hostname string) (grade Grade, output Output, err error) {
  35. cidr, port, _ := net.SplitHostPort(addr)
  36. _, ipnet, err := net.ParseCIDR(cidr)
  37. if err != nil {
  38. return Skipped, nil, nil
  39. }
  40. b, err := bundler.NewBundler(caBundleFile, intBundleFile)
  41. if err != nil {
  42. return
  43. }
  44. var wg sync.WaitGroup
  45. wg.Add(numWorkers)
  46. dialer := &net.Dialer{Timeout: timeout}
  47. config := &tls.Config{InsecureSkipVerify: true}
  48. addrs := make(chan string)
  49. chains := make(chan []*x509.Certificate, numWorkers)
  50. go func() {
  51. for chain := range chains {
  52. b.Bundle(chain, nil, bundler.Force)
  53. }
  54. }()
  55. for i := 0; i < numWorkers; i++ {
  56. go func() {
  57. for addr := range addrs {
  58. conn, err := tls.DialWithDialer(dialer, Network, addr, config)
  59. if err != nil {
  60. continue
  61. }
  62. conn.Close()
  63. if conn.ConnectionState().HandshakeComplete {
  64. chains <- conn.ConnectionState().PeerCertificates
  65. }
  66. }
  67. wg.Done()
  68. }()
  69. }
  70. for ip := ipnet.IP.To16(); ipnet.Contains(ip); incrementBytes(ip) {
  71. addrs <- net.JoinHostPort(ip.String(), port)
  72. }
  73. close(addrs)
  74. wg.Wait()
  75. close(chains)
  76. grade = Good
  77. return
  78. }