|
1 | 1 | package main |
2 | 2 |
|
3 | 3 | import ( |
4 | | - "crypto/tls" |
5 | 4 | "fmt" |
6 | 5 | "os" |
7 | | - "sort" |
8 | | - "time" |
9 | 6 |
|
| 7 | + "github.com/grokify/mogo/crypto/tlsutil" |
10 | 8 | "github.com/grokify/mogo/fmt/fmtutil" |
11 | | - "github.com/grokify/mogo/pointer" |
12 | 9 | ) |
13 | 10 |
|
14 | | -// List of weak TLS 1.2 ciphers |
15 | | -var weakCiphers = map[uint16]string{ |
16 | | - // tls.TLS_RSA_WITH_RC4_128_MD5: "TLS_RSA_WITH_RC4_128_MD5", |
17 | | - // tls.TLS_RSA_WITH_AES_256_CBC_SHA256: "TLS_RSA_WITH_AES_256_CBC_SHA256", |
18 | | - // tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", |
19 | | - // tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", |
20 | | - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", |
21 | | - tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", |
22 | | - tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", |
23 | | - tls.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", // RC4-based Ciphers (Insecure due to biases in RC4) |
24 | | - tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA", // 3DES-based Ciphers (Vulnerable to Sweet32 attack) |
25 | | - tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", |
26 | | - tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", |
27 | | - tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", |
28 | | - tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA: "TLS_ECDHE_RSA_WITH_RC4_128_SHA", // RC4-based Ciphers (Insecure due to biases in RC4) |
29 | | - tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA: "TLS_RSA_WITH_3DES_EDE_CBC_SHA", // 3DES-based Ciphers (Vulnerable to Sweet32 attack) |
30 | | - tls.TLS_RSA_WITH_AES_128_CBC_SHA: "TLS_RSA_WITH_AES_128_CBC_SHA", // RSA Key Exchange without Forward Secrecy |
31 | | - tls.TLS_RSA_WITH_AES_256_CBC_SHA: "TLS_RSA_WITH_AES_256_CBC_SHA", // RSA Key Exchange without Forward Secrecy |
32 | | - tls.TLS_RSA_WITH_AES_128_CBC_SHA256: "TLS_RSA_WITH_AES_128_CBC_SHA256", // RSA Key Exchange without Forward Secrecy |
33 | | - tls.TLS_RSA_WITH_RC4_128_SHA: "TLS_RSA_WITH_RC4_128_SHA", // RC4-based Ciphers (Insecure due to biases in RC4) |
34 | | -} |
35 | | - |
36 | | -/* strong ciphers |
37 | | -TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c) |
38 | | -TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d) |
39 | | -TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f) |
40 | | -TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b) |
41 | | -TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030) |
42 | | -TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c) |
43 | | -TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca8) |
44 | | -TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 (0xcca9) |
45 | | -*/ |
46 | | - |
47 | | -type CipherSuites struct { |
48 | | - Host string |
49 | | - Time *time.Time |
50 | | - Strong []string |
51 | | - Weak []string |
52 | | -} |
53 | | - |
54 | | -func checkAllCiphers(host string) { |
55 | | - fmt.Printf("Checking supported ciphers for %s\n", host) |
56 | | - |
57 | | - res := CipherSuites{ |
58 | | - Host: host, |
59 | | - Time: pointer.Pointer(time.Now().UTC()), |
60 | | - } |
61 | | - |
62 | | - for _, cipher := range tls.CipherSuites() { |
63 | | - config := &tls.Config{ |
64 | | - InsecureSkipVerify: true, // #nosec G402 -- intentional for cipher testing tool |
65 | | - CipherSuites: []uint16{cipher.ID}, |
66 | | - } |
67 | | - conn, err := tls.Dial("tcp", host, config) |
68 | | - if err == nil { |
69 | | - conn.Close() |
70 | | - if _, found := weakCiphers[cipher.ID]; found { |
71 | | - fmt.Printf("WEAK: %s\n", cipher.Name) |
72 | | - res.Weak = append(res.Weak, cipher.Name) |
73 | | - } else { |
74 | | - fmt.Printf("STRONG: %s\n", cipher.Name) |
75 | | - res.Strong = append(res.Strong, cipher.Name) |
76 | | - } |
77 | | - } |
78 | | - } |
79 | | - if len(res.Strong) > 0 { |
80 | | - sort.Strings(res.Strong) |
81 | | - } |
82 | | - if len(res.Weak) > 0 { |
83 | | - sort.Strings(res.Weak) |
84 | | - } |
85 | | - fmtutil.MustPrintJSON(res) |
86 | | -} |
87 | | - |
88 | 11 | func main() { |
89 | 12 | if len(os.Args) < 2 { |
90 | | - fmt.Println("Usage: go run main.go <host:port>") |
| 13 | + fmt.Printf("Usage: %s <host:port>\n", os.Args[0]) |
91 | 14 | os.Exit(1) |
92 | 15 | } |
93 | 16 |
|
94 | 17 | host := os.Args[1] |
95 | | - checkAllCiphers(host) |
| 18 | + fmt.Printf("Checking TLS support for %s\n\n", host) |
| 19 | + |
| 20 | + result := tlsutil.CheckHost(host) |
| 21 | + |
| 22 | + // Print text report |
| 23 | + fmt.Print(result.String()) |
| 24 | + |
| 25 | + // Print JSON output |
| 26 | + fmt.Println("\n=== JSON Output ===") |
| 27 | + fmtutil.MustPrintJSON(result) |
96 | 28 | } |
0 commit comments