Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
projectdiscovery
GitHub Repository: projectdiscovery/nuclei
Path: blob/dev/pkg/js/libs/smb/smb.go
2070 views
1
package smb
2
3
import (
4
"context"
5
"fmt"
6
"time"
7
8
"github.com/praetorian-inc/fingerprintx/pkg/plugins"
9
"github.com/projectdiscovery/go-smb2"
10
"github.com/projectdiscovery/nuclei/v3/pkg/protocols/common/protocolstate"
11
"github.com/zmap/zgrab2/lib/smb/smb"
12
)
13
14
type (
15
// SMBClient is a client for SMB servers.
16
// Internally client uses github.com/zmap/zgrab2/lib/smb/smb driver.
17
// github.com/projectdiscovery/go-smb2 driver
18
// @example
19
// ```javascript
20
// const smb = require('nuclei/smb');
21
// const client = new smb.SMBClient();
22
// ```
23
SMBClient struct{}
24
)
25
26
// ConnectSMBInfoMode tries to connect to provided host and port
27
// and discovery SMB information
28
// Returns handshake log and error. If error is not nil,
29
// state will be false
30
// @example
31
// ```javascript
32
// const smb = require('nuclei/smb');
33
// const client = new smb.SMBClient();
34
// const info = client.ConnectSMBInfoMode('acme.com', 445);
35
// log(to_json(info));
36
// ```
37
func (c *SMBClient) ConnectSMBInfoMode(ctx context.Context, host string, port int) (*smb.SMBLog, error) {
38
executionId := ctx.Value("executionId").(string)
39
return memoizedconnectSMBInfoMode(executionId, host, port)
40
}
41
42
// @memo
43
func connectSMBInfoMode(executionId string, host string, port int) (*smb.SMBLog, error) {
44
if !protocolstate.IsHostAllowed(executionId, host) {
45
// host is not valid according to network policy
46
return nil, protocolstate.ErrHostDenied.Msgf(host)
47
}
48
dialer := protocolstate.GetDialersWithId(executionId)
49
if dialer == nil {
50
return nil, fmt.Errorf("dialers not initialized for %s", executionId)
51
}
52
conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port))
53
if err != nil {
54
return nil, err
55
}
56
// try to get SMBv2/v3 info
57
result, err := getSMBInfo(conn, true, false)
58
_ = conn.Close() // close regardless of error
59
if err == nil {
60
return result, nil
61
}
62
63
// try to negotiate SMBv1
64
conn, err = dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port))
65
if err != nil {
66
return nil, err
67
}
68
defer func() {
69
_ = conn.Close()
70
}()
71
result, err = getSMBInfo(conn, true, true)
72
if err != nil {
73
return result, nil
74
}
75
return result, nil
76
}
77
78
// ListSMBv2Metadata tries to connect to provided host and port
79
// and list SMBv2 metadata.
80
// Returns metadata and error. If error is not nil,
81
// state will be false
82
// @example
83
// ```javascript
84
// const smb = require('nuclei/smb');
85
// const client = new smb.SMBClient();
86
// const metadata = client.ListSMBv2Metadata('acme.com', 445);
87
// log(to_json(metadata));
88
// ```
89
func (c *SMBClient) ListSMBv2Metadata(ctx context.Context, host string, port int) (*plugins.ServiceSMB, error) {
90
executionId := ctx.Value("executionId").(string)
91
if !protocolstate.IsHostAllowed(executionId, host) {
92
// host is not valid according to network policy
93
return nil, protocolstate.ErrHostDenied.Msgf(host)
94
}
95
return memoizedcollectSMBv2Metadata(executionId, host, port, 5*time.Second)
96
}
97
98
// ListShares tries to connect to provided host and port
99
// and list shares by using given credentials.
100
// Credentials cannot be blank. guest or anonymous credentials
101
// can be used by providing empty password.
102
// @example
103
// ```javascript
104
// const smb = require('nuclei/smb');
105
// const client = new smb.SMBClient();
106
// const shares = client.ListShares('acme.com', 445, 'username', 'password');
107
//
108
// for (const share of shares) {
109
// log(share);
110
// }
111
//
112
// ```
113
func (c *SMBClient) ListShares(ctx context.Context, host string, port int, user, password string) ([]string, error) {
114
executionId := ctx.Value("executionId").(string)
115
return memoizedlistShares(executionId, host, port, user, password)
116
}
117
118
// @memo
119
func listShares(executionId string, host string, port int, user string, password string) ([]string, error) {
120
if !protocolstate.IsHostAllowed(executionId, host) {
121
// host is not valid according to network policy
122
return nil, protocolstate.ErrHostDenied.Msgf(host)
123
}
124
dialer := protocolstate.GetDialersWithId(executionId)
125
if dialer == nil {
126
return nil, fmt.Errorf("dialers not initialized for %s", executionId)
127
}
128
129
conn, err := dialer.Fastdialer.Dial(context.TODO(), "tcp", fmt.Sprintf("%s:%d", host, port))
130
if err != nil {
131
return nil, err
132
}
133
defer func() {
134
_ = conn.Close()
135
}()
136
137
d := &smb2.Dialer{
138
Initiator: &smb2.NTLMInitiator{
139
User: user,
140
Password: password,
141
},
142
}
143
s, err := d.Dial(conn)
144
if err != nil {
145
return nil, err
146
}
147
defer func() {
148
_ = s.Logoff()
149
}()
150
151
names, err := s.ListSharenames()
152
if err != nil {
153
return nil, err
154
}
155
return names, nil
156
}
157
158