CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/auxiliary/scanner/msmail/exchange_enum.go
Views: 1904
1
//usr/bin/env go run "$0" "$@"; exit "$?"
2
3
package main
4
5
import (
6
"crypto/tls"
7
"fmt"
8
"metasploit/module"
9
"msmail"
10
"net/http"
11
"strconv"
12
"strings"
13
"sync"
14
)
15
16
func main() {
17
metadata := &module.Metadata{
18
Name: "Exchange email enumeration",
19
Description: "Error-based user enumeration for Office 365 integrated email addresses",
20
Authors: []string{"poptart", "jlarose", "Vincent Yiu", "grimhacker", "Nate Power", "Nick Powers", "clee-r7"},
21
Date: "2018-11-06",
22
Type: "single_scanner",
23
Privileged: false,
24
References: []module.Reference{},
25
Options: map[string]module.Option{
26
"RHOSTS": {Type: "string", Description: "Target endpoint", Required: true, Default: "outlook.office365.com"},
27
"EMAIL": {Type: "string", Description: "Single email address to do identity test against", Required: false, Default: ""},
28
"EMAIL_FILE": {Type: "string", Description: "Path to file containing list of email addresses", Required: false, Default: ""},
29
}}
30
31
module.Init(metadata, run_exchange_enum)
32
}
33
34
func run_exchange_enum(params map[string]interface{}) {
35
email := params["EMAIL"].(string)
36
emailFile := params["EMAIL_FILE"].(string)
37
threads, e := strconv.Atoi(params["THREADS"].(string))
38
ip := params["rhost"].(string)
39
40
if e != nil {
41
module.LogError("Unable to parse 'Threads' value using default (5)")
42
threads = 5
43
}
44
45
if threads > 100 {
46
module.LogInfo("Threads value too large, setting max(100)")
47
threads = 100
48
}
49
50
if email == "" && emailFile == "" {
51
module.LogError("Expected 'EMAIL' or 'EMAIL_FILE' field to be populated")
52
return
53
}
54
55
var validUsers []string
56
if email != "" {
57
validUsers = o365enum(ip, []string{email}, threads)
58
}
59
60
if emailFile != "" {
61
validUsers = o365enum(ip, msmail.ImportUserList(emailFile), threads)
62
}
63
64
msmail.ReportValidUsers(ip, validUsers)
65
}
66
67
func o365enum(ip string, emaillist []string, threads int) []string {
68
limit := threads
69
var wg sync.WaitGroup
70
queue := make(chan string)
71
//limit := 100
72
73
/*Keep in mind you, nothing has been added to handle successful auths
74
so the password for auth attempts has been hardcoded to something
75
that is not likely to be correct.
76
*/
77
pass := "Summer2018876"
78
URI := "https://" + ip + "/Microsoft-Server-ActiveSync"
79
var validemails []string
80
81
tr := &http.Transport{
82
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
83
}
84
85
for i := 0; i < limit; i++ {
86
wg.Add(1)
87
go func(i int) {
88
defer wg.Done()
89
for email := range queue {
90
responseCode := msmail.WebRequestBasicAuth(URI, email, pass, tr)
91
if strings.Contains(email, "@") && responseCode == 401 {
92
module.LogGood(email + " - 401")
93
validemails = append(validemails, email)
94
} else if strings.Contains(email, "@") && responseCode == 404 {
95
module.LogError(fmt.Sprintf("%s - %d", email, responseCode))
96
} else {
97
module.LogError(fmt.Sprintf("Unusual Response: %s - %d", email, responseCode))
98
}
99
}
100
}(i)
101
}
102
103
for i := 0; i < len(emaillist); i++ {
104
queue <- emaillist[i]
105
}
106
107
close(queue)
108
wg.Wait()
109
return validemails
110
}
111
112